CCapture directshow 视频捕获类
睿丰德科技 专注RFID识别技术和条码识别技术与管理软件的集成项目。质量追溯系统、MES系统、金蝶与条码系统对接、用友与条码系统对接
[cpp] view plaincopy
- // 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;
- }