A Class Capturing Video by DShow

A Class Capturing Video by DShow

no crap only codes

 1 class  CCaptureVideo :  public  CWnd 
 2 {
 3     friend  class  CSampleGrabberCB;
 4 public :
 5      void  GrabOneFrame(BOOL bGrab,  const  CString &  szFileName);
 6     HRESULT Init( int  iDeviceID,HWND hWnd);
 7      int  EnumDevices(HWND hList);
 8     CCaptureVideo();
 9      virtual   ~ CCaptureVideo();
10 private :
11     HWND m_hWnd;
12     IGraphBuilder  * m_pGB;
13     ICaptureGraphBuilder2 *  m_pCapture;
14     IBaseFilter *  m_pBF;
15     IMediaControl *  m_pMC;
16     IMediaEventEx  *  m_pME;
17     IVideoWindow *  m_pVW;
18     CComPtr < ISampleGrabber >  m_pGrabber;
19 protected :
20      void  FreeMediaType(AM_MEDIA_TYPE &  mt);
21      bool  BindFilter( int  deviceId, IBaseFilter  ** pFilter);
22      void  ResizeVideoWindow();
23     HRESULT SetupVideoWindow();
24     HRESULT InitCaptureGraphBuilder();
25 }
;

 1
 2 class  CSampleGrabberCB :  public  ISampleGrabberCB 
 3 {
 4 public :
 5      long  lWidth;
 6      long  lHeight;
 7      static  CString m_szFileName; //  位图文件名称
 8     CSampleGrabberCB( )
 9      {
10     }
 
11
12     STDMETHODIMP_(ULONG) AddRef() 
13      return   2 ; }
14
15     STDMETHODIMP_(ULONG) Release() 
16      return   1 ; }
17
18     STDMETHODIMP QueryInterface(REFIID riid,  void   **  ppv)
19      {
20          if ( riid  ==  IID_ISampleGrabberCB  ||  riid  ==  IID_IUnknown )
21         
22              * ppv  =  ( void   * ) static_cast < ISampleGrabberCB *>  (  this  );
23              return  NOERROR;
24         }
 
25          return  E_NOINTERFACE;
26     }

27
28     STDMETHODIMP SampleCB(  double  SampleTime, IMediaSample  *  pSample )
29      {
30          return   0 ;
31     }

32
33     STDMETHODIMP BufferCB(  double  dblSampleTime, BYTE  *  pBuffer,  long  lBufferSize )
34      {
35          if ! bOneShot ) return   0 ;
36         
37          if  ( ! pBuffer)
38              return  E_POINTER;
39
40          if (SaveBitmap(pBuffer, lBufferSize))
41          {
42              //  notify has create a bitmap file;
43             CGlobalData::m_pMainView -> HasSavedPhoto(m_szFileName);
44         }

45
46         bOneShot  =  FALSE;
47
48     
49          return   0 ;
50     }

51      // 创建位图文件
52     BOOL SaveBitmap(BYTE  *  pBuffer,  long  lBufferSize )
53      {
54         HANDLE hf  =  CreateFile(
55             m_szFileName,
56             GENERIC_WRITE, FILE_SHARE_READ, NULL,
57             CREATE_ALWAYS,
58             NULL, 
59             NULL );
60
61          if ( hf  ==  INVALID_HANDLE_VALUE )
62              return  FALSE;
63
64          //  写文件头 
65         BITMAPFILEHEADER bfh;
66         memset(  & bfh,  0 sizeof ( bfh ) );
67         bfh.bfType  =   ' MB ' ;
68         bfh.bfSize  =   sizeof ( bfh )  +  lBufferSize  +   sizeof ( BITMAPINFOHEADER );
69         bfh.bfOffBits  =   sizeof ( BITMAPINFOHEADER )  +   sizeof ( BITMAPFILEHEADER );
70         DWORD dwWritten  =   0 ;
71         WriteFile( hf,  & bfh,  sizeof ( bfh ),  & dwWritten, NULL );
72
73          //  写位图格式
74         BITMAPINFOHEADER bih;
75         memset(  & bih,  0 sizeof ( bih ) );
76         bih.biSize  =   sizeof ( bih );
77         bih.biWidth  =  lWidth;
78         bih.biHeight  =  lHeight;
79         bih.biPlanes  =   1 ;
80         bih.biBitCount  =   24 ;
81         WriteFile( hf,  & bih,  sizeof ( bih ),  & dwWritten, NULL );
82
83          //  写位图数据
84         WriteFile( hf, pBuffer, lBufferSize,  & dwWritten, NULL );
85
86         CloseHandle( hf );
87
88          return  TRUE;
89     }

90 }
;

/**/ ///////////////////////////////////////////////////////////////////// /
//  Construction/Destruction
/**/ ///////////////////////////////////////////////////////////////////// /
CCaptureVideo::CCaptureVideo()
{
    m_pBF 
=   0 ;
    m_hWnd 
=  NULL;
    m_pVW 
=  NULL;
    m_pMC 
=  NULL;
    m_pME 
=  NULL;
    m_pGB 
=  NULL;
    m_pCapture 
=  NULL; 
}

CCaptureVideo::
~ CCaptureVideo()
{
    
//  Stop media playback

    
if (m_pMC)
        m_pMC
-> StopWhenReady();
    
//  Stop receiving events
     if  (m_pME)
        m_pME
-> SetNotifyWindow(NULL, WM_GRAPHNOTIFY,  0 );

    
if (m_pVW) {
        m_pVW
-> put_Visible(OAFALSE);
        m_pVW
-> put_Owner(NULL);
    }



    SAFE_RELEASE(m_pMC);
    SAFE_RELEASE(m_pME);
    SAFE_RELEASE(m_pVW);
    SAFE_RELEASE(m_pGB);
    SAFE_RELEASE(m_pBF);
    SAFE_RELEASE(m_pCapture);
    
// CoUninitialize( );
}

int  CCaptureVideo::EnumDevices(HWND hList)
{
    
if  ( ! hList)
        
return   - 1 ;
    
int  id  =   0 ;
    
    
// 枚举视频扑捉设备
    ICreateDevEnum  * pCreateDevEnum;
    HRESULT hr 
=  CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, ( void ** ) & pCreateDevEnum);
    
    
if  (hr  !=  NOERROR) return   - 1 ;
    CComPtr
< IEnumMoniker >  pEm;
    hr 
=  pCreateDevEnum -> CreateClassEnumerator(CLSID_VideoInputDeviceCategory, & pEm,  0 );
    
    
if  (hr  !=  NOERROR) return   - 1 ;
    pEm
-> Reset();
    ULONG cFetched;
    IMoniker 
* pM;
    
while (hr  =  pEm -> Next( 1 & pM,  & cFetched), hr == S_OK)
    
{
        IPropertyBag 
* pBag;
        hr 
=  pM -> BindToStorage( 0 0 , IID_IPropertyBag, ( void   ** ) & pBag);
        
if (SUCCEEDED(hr)) 
        
{
            VARIANT var;
            var.vt 
=  VT_BSTR;
            hr 
=  pBag -> Read(L " FriendlyName " & var, NULL);
            
if  (hr  ==  NOERROR) 
            
{
                TCHAR str[
2048 ]; 
                id
++ ;
                WideCharToMultiByte(CP_ACP,
0 ,var.bstrVal,  - 1 , str,  2048 , NULL, NULL);
                ::SendMessage(hList, CB_ADDSTRING, 
0 ,(LPARAM)str);
                SysFreeString(var.bstrVal);
            }

            pBag
-> Release();
        }

        pM
-> Release();
    }

    
return  id;
}

HRESULT CCaptureVideo::Init(
int  iDeviceID, HWND hWnd)
{
    HRESULT hr;
    hr 
=  InitCaptureGraphBuilder();
    
if  (FAILED(hr)) {
        AfxMessageBox(
" Failed to get video interfaces! " );
        
return  hr;
    }


    
//  Bind Device Filter. We know the device because the id was passed in
     if ( ! BindFilter(iDeviceID,  & m_pBF)) return  S_FALSE;
    hr 
=  m_pGB -> AddFilter(m_pBF, L " Video Capture " );
    
if  (FAILED(hr))
    
{
        m_pBF
-> Release();
        
return  hr;
    }


    
//  create a sample grabber
    hr  =  m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
    
if ! m_pGrabber ) {
        AfxMessageBox(
" Fail to create SampleGrabber, maybe qedit.dll is not registered? " );
        
return  hr;
    }

    CComQIPtr
<  IBaseFilter,  & IID_IBaseFilter  >  pGrabBase( m_pGrabber );
    
    
// 设置视频格式
    AM_MEDIA_TYPE mt; 
    ZeroMemory(
& mt,  sizeof (AM_MEDIA_TYPE));
    mt.majortype 
=  MEDIATYPE_Video;
    mt.subtype 
=  MEDIASUBTYPE_RGB24;
    hr 
=  m_pGrabber -> SetMediaType( & mt);
    
    
if ( FAILED( hr ) ) {
        AfxMessageBox(
" Fail to set media type! " );
        
return  hr;
    }

    hr 
=  m_pGB -> AddFilter( pGrabBase, L " Grabber "  );
    
if ( FAILED( hr ) ) {
        AfxMessageBox(
" Fail to put sample grabber in graph " );
        
return  hr;
    }

    
    
//  try to render preview/capture pin
    hr  =  m_pCapture -> RenderStream( & PIN_CATEGORY_PREVIEW,  & MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
    
if ( FAILED( hr ) )
        hr 
=  m_pCapture -> RenderStream( & PIN_CATEGORY_CAPTURE,  & MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
    
    
if ( FAILED( hr ) ) {
        AfxMessageBox(
" Can’t build the graph " );
        
return  hr;
          }

    
    hr 
=  m_pGrabber -> GetConnectedMediaType(  & mt );
    
if  ( FAILED( hr) ) {
        AfxMessageBox(
" Failt to read the connected media type " );
        
return  hr;
    }

    
    VIDEOINFOHEADER 
*  vih  =  (VIDEOINFOHEADER * ) mt.pbFormat;
    mCB.lWidth 
=  vih -> bmiHeader.biWidth;
    mCB.lHeight 
=  vih -> bmiHeader.biHeight;
    FreeMediaType(mt);
    hr 
=  m_pGrabber -> SetBufferSamples( FALSE );
    hr 
=  m_pGrabber -> SetOneShot( FALSE );
    hr 
=  m_pGrabber -> SetCallback(  & mCB,  1  );
    
    
// 设置视频捕捉窗口
    m_hWnd  =  hWnd ; 
    SetupVideoWindow();

    hr 
=  m_pMC -> Run(); // 开始视频捕捉
     if (FAILED(hr))
    
{
        AfxMessageBox(
" Couldn’t run the graph! " );
        
return  hr;
    }


    
return  S_OK;
}

bool  CCaptureVideo::BindFilter( int  deviceId, IBaseFilter  ** pFilter)
{
    
if  (deviceId  <   0 )
        
return   false ;
    IBaseFilter 
*  pSrc  =  NULL;
    
//  enumerate all video capture devices
    CComPtr < ICreateDevEnum >  pCreateDevEnum  =  NULL;
    HRESULT hr 
=  CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
        IID_ICreateDevEnum, (
void ** ) & pCreateDevEnum);
    
if  (FAILED(hr))
    
{
        
return   false ;
    }

    CComPtr
< IEnumMoniker >  pEm  =  NULL;
    hr 
=  pCreateDevEnum -> CreateClassEnumerator(CLSID_VideoInputDeviceCategory, & pEm,  0 );
    
if  (FAILED(hr)) 
    
{
        
return   false ;
    }

    
// pEm->Reset();

    ULONG cFetched;
    IMoniker 
* pM;
    
int  index  =   0 ;
    
while (S_OK  ==  (pEm -> Next( 1 & pM,  & cFetched))  &&  index  <=  deviceId)
    
{
        IPropertyBag 
* pBag;
        hr 
=  pM -> BindToStorage( 0 0 , IID_IPropertyBag, ( void   ** ) & pBag);
        
if (SUCCEEDED(hr)) 
        
{
            VARIANT var;
            var.vt 
=  VT_BSTR;
            hr 
=  pBag -> Read(L " FriendlyName " & var, NULL);
            
if  (hr  ==  NOERROR) 
            
{
                
if  (index  ==  deviceId)
                
{
                    pM
-> BindToObject( 0 0 , IID_IBaseFilter, ( void ** ) & pSrc);
                }

                SysFreeString(var.bstrVal);
            }

            pBag
-> Release();
        }

        pM
-> Release();
        index
++ ;
    }


    
* pFilter  =  pSrc;
    
return   true ;
}


HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
    HRESULT hr;
    
    
//  创建IGraphBuilder接口
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
        IID_IGraphBuilder, (
void   ** ) & m_pGB);
    
if  (FAILED(hr))
        
return  hr;

    
//  创建ICaptureGraphBuilder2接口
    hr  =  CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
        IID_ICaptureGraphBuilder2, (
void   ** & m_pCapture);
    
if  (FAILED(hr))
        
return  hr;

    m_pCapture
-> SetFiltergraph(m_pGB);
    hr 
=  m_pGB -> QueryInterface(IID_IMediaControl, ( void   ** ) & m_pMC);
    
if  (FAILED(hr))
        
return  hr;

    hr 
=  m_pGB -> QueryInterface(IID_IVideoWindow, (LPVOID  * & m_pVW);
    
if  (FAILED(hr))
        
return  hr;

    hr 
=  m_pGB -> QueryInterface(IID_IMediaEvent, (LPVOID  * & m_pME);
    
if  (FAILED(hr))
        
return  hr;

    
//  Set the window handle used to process graph events
    hr  =  m_pME -> SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY,  0 );

    
return  hr;
}

HRESULT CCaptureVideo::SetupVideoWindow()
{
    HRESULT hr;
    hr 
=  m_pVW -> put_Owner((OAHWND)m_hWnd);
    
if  (FAILED(hr))
        
return  hr;

    hr 
=  m_pVW -> put_WindowStyle(WS_CHILD  |  WS_CLIPCHILDREN);
    
if  (FAILED(hr))
        
return  hr;

    ResizeVideoWindow();
    hr 
=  m_pVW -> put_Visible(OATRUE);

    
return  hr;
}

void  CCaptureVideo::ResizeVideoWindow()
{
    
if  (m_pVW) {
        
// 让图像充满整个窗口
        CRect rc;
        ::GetClientRect(m_hWnd,
& rc);
        m_pVW
-> SetWindowPosition( 0 0 , rc.right, rc.bottom);
    }
 
}

void  CCaptureVideo::GrabOneFrame(BOOL bGrab,  const  CString &  szFileName)
{
    bOneShot 
=  bGrab;
    CSampleGrabberCB::m_szFileName 
=  szFileName;
}

void  CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE &  mt)
{
    
if  (mt.cbFormat  !=   0 {
        CoTaskMemFree((PVOID)mt.pbFormat);
        
//  Strictly unnecessary but tidier
        mt.cbFormat  =   0 ;
        mt.pbFormat 
=  NULL;
    }

    
if  (mt.pUnk  !=  NULL)  {
        mt.pUnk
-> Release();
        mt.pUnk 
=  NULL;
    }

}
 

你可能感兴趣的:(A Class Capturing Video by DShow)