• CCapture directshow 视频捕获类


     

    [cpp] view plaincopy
     
    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 plaincopy
     
      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. }  
  • 相关阅读:
    docker 常用命令
    linux 查看服务器序列号
    centos 7 lsof 安装使用
    Jenkins +svn +maven +tomcat+ ansible 自动化批量部署
    nginx 部署前期一定要关闭selinux
    yum 执行不了, 解决方法
    IIS发布网站
    使用TreeView 使用多选功能
    C#类和接口
    关于C#垃圾回收
  • 原文地址:https://www.cnblogs.com/lidabo/p/3701654.html
Copyright © 2020-2023  润新知