CCapture directshow 视频捕获类

   本文来自:http://blog.csdn.NET/xgx198831/article/details/7284618


  1. // Capture.h for class CCapture  
  2.   
  3. #include <dshow.h>  
  4. #include <qedit.h>  
  5. #include <atlbase.h>  
  6. #if !defined(CAPTURE_H_________)  
  7. #define CAPTURE_H_________  
  8.   
  9. // image size: 160*120  176*144   320*240  640*480  1024*1806  
  10. #define IMG_WIDTH 320  
  11. #define IMG_HEIGHT 240  
  12.   
  13. typedef void (*capCallBackFunc)(LPVOID lParam);  
  14. enum DeviceType{DTypeVideo, DTypeAudio};  
  15. class CSampleGrabberCB; // 用于不会帧数据保存图片的接口  
  16. class CCapture  
  17. {  
  18.     friend class CSampleGrabberCB;  
  19. public:  
  20.     // 设置回调函数 用于处理获取的图片帧数据  
  21.     CDialog *m_dlgParent;  
  22.     capCallBackFunc calFunc;  
  23.     void SetCallBKFun(capCallBackFunc f);  
  24.     /  
  25.     CCapture();  
  26.     virtual ~CCapture();  
  27.     int EnumDevice(HWND hCmbList, DeviceType deviceType); // 设备枚举  
  28. //  void SaveGraph(TCHAR *wFileName);   // 保存滤波器链表  
  29.     void SetCameraFormat(HWND hwndParent);  // 设置摄像头的视频格式  
  30.     void SetCameraFilter(HWND hwndParent);  // 设置摄像头的图像参数  
  31.     HRESULT CaptureVideo(CString inFileName);   // 捕获保存视频  
  32.     HRESULT CaptureImage(CString inFileName);   // 抓取保存图片  
  33.     HRESULT CaptureImage(); // 抓取图片并显示  
  34.     HRESULT Preview(int iDevVideoID, HWND hVideo, int iDevAudioID = 0, HWND hAudio = NULL); // 采集预览视频  
  35.     HRESULT InitCaptureGraphBuilder();  // 创建滤波器管理器,查询其各种控制接口  
  36.     void StopCapture();  // 停止捕获  
  37.     void FreeMediaType(AM_MEDIA_TYPE &mt);  // 释放对象内存  
  38.   
  39.     void SetOnShot(BOOL bFlag);   // 设置是否捕获帧数据  
  40.     void SetParent(CDialog *pdlg);  
  41. protected:  
  42.     bool BindFilter(int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType); // 把指定的设备滤波器捆绑到链表中  
  43.     void ResizeVideoWindow();           // 更改视频显示窗口  
  44.     HRESULT SetupVideoWindow();         // 设置视频显示窗口的特性  
  45.     static UINT ThreadFunDrawText(LPVOID lParam);  
  46. private:  
  47.     HWND m_hWnd;            // 视频显示窗口的句柄  
  48.     IBaseFilter *m_pVideoCap;       // 视频捕获滤波器  
  49.     IBaseFilter *m_pAudioCap;       // 音频捕获滤波器  
  50.     CComPtr<ISampleGrabber> m_pGrabber;       // 抓取图片滤波器  
  51.     IBaseFilter *m_pMux;    // 写文件滤波器  
  52.     ICaptureGraphBuilder2 *m_pCapGB;    // 增强型捕获滤波器链表管理  
  53.     IGraphBuilder *m_pGB;   // 滤波链表管理器  
  54.     IVideoWindow *m_pVW;    // 视频显示窗口接口  
  55.     IMediaControl *m_pMC;   // 媒体控制接口  
  56.     static bool m_bRecording;       // 录制视频标志  
  57.   
  58.     IBaseFilter *m_pXviDCodec;   //mpeg4 滤波器  
  59. };  
  60.   
  61.   
  62. #endif  



[cpp]  view plain  copy
  1. /// Capture.cpp for class CCapture implement  
  2. //  
  3. ///  
  4.   
  5.   
  6. #include "StdAfx.h"  
  7. #include "Capture.h"  
  8. #include <atlconv.h>  
  9. #include "VideoChatDlg.h"  
  10. #include "yuv2bmp.h"  
  11.   
  12. #ifndef srelease  
  13. #define srelease(x) if (NULL != x)\  
  14. {\  
  15.     x->Release();\  
  16.     x = NULL;\  
  17. }  
  18. #endif  
  19.   
  20. #ifndef MAX_PATH  
  21. #define  MAX_PATH 1024  
  22. #endif  
  23. BOOL bOneShot = FALSE; // 全局变量  
  24. capCallBackFunc fun;  
  25.   
  26. class CSampleGrabberCB : public ISampleGrabberCB  
  27. {  
  28. public:  
  29.     long lWidth;  
  30.     long lHeight;  
  31.     CCapture *pCap;  
  32.     TCHAR m_szFileName[MAX_PATH]; // 位图文件名称  
  33.     CSampleGrabberCB(){  
  34.         strcpy(m_szFileName, ".\\sample.bmp");  
  35.     }  
  36.     STDMETHODIMP_(ULONG) AddRef() { return 2; }   
  37.     STDMETHODIMP_(ULONG) Release() { return 1; }   
  38.     STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){   
  39.         if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){    
  40.         *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );   
  41.             return NOERROR;   
  42.         }    
  43.         return E_NOINTERFACE;   
  44.     }   
  45.     STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){   
  46.         return 0;   
  47.     }   
  48.     STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){   
  49.         if( !bOneShot )  
  50.             return 0;  
  51.         if (!pBuffer)  
  52.         {  
  53.             AfxMessageBox(_T("Save Bmp File Failure!"));  
  54.             return E_POINTER;   
  55.         }  
  56.         if (pBuffer != NULL && pCap)  
  57.         {  
  58. //          BYTE *rgb = new BYTE[lWidth*lHeight*3];   
  59. //          YUV422_C_RGB(pBuffer,rgb, (int)lHeight, (int)lWidth);  
  60. //          outBmpBuf(pBuffer, pCap);  // 将一帧图像数据传给显示函数  
  61. //          ((CVideoNetDlg *)pCap->m_dlgParent)->SendVideo(pBuffer, (int)lBufferSize);  
  62.         }  
  63.     //  SaveBitmap(pBuffer, lBufferSize);  // 保存成位图文件  
  64. //      bOneShot = FALSE; // 停止捕获图像  
  65. //      AfxMessageBox(_T("Get bmp data success."));  
  66.         return 0;   
  67.     }  
  68.     void outBmpBuf(BYTE *buf, CCapture* cap)  
  69.     {  
  70.         cap->calFunc(buf);  
  71.     }  
  72.     // 创建位图文件  
  73.     BOOL SaveBitmap(BYTE *pBuffer, long lBufferLen)  
  74.     {  
  75.         HANDLE hf = CreateFile(m_szFileName, GENERIC_WRITE,   
  76.             FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);  
  77.         if (hf == INVALID_HANDLE_VALUE) return 0;  
  78.         // 写文件头  
  79.         BITMAPFILEHEADER fileheader;  
  80.         ZeroMemory(&fileheader, sizeof(BITMAPFILEHEADER));  
  81.         fileheader.bfType = 'MB';  
  82.         fileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lBufferLen;  
  83.         fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);  
  84.         DWORD dwWritter = 0;  
  85.         WriteFile(hf, &fileheader, sizeof(BITMAPFILEHEADER), &dwWritter, NULL);  
  86.         // 写文图格式  
  87.         BITMAPINFOHEADER infoHeader;  
  88.         ZeroMemory(&infoHeader, sizeof(BITMAPINFOHEADER));  
  89.         infoHeader.biSize = sizeof(BITMAPINFOHEADER);  
  90.         infoHeader.biSizeImage = lBufferLen;  
  91.         infoHeader.biWidth = lWidth;  
  92.         infoHeader.biHeight = lHeight;  
  93.         infoHeader.biBitCount = 24;  
  94.         WriteFile(hf, &infoHeader, sizeof(BITMAPINFOHEADER), &dwWritter, NULL);  
  95.         // 写位图数据  
  96.         WriteFile(hf, pBuffer, lBufferLen, &dwWritter, NULL);  
  97.         CloseHandle(hf);  
  98.         MessageBox(NULL, _T("Save bmp file succeed!"), _T("warn"), MB_OK|MB_ICONINFORMATION);  
  99.         return 0;  
  100.     }  
  101. };  
  102.   
  103. /  
  104. /// for class CCapture's Function  
  105. ///  
  106.   
  107. CSampleGrabberCB samCB;  
  108. CCapture::CCapture()  
  109. {  
  110.     CoInitialize(NULL);  // 初始化COM库  
  111.     m_hWnd = NULL;  
  112.     m_pVideoCap = NULL;  
  113.     m_pAudioCap = NULL;  
  114.     m_pCapGB = NULL;  
  115.     m_pGB = NULL;  
  116.     m_pMC = NULL;  
  117.     m_pMux = NULL;  
  118.     m_pVW = NULL;  
  119.     m_pGrabber = NULL;  
  120.     m_dlgParent = NULL;  
  121. }  
  122. bool CCapture::m_bRecording = false;  
  123.   
  124. CCapture::~CCapture()  
  125. {  
  126.     if (m_pMC) m_pMC->Stop();  
  127.     if (m_pVW)  
  128.     {  
  129.         m_pVW->put_Owner(NULL);  
  130.         m_pVW->put_Visible(OAFALSE);  
  131.     }  
  132.     m_hWnd = NULL;  
  133.     srelease(m_pVideoCap);  
  134.     srelease(m_pGB);  
  135.     srelease(m_pCapGB);  
  136.     srelease(m_pMC);  
  137.     srelease(m_pVW);  
  138.     m_bRecording = false;  
  139.     CoUninitialize(); // 释放COM库  
  140. }  
  141.   
  142. int CCapture::EnumDevice( HWND hCmbList, DeviceType deviceType )  
  143. {  
  144.     if (hCmbList == NULL) return -1;  
  145.     int id = 0;  
  146.     /枚举捕获设备  
  147.     ICreateDevEnum *pCreateDevEnum;  
  148.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,  
  149.         NULL,  
  150.         CLSCTX_INPROC_SERVER,  
  151.         IID_ICreateDevEnum,  
  152.         (LPVOID *)&pCreateDevEnum);  
  153.     if ( hr != NOERROR) return -1;  
  154.      获取视频类的枚举器  
  155.     IEnumMoniker *pEm;           //枚举监控器接口  
  156.     if (deviceType == DTypeVideo)  
  157.         hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);  
  158.     // 如果获取音频类的枚举器 用下面的代码  
  159.     else   
  160.          hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);  
  161. //  if (hr != NOERROR) return -1;  
  162.     if (!pEm || FAILED(hr)) return -1;  
  163.       
  164.     pEm->Reset();   // 类型枚举器复位  
  165.     ULONG cFetched;  
  166.     IMoniker *pM;    // 监控器接口指针  
  167.     while(hr = pEm->Next(1, &pM, &cFetched), hr == S_OK)  
  168.     {  
  169.         IPropertyBag *pBag;   // 属性页接口指针  
  170.         hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);  
  171.         // 获取设备属性页  
  172.         if (SUCCEEDED(hr))  
  173.         {  
  174.             VARIANT var;  
  175.             var.vt = VT_BSTR;       // 保存的是二进制数据  
  176.             // 获取firendlyName 形式的信息  
  177.             hr = pBag->Read(L"FriendlyName", &var, NULL);  
  178.             if (hr == NOERROR) // 获取成功  
  179.             {  
  180.                 id++;  
  181.                 char szDeviceName[256] = {0};  
  182.                 WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, szDeviceName,80, NULL, NULL);  // 字符串编码转换UNICODE TO ANSI  
  183.                 ::SendMessage(hCmbList, CB_ADDSTRING, 0, (LPARAM)szDeviceName);//添加到组合列表框  
  184.                 SysFreeString(var.bstrVal);  //释放资源,特别要注意  
  185.             }  
  186.             pBag->Release();  
  187.         }  
  188.         pM->Release();  
  189.     }  
  190.     return 0;  
  191. }  
  192.   
  193. void CCapture::ResizeVideoWindow()  
  194. {  
  195.     if (m_pVW)  
  196.     {  
  197.         // 让图像充满整个指定窗口  
  198.         CRect rc;  
  199.         ::GetClientRect(m_hWnd, &rc);  
  200.         m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);  
  201.     }  
  202. }  
  203.   
  204. HRESULT CCapture::SetupVideoWindow()  
  205. {  
  206.     HRESULT hr;  
  207.     //m_hWnd为类CCapture的成员变量,在使用该函数前须初始化  
  208.     hr = m_pVW->put_Visible(OAFALSE);  // 视频窗口不可见  
  209.     hr = m_pVW->put_Owner((OAHWND)m_hWnd);  // 设置视频窗口  
  210.     if (FAILED(hr)) return hr;  
  211.     hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); //设置窗口类型  
  212.     if (FAILED(hr)) return hr;  
  213.     ResizeVideoWindow();   // 更改窗口大小  
  214.     hr = m_pVW->put_Visible(OATRUE);  // 显示视频窗口  
  215.     return hr;  
  216. }  
  217.   
  218. HRESULT CCapture::InitCaptureGraphBuilder()  
  219. {  
  220.     HRESULT hr;  
  221.     //创建IGraphBuilder接口(滤波器链表管理器) m_pGB  
  222.     hr = CoCreateInstance(CLSID_FilterGraph, NULL,  
  223.         CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);  
  224.     if (FAILED(hr)) return hr;  
  225.     //创建ICaptureGraphBuilder2接口(增强型捕获滤波器链表管理器)m_pCapGB  
  226.     hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,  
  227.         CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);  
  228.     if (FAILED(hr)) return hr;  
  229.     // 创建抓取图片滤波器  
  230.     if (m_pGrabber){  
  231.         m_pGrabber.Release();  
  232.         m_pGrabber = NULL;  
  233.     }  
  234.   
  235.     hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void **)&m_pGrabber);  
  236. //  hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );   
  237.     if (FAILED(hr)) return hr;  
  238.     // 初始化滤波器链表管理器IGraphBuilder  
  239.     m_pCapGB->SetFiltergraph(m_pGB);  
  240.     // 查询媒体控制接口  
  241.     hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);  
  242.     if (FAILED(hr))  return hr;  
  243.     // 查询视频窗口接口  
  244.     hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);  
  245.     if (FAILED(hr)) return hr;  
  246.     /  
  247.     return hr;  
  248. }  
  249.   
  250. HRESULT CCapture::Preview( int iDevVideoID, HWND hVideo, int iDevAudioID /*= 0*/HWND hAudio /*= NULL*/ )  
  251. {  
  252.     HRESULT hr;  
  253.     if (m_pMC)  
  254.         m_pMC->Stop();  
  255.     m_bRecording = false;  
  256.     // 初始化视频捕获滤波器链表管理器  
  257.     hr = InitCaptureGraphBuilder();  
  258.     if (FAILED(hr)) return hr;  
  259.   
  260.     // 把指定的视频采集设备与滤波器捆绑  
  261.     if (BindFilter(iDevVideoID, &m_pVideoCap, DTypeVideo))   
  262.     {  
  263.         // 把滤波器添加到滤波器链表中  
  264.         hr = m_pGB->AddFilter(m_pVideoCap, L"Video Capture Filter");  
  265.         if (FAILED(hr)) return hr;  
  266.     }  
  267.     else return FALSE;  
  268.   
  269.     if (BindFilter(iDevAudioID, &m_pAudioCap, DTypeAudio))  
  270.     {  
  271.         hr = m_pGB->AddFilter(m_pAudioCap, L"Audio Capture Filter");  
  272.         if (FAILED(hr))  
  273.         {  
  274.             MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);  
  275.         //  return hr;  
  276.         }  
  277.     }  
  278.     else  
  279.     {  
  280.         MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);  
  281.     //  return FALSE;  
  282.     }  
  283.     // 如果我们想抓取24位的RGB图片,如下设置媒体图片类型  
  284.     CComQIPtr<IBaseFilter, &IID_IBaseFilter> pGrabBase(m_pGrabber);  
  285.   
  286.     AM_MEDIA_TYPE mediaType;  
  287.     VIDEOINFOHEADER vih;  
  288.   
  289.     IAMStreamConfig* pConfig = NULL;  
  290.     m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, IID_IAMStreamConfig, (void**)&pConfig);  
  291.     // 设置视频格式  
  292.     ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE));  
  293.     vih.bmiHeader.biWidth = IMG_WIDTH;  
  294.     vih.bmiHeader.biHeight = IMG_HEIGHT;  
  295.     vih.bmiHeader.biSizeImage = IMG_HEIGHT*IMG_WIDTH*3;  
  296.     mediaType.pbFormat = (BYTE *)(&vih);  
  297.     mediaType.cbFormat = sizeof(VIDEOINFOHEADER);  
  298.     mediaType.subtype = MEDIASUBTYPE_YUY2;  
  299.     mediaType.majortype = MEDIATYPE_Video;  
  300.     mediaType.formattype = FORMAT_VideoInfo;  
  301.     hr = pConfig->SetFormat(&mediaType);  
  302.     hr = m_pGrabber->SetMediaType(&mediaType);   
  303.     if( FAILED( hr ) ){   
  304.         AfxMessageBox("Fail to set media type!");   
  305.         return hr;   
  306.     }  
  307.       
  308.     hr = m_pGB->AddFilter(pGrabBase, L"SampleGrabber");  
  309.     if (FAILED(hr)) return hr;  
  310.     // 渲染媒体, 把链表中滤波器链接起来  
  311.     hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pAudioCap, NULL, NULL);  
  312.     hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);  
  313.     if (FAILED(hr))  
  314.         hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);  
  315.     if( FAILED( hr ) ){  
  316.         AfxMessageBox(_T("Can’t build the graph"));  
  317.         return hr;  
  318.     }  
  319.   
  320.     // 设置图片捕获数据  
  321.     hr = m_pGrabber->GetConnectedMediaType( &mediaType );  
  322.     if ( FAILED( hr) ){  
  323.         AfxMessageBox(_T("Failt to read the connected media type"));  
  324.         return hr;  
  325.     }  
  326.     VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)mediaType.pbFormat;  
  327.     samCB.lWidth = pVih->bmiHeader.biWidth;  
  328.     samCB.lHeight = pVih->bmiHeader.biHeight;  
  329.     samCB.pCap = (CCapture *)this;  
  330.     FreeMediaType(mediaType);  
  331.     hr = m_pGrabber->SetBufferSamples( TRUE );  // 如果此处为false 第一次抓取图片时失败(不用回调方式)  
  332.     hr = m_pGrabber->SetOneShot( FALSE );       
  333.     hr = m_pGrabber->SetCallback( &samCB, 1 );  
  334.     SetOnShot(TRUE);// ture 时开始捕获视频帧数据  
  335.     // 设置视频显示窗口  
  336.     m_hWnd = hVideo;  
  337.     SetupVideoWindow(); // 设置显示窗口  
  338.     hr = m_pMC->Run();  // 开始采集、预览视频,并在指定窗口显示  
  339.     if (FAILED(hr))   
  340.     {  
  341.         MessageBox(NULL, _T("请检查该设备是否被占用!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);  
  342.         return hr;  
  343.     }  
  344.     return S_OK;  
  345. }  
  346.   
  347. #if 1  // avi video format  
  348. HRESULT CCapture::CaptureVideo( CString inFileName )  // 录制视频  
  349. {  
  350.     HRESULT hr = 0;  
  351.     DWORD dwId;  
  352.     HANDLE hThread;  
  353.     m_bRecording = false;  
  354.     m_pMC->Stop();   // 先停止视频采集  
  355.   
  356.     // 设置文件名,注意第二个参数类型  
  357.     hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL);  
  358.   
  359.     //渲染媒体 连接捕获器和AVI Muxer过滤器   
  360.     hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, NULL, m_pMux);  
  361.     hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, m_pAudioCap, NULL, m_pMux);  
  362.     //设置音频流为主流   
  363.     IConfigAviMux *pConfigMux;  
  364.     m_pMux->QueryInterface(IID_IConfigAviMux, (void **)&pConfigMux);  
  365.     hr = pConfigMux->SetMasterStream(1);   // 0 为视频  1为音频  
  366.   
  367.     pConfigMux->Release();  
  368.     m_pMux->Release();  
  369.     m_bRecording = true;  
  370.     hThread = CreateThread(NULL, 0,  
  371.         (LPTHREAD_START_ROUTINE)ThreadFunDrawText,  
  372.         (LPVOID)m_hWnd,  
  373.         0, &dwId);  
  374.     m_pMC->Run();  // 恢复视频采集,同时写入文件  
  375.       
  376.     return hr;  
  377. }  
  378. #else  // mpeg4 format video  
  379. HRESULT CCapture::CaptureVideo(CString inFileName)  
  380. {  
  381.     HRESULT hr=0;  
  382.       
  383.     m_pMC->Stop();  
  384.       
  385.     m_pGB->AddFilter(m_pXviDCodec,L"99 Xvid MPEG-4 Codec");  
  386.     m_pXviDCodec->Release();  
  387.       
  388.     hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL );  
  389.     hr = ConnectFilters(m_pGB,m_pSmartTee_1,m_pXviDCodec, 0);    //0,连接capture引脚  
  390.     hr = ConnectFilters(m_pGB,m_pXviDCodec,m_pMux, 2);    //2,默认自然连接  
  391.     m_pMux->Release();  
  392.       
  393.     m_pMC->Run();  
  394.       
  395.     return hr;  
  396. }  
  397. #endif  
  398.   
  399. ///  
  400.   
  401. HRESULT CCapture::CaptureImage() // 抓取并显示图像  
  402. // 采用CB接口回调函数存储图片  
  403.     bOneShot = TRUE;  
  404.     return 0;  
  405. }  
  406.   
  407. HRESULT CCapture::CaptureImage( CString inFileName ) // 抓取图像  
  408. {  
  409.     HRESULT hr;  
  410.     AM_MEDIA_TYPE mediaType;  
  411.     hr = m_pGrabber->GetConnectedMediaType(&mediaType);  
  412.     if (FAILED(hr))  return hr;  
  413.     VIDEOINFOHEADER *pVih;  
  414.     if (mediaType.formattype == FORMAT_VideoInfo &&   
  415.         (mediaType.cbFormat >= sizeof(VIDEOINFOHEADER)) &&  
  416.         mediaType.pbFormat != NULL)  
  417.     {  
  418.         pVih = (VIDEOINFOHEADER *)mediaType.pbFormat;  
  419.     }  
  420.     else       
  421.         return VFW_E_INVALIDMEDIATYPE;  
  422.   
  423. //  hr = m_pGrabber->SetOneShot(TRUE);  
  424.     if (SUCCEEDED(m_pGrabber->SetBufferSamples(TRUE)) )  // 设置为缓冲形式)  
  425.     {  
  426.         long cbBuffer = 0;  
  427.         hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, NULL);  
  428.         BYTE *pBuffer = new BYTE[cbBuffer];  
  429.         if (!pBuffer) return -1;  
  430.         // 获取一帧媒体的数据  
  431.         hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, (long *)pBuffer);  
  432.         if (FAILED(hr))  return hr;  
  433. //          if (pBuffer != NULL)  
  434. //          {  
  435. //              calFunc(pBuffer);   // 将一帧图像数据传给显示函数  
  436. //      }  
  437.   
  438.         ///-------------------------测试所得数据是rgb格式还是yuv格式--------  
  439.         long n1,n2;  
  440.         int datalen = IMG_WIDTH*IMG_HEIGHT*3;  
  441.         BYTE *rgb = new BYTE[datalen];  
  442.           
  443.         YUV422_C_RGB(pBuffer,rgb, IMG_HEIGHT, IMG_WIDTH);  
  444.         n1 = strlen((char *)pBuffer);  
  445.         n2 = strlen((char *)rgb);  
  446. //      ((CVideoNetDlg *)(m_dlgParent))->SendVideo((BYTE *)pBuffer, (int)cbBuffer);  
  447.         ///------------------------------------------------------------------  
  448. ///  
  449.         // Create a file to hold the bitmap  
  450.         HANDLE hf = CreateFile(inFileName, GENERIC_WRITE, FILE_SHARE_READ,    
  451.             NULL, CREATE_ALWAYS, NULL, NULL );  
  452.           
  453.         if( hf == INVALID_HANDLE_VALUE ){  
  454.             MessageBox(NULL, _T("Create bmp file failure!"), _T(""), MB_OK|MB_ICONINFORMATION);  
  455.             return 0;  
  456.         }  
  457.           
  458.         // Write out the file header  
  459.         //  
  460.         // 信息头  
  461.         BITMAPFILEHEADER bfh;  
  462.         memset( &bfh, 0, sizeof( bfh ) );  
  463.         bfh.bfType = 'MB';  
  464.         bfh.bfSize = sizeof( bfh ) + cbBuffer + sizeof( BITMAPINFOHEADER );  
  465.         bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );  
  466.           
  467.         DWORD Written = 0;  
  468.         WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL );  
  469.           
  470.         // Write the bitmap format  
  471.         //文件头  
  472.         BITMAPINFOHEADER bih;  
  473.         memset( &bih, 0, sizeof( bih ) );  
  474.         bih.biSize = sizeof( bih );  
  475.         bih.biWidth = pVih->bmiHeader.biWidth;  
  476.         bih.biHeight = pVih->bmiHeader.biHeight;  
  477.         bih.biPlanes = 1;  
  478.         bih.biBitCount = 24;  
  479.           
  480.         Written = 0;  
  481.         WriteFile( hf, &bih, sizeof( bih ), &Written, NULL );  
  482.           
  483.         // Write the bitmap bits  
  484.         //  
  485.         Written = 0;  
  486.         WriteFile( hf, rgb, datalen, &Written, NULL );       
  487.         CloseHandle( hf );  
  488.         delete pBuffer;  
  489.         MessageBox(NULL, _T("Save photo succeeded!"), _T("抓取图片提示"), MB_OK|MB_ICONINFORMATION);  
  490.     }  
  491.     m_pGrabber->SetOneShot(FALSE);  
  492.     m_pGrabber->SetBufferSamples(FALSE);  
  493.     FreeMediaType(mediaType);  
  494.     return 0;  
  495. }  
  496.   
  497. bool CCapture::BindFilter( int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType )  
  498. {  
  499.     if (iDeviceID < 0) return false;  
  500.     // 枚举所有的视频设备  
  501.     ICreateDevEnum *pCreateDevEnum;  
  502.     //生成设备枚举器pCreateDevEnum  
  503.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,  
  504.         NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum);  
  505.     if (hr != NOERROR) return false;  
  506.     IEnumMoniker *pEM;  
  507.     // 创建视频输入设备类枚举器  
  508.     if (deviceType == DTypeVideo)  
  509.         hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEM, 0);  
  510.     // 音频设备枚举器  
  511.     else  
  512.         hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEM, 0);  
  513.     if (hr != NOERROR) return false;  
  514.     pEM->Reset();  // 复位该设备  
  515.     ULONG cFetched;  
  516.     IMoniker *pM;  
  517.     int indexDev = 0;  
  518.     // 获取设备  
  519.     while(hr = pEM->Next(1, &pM, &cFetched), hr == S_OK, indexDev <= iDeviceID)  
  520.     {  
  521.         IPropertyBag *pBag;  
  522.         // 获取该设备属性集  
  523.         hr = pM->BindToStorage(0,0,IID_IPropertyBag,(void **)&pBag);  
  524.         if (SUCCEEDED(hr))  
  525.         {  
  526.             VARIANT var;  
  527.             var.vt = VT_BSTR;  
  528.             hr = pBag->Read(L"FriendlyName", &var, NULL);  
  529.             if (hr == NOERROR)  
  530.             {  
  531.                 // 采集设备与捕获滤波器捆绑  
  532.                 if (indexDev == iDeviceID) pM->BindToObject(0, 0, IID_IBaseFilter, (void **)pOutFilter);  
  533.                 SysFreeString(var.bstrVal);  
  534.             }  
  535.             pBag->Release();  
  536.         }  
  537.         pM->Release();  
  538.         indexDev++;  
  539.     }  
  540.     return true;  
  541. }  
  542.   
  543. void CCapture::SetCameraFormat( HWND hwndParent ) // 设置视频格式  
  544. {  
  545.     HRESULT hr;  
  546.     IAMStreamConfig *pSC; // 流配置接口  
  547.     ISpecifyPropertyPages *pSpec; //属性页接口  
  548.     m_pMC->Stop();  // 只有停止后才能进行引脚属性的设置  
  549.     m_bRecording = false;  
  550.     // 首先查询捕获CAPTURE、视频Video接口  
  551.     hr = m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,  
  552.         m_pVideoCap, IID_IAMStreamConfig, (void **)&pSC);  
  553.   
  554.     CAUUID cauuid; // 所有属性页结构体  
  555.     hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);  
  556.     if (hr == S_OK)  
  557.     {  
  558.         // 显示属性页窗口  
  559.         hr = pSpec->GetPages(&cauuid);  // 获取所有属性页  
  560.         hr = OleCreatePropertyFrame(hwndParent, 30, 30, NULL, 1,  
  561.             (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL);  
  562.         // 释放内存资源  
  563.         CoTaskMemFree(cauuid.pElems);  
  564.         pSpec->Release();  
  565.         pSC->Release();  
  566.     }  
  567.     // 恢复运行  
  568.     m_pMC->Run();          
  569. }  
  570.   
  571. void CCapture::SetCameraFilter( HWND hwndParent ) // 设置图像各参数设置  
  572. {  
  573.     HRESULT hr = 0;  
  574.     ISpecifyPropertyPages *pSpec;  
  575.     hr = m_pVideoCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);  
  576.     if (SUCCEEDED(hr))  
  577.     {  
  578.         // 获取滤波器名称和IUnknown 接口指针  
  579.         FILTER_INFO FilterInfo;  
  580.         hr = m_pVideoCap->QueryFilterInfo(&FilterInfo);  
  581.         IUnknown *pFilterUnk;  
  582.         m_pVideoCap->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);  
  583.         // 显示该页  
  584.         CAUUID caGUID;  
  585.         pSpec->GetPages(&caGUID);  
  586.         OleCreatePropertyFrame(hwndParent,  
  587.             0, 0,  
  588.             FilterInfo.achName,  
  589.             1,  
  590.             &pFilterUnk,  
  591.             caGUID.cElems,  
  592.             caGUID.pElems,  
  593.             0,  
  594.             0, NULL);  
  595.         // 释放内存资源  
  596.         CoTaskMemFree(caGUID.pElems);  
  597.         pFilterUnk->Release();  
  598.         FilterInfo.pGraph->Release();  
  599.         pSpec->Release();  
  600.     }  
  601. }  
  602.   
  603. void CCapture::StopCapture()  
  604. {  
  605.     m_pMC->Stop();  
  606. }  
  607.   
  608. UINT CCapture::ThreadFunDrawText( LPVOID lParam )  
  609. {  
  610.     HWND hwnd = (HWND)lParam;  
  611.     if (hwnd == NULL) return -1;  
  612.     HDC hdc = GetDC(hwnd);  
  613.     CRect rcDraw, rcTime;  
  614.     CTime time, time0;  
  615.     CTimeSpan timespan;  
  616.     CString strTime;  
  617.     CBrush br;  
  618.     time0 = CTime::GetCurrentTime();  
  619.     br.CreateSolidBrush(RGB(255,0,0));  
  620.     GetClientRect(hwnd, &rcDraw);  
  621.     rcTime = rcDraw;  
  622.     rcTime.bottom = rcTime.top + 30;  
  623.     rcDraw.top = rcDraw.bottom - 30;  
  624.     SelectObject(hdc, &br);  
  625.     SetTextColor(hdc, 0x0000ff);  
  626.     SetBkMode(hdc, TRANSPARENT);  
  627.     while(m_bRecording)  
  628.     {  
  629.         time = CTime::GetCurrentTime();  
  630.         timespan = time - time0;  
  631.         strTime = time.Format(_T(" %Y-%m-%d 星期%w %H:%M:%S"));  
  632.         DrawText(hdc, strTime, strTime.GetLength(), &rcTime, DT_VCENTER|DT_LEFT|DT_SINGLELINE);  
  633.         strTime = timespan.Format(_T("%H:%M:%S "));  
  634.         strTime = _T("●录制 ") + strTime;  
  635.         DrawText(hdc, strTime, strTime.GetLength(), &rcDraw, DT_VCENTER|DT_RIGHT|DT_SINGLELINE);  
  636.     }  
  637.     return 0;  
  638. }  
  639.   
  640. void CCapture::FreeMediaType(AM_MEDIA_TYPE &mt)  
  641. {  
  642.     if (mt.cbFormat != 0)  
  643.     {  
  644.         CoTaskMemFree((PVOID)mt.pbFormat);  
  645.         mt.cbFormat = 0;  
  646.         mt.pbFormat = NULL;  
  647.     }  
  648.     if (mt.pUnk != NULL)  
  649.     {  
  650.         mt.pUnk->Release();  
  651.         mt.pUnk = NULL;  
  652.     }  
  653. }  
  654.   
  655. void CCapture::SetOnShot( BOOL bFlag )  
  656. {  
  657.     bOneShot = bFlag;  
  658. }  
  659.   
  660. void CCapture::SetCallBKFun( capCallBackFunc f )  
  661. {  
  662.     this->calFunc = f;  
  663.     samCB.pCap = static_cast<CCapture *>(this);  
  664. }  
  665.   
  666. void CCapture::SetParent( CDialog *pdlg )  
  667. {  
  668.     m_dlgParent = pdlg;  
  669. }  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值