CCapture directshow 视频捕获类

 
// 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;
}


 

你可能感兴趣的:(video,File,filter,null,Class,byte)