VideoPlay.cpp
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:8k
源码类别:

VC书籍

开发平台:

Visual C++

  1. // VideoPlay.cpp: implementation of the CVideoPlay class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "VideoPlay.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. CVideoPlay::CVideoPlay(HWND hwnd)
  15. {
  16.    
  17.    pigb  = NULL;
  18.    pimc  = NULL;
  19.    pimex = NULL;
  20.    pivw  = NULL;
  21.    pmp   = NULL;
  22.    pVCap = NULL;
  23.    CappFg = NULL;
  24.    CapPigb = NULL;
  25.    m_hwnd=hwnd;
  26. }
  27. CVideoPlay::~CVideoPlay()
  28. {
  29.   HELPER_RELEASE(pivw);
  30.   HELPER_RELEASE(pigb);
  31.   HELPER_RELEASE(pimc);
  32.   HELPER_RELEASE(pimex);
  33.   HELPER_RELEASE(pmp);
  34.   HELPER_RELEASE(CapPigb);
  35.   HELPER_RELEASE(CappFg);
  36.   HELPER_RELEASE(pVCap);
  37. }
  38. //实时捕捉图像的播放
  39. void CVideoPlay::RealPlay()
  40. {
  41. HRESULT hr;
  42.  
  43. //创建捕捉过滤器图表
  44. CHECK_ERROR(CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder,NULL,
  45. CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder,(void **)&CapPigb),
  46. "CoCreateInstance Error");
  47.   
  48. //创建过滤器图表
  49. CHECK_ERROR(hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
  50.         IID_IGraphBuilder, (LPVOID *)&CappFg),"Cannot instantiate filtergraph");
  51. //将捕捉过滤器图表和过滤器图表进行关联
  52. hr = CapPigb->SetFiltergraph(CappFg);
  53. if (hr != NOERROR)
  54. {
  55.      MessageBox(m_hwnd,"Cannot give graph to builder","Error",MB_OK);
  56.         return;
  57. }
  58. int uIndex=0;
  59. //创建视频设备枚举器
  60. ICreateDevEnum *pCreateDevEnum;
  61. hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  62.   IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  63. //创建一个类型枚举器,指向系统的视频设备列表
  64. IEnumMoniker *pEm;
  65. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
  66. &pEm, 0);
  67. HELPER_RELEASE(pCreateDevEnum);
  68. pEm->Reset();
  69. ULONG cFetched;
  70. IMoniker *pM;
  71. //枚举每个视频设备
  72. while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
  73.     {
  74. //生成并初始化管理该设备的过滤器
  75. hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&pVCap);
  76. if(pVCap== NULL) 
  77. {
  78.     MessageBox(m_hwnd,"Cannot get the capture filterr","Error",MB_OK);
  79. return;
  80. }
  81. HELPER_RELEASE(pM);
  82. uIndex++;
  83.     }
  84. HELPER_RELEASE(pEm);
  85. if(pVCap)
  86. hr = CappFg->AddFilter(pVCap, NULL); //添加过滤器到Filter Graph中
  87. if (hr != NOERROR) 
  88. {
  89.      MessageBox(m_hwnd,"Cannot add vidcap to filtergraph","Error",MB_OK);
  90. return;
  91. }
  92. //连接源过滤器和提交过滤器
  93. hr = CapPigb->RenderStream(&PIN_CATEGORY_PREVIEW,pVCap,NULL, NULL);
  94. if (hr != S_OK)
  95. {
  96.     MessageBox(m_hwnd,"This graph cannot preview properly","Error",MB_OK);
  97. return;
  98. }
  99. //在过滤器图表中查找一个与捕捉有关的接口
  100.     hr = CapPigb->FindInterface(&PIN_CATEGORY_PREVIEW,pVCap,IID_IVideoWindow,(void **)&pivw);
  101.     if (hr != NOERROR) 
  102. {
  103.        MessageBox(m_hwnd,"cannot find Video Window properly","Error",MB_OK);
  104. return;
  105.     
  106. else 
  107. {
  108. DisplayVideoWin(); //显示视频播放窗口
  109.    }
  110. //查询数据流控制接口
  111.     hr =CappFg->QueryInterface(IID_IMediaControl, (void **)&pimc);
  112.     if (SUCCEEDED(hr)) 
  113. {
  114.    hr = pimc->Run(); //播放视频
  115.    
  116. }
  117. else
  118. {
  119.         MessageBox(m_hwnd,"Cannot run preview graph","Error",MB_OK);
  120.     return;
  121.  
  122. }
  123. //显示视频播放窗口
  124. void CVideoPlay::DisplayVideoWin()
  125. {
  126. RECT grc;
  127.     if(pivw)
  128. {
  129. //设置窗口所有者
  130. pivw->put_Owner((OAHWND)m_hwnd);
  131. //设置窗口尺寸
  132.     pivw->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  133. //设置窗口位置
  134.         ::GetClientRect(m_hwnd, &grc);; 
  135.     pivw->SetWindowPosition(grc.left, grc.top, grc.right, grc.bottom);
  136. //显示窗口
  137.         pivw->put_Visible(OATRUE);
  138. }     
  139. }
  140. //停止播放视频
  141. void CVideoPlay::StopPlay()
  142. {
  143.  
  144.     if(pimc)
  145. {
  146. //停止播放视频
  147. pimc->Stop();  
  148. HELPER_RELEASE(pimc);
  149. }
  150. if (pivw)
  151.     {   
  152. //关闭视频播放窗口
  153.         pivw->put_Visible(OAFALSE);
  154.         pivw->put_Owner(NULL);
  155.         HELPER_RELEASE(pivw);
  156. }
  157. HELPER_RELEASE(CapPigb);
  158.     HELPER_RELEASE(CappFg);
  159.     HELPER_RELEASE(pVCap);
  160. }
  161. //播放视频文件
  162. void CVideoPlay::PlayFromFile(CString szFile)
  163. {
  164.       WCHAR wFile[MAX_PATH];
  165.   HRESULT   hr;
  166.   MultiByteToWideChar( CP_ACP, 0, szFile.GetBuffer(_MAX_PATH), -1, wFile, MAX_PATH );
  167.       szFile.ReleaseBuffer();
  168.   //创建过滤器图表生成器接口
  169.       CHECK_ERROR(::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  170.            IID_IGraphBuilder, (void **)&pigb),"CoCreateInstance Error") ;
  171.   //查询数据流控制接口
  172.       pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);  
  173.   //查询过滤器图表事件接口
  174.       hr=pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);
  175.   //查询视频播放窗口接口
  176.       pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw);
  177.   //查询数据流位置接口
  178.       hr=pigb->QueryInterface(IID_IMediaPosition, (void**) &pmp);
  179.       //为指定的多媒体文件创建一个过滤器图表进行处理
  180.       hr = pigb->RenderFile(wFile, NULL);
  181.   //得到视频文件的播放时间
  182.   if (SUCCEEDED(hr))             
  183.          hr=pmp->get_Duration(&tLength);  
  184.   //显示视频播放窗口
  185.   DisplayVideoWin();    
  186.   if (SUCCEEDED(hr))
  187.          pimc->Run();       //播放视频
  188.   pimex->SetNotifyWindow((OAHWND)m_hwnd, WM_PLAYOVER, 0);
  189. }
  190. int CVideoPlay::PlayOver()
  191. {
  192.   long evCode,evParam1,evParam2;
  193.   HRESULT   hr;
  194.   if(pimex)
  195.   {
  196.   while (SUCCEEDED(pimex->GetEvent(&evCode, &evParam1, &evParam2, 0)))
  197.       { // Spin through the events
  198.                hr = pimex->FreeEventParams(evCode, evParam1, evParam2);
  199.                 if (EC_COMPLETE == evCode)
  200.                   { // Finished
  201.                     if (pivw)
  202.                       { // Relinquish ownership (IMPORTANT!) after hiding
  203.                         pivw->put_Visible(OAFALSE);
  204.                         pivw->put_Owner(NULL);
  205.                         HELPER_RELEASE(pivw);
  206.                       } // Relinquish ownership (IMPORTANT!) after hiding
  207.                  //   HELPER_RELEASE(pif);
  208.                     HELPER_RELEASE(pigb);
  209.                     HELPER_RELEASE(pimc);
  210.                   HELPER_RELEASE(pmp);
  211.     HELPER_RELEASE(pimex);
  212. return 0;
  213.   break;
  214. }
  215.    }
  216.   }
  217.   return -1;
  218. }
  219. //继续播放
  220. void CVideoPlay::ResumePlay()
  221. {
  222.   HRESULT hr; 
  223. //得到当前播放位置
  224. hr = pmp->get_CurrentPosition(&tCurrent);
  225.     if (SUCCEEDED(hr)) 
  226. {
  227.        // 如果已在播放文件的最后(播放时间剩下不到1分钟),当前位置回到文件头
  228.        if ((tRemain=tLength - tCurrent) < 1) 
  229.          pmp->put_CurrentPosition(0);
  230.    //不在文件尾,当前位置不变
  231.        else
  232.      pmp->put_CurrentPosition(tCurrent);
  233.     }
  234.     if(pimc)
  235.    pimc->Run(); //继续播放文件
  236. }
  237. //暂停播放
  238. void CVideoPlay::PausePlay()
  239. {
  240. if(pimc)
  241. pimc->Pause();
  242. }
  243. //搜索视频设备,并返回视频设备名列表
  244. void CVideoPlay::FindDevice(CStringList &DevName)
  245. {
  246.     HRESULT hr;
  247. int uIndex=0;
  248. //创建一个系统设备枚举器接口
  249. ICreateDevEnum *pCreateDevEnum;  
  250. hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  251.   IID_ICreateDevEnum, (void**)&pCreateDevEnum);  
  252. //创建一个类型枚举器,指向系统的视频设备列表
  253.     IEnumMoniker *pEm;  
  254.     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
  255. &pEm, 0);
  256.     HELPER_RELEASE(pCreateDevEnum);
  257. if(pEm)
  258. {
  259. pEm->Reset();
  260. ULONG cFetched;
  261. IMoniker *pM;
  262. //枚举每个视频设备
  263. while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
  264. {
  265. IPropertyBag *pBag;
  266. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  267. if(SUCCEEDED(hr)) 
  268. {
  269. VARIANT var;
  270. var.vt = VT_BSTR;
  271. //得到视频设备的友好名称
  272. hr = pBag->Read(L"FriendlyName", &var, NULL);
  273. if (hr == NOERROR)
  274. {
  275. CString achName;
  276. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, achName.GetBuffer(50),80,NULL, NULL);
  277. achName.ReleaseBuffer();
  278. //将设备名添加到设备名列表末尾
  279. DevName.AddTail(achName);
  280. SysFreeString(var.bstrVal);
  281. }
  282.    HELPER_RELEASE(pBag);
  283.   
  284. }
  285. HELPER_RELEASE(pM);
  286. uIndex++;
  287. }
  288.     HELPER_RELEASE(pEm);
  289. }
  290. }
  291. CVideoPlay::CVideoPlay()
  292. {
  293.    pigb  = NULL;
  294.    pimc  = NULL;
  295.    pimex = NULL;
  296.    pivw  = NULL;
  297.    pmp   = NULL;
  298.    pVCap = NULL;
  299.    CappFg = NULL;
  300.    CapPigb = NULL;
  301. }