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