directshow和vfw采集并转发视频数据的接口

/********************此文可以被转发,但请转发者保留作者的署名权
****李浩
****msn:lihao_nx@hotmail.com
****
****email:lihaoyxj@gmail.com
****出处:lihaoyxj.cublog.cn
****from:http://blog.csdn.net/lihao_ningxia
*****************/
vfw

//head file

// VideoCapture.h: interface for the VideoCapture class.

////////////////////////////////////////////////////////////////////////

#if !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_)

#define AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000



#include<vfw.h>
#include<afxmt.h>
#include<afxole.h>

#include "CommClient.h"
#include "Encoder/libr263.h"
#include "Decoder/tmndec.h"

/****************************   NOTE **************************/
//  If the parameters below are changed then change following
//  > cdata & cbuffer_size in VideoNetDlg.cpp
//  > rgbdata & buffersize in VideoNetDlg.cpp
//  > update CPARAMS structure before compression
//  > computation of local_wnd_x para in OnInitDialog()
//
////////////////////////////////////////////////////////////////

#define QCIF_WIDTH  176
#define QCIF_HEIGHT 144
//#define QCIF_WIDTH  320
//#define QCIF_HEIGHT 240

#define IMAGE_WIDTH       QCIF_WIDTH
#define IMAGE_HEIGHT      QCIF_HEIGHT

// 回调函数定义
typedef LRESULT (*CALLBACKFUNC)(HWND,LPVIDEOHDR);

class VideoCapture 
{
public:
   
    HWND m_capwnd;
    CStdioFile log;
    CAPDRIVERCAPS caps;
    CMutex protectframe;
    int avgaudiosize;
    BOOL isOver;
    CDialog *dlg;
    BITMAPINFOHEADER m_bmpheader;
    BITMAPINFO m_bmpinfo;

    VideoCapture();
    virtual ~VideoCapture();
    BOOL Initialize();
    BOOL  SetCapturePara();
    void Destroy();
    void GetDriverCaps();
    void SetAudioFormat();
    int AllocateMemory(PBITMAPINFO &bmpinfo);
    int getFormatSize(BITMAPINFO bmp);
    int getImageSize(BITMAPINFO bmp);

    // 启动视频捕获
    BOOL StartCapture(HDC BackDC);
    BOOL StopCapture();

    friend LRESULT CALLBACK OnCaptureVideo(HWND hWnd, LPVIDEOHDR lpheader) ;

    void*            m_pParam;
protected:
    void DrawLocalScreen(LPVIDEOHDR lphdr);
    void InitCompressor();
    void CompressFrame(LPVIDEOHDR lphdr);
    CALLBACKFUNC    m_OnCaptureVideo;
   
    // 压缩参数
    COMPVARS        m_CV;

    // 视频回放句柄
    HDC                m_LocalScreenDC;
    HDRAWDIB        m_hdib;

    // 数据通信接口
    CCommClient*    m_pCommClient;
   
    // Compression parameters....
    CParam cparams;
   
    // Buffer for storing YUV data....
    unsigned int yuv[ QCIF_WIDTH*QCIF_HEIGHT  + (QCIF_WIDTH*QCIF_HEIGHT)/2 ];
public:
    void SetCommClient(CCommClient* pClient);
    //////////////////////////////////////////////////////////////////////////
    //
    // 设置采集数据回调接口
    //
    void SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam);

    //////////////////////////////////////////////////////////////////////////
    //
    // 回放远程视频
    //
    void DrawRemoteScreen(char *data, UINT size, HDC hScreenDC);
};


#endif // !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_)


//cpp file
////////////////////////////////////////////////////////////////////////////
//
//
//    Project     : VideoNet version 1.1.
//
//    File description :
//    Name    :  VideoCapture.cpp
//    Details :  Captures the frames from webcam.
//
//
/////////////////////////////////////////////////////////////////////////////


#include "Stdafx.h"
#include "VideoCapture.h"

#include <afxmt.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#pragma comment(lib,"vfw32")
#pragma comment(lib,"winmm")


// Global varialbes...
int count=0;
unsigned char cdata[10000];
int cbuffer_size=10000;
unsigned char rgbdata[80000];
int buffersize=80000;

// Callback function gets invoked during compression...
// It returns the compressed data byte by byte...
void OwnWriteFunction(int byte)
{
    if(count<cbuffer_size)
        cdata[count]=(unsigned char)byte;
   
    count++;
   
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

VideoCapture::VideoCapture()
{
    m_capwnd            = NULL;
    isOver                = FALSE;
    m_OnCaptureVideo    = NULL;
   
    log.Open("videocapture.log",CFile::modeCreate | CFile::modeWrite);
}


VideoCapture::~VideoCapture()
{
}


BOOL VideoCapture::Initialize()
{
    char devname[100],devversion[100];
    char str[200];
    int index=0;
   
    // 初始化压缩编码器
    InitCompressor();
   
    // 创建摄像头句柄
    m_capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
    if(m_capwnd==NULL)
    {
        log.WriteString(""n Unable to create capture window");
        return FALSE;
    }

    // 连接摄像头设备   
    capSetUserData( m_capwnd, this );
   
    // 显示视频设置对话框,进行配置视频的大小、颜色位数等。
    capDlgVideoFormat( m_capwnd );

    // 取得视频图像数据头,后面压缩时需要用到
    capGetVideoFormat( m_capwnd, &m_bmpinfo, sizeof(BITMAPINFO) );
   
    // 设置回调函数
    capSetCallbackOnVideoStream( m_capwnd, OnCaptureVideo );
   
    capGetDriverDescription(index,devname,100,devversion,100);
   
    sprintf(str,""n Driver name = %s version = %s ",devname,devversion);
    log.WriteString(str);
   
    // Connect to webcam driver
    if( ! capDriverConnect(m_capwnd,index) )
    {
       
        // Device may be open already or it may not have been
        // closed properly last time.
        AfxMessageBox("Unable to open Video Capture Device");
        log.WriteString(""n Unable to connect driver to the window");
        m_capwnd=NULL;
        return FALSE;
    }
   
    // Set the capture parameters
    if(SetCapturePara()==FALSE)
    {
        log.WriteString(""n Setting capture parameters failed");
        capDriverDisconnect(m_capwnd);
        return FALSE;
    }


    return TRUE;
}




/**
*   Start capturing frames from webcam
*
*/

BOOL VideoCapture::StartCapture(HDC    BackDC)
{
    m_LocalScreenDC    = BackDC;
   
    // 初始化视频回放对象
    m_hdib    = ::DrawDibOpen();
    if( m_hdib != NULL )
    {
        ::DrawDibBegin(
            m_hdib,
            m_LocalScreenDC,
            -1,                // don't stretch
            -1,                // don't stretch
            &m_bmpinfo.bmiHeader,
            IMAGE_WIDTH,         // width of image
            IMAGE_HEIGHT,        // height of image
            0               
            );
    }
   
    // 开始视频采集
    if(capCaptureSequenceNoFile(m_capwnd)==FALSE)
    {
        log.WriteString(""n Failed to capture Sequence ..");
        return FALSE;
    }
   
    return TRUE;
   
}





/**
*   Stop the capturing process
*
*/

BOOL VideoCapture::StopCapture()
{
   
    capCaptureStop(m_capwnd);
    capCaptureAbort(m_capwnd);
    Sleep(500);   
   
    return TRUE;
}






/**
*   Stop the catpure process and disconnect the driver
*
*/
void VideoCapture::Destroy()
{
   
    if(m_capwnd==NULL) return;
   
    // Stop the capturing process   
    capCaptureAbort(m_capwnd);
   
    // Disable the callback function..
    capSetCallbackOnVideoStream(m_capwnd, NULL);
   
    Sleep(300);        // This delay is important...
   
    // Finally disconnect the driver
    capDriverDisconnect(m_capwnd);
}








/**
*
*     Set various capture parameters...
*
*/

BOOL  VideoCapture::SetCapturePara()
{
    CAPTUREPARMS CapParms={0};   
   
   
    capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms));
   
    CapParms.fAbortLeftMouse = FALSE;
    CapParms.fAbortRightMouse = FALSE;
    CapParms.fYield = TRUE;
    CapParms.fCaptureAudio = FALSE;
    CapParms.wPercentDropForError = 50;
    CapParms.dwRequestMicroSecPerFrame = (DWORD) ( 1.0e6 / 15.0 );
   
    if(capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms))==FALSE)
    {
        log.WriteString(""n Failed to set the capture parameters ");
        return FALSE;
    }
   
    // Set Video Format
   
    capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));
   
    m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH;
    m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT;
   
    BOOL ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));
   
    if(ret==TRUE)
        log.WriteString(""n Video parameters set properly");
   
    return TRUE;
}




/**
*
*  Allocate Memory for DIB image buffer
*
*/

int VideoCapture::AllocateMemory(PBITMAPINFO &bmpinfo)
{
    int size1,size2,size;
    BITMAPINFO tbmp;
    char  str[200];
   
    capGetVideoFormat(m_capwnd,&tbmp,sizeof(tbmp));
   
    size1 = getFormatSize ( tbmp );
    size2 = getImageSize ( tbmp );
    size = size1 + size2;
   
   
    sprintf(str,""n Formatsize = %d imagesize = %d , fun_size = %d ",
        size1,size2, capGetVideoFormatSize(m_capwnd));
    log.WriteString(str);
   
    bmpinfo=(BITMAPINFO *) new BYTE[size];
   
   
    if(bmpinfo==NULL)
    {
        AfxMessageBox("Unable to allocate memory");
        return -1;
    }
   
    memset(bmpinfo,0,sizeof(*bmpinfo));
   
    capGetVideoFormat(m_capwnd,bmpinfo,sizeof(*bmpinfo));
    return size1;
}




/**
*
*   Calculates the Format Size for DIB image
*
*/

int VideoCapture::getFormatSize(BITMAPINFO bmp)
{
    int size;
    size=(bmp.bmiHeader.biSize!=0)?bmp.bmiHeader.biSize :sizeof(BITMAPINFOHEADER);
   
    //return (size+ bmp.bmiHeader.biClrUsed *sizeof(RGBQUAD));
   
    return size; //RGBQUAD is absent for 24 bit bmp image.
}



/**
*    Calculates the Size of Image
*
*/

int VideoCapture::getImageSize(BITMAPINFO bmp)
{
    int size;
    BITMAPINFOHEADER head=bmp.bmiHeader;
   
   
    if( head.biSizeImage==0 )
    {
        size=( head.biWidth * head.biHeight * head.biBitCount)/8;
    }
    else
        size = head.biSizeImage;
   
    return size;
   
}


//////////////////////////////////////////////////////////////////////////
//
// 设置采集数据回调接口
//
void VideoCapture::SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam)
{
    m_OnCaptureVideo    = OnCaptureVideo;
    m_pParam            = pParam;
}

/**
*    Invoked when the video frame is captured by the driver
*
*
*/

LRESULT CALLBACK OnCaptureVideo(HWND mwnd,LPVIDEOHDR lphdr)
{
   
    VideoCapture *vidcap=(VideoCapture *)capGetUserData(mwnd);
   
    if( vidcap!=NULL )
    {
        vidcap->DrawLocalScreen( lphdr );
        vidcap->CompressFrame( lphdr );
//        if ( vidcap->m_OnCaptureVideo != NULL )
//        {
//            (*vidcap->m_OnCaptureVideo)( mwnd, lphdr );
//            vidcap->DrawLocalScreen( lphdr );
//            vidcap->CompressFrame( lphdr );
//        }
    }
   
    return TRUE;
}


void VideoCapture::CompressFrame(LPVIDEOHDR lphdr)
{
//    BOOL        bKeyFrame;
//    DWORD        OutActSize;
//    BYTE*        Buf;
//   
//    OutActSize    = m_bmpinfo.bmiHeader.biSizeImage;
//    bKeyFrame    = 0;
//   
//    Buf            = (BYTE*)ICSeqCompressFrame( &m_CV,0,lphdr->lpData,&bKeyFrame,(long*)&OutActSize);

    Bits bits;        // Various count about compression

    //Convert the data from rgb format to YUV format   
    ConvertRGB2YUV( IMAGE_WIDTH,IMAGE_HEIGHT, lphdr->lpData, yuv );

    // Reset the counter
    count=0;
   
    // 压缩数据
    cparams.format=CPARAM_QCIF;
    cparams.inter = CPARAM_INTRA; 
    cparams.Q_intra = 8;
    cparams.data=yuv;        //  Data in YUV format...
    ::CompressFrame(&cparams, &bits);

    // 传送数据
    m_pCommClient->SendPacket( (char*)cdata, count, PACKET_VIDEO );
}

void VideoCapture::InitCompressor()
{
//    memset( &m_CV,0,sizeof(COMPVARS) );
//    m_CV.cbSize        = sizeof( m_CV );
//    ICCompressorChoose( m_capwnd, 0, NULL, NULL, &m_CV, "Choose a Compressor" );
   
    // Initialize table for RGB to YUV conversion
    InitLookupTable();

    // Initialize the compressor
    cparams.format = CPARAM_QCIF;
    InitH263Encoder(&cparams);

    // Set up the callback function
    WriteByteFunction = OwnWriteFunction;
   
    // Initialize decompressor
    InitH263Decoder();
   
    return;
}

//////////////////////////////////////////////////////////////////////////
//
// 回放本地视频
//
void VideoCapture::DrawLocalScreen(LPVIDEOHDR lphdr)
{
    ::DrawDibDraw(
        m_hdib,
        m_LocalScreenDC,
        0,        // dest : left pos
        0,        // dest : top pos
        -1,                     // don't zoom x
        -1,                     // don't zoom y
        &m_bmpinfo.bmiHeader,             // bmp header info
        lphdr->lpData,                     // bmp data
        0,                     // src :left
        0,                     // src :top
        IMAGE_WIDTH,                 // src : width
        IMAGE_HEIGHT,                 // src : height
        DDF_SAME_DRAW             // use prev params....
        );
}

//////////////////////////////////////////////////////////////////////////
//
// 设置通信接口
//
void VideoCapture::SetCommClient(CCommClient *pClient)
{
    m_pCommClient    = pClient;
}

//////////////////////////////////////////////////////////////////////////
//
// 回放远程视频
//
void VideoCapture::DrawRemoteScreen(char *data, UINT size, HDC hScreenDC)
{
    int            iErrorCode;
    int            iDataSize;
    u_char*        upData;

    iDataSize    = size;
    upData        = (u_char*)data;

    iErrorCode    = DecompressFrame( upData, iDataSize, rgbdata, buffersize );

    if ( iErrorCode == 0 ) return;

    ::DrawDibDraw(
        m_hdib,
        hScreenDC,
        0,        // dest : left pos
        0,        // dest : top pos
        -1,                     // don't zoom x
        -1,                     // don't zoom y
        &m_bmpinfo.bmiHeader,             // bmp header info
        rgbdata,                     // bmp data
        0,                     // src :left
        0,                     // src :top
        IMAGE_WIDTH,                 // src : width
        IMAGE_HEIGHT,                 // src : height
        DDF_SAME_DRAW             // use prev params....
        );
}



/********************此文可以被转发,但请转发者保留作者的署名权
****李浩
****msn:lihao_nx@hotmail.com
****
****email:lihaoyxj@gmail.com
****出处:lihaoyxj.cublog.cn
****from:http://blog.csdn.net/lihao_ningxia
*****************/


//DSHOW
//head file
// CCaptureVideo视频捕捉类头文件
/////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_
/////////////////////////////////////////////////////////////////////
// CaptureVideo.h : header file
/////////////////////////////////////////////////////////////////////
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <atlbase.h>
#include <windows.h>
#include <dshow.h>
#pragma include_alias( "dxtrans.h", "qedit.h" )

#define __IDxtCompositor_INTERFACE_DEFINED__

#define __IDxtAlphaSetter_INTERFACE_DEFINED__

#define __IDxtJpeg_INTERFACE_DEFINED__

#define __IDxtKey_INTERFACE_DEFINED__

#include <Qedit.h> // ISampleGrabberCB
#ifndef SAFE_RELEASE
#define SAFE_RELEASE( x ) "
if ( NULL != x ) "
{ "
  x->Release( ); "
  x = NULL; "
}
#endif

class CCamFrameHandler {
public:
    virtual void CamFrameData(double dblSampleTime, BYTE * pBuffer, long lBufferSize) = 0 ;
};

class CSampleGrabberCB : public ISampleGrabberCB
{
public:
    long                   lWidth ;
    long                   lHeight ;
    CCamFrameHandler    *  frame_handler ;
    BOOL                   bGrabVideo ;
public:
    CSampleGrabberCB(){
        lWidth = 0 ;
        lHeight = 0 ;
        bGrabVideo = FALSE ;
        frame_handler = NULL ;
    }
    STDMETHODIMP_(ULONG) AddRef() { return 2; }
    STDMETHODIMP_(ULONG) Release() { return 1; }
    STDMETHODIMP QueryInterface(REFIID riid, void ** ppv) {
        if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){
            *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
            return NOERROR;
        }
        return E_NOINTERFACE;
    }

    STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )  {
        return 0;
    }

    STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){
        if (!pBuffer) return E_POINTER;
        if(bGrabVideo && frame_handler) frame_handler->CamFrameData(dblSampleTime, pBuffer, lBufferSize) ;
        return 0;
    }
};

class CCaptureVideo : public CWnd
{
    friend class CSampleGrabberCB;
  public:
    void GrabVideoFrames(BOOL bGrabVideoFrames, CCamFrameHandler * frame_handler);
    HRESULT Start(int iDeviceID,HWND hWnd);
    HRESULT Stop();
    int EnumDevices(HWND hList);
    CCaptureVideo();
    virtual ~CCaptureVideo();
  private:
    HWND                    m_hWnd;
    IGraphBuilder *            m_pGB;
    ICaptureGraphBuilder2*    m_pCapture;
    IBaseFilter*            m_pBF;
    IMediaControl*            m_pMC;
    IVideoWindow*            m_pVW;
    ISampleGrabber*            m_pGrabber;
  protected:
    void FreeMediaType(AM_MEDIA_TYPE& mt);
    bool BindFilter(int deviceId, IBaseFilter **pFilter);
    void ResizeVideoWindow();
    HRESULT SetupVideoWindow();
    HRESULT InitCaptureGraphBuilder();
};
#endif // !defined(AFX_CAPTUREVIDEO_H__F5345AA4_A39F_4B07_B843_3D87C4287AA0__INCLUDED_)


//cpp file
//-------------------------------------------------------------------
// CCaptureVideo视频捕捉类实现文件CaptureVideo.cpp
//-------------------------------------------------------------------
// CaptureVideo.cpp: implementation of the CCaptureVideo class.
//
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CaptureVideo.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CSampleGrabberCB mCB;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureVideo::CCaptureVideo()
{
  //COM Library Intialization
  if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
  {
    AfxMessageBox("CoInitialize Failed!"r"n");
    return;
  }
  m_hWnd = NULL;
  m_pVW = NULL;
  m_pMC = NULL;
  m_pGB = NULL;
  m_pBF = NULL;
  m_pGrabber = NULL;
  m_pCapture = NULL;
}

CCaptureVideo::~CCaptureVideo()
{
  // Stop media playback
    // Stop media playback
    if(m_pMC)m_pMC->StopWhenReady();
    if(m_pVW){
        m_pVW->put_Visible(OAFALSE);
        m_pVW->put_Owner(NULL);
    }
    SAFE_RELEASE(m_pMC);
    SAFE_RELEASE(m_pVW);
    SAFE_RELEASE(m_pGB);
    SAFE_RELEASE(m_pBF);
    SAFE_RELEASE(m_pGrabber);
    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::Stop()
{
    // Stop media playback
    if(m_pMC)m_pMC->StopWhenReady();
    if(m_pVW){
        m_pVW->put_Visible(OAFALSE);
        m_pVW->put_Owner(NULL);
    }
    SAFE_RELEASE(m_pMC);
    SAFE_RELEASE(m_pVW);
    SAFE_RELEASE(m_pGB);
    SAFE_RELEASE(m_pBF);
    SAFE_RELEASE(m_pGrabber);
    SAFE_RELEASE(m_pCapture);
    return S_OK ;
}
HRESULT CCaptureVideo::Start(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"Capture Filter");
  // hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
  // m_pBF, NULL, NULL);
  // create a sample grabber
  hr = CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&m_pGrabber );
  if(FAILED(hr)){
    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_IYUV;// MEDIASUBTYPE_RGB24; // 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;
  mCB.bGrabVideo = FALSE ;
  mCB.frame_handler = NULL ;
  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;

  // enumerate all video capture devices
  CComPtr<ICreateDevEnum> pCreateDevEnum;
  HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  if (hr != NOERROR)
  {
    return false;
  }
  CComPtr<IEnumMoniker> pEm;
  hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
  if (hr != NOERROR)
  {
    return false;
  }
  pEm->Reset();
  ULONG cFetched;
  IMoniker *pM;
  int index = 0;
  while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, 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**)pFilter);
        }
        SysFreeString(var.bstrVal);
      }
      pBag->Release();
    }
    pM->Release();
    index++;
  }
  return true;
}

HRESULT CCaptureVideo::InitCaptureGraphBuilder()
{
  HRESULT hr;

  // 创建IGraphBuilder接口
  hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
  // 创建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;
  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::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;
  }
}
void CCaptureVideo::GrabVideoFrames(BOOL bGrabVideoFrames, CCamFrameHandler * frame_handler)
{
    mCB.frame_handler = frame_handler ;
    mCB.bGrabVideo = bGrabVideoFrames ;
}
posted @ 2009-05-19 09:43  浩@子  阅读(1893)  评论(0编辑  收藏  举报