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