CCapture directshow 视频捕获类

[cpp] view plaincopy

  1. // Capture.h for class CCapture
  2. #include <dshow.h>

  3. #include <qedit.h>

  4. #include <atlbase.h>

  5. #if !defined(CAPTURE_H_________)

  6. #define CAPTURE_H_________
  7. // image size: 160*120  176*144   320*240  640*480  1024*1806

  8. #define IMG_WIDTH 320

  9. #define IMG_HEIGHT 240
  10. typedef void (*capCallBackFunc)(LPVOID lParam);

  11. enum DeviceType{DTypeVideo, DTypeAudio};

  12. class CSampleGrabberCB; // 用于不会帧数据保存图片的接口

  13. class CCapture

  14. {

  15. friend class CSampleGrabberCB;

  16. public:

  17. // 设置回调函数 用于处理获取的图片帧数据

  18. CDialog *m_dlgParent;

  19. capCallBackFunc calFunc;

  20. void SetCallBKFun(capCallBackFunc f);

  21. /////////////////////////////////

  22. CCapture();

  23. virtual ~CCapture();

  24. int EnumDevice(HWND hCmbList, DeviceType deviceType); // 设备枚举

  25. //  void SaveGraph(TCHAR *wFileName);   // 保存滤波器链表

  26. void SetCameraFormat(HWND hwndParent);  // 设置摄像头的视频格式

  27. void SetCameraFilter(HWND hwndParent);  // 设置摄像头的图像参数

  28. HRESULT CaptureVideo(CString inFileName);   // 捕获保存视频

  29. HRESULT CaptureImage(CString inFileName);   // 抓取保存图片

  30. HRESULT CaptureImage(); // 抓取图片并显示

  31. HRESULT Preview(int iDevVideoID, HWND hVideo, int iDevAudioID = 0, HWND hAudio = NULL); // 采集预览视频

  32. HRESULT InitCaptureGraphBuilder();  // 创建滤波器管理器,查询其各种控制接口

  33. void StopCapture();  // 停止捕获

  34. void FreeMediaType(AM_MEDIA_TYPE &mt);  // 释放对象内存
  35. void SetOnShot(BOOL bFlag);   // 设置是否捕获帧数据

  36. void SetParent(CDialog *pdlg);

  37. protected:

  38. bool BindFilter(int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType); // 把指定的设备滤波器捆绑到链表中

  39. void ResizeVideoWindow();           // 更改视频显示窗口

  40. HRESULT SetupVideoWindow();         // 设置视频显示窗口的特性

  41. static UINT ThreadFunDrawText(LPVOID lParam);

  42. private:

  43. HWND m_hWnd;            // 视频显示窗口的句柄

  44. IBaseFilter *m_pVideoCap;       // 视频捕获滤波器

  45. IBaseFilter *m_pAudioCap;       // 音频捕获滤波器

  46. CComPtr<ISampleGrabber> m_pGrabber;       // 抓取图片滤波器

  47. IBaseFilter *m_pMux;    // 写文件滤波器

  48. ICaptureGraphBuilder2 *m_pCapGB;    // 增强型捕获滤波器链表管理

  49. IGraphBuilder *m_pGB;   // 滤波链表管理器

  50. IVideoWindow *m_pVW;    // 视频显示窗口接口

  51. IMediaControl *m_pMC;   // 媒体控制接口

  52. static bool m_bRecording;       // 录制视频标志
  53. IBaseFilter *m_pXviDCodec;   //mpeg4 滤波器

  54. };
  55. #endif

[cpp] view plaincopy

    1. /// Capture.cpp for class CCapture implement

    2. //

    3. ///

    4. ////////////////////////////////////////
    5. #include "StdAfx.h"

    6. #include "Capture.h"

    7. #include <atlconv.h>

    8. #include "VideoChatDlg.h"

    9. #include "yuv2bmp.h"
    10. #ifndef srelease

    11. #define srelease(x) if (NULL != x)\

    12. {\

    13. x->Release();\

    14. x = NULL;\

    15. }

    16. #endif
    17. #ifndef MAX_PATH

    18. #define  MAX_PATH 1024

    19. #endif

    20. BOOL bOneShot = FALSE; // 全局变量

    21. capCallBackFunc fun;
    22. class CSampleGrabberCB : public ISampleGrabberCB

    23. {

    24. public:

    25. long lWidth;

    26. long lHeight;

    27. CCapture *pCap;

    28. TCHAR m_szFileName[MAX_PATH]; // 位图文件名称

    29. CSampleGrabberCB(){

    30. strcpy(m_szFileName, ".\\sample.bmp");

    31. }

    32. STDMETHODIMP_(ULONG) AddRef() { return 2; }

    33. STDMETHODIMP_(ULONG) Release() { return 1; }

    34. STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){

    35. if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){

    36. *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );

    37. return NOERROR;

    38. }

    39. return E_NOINTERFACE;

    40. }

    41. STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){

    42. return 0;

    43. }

    44. STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){

    45. if( !bOneShot )

    46. return 0;

    47. if (!pBuffer)

    48. {

    49. AfxMessageBox(_T("Save Bmp File Failure!"));

    50. return E_POINTER;

    51. }

    52. if (pBuffer != NULL && pCap)

    53. {

    54. //          BYTE *rgb = new BYTE[lWidth*lHeight*3];

    55. //          YUV422_C_RGB(pBuffer,rgb, (int)lHeight, (int)lWidth);

    56. //          outBmpBuf(pBuffer, pCap);  // 将一帧图像数据传给显示函数

    57. //          ((CVideoNetDlg *)pCap->m_dlgParent)->SendVideo(pBuffer, (int)lBufferSize);

    58. }

    59. //  SaveBitmap(pBuffer, lBufferSize);  // 保存成位图文件

    60. //      bOneShot = FALSE; // 停止捕获图像

    61. //      AfxMessageBox(_T("Get bmp data success."));

    62. return 0;

    63. }

    64. void outBmpBuf(BYTE *buf, CCapture* cap)

    65. {

    66. cap->calFunc(buf);

    67. }

    68. // 创建位图文件

    69. BOOL SaveBitmap(BYTE *pBuffer, long lBufferLen)

    70. {

    71. HANDLE hf = CreateFile(m_szFileName, GENERIC_WRITE,

    72. FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);

    73. if (hf == INVALID_HANDLE_VALUE) return 0;

    74. // 写文件头

    75. BITMAPFILEHEADER fileheader;

    76. ZeroMemory(&fileheader, sizeof(BITMAPFILEHEADER));

    77. fileheader.bfType = ‘MB‘;

    78. fileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lBufferLen;

    79. fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

    80. DWORD dwWritter = 0;

    81. WriteFile(hf, &fileheader, sizeof(BITMAPFILEHEADER), &dwWritter, NULL);

    82. // 写文图格式

    83. BITMAPINFOHEADER infoHeader;

    84. ZeroMemory(&infoHeader, sizeof(BITMAPINFOHEADER));

    85. infoHeader.biSize = sizeof(BITMAPINFOHEADER);

    86. infoHeader.biSizeImage = lBufferLen;

    87. infoHeader.biWidth = lWidth;

    88. infoHeader.biHeight = lHeight;

    89. infoHeader.biBitCount = 24;

    90. WriteFile(hf, &infoHeader, sizeof(BITMAPINFOHEADER), &dwWritter, NULL);

    91. // 写位图数据

    92. WriteFile(hf, pBuffer, lBufferLen, &dwWritter, NULL);

    93. CloseHandle(hf);

    94. MessageBox(NULL, _T("Save bmp file succeed!"), _T("warn"), MB_OK|MB_ICONINFORMATION);

    95. return 0;

    96. }

    97. };
    98. /////////////////////////////////////////////

    99. /// for class CCapture‘s Function

    100. ///

    101. ////////////////////////////////////////////////

    102. CSampleGrabberCB samCB;

    103. CCapture::CCapture()

    104. {

    105. CoInitialize(NULL);  // 初始化COM库

    106. m_hWnd = NULL;

    107. m_pVideoCap = NULL;

    108. m_pAudioCap = NULL;

    109. m_pCapGB = NULL;

    110. m_pGB = NULL;

    111. m_pMC = NULL;

    112. m_pMux = NULL;

    113. m_pVW = NULL;

    114. m_pGrabber = NULL;

    115. m_dlgParent = NULL;

    116. }

    117. bool CCapture::m_bRecording = false;
    118. CCapture::~CCapture()

    119. {

    120. if (m_pMC) m_pMC->Stop();

    121. if (m_pVW)

    122. {

    123. m_pVW->put_Owner(NULL);

    124. m_pVW->put_Visible(OAFALSE);

    125. }

    126. m_hWnd = NULL;

    127. srelease(m_pVideoCap);

    128. srelease(m_pGB);

    129. srelease(m_pCapGB);

    130. srelease(m_pMC);

    131. srelease(m_pVW);

    132. m_bRecording = false;

    133. CoUninitialize(); // 释放COM库

    134. }
    135. int CCapture::EnumDevice( HWND hCmbList, DeviceType deviceType )

    136. {

    137. if (hCmbList == NULL) return -1;

    138. int id = 0;

    139. /////枚举捕获设备

    140. ICreateDevEnum *pCreateDevEnum;

    141. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,

    142. NULL,

    143. CLSCTX_INPROC_SERVER,

    144. IID_ICreateDevEnum,

    145. (LPVOID *)&pCreateDevEnum);

    146. if ( hr != NOERROR) return -1;

    147. //////// 获取视频类的枚举器

    148. IEnumMoniker *pEm;           //枚举监控器接口

    149. if (deviceType == DTypeVideo)

    150. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);

    151. // 如果获取音频类的枚举器 用下面的代码

    152. else

    153. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);

    154. //  if (hr != NOERROR) return -1;

    155. if (!pEm || FAILED(hr)) return -1;

    156. ////////////////////////

    157. pEm->Reset();   // 类型枚举器复位

    158. ULONG cFetched;

    159. IMoniker *pM;    // 监控器接口指针

    160. while(hr = pEm->Next(1, &pM, &cFetched), hr == S_OK)

    161. {

    162. IPropertyBag *pBag;   // 属性页接口指针

    163. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);

    164. // 获取设备属性页

    165. if (SUCCEEDED(hr))

    166. {

    167. VARIANT var;

    168. var.vt = VT_BSTR;       // 保存的是二进制数据

    169. // 获取firendlyName 形式的信息

    170. hr = pBag->Read(L"FriendlyName", &var, NULL);

    171. if (hr == NOERROR) // 获取成功

    172. {

    173. id++;

    174. char szDeviceName[256] = {0};

    175. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, szDeviceName,80, NULL, NULL);  // 字符串编码转换UNICODE TO ANSI

    176. ::SendMessage(hCmbList, CB_ADDSTRING, 0, (LPARAM)szDeviceName);//添加到组合列表框

    177. SysFreeString(var.bstrVal);  //释放资源,特别要注意

    178. }

    179. pBag->Release();

    180. }

    181. pM->Release();

    182. }

    183. return 0;

    184. }
    185. void CCapture::ResizeVideoWindow()

    186. {

    187. if (m_pVW)

    188. {

    189. // 让图像充满整个指定窗口

    190. CRect rc;

    191. ::GetClientRect(m_hWnd, &rc);

    192. m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);

    193. }

    194. }
    195. HRESULT CCapture::SetupVideoWindow()

    196. {

    197. HRESULT hr;

    198. //m_hWnd为类CCapture的成员变量,在使用该函数前须初始化

    199. hr = m_pVW->put_Visible(OAFALSE);  // 视频窗口不可见

    200. hr = m_pVW->put_Owner((OAHWND)m_hWnd);  // 设置视频窗口

    201. if (FAILED(hr)) return hr;

    202. hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); //设置窗口类型

    203. if (FAILED(hr)) return hr;

    204. ResizeVideoWindow();   // 更改窗口大小

    205. hr = m_pVW->put_Visible(OATRUE);  // 显示视频窗口

    206. return hr;

    207. }
    208. HRESULT CCapture::InitCaptureGraphBuilder()

    209. {

    210. HRESULT hr;

    211. //创建IGraphBuilder接口(滤波器链表管理器) m_pGB

    212. hr = CoCreateInstance(CLSID_FilterGraph, NULL,

    213. CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);

    214. if (FAILED(hr)) return hr;

    215. //创建ICaptureGraphBuilder2接口(增强型捕获滤波器链表管理器)m_pCapGB

    216. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,

    217. CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);

    218. if (FAILED(hr)) return hr;

    219. // 创建抓取图片滤波器

    220. if (m_pGrabber){

    221. m_pGrabber.Release();

    222. m_pGrabber = NULL;

    223. }
    224. hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void **)&m_pGrabber);

    225. //  hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );

    226. if (FAILED(hr)) return hr;

    227. // 初始化滤波器链表管理器IGraphBuilder

    228. m_pCapGB->SetFiltergraph(m_pGB);

    229. // 查询媒体控制接口

    230. hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);

    231. if (FAILED(hr))  return hr;

    232. // 查询视频窗口接口

    233. hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);

    234. if (FAILED(hr)) return hr;

    235. /////

    236. return hr;

    237. }
    238. HRESULT CCapture::Preview( int iDevVideoID, HWND hVideo, int iDevAudioID /*= 0*/, HWND hAudio /*= NULL*/ )

    239. {

    240. HRESULT hr;

    241. if (m_pMC)

    242. m_pMC->Stop();

    243. m_bRecording = false;

    244. // 初始化视频捕获滤波器链表管理器

    245. hr = InitCaptureGraphBuilder();

    246. if (FAILED(hr)) return hr;
    247. // 把指定的视频采集设备与滤波器捆绑

    248. if (BindFilter(iDevVideoID, &m_pVideoCap, DTypeVideo))

    249. {

    250. // 把滤波器添加到滤波器链表中

    251. hr = m_pGB->AddFilter(m_pVideoCap, L"Video Capture Filter");

    252. if (FAILED(hr)) return hr;

    253. }

    254. else return FALSE;
    255. if (BindFilter(iDevAudioID, &m_pAudioCap, DTypeAudio))

    256. {

    257. hr = m_pGB->AddFilter(m_pAudioCap, L"Audio Capture Filter");

    258. if (FAILED(hr))

    259. {

    260. MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);

    261. //  return hr;

    262. }

    263. }

    264. else

    265. {

    266. MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);

    267. //  return FALSE;

    268. }

    269. // 如果我们想抓取24位的RGB图片,如下设置媒体图片类型

    270. CComQIPtr<IBaseFilter, &IID_IBaseFilter> pGrabBase(m_pGrabber);
    271. AM_MEDIA_TYPE mediaType;

    272. VIDEOINFOHEADER vih;
    273. IAMStreamConfig* pConfig = NULL;

    274. m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, IID_IAMStreamConfig, (void**)&pConfig);

    275. // 设置视频格式

    276. ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE));

    277. vih.bmiHeader.biWidth = IMG_WIDTH;

    278. vih.bmiHeader.biHeight = IMG_HEIGHT;

    279. vih.bmiHeader.biSizeImage = IMG_HEIGHT*IMG_WIDTH*3;

    280. mediaType.pbFormat = (BYTE *)(&vih);

    281. mediaType.cbFormat = sizeof(VIDEOINFOHEADER);

    282. mediaType.subtype = MEDIASUBTYPE_YUY2;

    283. mediaType.majortype = MEDIATYPE_Video;

    284. mediaType.formattype = FORMAT_VideoInfo;

    285. hr = pConfig->SetFormat(&mediaType);

    286. hr = m_pGrabber->SetMediaType(&mediaType);

    287. if( FAILED( hr ) ){

    288. AfxMessageBox("Fail to set media type!");

    289. return hr;

    290. }
    291. hr = m_pGB->AddFilter(pGrabBase, L"SampleGrabber");

    292. if (FAILED(hr)) return hr;

    293. // 渲染媒体, 把链表中滤波器链接起来

    294. hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pAudioCap, NULL, NULL);

    295. hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);

    296. if (FAILED(hr))

    297. hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);

    298. if( FAILED( hr ) ){

    299. AfxMessageBox(_T("Can’t build the graph"));

    300. return hr;

    301. }
    302. ////////// 设置图片捕获数据

    303. hr = m_pGrabber->GetConnectedMediaType( &mediaType );

    304. if ( FAILED( hr) ){

    305. AfxMessageBox(_T("Failt to read the connected media type"));

    306. return hr;

    307. }

    308. VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)mediaType.pbFormat;

    309. samCB.lWidth = pVih->bmiHeader.biWidth;

    310. samCB.lHeight = pVih->bmiHeader.biHeight;

    311. samCB.pCap = (CCapture *)this;

    312. FreeMediaType(mediaType);

    313. hr = m_pGrabber->SetBufferSamples( TRUE );  // 如果此处为false 第一次抓取图片时失败(不用回调方式)

    314. hr = m_pGrabber->SetOneShot( FALSE );

    315. hr = m_pGrabber->SetCallback( &samCB, 1 );

    316. SetOnShot(TRUE);// ture 时开始捕获视频帧数据

    317. // 设置视频显示窗口

    318. m_hWnd = hVideo;

    319. SetupVideoWindow(); // 设置显示窗口

    320. hr = m_pMC->Run();  // 开始采集、预览视频,并在指定窗口显示

    321. if (FAILED(hr))

    322. {

    323. MessageBox(NULL, _T("请检查该设备是否被占用!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);

    324. return hr;

    325. }

    326. return S_OK;

    327. }
    328. #if 1  // avi video format

    329. HRESULT CCapture::CaptureVideo( CString inFileName )  // 录制视频

    330. {

    331. HRESULT hr = 0;

    332. DWORD dwId;

    333. HANDLE hThread;

    334. m_bRecording = false;

    335. m_pMC->Stop();   // 先停止视频采集
    336. // 设置文件名,注意第二个参数类型

    337. hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL);
    338. //渲染媒体 连接捕获器和AVI Muxer过滤器

    339. hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, NULL, m_pMux);

    340. hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, m_pAudioCap, NULL, m_pMux);

    341. //设置音频流为主流

    342. IConfigAviMux *pConfigMux;

    343. m_pMux->QueryInterface(IID_IConfigAviMux, (void **)&pConfigMux);

    344. hr = pConfigMux->SetMasterStream(1);   // 0 为视频  1为音频
    345. pConfigMux->Release();

    346. m_pMux->Release();

    347. m_bRecording = true;

    348. hThread = CreateThread(NULL, 0,

    349. (LPTHREAD_START_ROUTINE)ThreadFunDrawText,

    350. (LPVOID)m_hWnd,

    351. 0, &dwId);

    352. m_pMC->Run();  // 恢复视频采集,同时写入文件
    353. return hr;

    354. }

    355. #else  // mpeg4 format video

    356. HRESULT CCapture::CaptureVideo(CString inFileName)

    357. {

    358. HRESULT hr=0;
    359. m_pMC->Stop();
    360. m_pGB->AddFilter(m_pXviDCodec,L"99 Xvid MPEG-4 Codec");

    361. m_pXviDCodec->Release();
    362. hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL );

    363. hr = ConnectFilters(m_pGB,m_pSmartTee_1,m_pXviDCodec, 0);    //0,连接capture引脚

    364. hr = ConnectFilters(m_pGB,m_pXviDCodec,m_pMux, 2);    //2,默认自然连接

    365. m_pMux->Release();
    366. m_pMC->Run();
    367. return hr;

    368. }

    369. #endif
    370. ///////////////////////////////
    371. HRESULT CCapture::CaptureImage() // 抓取并显示图像

    372. { // 采用CB接口回调函数存储图片

    373. bOneShot = TRUE;

    374. return 0;

    375. }
    376. HRESULT CCapture::CaptureImage( CString inFileName ) // 抓取图像

    377. {

    378. HRESULT hr;

    379. AM_MEDIA_TYPE mediaType;

    380. hr = m_pGrabber->GetConnectedMediaType(&mediaType);

    381. if (FAILED(hr))  return hr;

    382. VIDEOINFOHEADER *pVih;

    383. if (mediaType.formattype == FORMAT_VideoInfo &&

    384. (mediaType.cbFormat >= sizeof(VIDEOINFOHEADER)) &&

    385. mediaType.pbFormat != NULL)

    386. {

    387. pVih = (VIDEOINFOHEADER *)mediaType.pbFormat;

    388. }

    389. else

    390. return VFW_E_INVALIDMEDIATYPE;
    391. //  hr = m_pGrabber->SetOneShot(TRUE);

    392. if (SUCCEEDED(m_pGrabber->SetBufferSamples(TRUE)) )  // 设置为缓冲形式)

    393. {

    394. long cbBuffer = 0;

    395. hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, NULL);

    396. BYTE *pBuffer = new BYTE[cbBuffer];

    397. if (!pBuffer) return -1;

    398. // 获取一帧媒体的数据

    399. hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, (long *)pBuffer);

    400. if (FAILED(hr))  return hr;

    401. //          if (pBuffer != NULL)

    402. //          {

    403. //              calFunc(pBuffer);   // 将一帧图像数据传给显示函数

    404. //      }
    405. ///-------------------------测试所得数据是rgb格式还是yuv格式--------

    406. long n1,n2;

    407. int datalen = IMG_WIDTH*IMG_HEIGHT*3;

    408. BYTE *rgb = new BYTE[datalen];
    409. YUV422_C_RGB(pBuffer,rgb, IMG_HEIGHT, IMG_WIDTH);

    410. n1 = strlen((char *)pBuffer);

    411. n2 = strlen((char *)rgb);

    412. //      ((CVideoNetDlg *)(m_dlgParent))->SendVideo((BYTE *)pBuffer, (int)cbBuffer);

    413. ///------------------------------------------------------------------

    414. ///////////////////////////////////////////////////////////////

    415. // Create a file to hold the bitmap

    416. HANDLE hf = CreateFile(inFileName, GENERIC_WRITE, FILE_SHARE_READ,

    417. NULL, CREATE_ALWAYS, NULL, NULL );
    418. if( hf == INVALID_HANDLE_VALUE ){

    419. MessageBox(NULL, _T("Create bmp file failure!"), _T(""), MB_OK|MB_ICONINFORMATION);

    420. return 0;

    421. }
    422. // Write out the file header

    423. //

    424. // 信息头

    425. BITMAPFILEHEADER bfh;

    426. memset( &bfh, 0, sizeof( bfh ) );

    427. bfh.bfType = ‘MB‘;

    428. bfh.bfSize = sizeof( bfh ) + cbBuffer + sizeof( BITMAPINFOHEADER );

    429. bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
    430. DWORD Written = 0;

    431. WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL );
    432. // Write the bitmap format

    433. //文件头

    434. BITMAPINFOHEADER bih;

    435. memset( &bih, 0, sizeof( bih ) );

    436. bih.biSize = sizeof( bih );

    437. bih.biWidth = pVih->bmiHeader.biWidth;

    438. bih.biHeight = pVih->bmiHeader.biHeight;

    439. bih.biPlanes = 1;

    440. bih.biBitCount = 24;
    441. Written = 0;

    442. WriteFile( hf, &bih, sizeof( bih ), &Written, NULL );
    443. // Write the bitmap bits

    444. //

    445. Written = 0;

    446. WriteFile( hf, rgb, datalen, &Written, NULL );

    447. CloseHandle( hf );

    448. delete pBuffer;

    449. MessageBox(NULL, _T("Save photo succeeded!"), _T("抓取图片提示"), MB_OK|MB_ICONINFORMATION);

    450. }

    451. m_pGrabber->SetOneShot(FALSE);

    452. m_pGrabber->SetBufferSamples(FALSE);

    453. FreeMediaType(mediaType);

    454. return 0;

    455. }
    456. bool CCapture::BindFilter( int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType )

    457. {

    458. if (iDeviceID < 0) return false;

    459. // 枚举所有的视频设备

    460. ICreateDevEnum *pCreateDevEnum;

    461. //生成设备枚举器pCreateDevEnum

    462. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,

    463. NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum);

    464. if (hr != NOERROR) return false;

    465. IEnumMoniker *pEM;

    466. // 创建视频输入设备类枚举器

    467. if (deviceType == DTypeVideo)

    468. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEM, 0);

    469. // 音频设备枚举器

    470. else

    471. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEM, 0);

    472. if (hr != NOERROR) return false;

    473. pEM->Reset();  // 复位该设备

    474. ULONG cFetched;

    475. IMoniker *pM;

    476. int indexDev = 0;

    477. // 获取设备

    478. while(hr = pEM->Next(1, &pM, &cFetched), hr == S_OK, indexDev <= iDeviceID)

    479. {

    480. IPropertyBag *pBag;

    481. // 获取该设备属性集

    482. hr = pM->BindToStorage(0,0,IID_IPropertyBag,(void **)&pBag);

    483. if (SUCCEEDED(hr))

    484. {

    485. VARIANT var;

    486. var.vt = VT_BSTR;

    487. hr = pBag->Read(L"FriendlyName", &var, NULL);

    488. if (hr == NOERROR)

    489. {

    490. // 采集设备与捕获滤波器捆绑

    491. if (indexDev == iDeviceID) pM->BindToObject(0, 0, IID_IBaseFilter, (void **)pOutFilter);

    492. SysFreeString(var.bstrVal);

    493. }

    494. pBag->Release();

    495. }

    496. pM->Release();

    497. indexDev++;

    498. }

    499. return true;

    500. }
    501. void CCapture::SetCameraFormat( HWND hwndParent ) // 设置视频格式

    502. {

    503. HRESULT hr;

    504. IAMStreamConfig *pSC; // 流配置接口

    505. ISpecifyPropertyPages *pSpec; //属性页接口

    506. m_pMC->Stop();  // 只有停止后才能进行引脚属性的设置

    507. m_bRecording = false;

    508. // 首先查询捕获CAPTURE、视频Video接口

    509. hr = m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,

    510. m_pVideoCap, IID_IAMStreamConfig, (void **)&pSC);
    511. CAUUID cauuid; // 所有属性页结构体

    512. hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);

    513. if (hr == S_OK)

    514. {

    515. // 显示属性页窗口

    516. hr = pSpec->GetPages(&cauuid);  // 获取所有属性页

    517. hr = OleCreatePropertyFrame(hwndParent, 30, 30, NULL, 1,

    518. (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL);

    519. // 释放内存资源

    520. CoTaskMemFree(cauuid.pElems);

    521. pSpec->Release();

    522. pSC->Release();

    523. }

    524. // 恢复运行

    525. m_pMC->Run();

    526. }
    527. void CCapture::SetCameraFilter( HWND hwndParent ) // 设置图像各参数设置

    528. {

    529. HRESULT hr = 0;

    530. ISpecifyPropertyPages *pSpec;

    531. hr = m_pVideoCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);

    532. if (SUCCEEDED(hr))

    533. {

    534. // 获取滤波器名称和IUnknown 接口指针

    535. FILTER_INFO FilterInfo;

    536. hr = m_pVideoCap->QueryFilterInfo(&FilterInfo);

    537. IUnknown *pFilterUnk;

    538. m_pVideoCap->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);

    539. // 显示该页

    540. CAUUID caGUID;

    541. pSpec->GetPages(&caGUID);

    542. OleCreatePropertyFrame(hwndParent,

    543. 0, 0,

    544. FilterInfo.achName,

    545. 1,

    546. &pFilterUnk,

    547. caGUID.cElems,

    548. caGUID.pElems,

    549. 0,

    550. 0, NULL);

    551. // 释放内存资源

    552. CoTaskMemFree(caGUID.pElems);

    553. pFilterUnk->Release();

    554. FilterInfo.pGraph->Release();

    555. pSpec->Release();

    556. }

    557. }
    558. void CCapture::StopCapture()

    559. {

    560. m_pMC->Stop();

    561. }
    562. UINT CCapture::ThreadFunDrawText( LPVOID lParam )

    563. {

    564. HWND hwnd = (HWND)lParam;

    565. if (hwnd == NULL) return -1;

    566. HDC hdc = GetDC(hwnd);

    567. CRect rcDraw, rcTime;

    568. CTime time, time0;

    569. CTimeSpan timespan;

    570. CString strTime;

    571. CBrush br;

    572. time0 = CTime::GetCurrentTime();

    573. br.CreateSolidBrush(RGB(255,0,0));

    574. GetClientRect(hwnd, &rcDraw);

    575. rcTime = rcDraw;

    576. rcTime.bottom = rcTime.top + 30;

    577. rcDraw.top = rcDraw.bottom - 30;

    578. SelectObject(hdc, &br);

    579. SetTextColor(hdc, 0x0000ff);

    580. SetBkMode(hdc, TRANSPARENT);

    581. while(m_bRecording)

    582. {

    583. time = CTime::GetCurrentTime();

    584. timespan = time - time0;

    585. strTime = time.Format(_T(" %Y-%m-%d 星期%w %H:%M:%S"));

    586. DrawText(hdc, strTime, strTime.GetLength(), &rcTime, DT_VCENTER|DT_LEFT|DT_SINGLELINE);

    587. strTime = timespan.Format(_T("%H:%M:%S "));

    588. strTime = _T("●录制 ") + strTime;

    589. DrawText(hdc, strTime, strTime.GetLength(), &rcDraw, DT_VCENTER|DT_RIGHT|DT_SINGLELINE);

    590. }

    591. return 0;

    592. }
    593. void CCapture::FreeMediaType(AM_MEDIA_TYPE &mt)

    594. {

    595. if (mt.cbFormat != 0)

    596. {

    597. CoTaskMemFree((PVOID)mt.pbFormat);

    598. mt.cbFormat = 0;

    599. mt.pbFormat = NULL;

    600. }

    601. if (mt.pUnk != NULL)

    602. {

    603. mt.pUnk->Release();

    604. mt.pUnk = NULL;

    605. }

    606. }
    607. void CCapture::SetOnShot( BOOL bFlag )

    608. {

    609. bOneShot = bFlag;

    610. }
    611. void CCapture::SetCallBKFun( capCallBackFunc f )

    612. {

    613. this->calFunc = f;

    614. samCB.pCap = static_cast<CCapture *>(this);

    615. }
    616. void CCapture::SetParent( CDialog *pdlg )

    617. {

    618. m_dlgParent = pdlg;

    619. }

CCapture directshow 视频捕获类,码迷,mamicode.com

时间: 2024-08-07 21:09:45

CCapture directshow 视频捕获类的相关文章

视频捕获

目 录 一. 视频捕获快速入门 2 二.基本的捕获设置 3 1.设置捕获速度: 3 2.设置终止捕获 4 3.捕获的时间限制 4 三.关于捕获窗口 4 1.创建一个AVICAP捕获窗口 5 2.将一个捕获窗口连接至捕获设备 5 3. 父窗口与子窗口的交互 5 4.捕获窗口的状态 6 四.视频捕获驱动和音频驱动 6 1.视频捕获驱动的性能: 6 2.视频对话框: 6 3.PREVIEW 和 OVERLAY模式: 7 4.视频格式 7 5.视频捕获设置 7 6.声频格式 8 五.使用视频捕获 8 1

背景建模技术(五):视频捕获(VideoCapture)模块

本次对"视频捕获(VideoCapture)模块"做出分析,给出源代码和对应的程序流程框架. 视频捕获模块的主要功能是设置视频或相机参数,并读取设置配置参数,最后进入帧处理模块的process进程,该模块的源码如下,请重点关注start()函数: #include "VideoCapture.h" namespace bgslibrary { namespace VC_ROI { IplImage* img_input1 = 0; IplImage* img_inp

TVideoCapture类的源码,继承TCustomPanel,用于视频捕获(用到了SendMessage和SetWindowPos等API)good

[cpp] view plain copy print? unit VideoCapture; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Imaging.jpeg; type T

webrtc之视频捕获模块--video_capture

webrtc的video_capture模块,为我们在不同端设备上采集视频提供了一个跨平台封装的视频采集功能,如下图中的webrtc的video_capture源码,现webrtc的video_capture模块支持android.ios.linux.mac和windows各操作平台下的视频采集,  我们在不同端设备上开发视频直播的时刻,也可以使用该模块进行视频采集. 该视频采集模块的库头文件为: class VideoCaptureModule: public RefCountedModule

Python-正则零宽断言及命名捕获(类PHP)

(一)零宽断言 说明:本文的例子使用python描述      首先说明一下什么是零宽断言,所谓零宽断言就是并不去真正的匹配字符串文本,而仅仅是匹配对应的位置.      正则表达式中有很多这样的断言,常见的如匹配字符串或者行的起始位置 ^ 和 /A,匹配字符串或者行的末尾 $ 和 /Z,单词边界/B等等.这些简单的就不说了,今天主要说一下界定的使用方法(有些资料叫环式结构,名字而已,不重要).界定也是一种零宽断言,界定主要有四类:      1.前向界定(肯定顺序环视)(?=exp)     

OPenCV_摄像头视频捕获并画矩形框

#include "stdafx.h" #include "opencv2/imgproc/imgproc.hpp" #include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp> #include <stdio.h> #include <iostream> using namespace cv; using namespace std;

Android(java)学习笔记144:Android音视频录制类MediaRecorder用法举例

Android语音录制可以通过MediaRecorder和AudioRecorder.MediaRecorder本来是多媒体录制控件,可以同时录制视频和语音,当不指定视频源时就只录制语音(默认录制语言):AudioRecorder只能录制语音.二者录制的区别在于,MediaRecorder固定了语音的编码格式,具体平台支持类型可以在http://developer.android.com/guide/appendix/media-formats.html这里查看,而且使用时指定输出文件,在录制的

C# 视频转换类

using System.Web; using System.Configuration; namespace DotNet.Utilities { public class VideoConvert : System.Web.UI.Page { public VideoConvert() { } string[] strArrMencoder = new string[] { "wmv", "rmvb", "rm" }; string[] st

视频工具类产品是个什么玩意,产品经理怎么构思一款视频工具类产品

是什么 是一款工具产品.通过美化视频,赢得朋友称赞,带给用户的满足感,促使企业盈利. 为什么有啥用 为了解决用户“不懂专业摄影与后期,又想拍出好视频”这一痛点,可以通过打造一款傻瓜式的“短视频伴侣”软件,提供“素材模板”.“社区交友”.“内容存储”.“智能媒资”等附加服务,多维度的赋能视频工具产品,迅速扩大市场占有率,促使企业盈利. 值得一提的是,智商税是不能开专票的.愿意踩雷体验摄影圈子魔幻的氪金操作也是一种勇气,那么好吃懒做的小韭菜也想玩怎办?开开心心找个“神器”随便套套模板,居然可以吊打周