zoukankan      html  css  js  c++  java
  • DirectShow的截图方案简述

    http://blog.csdn.net/Macapplelove/archive/2010/10/23/5961173.aspx

    DirectShow的截图方案简述
    用directshow可以有多种实现的方案,下面介绍三种:

    第一种采用IMediaDet接口的GetBitmaps方法,速度很快,但是Video的类型有限制,对于WMF类型、RMVB等都无法正常截图,下面是例子代码:
    BOOL Grabber1()
    {
    if(!m_pMediaDet) // IMediaDet接口,它除了用于截图还可以用于判断媒体类型
       return FALSE;
    BOOL bResult = FALSE;
    HRESULT thr;
    long width = 0, height = 0;
    AM_MEDIA_TYPE mt;
    m_pMediaDet->put_Filename(m_strMediaFile.AllocSysString());
    thr = m_pMediaDet->get_StreamMediaType(&mt);

    if (1/*mt.formattype != FORMAT_VideoInfo*/) //在此有类型限制
    {
       VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat);
       width = pVih->bmiHeader.biWidth;
       height = pVih->bmiHeader.biHeight;
       if (height < 0)
        height *= -1;
    }
    else
    {
       return VFW_E_INVALIDMEDIATYPE;     
         }
    FreeMediaType(mt);

    long size;
    char * pBuffer;
    int gt; // grabber time
    gt = m_curpos * m_Duration / m_filelength;
    thr = m_pMediaDet->GetBitmapBits(gt,&size,NULL,width,height);
    if(SUCCEEDED(thr))
    {
       pBuffer = new char[size];
       if(!pBuffer)
        return E_OUTOFMEMORY;
    }
    try
    {
       thr = m_pMediaDet->GetBitmapBits(gt,0,pBuffer,width,height);
    }
    catch(...)
    {
       delete [] pBuffer;
       throw;
    }
    if(SUCCEEDED(thr))
    {
       BITMAPINFOHEADER * bmih = (BITMAPINFOHEADER*)pBuffer;
       HDC hdcDest = ::GetDC(0);
       void * pData = pBuffer + sizeof(BITMAPINFOHEADER);
       // Note: In general a BITMAPINFOHEADER can include extra color
       // information at the end, so calculating the offset to the image
       // data is not generally correct. However, the IMediaDet interface
       // always returns an RGB-24 image with no extra color information
       BITMAPINFO bmi;
       ZeroMemory(&bmi, sizeof(BITMAPINFO));
       CopyMemory(&(bmi.bmiHeader),bmih,sizeof(BITMAPINFOHEADER));
       HBITMAP hB = CreateDIBitmap(hdcDest,
        bmih,
        CBM_INIT,
        pData,
        &bmi,
        DIB_RGB_COLORS);
       // write to bitmap
        BITMAPFILEHEADER   hdr;     //Bitmap的头信息
        LPBITMAPINFOHEADER    lpbi; // Bitmap的文件信息(包括数据)
        lpbi = (LPBITMAPINFOHEADER)pBuffer;
        int nColors = 1 << lpbi->biBitCount;
        if (nColors > 256)
         nColors = 0;
        hdr.bfType     = ((WORD) ('M' << 8) | 'B');     //always is "BM"
        hdr.bfSize     = size + sizeof( hdr );
        hdr.bfReserved1    = 0;
        hdr.bfReserved2    = 0;
        hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize);

    // 保存图 
    CString bmpPath(m_grbDirectory);
        bmpPath += "\\temp.bmp";
        CFile bitmapFile(bmpPath, CFile::modeNoTruncate|
        CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
        bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER));
        bitmapFile.Write(pBuffer, size);
        bitmapFile.Close();
        bResult = TRUE;
    }
    bResult = FALSE;
    delete [] pBuffer;
    return bResult;
    }

    第二种方案采用的是IBasicVideo中的GetCurrentImage方法,这种方案几乎可以处理所有的视频类型,但是每一次截图都有一个短暂的暂停,也是就停顿,下面是例子:

    BOOL Grabber2()
    {
    if(m_pGraph == NULL)
        return FALSE;
    else
        m_pGraph->QueryInterface(IID_IBasicVideo,(void **)&m_pBasicVideo);

    if(m_pBasicVideo == NULL)
        return FALSE;
    long bitmapSize = 0;
    BOOL bResult = FALSE;
    if (SUCCEEDED(m_pBasicVideo->GetCurrentImage(&bitmapSize, 0)))
    {
        unsigned char * buffer = new unsigned char[bitmapSize];
        if (SUCCEEDED(m_pBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))
        {
         BITMAPFILEHEADER hdr;
         LPBITMAPINFOHEADER lpbi;
         lpbi = (LPBITMAPINFOHEADER)buffer;
         int nColors = 0;
         if( lpbi->biBitCount <=8)
         nColors = 1 << lpbi->biBitCount;
         hdr.bfType = ((WORD) ('M' << 8) | 'B'); //always is "BM"
         hdr.bfSize = bitmapSize + sizeof( hdr );
         hdr.bfReserved1 = 0;
         hdr.bfReserved2 = 0;
         hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize +
         nColors * sizeof(RGBQUAD));
     
         // write to file 
         CString bmpPath(m_grbDirectory);
         bmpPath += "\\";// to save something
         bmpPath += RandString(16);
         bmpPath += ".bmp";
         CFile bitmapFile(bmpPath, CFile::modeNoTruncate|
         CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
         bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER));
         bitmapFile.Write(buffer,bitmapSize);
         bitmapFile.Close();
         bResult = TRUE;
        // MessageBox(bmpPath,"成功保存提示");
         CRect rcTmp;
         GetWindowRect(&rcTmp);
         m_windowmove = -m_windowmove;
         rcTmp.OffsetRect(CPoint(0,m_windowmove));
         MoveWindow(rcTmp);
        }
        delete [] buffer;
        bResult = FALSE;
    }
    if(m_pBasicVideo != NULL)
    {
        m_pBasicVideo->Release();
        m_pBasicVideo = NULL;
    }

    return bResult;
    }


    为了寻求既快而且能处理所有类型的方案,找到了IVMRWindowlessControl9接口。它是VRM9中才有的,所以必须引入d3d9.h和vrm9.h头文件。

    但是在之前用的IMediaDet接口中包含了Qedit.h,而这个文件和上述两个头文件是不相容的。所以如果同在一个.h中#include他们会出现类似这样的报错:
    syntax      error      :      identifier      'IDirect3DSurface9'  
    所以,我尝试着把qedit.h放置到.cpp中去,错误虽然少了,但变成了这些:
    error C2061: syntax error : identifier 'LPDIRECT3D'
    error C2061: syntax error : identifier 'LPDIRECT3DDEVICE'
    error C2061: syntax error : identifier 'LPDIRECT3DDEVICE2'

    为了解决问题,可以把qedit.h去掉,但是那样就没法用IMediaDet接口了。所以,必须建立一个小点的头文件,把包含ImediaDet那部分copy进去,然后使用它就可以了,我把用到的置于了mediadet.h中,主要包含了SampleGrabberCB和IMediaDet以及CLSID的定义。这样问题就解决了。

    例子代码如下:

          if(m_pVMRWC && m_fStyle == VIDEO_STYLE)
          {
              BYTE* lpCurrImage = NULL;

              // Read the current video frame into a byte buffer.    The information
              // will be returned in a packed Windows DIB and will be allocated
              // by the VMR.
              if(m_pVMRWC->GetCurrentImage(&lpCurrImage) == S_OK)
              {
                  BITMAPFILEHEADER      hdr;
                  DWORD                 dwSize, dwWritten;
                  LPBITMAPINFOHEADER    pdib = (LPBITMAPINFOHEADER) lpCurrImage;

                  // Create a new file to store the bitmap data 
         CString bmpPath(m_grbDirectory);
         bmpPath += "\\";// to save something
         bmpPath += RandString(16);
         bmpPath += ".bmp";
                  HANDLE hFile = CreateFile(TEXT(bmpPath), GENERIC_WRITE, FILE_SHARE_READ, NULL,
                                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

                  if (hFile == INVALID_HANDLE_VALUE)
                      return FALSE;

                  // Initialize the bitmap header
                  dwSize = DibSize(pdib);
                  hdr.bfType            = BFT_BITMAP;
                  hdr.bfSize            = dwSize + sizeof(BITMAPFILEHEADER);
                  hdr.bfReserved1       = 0;
                  hdr.bfReserved2       = 0;
                  hdr.bfOffBits         = (DWORD)sizeof(BITMAPFILEHEADER) + pdib->biSize +
                      DibPaletteSize(pdib);

                  // Write the bitmap header and bitmap bits to the file
                  WriteFile(hFile, (LPCVOID) &hdr, sizeof(BITMAPFILEHEADER), &dwWritten, 0);
                  WriteFile(hFile, (LPCVOID) pdib, dwSize, &dwWritten, 0);

                  // Close the file
                  CloseHandle(hFile);

                  // The app must free the image data returned from GetCurrentImage()
                  CoTaskMemFree(lpCurrImage);

                  // Give user feedback that the write has completed
                  // MessageBox(bmpPath);
                  return TRUE;
              }
          }
          return FALSE;

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Macapplelove/archive/2010/10/23/5961173.aspx

  • 相关阅读:
    print 参数
    note
    action标签的属性说明
    Cannot load JDBC driver class 'oracle.jdbc.driver.OracleDriver'
    润乾报表
    javax.naming.NameNotFoundException: Name ZKING is not bound in this Context 的问题
    Myeclipse2013安装svn插件
    Myeclipse2013的优化设置
    Myeclipse解析.classpath文件
    Struts
  • 原文地址:https://www.cnblogs.com/carl2380/p/1934372.html
Copyright © 2011-2022 走看看