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


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo CCaptureVideo

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值