directshow和vfw采集并转发视频数据的接口
/********************此文可以被转发,但请转发者保留作者的署名权
****李浩
****msn:lihao_nx@hotmail.com
****
****email:lihaoyxj@gmail.com
****出处:lihaoyxj.cublog.cn
****from:http://blog.csdn.net/lihao_ningxia
*****************/
vfw
#if _MSC_VER > 1000****李浩
****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_
#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
*****************/
****李浩
****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 ;
}