您的位置:首页 > 其它

CCapture directshow 视频捕获类

2012-02-22 19:58 387 查看
// Capture.h for class CCapture

#include <dshow.h>
#include <qedit.h>
#include <atlbase.h>
#if !defined(CAPTURE_H_________)
#define CAPTURE_H_________

// image size: 160*120  176*144   320*240  640*480  1024*1806
#define IMG_WIDTH 320
#define IMG_HEIGHT 240

typedef void (*capCallBackFunc)(LPVOID lParam);
enum DeviceType{DTypeVideo, DTypeAudio};
class CSampleGrabberCB; // 用于不会帧数据保存图片的接口
class CCapture
{
friend class CSampleGrabberCB;
public:
// 设置回调函数 用于处理获取的图片帧数据
CDialog *m_dlgParent;
capCallBackFunc calFunc;
void SetCallBKFun(capCallBackFunc f);
/////////////////////////////////
CCapture();
virtual ~CCapture();
int EnumDevice(HWND hCmbList, DeviceType deviceType); // 设备枚举
//	void SaveGraph(TCHAR *wFileName);	// 保存滤波器链表
void SetCameraFormat(HWND hwndParent);	// 设置摄像头的视频格式
void SetCameraFilter(HWND hwndParent);	// 设置摄像头的图像参数
HRESULT CaptureVideo(CString inFileName);	// 捕获保存视频
HRESULT CaptureImage(CString inFileName);	// 抓取保存图片
HRESULT CaptureImage(); // 抓取图片并显示
HRESULT Preview(int iDevVideoID, HWND hVideo, int iDevAudioID = 0, HWND hAudio = NULL);	// 采集预览视频
HRESULT InitCaptureGraphBuilder();	// 创建滤波器管理器,查询其各种控制接口
void StopCapture();  // 停止捕获
void FreeMediaType(AM_MEDIA_TYPE &mt);  // 释放对象内存

void SetOnShot(BOOL bFlag);   // 设置是否捕获帧数据
void SetParent(CDialog *pdlg);
protected:
bool BindFilter(int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType); // 把指定的设备滤波器捆绑到链表中
void ResizeVideoWindow();			// 更改视频显示窗口
HRESULT SetupVideoWindow();			// 设置视频显示窗口的特性
static UINT ThreadFunDrawText(LPVOID lParam);
private:
HWND m_hWnd;			// 视频显示窗口的句柄
IBaseFilter *m_pVideoCap;		// 视频捕获滤波器
IBaseFilter *m_pAudioCap;		// 音频捕获滤波器
CComPtr<ISampleGrabber> m_pGrabber;		// 抓取图片滤波器
IBaseFilter *m_pMux;	// 写文件滤波器
ICaptureGraphBuilder2 *m_pCapGB;	// 增强型捕获滤波器链表管理
IGraphBuilder *m_pGB;	// 滤波链表管理器
IVideoWindow *m_pVW;	// 视频显示窗口接口
IMediaControl *m_pMC;	// 媒体控制接口
static bool m_bRecording;		// 录制视频标志

IBaseFilter *m_pXviDCodec;   //mpeg4 滤波器
};

#endif


/// Capture.cpp for class CCapture implement
//
///
////////////////////////////////////////

#include "StdAfx.h"
#include "Capture.h"
#include <atlconv.h>
#include "VideoChatDlg.h"
#include "yuv2bmp.h"

#ifndef srelease
#define srelease(x) if (NULL != x)\
{\
x->Release();\
x = NULL;\
}
#endif

#ifndef MAX_PATH
#define  MAX_PATH 1024
#endif
BOOL bOneShot = FALSE; // 全局变量
capCallBackFunc fun;

class CSampleGrabberCB : public ISampleGrabberCB
{
public:
long lWidth;
long lHeight;
CCapture *pCap;
TCHAR m_szFileName[MAX_PATH]; // 位图文件名称
CSampleGrabberCB(){
strcpy(m_szFileName, ".\\sample.bmp");
}
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( !bOneShot )
return 0;
if (!pBuffer)
{
AfxMessageBox(_T("Save Bmp File Failure!"));
return E_POINTER;
}
if (pBuffer != NULL && pCap)
{
// 			BYTE *rgb = new BYTE[lWidth*lHeight*3];
// 			YUV422_C_RGB(pBuffer,rgb, (int)lHeight, (int)lWidth);
//			outBmpBuf(pBuffer, pCap);  // 将一帧图像数据传给显示函数
//			((CVideoNetDlg *)pCap->m_dlgParent)->SendVideo(pBuffer, (int)lBufferSize);
}
//	SaveBitmap(pBuffer, lBufferSize);  // 保存成位图文件
//		bOneShot = FALSE; // 停止捕获图像
//		AfxMessageBox(_T("Get bmp data success."));
return 0;
}
void outBmpBuf(BYTE *buf, CCapture* cap)
{
cap->calFunc(buf);
}
// 创建位图文件
BOOL SaveBitmap(BYTE *pBuffer, long lBufferLen)
{
HANDLE hf = CreateFile(m_szFileName, GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
if (hf == INVALID_HANDLE_VALUE) return 0;
// 写文件头
BITMAPFILEHEADER fileheader;
ZeroMemory(&fileheader, sizeof(BITMAPFILEHEADER));
fileheader.bfType = 'MB';
fileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lBufferLen;
fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
DWORD dwWritter = 0;
WriteFile(hf, &fileheader, sizeof(BITMAPFILEHEADER), &dwWritter, NULL);
// 写文图格式
BITMAPINFOHEADER infoHeader;
ZeroMemory(&infoHeader, sizeof(BITMAPINFOHEADER));
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biSizeImage = lBufferLen;
infoHeader.biWidth = lWidth;
infoHeader.biHeight = lHeight;
infoHeader.biBitCount = 24;
WriteFile(hf, &infoHeader, sizeof(BITMAPINFOHEADER), &dwWritter, NULL);
// 写位图数据
WriteFile(hf, pBuffer, lBufferLen, &dwWritter, NULL);
CloseHandle(hf);
MessageBox(NULL, _T("Save bmp file succeed!"), _T("warn"), MB_OK|MB_ICONINFORMATION);
return 0;
}
};

/////////////////////////////////////////////
/// for class CCapture's Function
///
////////////////////////////////////////////////
CSampleGrabberCB samCB;
CCapture::CCapture()
{
CoInitialize(NULL);  // 初始化COM库
m_hWnd = NULL;
m_pVideoCap = NULL;
m_pAudioCap = NULL;
m_pCapGB = NULL;
m_pGB = NULL;
m_pMC = NULL;
m_pMux = NULL;
m_pVW = NULL;
m_pGrabber = NULL;
m_dlgParent = NULL;
}
bool CCapture::m_bRecording = false;

CCapture::~CCapture()
{
if (m_pMC) m_pMC->Stop();
if (m_pVW)
{
m_pVW->put_Owner(NULL);
m_pVW->put_Visible(OAFALSE);
}
m_hWnd = NULL;
srelease(m_pVideoCap);
srelease(m_pGB);
srelease(m_pCapGB);
srelease(m_pMC);
srelease(m_pVW);
m_bRecording = false;
CoUninitialize(); // 释放COM库
}

int CCapture::EnumDevice( HWND hCmbList, DeviceType deviceType )
{
if (hCmbList == NULL) return -1;
int id = 0;
/////枚举捕获设备
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,
(LPVOID *)&pCreateDevEnum);
if ( hr != NOERROR) return -1;
//////// 获取视频类的枚举器
IEnumMoniker *pEm;			 //枚举监控器接口
if (deviceType == DTypeVideo)
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
// 如果获取音频类的枚举器 用下面的代码
else
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);
//	if (hr != NOERROR) return -1;
if (!pEm || FAILED(hr)) 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;		// 保存的是二进制数据
// 获取firendlyName 形式的信息
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR) // 获取成功
{
id++;
char szDeviceName[256] = {0};
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, szDeviceName,80, NULL, NULL);  // 字符串编码转换UNICODE TO ANSI
::SendMessage(hCmbList, CB_ADDSTRING, 0, (LPARAM)szDeviceName);//添加到组合列表框
SysFreeString(var.bstrVal);  //释放资源,特别要注意
}
pBag->Release();
}
pM->Release();
}
return 0;
}

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

HRESULT CCapture::SetupVideoWindow()
{
HRESULT hr;
//m_hWnd为类CCapture的成员变量,在使用该函数前须初始化
hr = m_pVW->put_Visible(OAFALSE);  // 视频窗口不可见
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;
}

HRESULT CCapture::InitCaptureGraphBuilder()
{
HRESULT hr;
//创建IGraphBuilder接口(滤波器链表管理器) m_pGB
hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
if (FAILED(hr)) return hr;
//创建ICaptureGraphBuilder2接口(增强型捕获滤波器链表管理器)m_pCapGB
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
if (FAILED(hr)) return hr;
// 创建抓取图片滤波器
if (m_pGrabber){
m_pGrabber.Release();
m_pGrabber = NULL;
}

hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void **)&m_pGrabber);
//	hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
if (FAILED(hr)) return hr;
// 初始化滤波器链表管理器IGraphBuilder
m_pCapGB->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 CCapture::Preview( int iDevVideoID, HWND hVideo, int iDevAudioID /*= 0*/, HWND hAudio /*= NULL*/ )
{
HRESULT hr;
if (m_pMC)
m_pMC->Stop();
m_bRecording = false;
// 初始化视频捕获滤波器链表管理器
hr = InitCaptureGraphBuilder();
if (FAILED(hr)) return hr;

// 把指定的视频采集设备与滤波器捆绑
if (BindFilter(iDevVideoID, &m_pVideoCap, DTypeVideo))
{
// 把滤波器添加到滤波器链表中
hr = m_pGB->AddFilter(m_pVideoCap, L"Video Capture Filter");
if (FAILED(hr)) return hr;
}
else return FALSE;

if (BindFilter(iDevAudioID, &m_pAudioCap, DTypeAudio))
{
hr = m_pGB->AddFilter(m_pAudioCap, L"Audio Capture Filter");
if (FAILED(hr))
{
MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
//	return hr;
}
}
else
{
MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
//	return FALSE;
}
// 如果我们想抓取24位的RGB图片,如下设置媒体图片类型
CComQIPtr<IBaseFilter, &IID_IBaseFilter> pGrabBase(m_pGrabber);

AM_MEDIA_TYPE mediaType;
VIDEOINFOHEADER vih;

IAMStreamConfig* pConfig = NULL;
m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, IID_IAMStreamConfig, (void**)&pConfig);
// 设置视频格式
ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE));
vih.bmiHeader.biWidth = IMG_WIDTH;
vih.bmiHeader.biHeight = IMG_HEIGHT;
vih.bmiHeader.biSizeImage = IMG_HEIGHT*IMG_WIDTH*3;
mediaType.pbFormat = (BYTE *)(&vih);
mediaType.cbFormat = sizeof(VIDEOINFOHEADER);
mediaType.subtype = MEDIASUBTYPE_YUY2;
mediaType.majortype = MEDIATYPE_Video;
mediaType.formattype = FORMAT_VideoInfo;
hr = pConfig->SetFormat(&mediaType);
hr = m_pGrabber->SetMediaType(&mediaType);
if( FAILED( hr ) ){
AfxMessageBox("Fail to set media type!");
return hr;
}

hr = m_pGB->AddFilter(pGrabBase, L"SampleGrabber");
if (FAILED(hr)) return hr;
// 渲染媒体, 把链表中滤波器链接起来
hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pAudioCap, NULL, NULL);
hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);
if (FAILED(hr))
hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);
if( FAILED( hr ) ){
AfxMessageBox(_T("Can’t build the graph"));
return hr;
}

////////// 设置图片捕获数据
hr = m_pGrabber->GetConnectedMediaType( &mediaType );
if ( FAILED( hr) ){
AfxMessageBox(_T("Failt to read the connected media type"));
return hr;
}
VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)mediaType.pbFormat;
samCB.lWidth = pVih->bmiHeader.biWidth;
samCB.lHeight = pVih->bmiHeader.biHeight;
samCB.pCap = (CCapture *)this;
FreeMediaType(mediaType);
hr = m_pGrabber->SetBufferSamples( TRUE );  // 如果此处为false 第一次抓取图片时失败(不用回调方式)
hr = m_pGrabber->SetOneShot( FALSE );
hr = m_pGrabber->SetCallback( &samCB, 1 );
SetOnShot(TRUE);// ture 时开始捕获视频帧数据
// 设置视频显示窗口
m_hWnd = hVideo;
SetupVideoWindow(); // 设置显示窗口
hr = m_pMC->Run();  // 开始采集、预览视频,并在指定窗口显示
if (FAILED(hr))
{
MessageBox(NULL, _T("请检查该设备是否被占用!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
return hr;
}
return S_OK;
}

#if 1  // avi video format
HRESULT CCapture::CaptureVideo( CString inFileName )  // 录制视频
{
HRESULT hr = 0;
DWORD dwId;
HANDLE hThread;
m_bRecording = false;
m_pMC->Stop();   // 先停止视频采集

// 设置文件名,注意第二个参数类型
hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL);

//渲染媒体 连接捕获器和AVI Muxer过滤器
hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, NULL, m_pMux);
hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, m_pAudioCap, NULL, m_pMux);
//设置音频流为主流
IConfigAviMux *pConfigMux;
m_pMux->QueryInterface(IID_IConfigAviMux, (void **)&pConfigMux);
hr = pConfigMux->SetMasterStream(1);   // 0 为视频  1为音频

pConfigMux->Release();
m_pMux->Release();
m_bRecording = true;
hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)ThreadFunDrawText,
(LPVOID)m_hWnd,
0, &dwId);
m_pMC->Run();  // 恢复视频采集,同时写入文件

return hr;
}
#else  // mpeg4 format video
HRESULT CCapture::CaptureVideo(CString inFileName)
{
HRESULT hr=0;

m_pMC->Stop();

m_pGB->AddFilter(m_pXviDCodec,L"99 Xvid MPEG-4 Codec");
m_pXviDCodec->Release();

hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL );
hr = ConnectFilters(m_pGB,m_pSmartTee_1,m_pXviDCodec, 0);    //0,连接capture引脚
hr = ConnectFilters(m_pGB,m_pXviDCodec,m_pMux, 2);    //2,默认自然连接
m_pMux->Release();

m_pMC->Run();

return hr;
}
#endif

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

HRESULT CCapture::CaptureImage() // 抓取并显示图像
{ // 采用CB接口回调函数存储图片
bOneShot = TRUE;
return 0;
}

HRESULT CCapture::CaptureImage( CString inFileName ) // 抓取图像
{
HRESULT hr;
AM_MEDIA_TYPE mediaType;
hr = m_pGrabber->GetConnectedMediaType(&mediaType);
if (FAILED(hr))  return hr;
VIDEOINFOHEADER *pVih;
if (mediaType.formattype == FORMAT_VideoInfo &&
(mediaType.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
mediaType.pbFormat != NULL)
{
pVih = (VIDEOINFOHEADER *)mediaType.pbFormat;
}
else
return VFW_E_INVALIDMEDIATYPE;

//	hr = m_pGrabber->SetOneShot(TRUE);
if (SUCCEEDED(m_pGrabber->SetBufferSamples(TRUE)) )  // 设置为缓冲形式)
{
long cbBuffer = 0;
hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
BYTE *pBuffer = new BYTE[cbBuffer];
if (!pBuffer) return -1;
// 获取一帧媒体的数据
hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, (long *)pBuffer);
if (FAILED(hr))  return hr;
//  		if (pBuffer != NULL)
//  		{
//  			calFunc(pBuffer);   // 将一帧图像数据传给显示函数
// 		}

///-------------------------测试所得数据是rgb格式还是yuv格式--------
long n1,n2;
int datalen = IMG_WIDTH*IMG_HEIGHT*3;
BYTE *rgb = new BYTE[datalen];

YUV422_C_RGB(pBuffer,rgb, IMG_HEIGHT, IMG_WIDTH);
n1 = strlen((char *)pBuffer);
n2 = strlen((char *)rgb);
//		((CVideoNetDlg *)(m_dlgParent))->SendVideo((BYTE *)pBuffer, (int)cbBuffer);
///------------------------------------------------------------------
///////////////////////////////////////////////////////////////
// Create a file to hold the bitmap
HANDLE hf = CreateFile(inFileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, NULL, NULL );

if( hf == INVALID_HANDLE_VALUE ){
MessageBox(NULL, _T("Create bmp file failure!"), _T(""), MB_OK|MB_ICONINFORMATION);
return 0;
}

// Write out the file header
//
// 信息头
BITMAPFILEHEADER bfh;
memset( &bfh, 0, sizeof( bfh ) );
bfh.bfType = 'MB';
bfh.bfSize = sizeof( bfh ) + cbBuffer + sizeof( BITMAPINFOHEADER );
bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );

DWORD Written = 0;
WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL );

// Write the bitmap format
//文件头
BITMAPINFOHEADER bih;
memset( &bih, 0, sizeof( bih ) );
bih.biSize = sizeof( bih );
bih.biWidth = pVih->bmiHeader.biWidth;
bih.biHeight = pVih->bmiHeader.biHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;

Written = 0;
WriteFile( hf, &bih, sizeof( bih ), &Written, NULL );

// Write the bitmap bits
//
Written = 0;
WriteFile( hf, rgb, datalen, &Written, NULL );
CloseHandle( hf );
delete pBuffer;
MessageBox(NULL, _T("Save photo succeeded!"), _T("抓取图片提示"), MB_OK|MB_ICONINFORMATION);
}
m_pGrabber->SetOneShot(FALSE);
m_pGrabber->SetBufferSamples(FALSE);
FreeMediaType(mediaType);
return 0;
}

bool CCapture::BindFilter( int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType )
{
if (iDeviceID < 0) return false;
// 枚举所有的视频设备
ICreateDevEnum *pCreateDevEnum;
//生成设备枚举器pCreateDevEnum
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum);
if (hr != NOERROR) return false;
IEnumMoniker *pEM;
// 创建视频输入设备类枚举器
if (deviceType == DTypeVideo)
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEM, 0);
// 音频设备枚举器
else
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEM, 0);
if (hr != NOERROR) return false;
pEM->Reset();  // 复位该设备
ULONG cFetched;
IMoniker *pM;
int indexDev = 0;
// 获取设备
while(hr = pEM->Next(1, &pM, &cFetched), hr == S_OK, indexDev <= iDeviceID)
{
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 (indexDev == iDeviceID) pM->BindToObject(0, 0, IID_IBaseFilter, (void **)pOutFilter);
SysFreeString(var.bstrVal);
}
pBag->Release();
}
pM->Release();
indexDev++;
}
return true;
}

void CCapture::SetCameraFormat( HWND hwndParent ) // 设置视频格式
{
HRESULT hr;
IAMStreamConfig *pSC; // 流配置接口
ISpecifyPropertyPages *pSpec; //属性页接口
m_pMC->Stop();  // 只有停止后才能进行引脚属性的设置
m_bRecording = false;
// 首先查询捕获CAPTURE、视频Video接口
hr = m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
m_pVideoCap, IID_IAMStreamConfig, (void **)&pSC);

CAUUID cauuid; // 所有属性页结构体
hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
if (hr == S_OK)
{
// 显示属性页窗口
hr = pSpec->GetPages(&cauuid);  // 获取所有属性页
hr = OleCreatePropertyFrame(hwndParent, 30, 30, NULL, 1,
(IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL);
// 释放内存资源
CoTaskMemFree(cauuid.pElems);
pSpec->Release();
pSC->Release();
}
// 恢复运行
m_pMC->Run();
}

void CCapture::SetCameraFilter( HWND hwndParent ) // 设置图像各参数设置
{
HRESULT hr = 0;
ISpecifyPropertyPages *pSpec;
hr = m_pVideoCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
if (SUCCEEDED(hr))
{
// 获取滤波器名称和IUnknown 接口指针
FILTER_INFO FilterInfo;
hr = m_pVideoCap->QueryFilterInfo(&FilterInfo);
IUnknown *pFilterUnk;
m_pVideoCap->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);
// 显示该页
CAUUID caGUID;
pSpec->GetPages(&caGUID);
OleCreatePropertyFrame(hwndParent,
0, 0,
FilterInfo.achName,
1,
&pFilterUnk,
caGUID.cElems,
caGUID.pElems,
0,
0, NULL);
// 释放内存资源
CoTaskMemFree(caGUID.pElems);
pFilterUnk->Release();
FilterInfo.pGraph->Release();
pSpec->Release();
}
}

void CCapture::StopCapture()
{
m_pMC->Stop();
}

UINT CCapture::ThreadFunDrawText( LPVOID lParam )
{
HWND hwnd = (HWND)lParam;
if (hwnd == NULL) return -1;
HDC hdc = GetDC(hwnd);
CRect rcDraw, rcTime;
CTime time, time0;
CTimeSpan timespan;
CString strTime;
CBrush br;
time0 = CTime::GetCurrentTime();
br.CreateSolidBrush(RGB(255,0,0));
GetClientRect(hwnd, &rcDraw);
rcTime = rcDraw;
rcTime.bottom = rcTime.top + 30;
rcDraw.top = rcDraw.bottom - 30;
SelectObject(hdc, &br);
SetTextColor(hdc, 0x0000ff);
SetBkMode(hdc, TRANSPARENT);
while(m_bRecording)
{
time = CTime::GetCurrentTime();
timespan = time - time0;
strTime = time.Format(_T(" %Y-%m-%d 星期%w %H:%M:%S"));
DrawText(hdc, strTime, strTime.GetLength(), &rcTime, DT_VCENTER|DT_LEFT|DT_SINGLELINE);
strTime = timespan.Format(_T("%H:%M:%S "));
strTime = _T("●录制 ") + strTime;
DrawText(hdc, strTime, strTime.GetLength(), &rcDraw, DT_VCENTER|DT_RIGHT|DT_SINGLELINE);
}
return 0;
}

void CCapture::FreeMediaType(AM_MEDIA_TYPE &mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
mt.pUnk->Release();
mt.pUnk = NULL;
}
}

void CCapture::SetOnShot( BOOL bFlag )
{
bOneShot = bFlag;
}

void CCapture::SetCallBKFun( capCallBackFunc f )
{
this->calFunc = f;
samCB.pCap = static_cast<CCapture *>(this);
}

void CCapture::SetParent( CDialog *pdlg )
{
m_dlgParent = pdlg;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: