Capture.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:61k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2.  *  Openmysee
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19. #include "stdafx.h"
  20. #include <atlbase.h>
  21. #include <dmodshow.h>
  22. #include <qedit.h>
  23. #include "capture.h"
  24. #include "utilities.h"
  25. #include "audiocompressselectordlg.h"
  26. #include "GVCaptureDlg.h"
  27. #include "audiochangeddlg.h"
  28. #include "videochanged.h"
  29. #include "SysConfig.h"
  30. #include "wmcodecconst.h"
  31. #include "VideoEncParams.h"
  32. #include "macros.h"
  33. #include "videoenc.h"
  34. #include "streams.h"
  35. #pragma comment(lib,"Dmoguids")
  36. #pragma comment(lib,"Winmm")
  37. //static const GUID CLSID_TVStreamSink = 
  38. //{ 0x1860c8d5, 0x370b, 0x4334, { 0x99, 0xf1, 0xb7, 0xc, 0x37, 0x9f, 0xac, 0x67 } };
  39. // {C2B146BB-C61D-4673-AF41-5079E6855401}
  40. static const GUID CLSID_TVStreamSink = 
  41. { 0xc2b146bb, 0xc61d, 0x4673, { 0xaf, 0x41, 0x50, 0x79, 0xe6, 0x85, 0x54, 0x1 } };
  42. static const GUID CLSID_FVideoOverlay =
  43. {0xae1c4226, 0xb8ec, 0x4204,  { 0xbf, 0x15, 0x92, 0x56, 0x63, 0xde, 0x51, 0x68} };
  44. //用于WM9的外部变量
  45. extern CVideoEncParams g_VideoEncodingParams;
  46. //////////////////////////////////////////////////////////////////////////
  47. //以下是构造和析构函数
  48. //////////////////////////////////////////////////////////////////////////
  49. CCaptureGraph::CCaptureGraph()
  50. {
  51. m_config = FALSE;
  52. state = NULL;
  53. sstate = 0;
  54. m_RefCount = 0;
  55. m_pGB = NULL;         // capture graph
  56. m_pVW = NULL;          // video window
  57. m_pMC = NULL;         // media control
  58. m_pTVConfig = NULL; // tv sink config
  59. // filters in graph 
  60. m_pVideoCapture = NULL;
  61. m_pVideoEncoder = NULL;
  62. m_pAudioEncoder = NULL;
  63. m_pAudioCapture = NULL;
  64. m_pTVStreamSink = NULL;
  65. m_pVideoSmartTee = NULL;
  66. m_pAudioSmartTee = NULL;
  67. m_pAVIMuxer = NULL;
  68. m_pFileWriter = NULL;
  69. m_pftrDVSpliter = NULL;
  70. m_pDVDecoder = NULL;
  71. //xiezhouwei 05-08-17添加
  72. m_pVideoOverlay = NULL;
  73. m_arrayOtherFilter.RemoveAll();
  74. m_bGraphBuiled = FALSE; 
  75. m_bIsPreview = TRUE;
  76. m_bIsOnlyAudio = FALSE;
  77. m_bSave = FALSE; // added by zk for saving 2004-04-16
  78. m_bNeedOverlay = TRUE;
  79. mbIsDV = FALSE; //added by xiezhouwei 2005-09-01
  80. m_bISCrossBar = FALSE; //默认不选择CrossBar
  81. m_strCurVideoEncoder.Empty();
  82. m_pCurAudioAMT = NULL;
  83. m_hWndOwner = NULL;
  84. ZeroMemory(m_szAVIFile,sizeof(m_szAVIFile));
  85. }
  86. CCaptureGraph::~CCaptureGraph()
  87. {
  88. Uninitialize();
  89. }
  90. STDMETHODIMP_(ULONG) CCaptureGraph::AddRef()
  91. {
  92. return ++m_RefCount;
  93. }
  94. STDMETHODIMP_(ULONG) CCaptureGraph::Release()
  95. {
  96. m_RefCount--;
  97. if(m_RefCount == 0)
  98. delete this;
  99. return m_RefCount;
  100. }
  101. STDMETHODIMP CCaptureGraph::QueryInterface(REFIID iid, void** ppInter)
  102. {
  103. // we need not to implement this now
  104. // it only for late_use
  105. return E_NOTIMPL;
  106. }
  107. STDMETHODIMP CCaptureGraph::Initialize()
  108. {
  109. HRESULT hr = CoInitialize(NULL);
  110. if (FAILED(hr))
  111. {
  112. TRACE0("ERROR - Could not initialize COM library");
  113. return hr;
  114. }
  115. // Create the filter graph manager and query for interfaces.
  116. hr = CoCreateInstance(CLSID_FilterGraph, 
  117. NULL, 
  118. CLSCTX_INPROC_SERVER, 
  119. IID_IGraphBuilder, 
  120. (void **)&m_pGB);
  121. if (FAILED(hr))
  122. {
  123. TRACE0("ERROR - Could not create the Filter Graph Manager.");
  124. return hr;
  125. }
  126. hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  127. if (FAILED(hr))
  128. {
  129. TRACE0("ERROR - Could not Get IMediaControl");
  130. return hr;
  131. }
  132. // for DEBUG
  133. #ifdef _DEBUG
  134. AddGraphToRot(m_pGB, &g_dwRegister);
  135. #endif //_DEBUG
  136. return S_OK;
  137. }
  138. STDMETHODIMP CCaptureGraph::Uninitialize()
  139. {
  140. // first unDEBUG
  141. #ifdef _DEBUG
  142. RemoveGraphFromRot(g_dwRegister);
  143. #endif //_DEBUG
  144. RemoveFilter(m_pVideoCapture);
  145. RemoveFilter(m_pAudioCapture);
  146. RemoveFilter(m_pVideoEncoder);
  147. RemoveFilter(m_pAudioEncoder);
  148. RemoveFilter(m_pVideoSmartTee);
  149. RemoveFilter(m_pAudioSmartTee);
  150. RemoveFilter(m_pTVStreamSink);
  151. RemoveFilter(m_pVideoOverlay);
  152. RemoveFilter(m_pAVIMuxer);
  153. RemoveFilter(m_pFileWriter);
  154. RemoveFilter(m_pDVDecoder);
  155. state = NULL;
  156. SAFE_RELEASE(m_pGB);
  157. SAFE_RELEASE(m_pVW);
  158. SAFE_RELEASE(m_pMC);
  159. // SAFE_RELEASE(m_pTVConfig);
  160. // filters in graph 
  161. SAFE_RELEASE(m_pVideoCapture);
  162. SAFE_RELEASE(m_pVideoEncoder);
  163. SAFE_RELEASE(m_pAudioEncoder);
  164. SAFE_RELEASE(m_pAudioCapture);
  165. // SAFE_RELEASE(m_pTVStreamSink);
  166. SAFE_RELEASE(m_pVideoSmartTee);
  167. SAFE_RELEASE(m_pAudioSmartTee);
  168. SAFE_RELEASE(m_pAVIMuxer);
  169. SAFE_RELEASE(m_pFileWriter);
  170. SAFE_RELEASE(m_pVideoOverlay);
  171. SAFE_RELEASE(m_pDVDecoder);
  172. m_hWndOwner = NULL;
  173. CoUninitialize();
  174. return S_OK;
  175. }
  176. // controls
  177. STDMETHODIMP CCaptureGraph::Run()
  178. {
  179. HRESULT hr;
  180. if(!m_bGraphBuiled)
  181. {
  182. if(FAILED(BuildGraph()))
  183. {
  184. DisassembleGraph();
  185. return E_FAIL;
  186. }
  187. }
  188. CComPtr <IVideoWindow> lpVideoWindow;
  189. hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
  190. if (FAILED(hr))
  191. {
  192. return hr;
  193. }
  194. hr = lpVideoWindow->put_Visible(OATRUE);
  195. ASSERT(m_pMC);
  196. return m_pMC->Run();
  197. }
  198. STDMETHODIMP CCaptureGraph::Stop()
  199. {
  200. HRESULT hr;
  201. ASSERT(m_pMC);
  202. CComPtr <IVideoWindow> lpVideoWindow;
  203. hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
  204. if (FAILED(hr))
  205. {
  206. return hr;
  207. }
  208. hr = lpVideoWindow->put_AutoShow(OAFALSE);
  209. hr = lpVideoWindow->put_Visible(OAFALSE);
  210. return m_pMC->Stop();
  211. }
  212. STDMETHODIMP CCaptureGraph::Pause()
  213. {
  214. ASSERT(m_pMC);
  215. return m_pMC->Pause();
  216. }
  217. // enums,it respectively call EnumSpeciFilters
  218. // with diffrent specification
  219. STDMETHODIMP CCaptureGraph::EnumVideoCapDevices(CStringArray &strArrayType)
  220. {
  221. return EnumSpeciFilters(VIDEO_CAP, strArrayType);
  222. }
  223. STDMETHODIMP CCaptureGraph::EnumAudioCapDevices(CStringArray &strArrayType)
  224. {
  225.     return EnumSpeciFilters(AUDIO_CAP, strArrayType);
  226. }
  227. STDMETHODIMP CCaptureGraph::EnumVideoEncoders(CStringArray &strArrayType)
  228. {
  229. return EnumSpeciFilters(VIDEO_COMPRESS, strArrayType);
  230. }
  231. STDMETHODIMP CCaptureGraph::EnumAudioEncoders(CStringArray &strArrayType)
  232. {
  233. return EnumSpeciFilters(AUDIO_COMPRESS, strArrayType);
  234. }
  235. // configs
  236. STDMETHODIMP CCaptureGraph::ConfigVideoCapDeviceByName(HWND hParent)
  237. {
  238. if (NULL == m_pVideoCapture)
  239. {
  240. AfxMessageBox("视频采集设备未找到");
  241. return S_OK;
  242. }
  243. // must be added in the graph this time
  244. m_pGB->AddFilter(m_pVideoCapture, NULL);
  245. /*
  246. * FIRST: prompt user to set filter configuration
  247. */
  248. // Get property page interface 
  249. HRESULT hr;
  250. IAMVfwCaptureDialogs* pDlg;
  251. hr = m_pVideoCapture->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)(&pDlg));
  252. if(!FAILED(hr))
  253. {
  254. if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Format)))
  255. {
  256. hr = pDlg->ShowDialog(VfwCaptureDialog_Format, hParent);
  257. }
  258. if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Source)))
  259. {
  260. hr = pDlg->ShowDialog(VfwCaptureDialog_Source, hParent);
  261. }
  262. if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Display)))
  263. {
  264. hr = pDlg->ShowDialog(VfwCaptureDialog_Display, hParent);
  265. }
  266. return hr;
  267. }
  268. ISpecifyPropertyPages *pSpec;
  269. hr = m_pVideoCapture->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
  270. if(FAILED(hr))
  271. {
  272. return E_FAIL;
  273. }
  274. // Popup page
  275. CString str(_T("Video Capture Configuration 1")); // dlg caption
  276. WCHAR wstrCaption[256];
  277. CAUUID cauuid;
  278. pSpec->GetPages(&cauuid);
  279. pSpec->Release();
  280. if(cauuid.cElems >= 1)
  281. {
  282. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  283. str.GetBuffer(str.GetLength()), -1, 
  284. wstrCaption, sizeof(wstrCaption) / sizeof(WCHAR));
  285. hr = OleCreatePropertyFrame(hParent, 30, 30, wstrCaption, 1,
  286. (IUnknown **)&m_pVideoCapture, cauuid.cElems,
  287. (GUID *)cauuid.pElems, 0, 0, NULL);
  288. if(FAILED(hr))
  289. {
  290. CoTaskMemFree(cauuid.pElems);
  291. pSpec->Release();
  292. return E_FAIL;
  293. }
  294. }
  295. // Destructor
  296. CoTaskMemFree(cauuid.pElems);
  297. return S_OK;
  298. }
  299. // configs
  300. STDMETHODIMP CCaptureGraph::ConfigAudioCapDeviceByName(HWND hParent)
  301. {
  302.     if (NULL == m_pAudioCapture)
  303.     {
  304.         AfxMessageBox("视频采集设备未找到");
  305.         return S_OK;
  306.     }
  307.     // must be added in the graph this time
  308.     m_pGB->AddFilter(m_pAudioCapture, NULL);
  309.     /*
  310.     * FIRST: prompt user to set filter configuration
  311.     */
  312.     // Get property page interface 
  313.     HRESULT hr;
  314.     IAMVfwCaptureDialogs* pDlg;
  315.     hr = m_pAudioCapture->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)(&pDlg));
  316.     if(!FAILED(hr))
  317.     {
  318.         if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Format)))
  319.         {
  320.             hr = pDlg->ShowDialog(VfwCaptureDialog_Format, hParent);
  321.         }
  322.         if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Source)))
  323.         {
  324.             hr = pDlg->ShowDialog(VfwCaptureDialog_Source, hParent);
  325.         }
  326.         if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Display)))
  327.         {
  328.             hr = pDlg->ShowDialog(VfwCaptureDialog_Display, hParent);
  329.         }
  330.         return hr;
  331.     }
  332.     ISpecifyPropertyPages *pSpec;
  333.     hr = m_pAudioCapture->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
  334.     if(FAILED(hr))
  335.     {
  336.         return E_FAIL;
  337.     }
  338.     // Popup page
  339.     CString str(_T("Audio Capture Configuration 1")); // dlg caption
  340.     WCHAR wstrCaption[256];
  341.     CAUUID cauuid;
  342.     pSpec->GetPages(&cauuid);
  343.     pSpec->Release();
  344.     if(cauuid.cElems >= 1)
  345.     {
  346.         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  347.             str.GetBuffer(str.GetLength()), -1, 
  348.             wstrCaption, sizeof(wstrCaption) / sizeof(WCHAR));
  349.         hr = OleCreatePropertyFrame(hParent, 30, 30, wstrCaption, 1,
  350.             (IUnknown **)&m_pAudioCapture, cauuid.cElems,
  351.             (GUID *)cauuid.pElems, 0, 0, NULL);
  352.         if(FAILED(hr))
  353.         {
  354.             CoTaskMemFree(cauuid.pElems);
  355.             pSpec->Release();
  356.             return E_FAIL;
  357.         }
  358.     }
  359.     // Destructor
  360.     CoTaskMemFree(cauuid.pElems);
  361.     return S_OK;
  362. }
  363. //Arthur?
  364. bool isEqualFOURCC(FOURCC fccA, FOURCC fccB) {
  365. int i;
  366. for(i=0; i<4; i++) {
  367. if (tolower((unsigned char)fccA) != tolower((unsigned char)fccB))
  368. return false;
  369. fccA>>=8;
  370. fccB>>=8;
  371. }
  372. return true;
  373. }
  374. ////////////////
  375. HIC hic=0;
  376. BYTE *pState = NULL;
  377. int size = 0;
  378. ICINFO in;
  379. STDMETHODIMP CCaptureGraph::ConfigVideoEncoderByName(HWND hParent)
  380. {
  381. HRESULT hr;
  382. if (NULL == m_pVideoEncoder)
  383. {
  384. return E_FAIL;
  385. }
  386. if (NULL == hParent)
  387. {
  388. AfxMessageBox("hParent不能为空");
  389. }
  390. hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
  391. if (FAILED(hr))
  392. {
  393. return E_FAIL;
  394. }
  395. if (TRUE == IsDMOFilter())
  396. {
  397. return S_OK;
  398. }
  399. //ASSERT(m_pVideoEncoder);
  400. if(hic)
  401. {
  402. ICClose(hic);
  403. TRACE("hic值为:%d",hic);
  404. }
  405. //Arthur:?将压缩信息中ICTYPE_VIDEO进行枚举。若能打开则取出他的信息。
  406. //判断它的描述信息是否和当前的m_strCurVideoEncoder一致。一致则显示配置
  407. //配置信息框。(若pState中有可设置的值。则将之,设入。?是否会将上次的
  408. //pState设置到这次的hic中去。)再用ICGetState得到信息。再将之设回去??
  409. //何必呢?并将之保存在state变量中。
  410. //一切连接好后,若用户选择马上中断则会,将全部filter移出。若不是则将之
  411. //移出后再立刻接上会不会有问题,是否执行了重定位操作。
  412. ICINFO info;
  413. for(int i=0; ICInfo(ICTYPE_VIDEO, i, &info); i++)//Arthur:该函数的用法逐步取出i个ICINFO结构。
  414. {
  415. hic = ICOpen(info.fccType, info.fccHandler, ICMODE_COMPRESS);//Arthur:打开该压缩器。
  416. if(hic == NULL)
  417. continue;
  418. ICINFO ici = { sizeof(ICINFO) };
  419. CHAR* lpszDes;
  420. if (ICGetInfo(hic, &ici, sizeof(ICINFO)))//Arthur:得到该压缩器。并将描述信息放入
  421. //lpszDes中
  422. {
  423. int cch = lstrlenW(ici.szDescription) + 1;
  424. lpszDes = new char[cch * 2];
  425. if (!lpszDes)
  426. {
  427. AfxMessageBox("开辟描述名buf失败");
  428. return E_OUTOFMEMORY;
  429. }
  430. WideCharToMultiByte(GetACP(), 0, ici.szDescription, 
  431. -1,lpszDes, cch, NULL, NULL); 
  432. }
  433. if(CString(lpszDes) == m_strCurVideoEncoder)//若取出的,是自己要的
  434. {
  435. if(ICQueryConfigure(hic))
  436. {
  437. if (state)
  438. ICSetState(hic, state, sstate);
  439. if (NULL == hParent || 0 == hic)
  440. {
  441. AfxMessageBox("父窗口指针为空,无法显示");
  442. return E_FAIL;
  443. }
  444. ICConfigure(hic, hParent);//Arthur:显示该压缩码的对话框。
  445. if(pState)
  446. delete [] pState;
  447. size = ICGetStateSize(hic);
  448. pState = new BYTE[size];
  449. if (0 == hic || NULL == pState)
  450. {
  451. AfxMessageBox("pState为零");
  452. return E_FAIL;
  453. }
  454. int nt = ICGetState(hic, pState, size);//Arthur:得到hic此时的状态信息
  455. if(nt > 0)
  456. {
  457. m_config = TRUE;
  458. if (NULL == state)
  459. {
  460. state=new BYTE[size + 1];
  461. if (NULL == state)
  462. {
  463. AfxMessageBox("State为零");
  464. return E_FAIL;
  465. }
  466. }
  467. ICSetState(hic, pState, size);//为什么要重新设置一次,此时pState的信息已经是完善了的。
  468. memcpy(state,pState,size);
  469. sstate=size;
  470. }
  471. }
  472. if (lpszDes)
  473. {
  474. delete [] lpszDes;
  475. }
  476. break;
  477. }
  478. ICClose(hic);
  479. hic = 0;
  480. if (lpszDes)
  481. {
  482. delete [] lpszDes;
  483. }
  484. }
  485. OAFilterState ofs;
  486. m_pMC->GetState(1000, &ofs);
  487. if(ofs == State_Running)
  488. {
  489. CVideoChanged vc;
  490. if(vc.DoModal() == IDOK)
  491. {
  492. CWnd wd;
  493. wd.Attach(m_hWndOwner);
  494. ((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
  495. DisassembleGraph();
  496. ((CGVCaptureDlg*)wd.GetParent())->OnNotifyPlay();
  497. wd.Detach();
  498. }
  499. }
  500. else
  501. {
  502. if(m_bGraphBuiled)
  503. {
  504. DisassembleGraph();
  505. if(FAILED(BuildGraph()))
  506. {
  507. DisassembleGraph();
  508. return E_FAIL;
  509. }
  510. }
  511. }
  512. return S_OK;
  513. }
  514. STDMETHODIMP CCaptureGraph::ConfigAudioEncoderByName(HWND hParent)
  515. {
  516. if (NULL == m_pAudioEncoder)
  517. {
  518. return E_FAIL;
  519. }
  520. if (NULL == m_hWndOwner)
  521. {
  522. AfxMessageBox("m_hWndOwner不能为空");
  523. }
  524. CWnd wnd;
  525. wnd.Attach(m_hWndOwner);
  526. CAudioCompressSelectorDlg afs(this, &wnd);
  527. if(afs.DoModal()== IDOK)
  528. {
  529. OAFilterState ofs;
  530. m_pMC->GetState(1000, &ofs);
  531. if(ofs == State_Running)
  532. {
  533. CAudioChangedDlg vc;
  534. if(vc.DoModal() == IDOK)
  535. {
  536. AfxMessageBox("不可能执行的代码");
  537. ((CGVCaptureDlg*)wnd.GetParent())->OnNotifyStop();
  538. DisassembleGraph();
  539. ((CGVCaptureDlg*)wnd.GetParent())->OnNotifyPlay();
  540. }
  541. }
  542. else
  543. {
  544. if(m_bGraphBuiled)
  545. {
  546. DisassembleGraph();
  547. if(FAILED(BuildGraph()))
  548. {
  549. wnd.Detach();
  550. DisassembleGraph();
  551. return E_FAIL;
  552. }
  553. }
  554. }
  555. }
  556. wnd.Detach();
  557. return S_OK;
  558. }
  559. //系统设置框
  560. STDMETHODIMP CCaptureGraph::ConfigSysCfg(HWND hParent)
  561. {
  562. CSysConfig afs;
  563. afs.DoModal();
  564. return S_OK;
  565. }
  566. // some filter creations must be implemented by enumulator
  567. // implemented with FindFilterByName auxily function
  568. HRESULT CCaptureGraph::CreateVideoCapDeviceFilterByName(LPTSTR strName)
  569. {
  570. // here we disassamble the graph
  571. if (m_bGraphBuiled)
  572. {
  573. DisassembleGraph();
  574. }
  575. RemoveFilter(m_pVideoCapture);
  576. SAFE_RELEASE(m_pVideoCapture);
  577. FindFilterByName(strName, &m_pVideoCapture, VIDEO_CAP);
  578. if(m_pVideoCapture == NULL)
  579. {
  580. TRACE0("no this filte in system");
  581. return S_FALSE;
  582. }
  583. return NOERROR;
  584. }
  585. // some filter creations must be implemented by enumulator
  586. // implemented with FindFilterByName auxily function
  587. HRESULT CCaptureGraph::CreateAudioCapDeviceFilterByName(LPTSTR strName)
  588. {
  589.     // here we disassamble the graph
  590.     if (m_bGraphBuiled)
  591.     {
  592.         DisassembleGraph();
  593.     }
  594.     RemoveFilter(m_pAudioCapture);
  595.     SAFE_RELEASE(m_pAudioCapture);
  596.     FindFilterByName(strName, &m_pAudioCapture, AUDIO_CAP);
  597.     if(m_pAudioCapture == NULL)
  598.     {
  599.         TRACE0("no this filte in system");
  600.         return S_FALSE;
  601.     }
  602.     return NOERROR;
  603. }
  604. BOOL CCaptureGraph::IsDMOFilter()
  605. {
  606. HRESULT hr;
  607. IDMOWrapperFilter *pDmoWrapper;
  608. hr = m_pVideoEncoder->QueryInterface(IID_IDMOWrapperFilter, (void**)&pDmoWrapper);
  609. if (SUCCEEDED(hr)) 
  610. {
  611. return TRUE;
  612. }
  613. return FALSE;
  614. }
  615. STDMETHODIMP CCaptureGraph::BuildVideoDMOEncoder()
  616. {
  617. AM_MEDIA_TYPE mtIn, mtOut;
  618. mtIn.majortype = MEDIATYPE_Video; //set this for the call to "Connect Filters"
  619. mtIn.cbFormat = 0;
  620. GetInputMediaType(m_pVideoCapture, mtIn); //S_FALSE is ok here
  621. // now connect these filters and render them
  622. if (NULL == m_pVideoOverlay)
  623. {
  624. if(FAILED(ConnectPins(m_pVideoCapture, NULL, m_pVideoEncoder, NULL, &mtIn)))
  625. {
  626. AfxMessageBox("不能进行播放,请重新选择视频编码器。");
  627. return E_FAIL;
  628. }
  629. }
  630. else
  631. {
  632. if(FAILED(ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL, &mtIn)))
  633. {
  634. AfxMessageBox("不能进行播放,请重新选择视频编码器。");
  635. return E_FAIL;
  636. }
  637. }
  638. CComQIPtr<IMediaObject, &IID_IMediaObject> pDMO(m_pVideoEncoder);
  639. ConfigureDMO(pDMO, &mtIn, &mtOut);
  640. // Get Wrapper's output pin
  641. IPin* pOutPin = FindPinOnFilter( m_pVideoEncoder, NULL, PINDIR_OUTPUT );
  642. if(pOutPin == NULL)
  643. {
  644. TRACE("Failed to get wrapper's output pin!");
  645. return E_FAIL;
  646. }
  647. // Set the output media type
  648. CComQIPtr<IAMStreamConfig, &IID_IAMStreamConfig> pIAMStreamConfig( pOutPin );    
  649. ON_QI_FAIL("Failed to QI for IAMStreamConfig!", pIAMStreamConfig)
  650. // Set the media type
  651. HRESULT hr = pIAMStreamConfig->SetFormat( &mtOut );
  652. ON_FAIL("Failed to set wrapper's output type!", hr)
  653. FreeMediaType(mtIn);
  654. FreeMediaType(mtOut);
  655. return S_OK;
  656. }
  657. HRESULT CCaptureGraph::CreateV9EncoderFilter()
  658. {
  659. // here we disassamble the graph
  660. // DisassembleGraph();
  661. HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pVideoEncoder);
  662. if (SUCCEEDED(hr)) 
  663. {
  664. // Query for IDMOWrapperFilter.
  665. IDMOWrapperFilter *pDmoWrapper;
  666. hr = m_pVideoEncoder->QueryInterface(IID_IDMOWrapperFilter, (void**)&pDmoWrapper);
  667. if (SUCCEEDED(hr)) 
  668. {     
  669. // Initialize the filter.
  670. hr = pDmoWrapper->Init(CLSID_CWMVEncMediaObject2, CLSID_VideoCompressorCategory); 
  671. pDmoWrapper->Release();
  672. if (SUCCEEDED(hr)) 
  673. {
  674. // Add the filter to the graph.
  675. hr = m_pGB->AddFilter(m_pVideoEncoder, L"My DMO");
  676. }
  677. }
  678. }
  679. return hr;
  680. }
  681. HRESULT CCaptureGraph::CreateVideoEncoderFilterByName(LPTSTR strName)
  682. {
  683. // here we disassamble the graph
  684. if (NULL == strName)
  685. {
  686. AfxMessageBox("Filter名称为空");
  687. return E_FAIL;
  688. }
  689. if (m_bGraphBuiled)
  690. {
  691. DisassembleGraph();
  692. }
  693. RemoveFilter(m_pVideoEncoder);
  694. SAFE_RELEASE(m_pVideoEncoder);
  695. if (0 == strcmp(strName, "MicroSoft Media 9 DMO"))
  696. {
  697. CreateV9EncoderFilter();
  698. }
  699. else
  700. {
  701. FindFilterByName(strName, &m_pVideoEncoder, VIDEO_COMPRESS);
  702. }
  703. if(m_pVideoEncoder == NULL)
  704. {
  705. TRACE0("no this filte in system");
  706. return S_FALSE;
  707. }
  708. m_strCurVideoEncoder = strName;
  709. return NOERROR;
  710. }
  711. HRESULT CCaptureGraph::CreateAudioEncoderFilterByName(LPTSTR strName)
  712. {
  713. // here we disassamble the graph
  714. if (NULL == strName)
  715. {
  716. AfxMessageBox("Filter名称为空");
  717. return E_FAIL;
  718. }
  719. if (m_bGraphBuiled)
  720. {
  721. DisassembleGraph();
  722. }
  723. RemoveFilter(m_pAudioEncoder);
  724. SAFE_RELEASE(m_pAudioEncoder);
  725. FindFilterByName(strName, &m_pAudioEncoder, AUDIO_COMPRESS);
  726. if (m_pAudioEncoder == NULL)
  727. {
  728. TRACE0("no this filte in system");
  729. return S_FALSE;
  730. }
  731. if(m_pCurAudioAMT)
  732. {
  733. HeapFree(GetProcessHeap(), 0, m_pCurAudioAMT);
  734. m_pCurAudioAMT = NULL;
  735. }
  736. return NOERROR;
  737. }
  738. //xiezhouwei 05-08-17 添加
  739. /*
  740. // 设置是否需要字幕的
  741. void CCaptureGraph::SetNeedOverlay(bool abNeedOverlay)
  742. {
  743. m_bNeedOverlay = abNeedOverlay;
  744. }
  745. */
  746. //初始化字幕Filter
  747. HRESULT CCaptureGraph::CreateUideoOverlay()
  748. {
  749. HRESULT hr;
  750. hr = CoCreateInstance(CLSID_FVideoOverlay, 
  751. NULL, 
  752. CLSCTX_INPROC, 
  753. IID_IBaseFilter,
  754. (void **)&m_pVideoOverlay);
  755. if(FAILED(hr))
  756. {
  757. TRACE("Could not instantiate VideoOverlay filter");
  758. }
  759. return hr;
  760. }
  761. //配置字幕property。
  762. HRESULT CCaptureGraph::ConfigVideoOverlay(HWND hParent)
  763. {
  764. ASSERT(m_pVideoOverlay);
  765. HRESULT hr;
  766. ISpecifyPropertyPages *pSpec;
  767. hr = m_pVideoOverlay->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
  768. if(FAILED(hr))
  769. {
  770. return E_FAIL;
  771. }
  772. // Popup page
  773. CAUUID cauuid;
  774. pSpec->GetPages(&cauuid);
  775. if(cauuid.cElems >= 1)
  776. {
  777. hr = OleCreatePropertyFrame(NULL, 30, 30, /*wstrCaption*/NULL, 1,
  778. (IUnknown **)&pSpec, cauuid.cElems,
  779. (GUID *)cauuid.pElems, 0, 0, NULL);
  780. if(FAILED(hr))
  781. {
  782. CoTaskMemFree(cauuid.pElems);
  783. pSpec->Release();
  784. return hr;
  785. }
  786. }
  787. // Destructor
  788. CoTaskMemFree(cauuid.pElems);
  789. pSpec->Release();
  790. return hr;
  791. }
  792. //释放掉字幕filter
  793. void CCaptureGraph::ReleaseUideoOverlay()
  794. {
  795. //DisassembleGraph();
  796. if (TRUE == m_bGraphBuiled)
  797. {
  798. DisassembleGraph();
  799. }
  800. RemoveFilter(m_pVideoOverlay);
  801. SAFE_RELEASE(m_pVideoOverlay);
  802. }
  803. // preview
  804. VOID CCaptureGraph::SetPreview(BOOL bIsPreview)
  805. {
  806. if(m_bGraphBuiled)
  807. {
  808. if(bIsPreview)
  809. {
  810. m_pVW->put_Owner((OAHWND)m_hWndOwner);
  811. m_pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  812. CRect rc;
  813. GetClientRect(m_hWndOwner, &rc);
  814. m_pVW->put_Top(0);
  815. m_pVW->put_Left(0);
  816. m_pVW->put_Width(rc.Width());
  817. m_pVW->put_Height(rc.Height());
  818. m_pVW->put_Visible(-1);
  819. m_pVW->put_AutoShow(-1);
  820. }
  821. else
  822. {
  823. m_pVW->put_Visible(0);
  824. m_pVW->put_AutoShow(0);
  825. m_pVW->put_Owner(NULL);
  826. }
  827. }
  828. m_bIsPreview = bIsPreview;
  829. }
  830. void CCaptureGraph::SetOnlyAudio( BOOL bIsOnlyAudio )
  831. {
  832. OAFilterState ofs;
  833. m_pMC->GetState(1000, &ofs);
  834. m_bIsOnlyAudio = bIsOnlyAudio;
  835. if(ofs == State_Running)
  836. {
  837. //将对wd的操作解除。因为在DisassembleGraph中会会做的,
  838. //如果不解除,因为attach操作不允许同时做两遍,会导致断言。
  839. CWnd wd;
  840. wd.Attach(m_hWndOwner);
  841. ((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
  842. DisassembleGraph();
  843. ((CGVCaptureDlg*)wd.GetParent())->OnNotifyPlay();
  844. wd.Detach();
  845. }
  846. else
  847. {
  848. if(m_bGraphBuiled)
  849. {
  850. DisassembleGraph();
  851. if(FAILED(BuildGraph()))
  852. DisassembleGraph();
  853. }
  854. }
  855. }
  856. STDMETHODIMP CCaptureGraph::AddFilter(CLSID clsidFilter,    
  857.   IBaseFilter** ppIFilter,
  858.   LPCTSTR pstrFilterName)
  859. {
  860. HRESULT hr;
  861. ASSERT(m_pGB);
  862. ASSERT(ppIFilter);
  863. (*ppIFilter) = NULL;
  864. // try to instantiate the filter
  865. hr = CoCreateInstance(clsidFilter, 
  866. NULL, 
  867. CLSCTX_INPROC, 
  868. IID_IBaseFilter,
  869. (LPVOID*)(ppIFilter));
  870. if(FAILED(hr))
  871. {
  872. TRACE("Could not instantiate filter");
  873. return hr;
  874. }
  875. // Check for unicode or not
  876. #ifndef _UNICODE
  877. if(pstrFilterName)
  878. {
  879. // not unicode, we need to unicodify the string
  880. WCHAR wstrFilterName[256];
  881. MultiByteToWideChar(CP_ACP, 
  882. MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  883. pstrFilterName,
  884. -1, 
  885. wstrFilterName, 
  886. sizeof(wstrFilterName) / sizeof(WCHAR));
  887. // try to add it to the filter graph
  888. hr = m_pGB->AddFilter(*ppIFilter, wstrFilterName);
  889. }
  890. else
  891. {
  892. // No filter name specified, cannot convert
  893. // try to add it to the filter graph
  894. hr = m_pGB->AddFilter(*ppIFilter, NULL);
  895. }
  896. #else
  897. // already unicode, no need to change anything
  898. // try to add it to the filter graph
  899. hr = m_pGB->AddFilter(*ppIFilter, pstrFilterName);
  900. #endif
  901. // check the result of the operation
  902. if(FAILED(hr))
  903. {
  904. TRACE("Could not add filter to filter graphn");
  905. // free the filter definitely
  906. (*ppIFilter)->Release();
  907. (*ppIFilter) = NULL;
  908. return hr;
  909. }
  910. // that's it
  911. return hr;
  912. }
  913. STDMETHODIMP CCaptureGraph::RemoveFilter(IBaseFilter* pIFilter)
  914. {
  915. HRESULT hr;
  916. // Parameters...
  917. if(!pIFilter)
  918. // DON'T return an error, this is expected
  919. return NOERROR;
  920. ASSERT(m_pGB);
  921. // Just remove it from the graph
  922. hr = m_pGB->RemoveFilter(pIFilter);
  923. // Check the result
  924. if(FAILED(hr))
  925. TRACE("Could not remove filter from filter graphn");
  926. return hr;
  927. }
  928. STDMETHODIMP CCaptureGraph::ConnectPins(IBaseFilter* pIFilterOutput, 
  929. LPCTSTR pstrPinNameOutput,
  930. IBaseFilter* pIFilterInput, 
  931. LPCTSTR pstrPinNameInput,
  932. AM_MEDIA_TYPE* pmt)
  933. {
  934. HRESULT hr;
  935. ASSERT(m_pGB);
  936. // Parameters...
  937. if((!pIFilterOutput) || (!pIFilterInput))
  938. {
  939. ASSERT(pIFilterOutput && pIFilterInput);
  940. TRACE("ConnectPins called with NULL parametern");
  941. return E_INVALIDARG;
  942. }
  943. // Find the first pin
  944. IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput, 
  945. pstrPinNameOutput,
  946. PINDIR_OUTPUT);
  947. if(!pIPinOutput)
  948. {
  949. ASSERT(pIPinOutput);
  950. return E_FAIL;
  951. }
  952. // Find the second pin
  953. IPin* pIPinInput = FindPinOnFilter(pIFilterInput,
  954. pstrPinNameInput,
  955. PINDIR_INPUT);
  956. if(!pIPinInput)
  957. {
  958. ASSERT(pIPinInput);
  959. // release the other pin
  960. pIPinOutput->Release();
  961. return E_FAIL;
  962. }
  963. if(FAILED(pIPinOutput->Disconnect()))
  964. {
  965. ASSERT(FALSE);
  966. return E_FAIL;
  967. }
  968. if(FAILED(pIPinInput->Disconnect()))
  969. {
  970. ASSERT(FALSE);
  971. return E_FAIL;
  972. }
  973. // Now just connect the two pins
  974. hr = m_pGB->ConnectDirect(pIPinOutput, pIPinInput, pmt);
  975. ASSERT(SUCCEEDED(hr));
  976. if(FAILED(hr))
  977. TRACE("Could not connect pins!");
  978. // Release the two pins and return the result
  979. pIPinOutput->Release();
  980. pIPinInput->Release();
  981. return hr;
  982. }
  983. //自动连接Filter
  984. STDMETHODIMP CCaptureGraph::ConnectAutoPins(IBaseFilter* pIFilterOutput, 
  985. LPCTSTR pstrPinNameOutput,
  986. IBaseFilter* pIFilterInput, 
  987. LPCTSTR pstrPinNameInput)
  988. {
  989. HRESULT hr;
  990. ASSERT(m_pGB);
  991. // Parameters...
  992. if((!pIFilterOutput) || (!pIFilterInput))
  993. {
  994. ASSERT(pIFilterOutput && pIFilterInput);
  995. TRACE("ConnectPins called with NULL parametern");
  996. return E_INVALIDARG;
  997. }
  998. // Find the first pin
  999. IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput, 
  1000. pstrPinNameOutput,
  1001. PINDIR_OUTPUT);
  1002. if(!pIPinOutput)
  1003. {
  1004. ASSERT(pIPinOutput);
  1005. return E_FAIL;
  1006. }
  1007. // Find the second pin
  1008. IPin* pIPinInput = FindPinOnFilter(pIFilterInput,
  1009. pstrPinNameInput,
  1010. PINDIR_INPUT);
  1011. if(!pIPinInput)
  1012. {
  1013. ASSERT(pIPinInput);
  1014. // release the other pin
  1015. pIPinOutput->Release();
  1016. return E_FAIL;
  1017. }
  1018. if(FAILED(pIPinOutput->Disconnect()))
  1019. {
  1020. ASSERT(FALSE);
  1021. return E_FAIL;
  1022. }
  1023. if(FAILED(pIPinInput->Disconnect()))
  1024. {
  1025. ASSERT(FALSE);
  1026. return E_FAIL;
  1027. }
  1028. // Now just connect the two pins
  1029. hr = m_pGB->Connect(pIPinOutput, pIPinInput);
  1030. ASSERT(SUCCEEDED(hr));
  1031. if(FAILED(hr))
  1032. TRACE("Could not connect pins!");
  1033. // Release the two pins and return the result
  1034. pIPinOutput->Release();
  1035. pIPinInput->Release();
  1036. return hr;
  1037. }
  1038. STDMETHODIMP_(BOOL) CCaptureGraph::IsConnected(IBaseFilter *pFilter,
  1039.    LPCTSTR pstrPinName, 
  1040.    PIN_DIRECTION pd)
  1041. {
  1042. ASSERT(m_pGB);
  1043. // Parameters...
  1044. if((!pFilter))
  1045. {
  1046. ASSERT(pFilter);
  1047. TRACE("ConnectPins called with NULL parametern");
  1048. return FALSE;
  1049. }
  1050. // Find the pin
  1051. IPin* pIPin = FindPinOnFilter(pFilter, 
  1052. pstrPinName,
  1053. pd);
  1054. if(!pIPin)
  1055. {
  1056. ASSERT(pIPin);
  1057. return FALSE;
  1058. }
  1059. IPin  *pNextPin = NULL;
  1060. pIPin->ConnectedTo(&pNextPin);
  1061. if(!pNextPin)
  1062. {
  1063. return FALSE;
  1064. }
  1065. pIPin->Release();
  1066. pNextPin->Release();
  1067. //That's it...
  1068. return TRUE;
  1069. }
  1070. STDMETHODIMP CCaptureGraph::DisconnectPin(IBaseFilter *pIFilter, 
  1071.   LPCTSTR pstrPinName,
  1072.   PIN_DIRECTION dir)
  1073. {
  1074. HRESULT hr;
  1075. ASSERT(m_pGB);
  1076. // Parameters...
  1077. if(!pIFilter)
  1078. // DON'T fail on this, it is expected
  1079. return NOERROR;
  1080. // Find the pin
  1081. IPin* pIPin = FindPinOnFilter(pIFilter, pstrPinName, dir);
  1082. if(!pIPin)
  1083. {
  1084. TRACE("Could not find specified filter pinn");
  1085. return E_FAIL;
  1086. }
  1087. // Find the pin it's connected to
  1088. IPin* pIPinConnected;
  1089. hr = pIPin->ConnectedTo(&pIPinConnected);
  1090. if((FAILED(hr)) || (!pIPinConnected))
  1091. {
  1092. // Function call failed, pin not connected, nothing to do!
  1093. pIPin->Release();
  1094. return NOERROR;
  1095. }
  1096. // Try to disconnect the input pin first
  1097. if (dir == PINDIR_INPUT)
  1098. {
  1099. // ok now disconnect both of them
  1100. hr = m_pGB->Disconnect(pIPin);
  1101. if(FAILED(hr))
  1102. {
  1103. // just forget everything
  1104. ASSERT(SUCCEEDED(hr));
  1105. pIPin->Release();
  1106. pIPinConnected->Release();
  1107. TRACE("Disconnect failed on input pinn");
  1108. return hr;
  1109. }
  1110. hr = m_pGB->Disconnect(pIPinConnected);
  1111. if(FAILED(hr))
  1112. {
  1113. ASSERT(SUCCEEDED(hr));
  1114. TRACE("Disconnect failed on output pinn");
  1115. }
  1116. }
  1117. else
  1118. {
  1119. // ok now disconnect both of them
  1120. hr = m_pGB->Disconnect(pIPinConnected);
  1121. if(FAILED(hr))
  1122. {
  1123. ASSERT(SUCCEEDED(hr));
  1124. // just forget everything
  1125. pIPin->Release();
  1126. pIPinConnected->Release();
  1127. TRACE("Disconnect failed on input pinn");
  1128. return hr;
  1129. }
  1130. hr = m_pGB->Disconnect(pIPin);
  1131. if(FAILED(hr))
  1132. {
  1133. ASSERT(SUCCEEDED(hr));
  1134. TRACE("Disconnect failed on output pinn");
  1135. }
  1136. }
  1137. // Just release the two pins and return last result
  1138. pIPin->Release();
  1139. pIPinConnected->Release();
  1140. return hr;
  1141. }
  1142. STDMETHODIMP_(IPin*) CCaptureGraph::FindPinOnFilter(IBaseFilter* pIFilter, 
  1143. LPCTSTR pstrPinName,
  1144. PIN_DIRECTION dir)
  1145. {
  1146. HRESULT     hr;
  1147. IEnumPins*  pIEnumPins;
  1148. IPin*       pIPin;
  1149. PIN_INFO    pi;
  1150. ASSERT(m_pGB);
  1151. // Parameters...
  1152. if(!pIFilter)
  1153. return NULL;
  1154. // Enumerate pins on the filter
  1155. hr = pIFilter->EnumPins(&pIEnumPins);
  1156. if(FAILED(hr))
  1157. // pin was not found!
  1158. return NULL;
  1159. // Loop till we find no more pins
  1160. IPin* pIPinFound = NULL;
  1161. while( (!pIPinFound) && (pIEnumPins->Next(1, &pIPin, NULL)==S_OK) )
  1162. {
  1163. // Is this the pin?
  1164. hr = pIPin->QueryPinInfo(&pi);
  1165. if(!FAILED(hr))
  1166. {
  1167. // check if it is the right direction
  1168. if(pi.dir == dir)
  1169. {
  1170. // Let the graph builder find the right filter
  1171. TCHAR strFoundPinName[256];
  1172. #ifndef _UNICODE
  1173. // not unicode, we need to de-unicodify the returned pin name
  1174. WideCharToMultiByte(CP_ACP, NULL,
  1175. pi.achName, -1,
  1176. strFoundPinName, sizeof(strFoundPinName),
  1177. NULL, NULL);
  1178. #else
  1179. // just make a copy of the string
  1180. lstrcpyn(strFoundPinName, pi.achName, sizeof(strFoundPinName));
  1181. #endif
  1182. // check if there is a pin name specified
  1183. if(!pstrPinName)
  1184. {
  1185. // no name specified, take the first pin found
  1186. pIPinFound = pIPin;
  1187. pIPinFound->AddRef();
  1188. }
  1189. // check if we have the right pin name
  1190. else if(lstrcmp(strFoundPinName, pstrPinName)==0)
  1191. {
  1192. // yes we have!
  1193. pIPinFound = pIPin;
  1194. pIPinFound->AddRef();
  1195. }
  1196. }
  1197. // release the PIN_INFO data
  1198. pi.pFilter->Release();
  1199. }
  1200. // release the IPin pointer
  1201. pIPin->Release();
  1202. }
  1203. // Finished with the enumerator, let it go (be free)
  1204. pIEnumPins->Release();
  1205. // Return whatever we have found
  1206. return pIPinFound;
  1207. }
  1208. STDMETHODIMP CCaptureGraph::BuildGraph()
  1209. {
  1210. HRESULT hr;
  1211. //添加TV Sink Filter
  1212. hr = AddFilter(CLSID_TVStreamSink, &m_pTVStreamSink);
  1213. if (FAILED(hr))
  1214. {
  1215. return hr;
  1216. }
  1217. hr = m_pTVStreamSink->Release();
  1218. //添加IID_ITVSouceConfig接口
  1219. hr = m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (VOID**)&m_pTVConfig);
  1220. if(FAILED(hr))
  1221. {
  1222. TRACE("cant Get the ITVConfig interface!!");
  1223. return hr;
  1224. }
  1225. //判断是否为DV设备将判断结果置为mbISDV的值若是DV则走DV的流程
  1226. JudgeDV();
  1227. //若为只有音频设备,则调TV Sink接口
  1228. if(m_bIsOnlyAudio)
  1229. {
  1230. m_pTVConfig->SetAudioOrVideoOnly(m_bIsOnlyAudio);
  1231. }
  1232. m_pTVConfig->Release();
  1233. //若为DV则调用DV的Graph
  1234. if (TRUE == mbIsDV)
  1235. {
  1236. hr = DisplayDV();//DisplayDV();
  1237. if (SUCCEEDED(hr))
  1238. {
  1239. m_bGraphBuiled = TRUE;
  1240. return hr;
  1241. }
  1242. return hr;
  1243. }
  1244. //若不是DV则调用一般的Graph
  1245. hr = BuildGeneralGraph();
  1246. if (SUCCEEDED(hr))
  1247. {
  1248. m_bGraphBuiled = TRUE;
  1249. return hr;
  1250. }
  1251. return hr;
  1252. // that's ok, we can run it!
  1253. //m_bGraphBuiled = TRUE;
  1254. //return S_OK;
  1255. }
  1256. STDMETHODIMP CCaptureGraph::DisassembleGraph()
  1257. {
  1258. HRESULT hr;
  1259. /*
  1260. // first must stop
  1261. if(m_hWndOwner != NULL)
  1262. {
  1263. CWnd wd;
  1264. wd.Attach(m_hWndOwner);
  1265. //((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
  1266. wd.Detach();
  1267. }
  1268. */
  1269. RemoveFilter(m_pVideoCapture);
  1270. RemoveFilter(m_pVideoEncoder);
  1271. RemoveFilter(m_pAudioCapture);
  1272. RemoveFilter(m_pAudioEncoder);
  1273. RemoveFilter(m_pTVStreamSink);
  1274. RemoveFilter(m_pVideoSmartTee);
  1275. RemoveFilter(m_pftrDVSpliter);
  1276. RemoveFilter(m_pDVDecoder);
  1277. for(int i = 0; i < m_arrayOtherFilter.GetSize(); i++)
  1278. {
  1279. IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
  1280. RemoveFilter(pFilter);
  1281. }
  1282. // added by zk for saving 2004-04-16
  1283. if(m_pVideoSmartTee)
  1284. RemoveFilter(m_pVideoSmartTee);
  1285. if(m_pAudioSmartTee)
  1286. RemoveFilter(m_pAudioSmartTee);
  1287. if(m_pAVIMuxer)
  1288. RemoveFilter(m_pAVIMuxer);
  1289. if(m_pFileWriter)
  1290. RemoveFilter(m_pFileWriter);
  1291. // release All filter in the graph except for 
  1292. // videocapture and videoencoder.these two filters will be
  1293. // deleted in create CreateCapDeviceFilterByName and 
  1294. // CreateEncoderFilterByNamer
  1295. SAFE_RELEASE(m_pAudioCapture);
  1296. // SAFE_RELEASE(m_pTVStreamSink);
  1297. SAFE_RELEASE(m_pVideoSmartTee);
  1298. SAFE_RELEASE(m_pAudioSmartTee);
  1299. // SAFE_RELEASE(m_pTVConfig);
  1300. SAFE_RELEASE(m_pftrDVSpliter);
  1301. SAFE_RELEASE(m_pDVDecoder);
  1302. for(i=0; i<m_arrayOtherFilter.GetSize(); i++)
  1303. {
  1304. IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
  1305. SAFE_RELEASE(pFilter);
  1306. }
  1307. m_arrayOtherFilter.RemoveAll();
  1308. m_bGraphBuiled = FALSE;
  1309. CComPtr <IVideoWindow> lpVideoWindow;
  1310. hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
  1311. if (FAILED(hr))
  1312. {
  1313. return hr;
  1314. }
  1315. hr = lpVideoWindow->put_Visible(OAFALSE);
  1316. return S_OK;
  1317. }
  1318. //  [10/6/2005] xiezhouwei 
  1319. void CCaptureGraph::JudgeDV()
  1320. {
  1321. HRESULT hr;
  1322. CComPtr<ICaptureGraphBuilder2> lpgraphBuilder2;
  1323. //获得graphBuilder2_
  1324. hr = lpgraphBuilder2.CoCreateInstance(CLSID_CaptureGraphBuilder2); 
  1325. if (FAILED(hr))
  1326. {
  1327. return ;
  1328. }
  1329. hr = lpgraphBuilder2->SetFiltergraph(m_pGB);
  1330. if (FAILED(hr))
  1331. {
  1332. return ;
  1333. }
  1334. //判断是否为DV设备,如果不是就照正常的进行采集,否则链路将要变。
  1335. IAMStreamConfig *pSC;
  1336. mbIsDV =FALSE; //首先假设不是DV设备
  1337. hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
  1338. &MEDIATYPE_Interleaved, m_pVideoCapture,
  1339. IID_IAMStreamConfig, (void **)&pSC);
  1340. if(hr != NOERROR)
  1341. hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
  1342. &MEDIATYPE_Video, m_pVideoCapture,
  1343. IID_IAMStreamConfig, (void **)&pSC);
  1344. if (!FAILED(hr))
  1345. {
  1346. AM_MEDIA_TYPE *pmt;
  1347. if(pSC && pSC->GetFormat(&pmt) == S_OK)
  1348. {
  1349. if(pmt->formattype == FORMAT_DvInfo)
  1350. {
  1351. mbIsDV = TRUE;
  1352. }
  1353. }
  1354. pSC->Release();
  1355. }
  1356. }
  1357. HRESULT CCaptureGraph::BuildGeneralAudio()
  1358. {
  1359. HRESULT hr;
  1360. hr = GetAudioCaptureDevice();
  1361. if (FAILED(hr))
  1362. {
  1363. return hr;
  1364. }
  1365. hr = m_pGB->AddFilter(m_pAudioCapture, NULL);
  1366. if (FAILED(hr))
  1367. {
  1368. return hr;
  1369. }
  1370. if (NULL == m_pAudioEncoder)
  1371. {
  1372. AfxMessageBox("请选择正确的音频解码器");
  1373. return E_FAIL;
  1374. }
  1375. hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
  1376. if (FAILED(hr))
  1377. {
  1378. return hr;
  1379. }
  1380. hr = ConnectPins(m_pAudioCapture, NULL, m_pAudioEncoder, NULL);
  1381. if (FAILED(hr))
  1382. {
  1383. AfxMessageBox("请选择正确的音频解码器");
  1384. return hr;
  1385. }
  1386. hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
  1387. if (FAILED(hr))
  1388. {
  1389. return hr;
  1390. }
  1391. hr = ConnectPins(m_pAudioEncoder, NULL, m_pAudioSmartTee,NULL);
  1392. if (FAILED(hr))
  1393. {
  1394. AfxMessageBox("音频部分构建出错");
  1395. return hr;
  1396. }
  1397. //[AudioSmartTee] -> [TVSink]
  1398. hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
  1399. if(FAILED(hr))
  1400. {
  1401. AfxMessageBox("不能进行播放,请重新选择音频编码器。");
  1402. return hr;
  1403. }
  1404. return hr;
  1405. }
  1406. //在VideoGraph中加入字幕Filter
  1407. HRESULT CCaptureGraph::AddVideoOverlayFilter()
  1408. {
  1409. HRESULT hr;
  1410. hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
  1411. if (FAILED(hr))
  1412. {
  1413. return hr;
  1414. }
  1415. hr = ConnectPins(m_pVideoCapture, NULL, m_pVideoOverlay, NULL);
  1416. if (FAILED(hr))
  1417. {
  1418. AfxMessageBox("连接字幕Filter出错");
  1419. return hr;
  1420. }
  1421. if (NULL == m_pVideoEncoder)
  1422. {
  1423. AfxMessageBox("视频编码器出错");
  1424. return E_FAIL;
  1425. }
  1426. hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
  1427. if (FAILED(hr))
  1428. {
  1429. return hr;
  1430. }
  1431. //如果是DMO组件
  1432. if (IsDMOFilter())
  1433. {
  1434. hr = BuildVideoDMOEncoder();
  1435. if (FAILED(hr))
  1436. {
  1437. return hr;
  1438. }
  1439. }
  1440. else
  1441. {
  1442. hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
  1443. if (FAILED(hr))
  1444. {
  1445. AfxMessageBox("视频编码器出错。请重新选择视频编码器");
  1446. return hr;
  1447. }
  1448. }
  1449. return hr;
  1450. }
  1451. //视频部分预览
  1452. HRESULT CCaptureGraph::BuildVideoPreview()
  1453. {
  1454. HRESULT hr;
  1455. CComPtr <IPin> lpPin = NULL; 
  1456. //pPreview = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"))
  1457. lpPin = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"));
  1458. if (lpPin == NULL)
  1459. {
  1460. AfxMessageBox("预览pin出错");
  1461. return E_FAIL;
  1462. }
  1463. hr = m_pGB->Render(lpPin);
  1464. CComPtr <IVideoWindow> lpVideoWindow;
  1465. hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
  1466. if (FAILED(hr))
  1467. {
  1468. return hr;
  1469. }
  1470. hr = lpVideoWindow->put_Owner((OAHWND)m_hWndOwner);
  1471. lpVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
  1472. CRect rc;
  1473. GetClientRect(m_hWndOwner, &rc);
  1474. lpVideoWindow->put_Top(0);
  1475. lpVideoWindow->put_Left(0);
  1476. lpVideoWindow->put_Width(rc.Width());
  1477. lpVideoWindow->put_Height(rc.Height());
  1478. lpVideoWindow->put_Visible(-1);
  1479. lpVideoWindow->put_AutoShow(-1);
  1480. return hr;
  1481. }
  1482. HRESULT CCaptureGraph::OpenCrossBar()
  1483. {
  1484. HRESULT hr;
  1485. CComPtr<IBaseFilter> pNULL;
  1486. hr = AddFilter(CLSID_NullRenderer, &pNULL);
  1487. if(FAILED(hr))
  1488. {
  1489. TRACE("cant add smarttee filter to graph");
  1490. return hr;
  1491. }
  1492. //获得lpgraphBuilder2_
  1493. CComPtr<ICaptureGraphBuilder2> lpgraphBuilder2_;
  1494. hr = lpgraphBuilder2_.CoCreateInstance(CLSID_CaptureGraphBuilder2);
  1495. if (FAILED(hr))
  1496. {
  1497. return hr;
  1498. }
  1499. hr = lpgraphBuilder2_->SetFiltergraph(m_pGB);
  1500. hr = lpgraphBuilder2_->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pVideoCapture, 0, pNULL );
  1501. hr = lpgraphBuilder2_->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCapture, 0, pNULL );
  1502. if (SUCCEEDED(hr))
  1503. {
  1504. IAMCrossbar *pX;
  1505. hr = lpgraphBuilder2_->FindInterface(&PIN_CATEGORY_CAPTURE,
  1506. &MEDIATYPE_Interleaved, m_pVideoCapture,
  1507. IID_IAMCrossbar, (void **)&pX);
  1508. if(FAILED(hr))
  1509. {
  1510. hr = lpgraphBuilder2_->FindInterface(&PIN_CATEGORY_CAPTURE,
  1511. &MEDIATYPE_Video, m_pVideoCapture,
  1512. IID_IAMCrossbar, (void **)&pX);
  1513. }
  1514. if (SUCCEEDED(hr))
  1515. {
  1516. ISpecifyPropertyPages *pSpec;
  1517. CAUUID cauuid;
  1518. hr = pX->QueryInterface(IID_ISpecifyPropertyPages,
  1519. (void **)&pSpec);
  1520. if(S_OK == hr)
  1521. {
  1522. hr = pSpec->GetPages(&cauuid);
  1523. hr = OleCreatePropertyFrame(m_hWndOwner, 30, 30, NULL, 1,
  1524. (IUnknown **)&pX, cauuid.cElems,
  1525. (GUID *)cauuid.pElems, 0, 0, NULL); 
  1526. CoTaskMemFree(cauuid.pElems);
  1527. pSpec->Release(); 
  1528. }
  1529. pX->Release();                
  1530. }
  1531. }
  1532. return hr;
  1533. }
  1534. //构建并预览一般的Graph的视频部分
  1535. HRESULT CCaptureGraph::BuildGeneralVideo()
  1536. {
  1537. HRESULT hr;
  1538. if (NULL == m_pVideoCapture)
  1539. {
  1540. AfxMessageBox("视频采集设备出错");
  1541. return E_FAIL;
  1542. }
  1543. hr = m_pGB->AddFilter(m_pVideoCapture, NULL);
  1544. if (FAILED(hr))
  1545. {
  1546. return hr;
  1547. }
  1548. if (TRUE == m_bISCrossBar)
  1549. {
  1550. hr = OpenCrossBar();
  1551. }
  1552. //如果有字幕的Filter
  1553. if (NULL != m_pVideoOverlay)
  1554. {
  1555. hr = AddVideoOverlayFilter();
  1556. if (FAILED(hr))
  1557. {
  1558. return hr;
  1559. }
  1560. }
  1561. else
  1562. {
  1563. if (NULL == m_pVideoEncoder)
  1564. {
  1565. AfxMessageBox("视频编码器出错");
  1566. return E_FAIL;
  1567. }
  1568. hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
  1569. if (FAILED(hr))
  1570. {
  1571. return hr;
  1572. }
  1573. //如果是DMO组件
  1574. if (IsDMOFilter())
  1575. {
  1576. hr = BuildVideoDMOEncoder();
  1577. if (FAILED(hr))
  1578. {
  1579. return hr;
  1580. }
  1581. }
  1582. else
  1583. {
  1584. hr = ConnectPins(m_pVideoCapture, NULL, m_pVideoEncoder, NULL);
  1585. if (FAILED(hr))
  1586. {
  1587. AfxMessageBox("视频编码器出错。请重新选择视频编码器");
  1588. return hr;
  1589. }
  1590. }
  1591. }
  1592. hr = AddFilter(CLSID_InfTee, &m_pVideoSmartTee);
  1593. if (FAILED(hr))
  1594. {
  1595. return hr;
  1596. }
  1597. hr = ConnectPins(m_pVideoEncoder, NULL, m_pVideoSmartTee, NULL);
  1598. if (FAILED(hr))
  1599. {
  1600. AfxMessageBox("视频编码器出错,请重新选择视频编码器");
  1601. return hr;
  1602. }
  1603. //[VideoSmartTee] -> [TVSink]
  1604. hr = ConnectPins(m_pVideoSmartTee, __T("Output1"), m_pTVStreamSink, __T("Video"));
  1605. if(FAILED(hr))
  1606. {
  1607. AfxMessageBox("不能进行播放,请重新选择音频编码器。");
  1608. return hr;
  1609. }
  1610. if (m_bIsPreview)
  1611. {
  1612. hr = BuildVideoPreview();
  1613. }
  1614. return hr;
  1615. }
  1616. HRESULT CCaptureGraph::BuildSaveGraph()
  1617. {
  1618. HRESULT hr;
  1619. //Add AVI Muxer and Filewriter
  1620. if(FAILED(AddFilter(CLSID_AviDest, &m_pAVIMuxer)))
  1621. {
  1622. TRACE("cant add Avi mux filter to graph");
  1623. return E_FAIL;
  1624. }
  1625. if(FAILED(AddFilter(CLSID_FileWriter, &m_pFileWriter)))
  1626. {
  1627. TRACE("cant add Filewriter filter to graph");
  1628. return E_FAIL;
  1629. }
  1630. IConfigAviMux* lpAviMux = NULL;
  1631. hr = m_pAVIMuxer->QueryInterface(IID_IConfigAviMux, (void**)&lpAviMux); 
  1632. if (FAILED(hr))
  1633. {
  1634. AfxMessageBox("AVI 设置失败");
  1635. lpAviMux->Release();
  1636. return E_FAIL;
  1637. }
  1638. hr = lpAviMux->SetOutputCompatibilityIndex(TRUE);
  1639. if (FAILED(hr))
  1640. {
  1641. AfxMessageBox("AVI 设置失败");
  1642. lpAviMux->Release();
  1643. return E_FAIL;
  1644. }
  1645. hr = lpAviMux->SetMasterStream(0);//为音频输入PIN序号 
  1646. if (FAILED(hr))
  1647. {
  1648. AfxMessageBox("AVI 设置失败");
  1649. lpAviMux->Release();
  1650. return E_FAIL;
  1651. }
  1652. lpAviMux->Release();
  1653. //[AudioSmartTee] --> [AVIMux]
  1654. if(FAILED(ConnectPins(m_pAudioSmartTee, __T("Output2"), m_pAVIMuxer, __T("Input 01"))))
  1655. {
  1656. AfxMessageBox("不能保存音频。");
  1657. return E_FAIL;
  1658. }
  1659. if (!m_bIsOnlyAudio)//如果不是只采音频的情况
  1660. {
  1661. if ( m_bIsPreview )
  1662. {
  1663. //[VideoSmartTee] --> [AVIMux]
  1664. if(FAILED(ConnectPins(m_pVideoSmartTee, __T("Output3"), m_pAVIMuxer, __T("Input 02"))))
  1665. {
  1666. AfxMessageBox("不能保存视频。");
  1667. return E_FAIL;
  1668. }
  1669. }
  1670. else
  1671. {
  1672. //[VideoSmartTee] --> [AVIMux]
  1673. if(FAILED(ConnectPins(m_pVideoSmartTee, __T("Output2"), m_pAVIMuxer, __T("Input 02"))))
  1674. {
  1675. AfxMessageBox("不能保存视频。");
  1676. return E_FAIL;
  1677. }
  1678. }
  1679. }
  1680. //Set Output FileName
  1681. IFileSinkFilter *pFileSink = NULL;
  1682. m_pFileWriter->QueryInterface(IID_IFileSinkFilter, (VOID**)(&pFileSink));
  1683. if (NULL == pFileSink)
  1684. {
  1685. return E_FAIL;
  1686. }
  1687. WCHAR wstrFilename[MAX_PATH];
  1688. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  1689. m_szAVIFile, -1, 
  1690. wstrFilename, sizeof(wstrFilename) / sizeof(WCHAR));
  1691. pFileSink->SetFileName(wstrFilename, NULL);
  1692. pFileSink->Release();
  1693. hr = ConnectPins(m_pAVIMuxer, NULL, m_pFileWriter, NULL);
  1694. if(FAILED(hr))
  1695. {
  1696. AfxMessageBox("不能保存成文件。");
  1697. return E_FAIL;
  1698. }
  1699. return hr;
  1700. }
  1701. HRESULT CCaptureGraph::BuildGeneralGraph()
  1702. {
  1703. HRESULT hr;
  1704. hr = BuildGeneralAudio();
  1705. if (FAILED(hr))
  1706. {
  1707. return hr;
  1708. }
  1709. //构建视频部分
  1710. if (FALSE == m_bIsOnlyAudio)
  1711. {
  1712. hr = BuildGeneralVideo();
  1713. }
  1714. if (FAILED(hr))
  1715. {
  1716. return hr;
  1717. }
  1718. if (m_bSave)
  1719. {
  1720. hr = BuildSaveGraph();
  1721. }
  1722. return hr;
  1723. }
  1724. // audio compression format
  1725. HRESULT CCaptureGraph::EnumAudioWaveFormat(CListBox* pLB)// called by main dlg
  1726. {
  1727. IPin *pOutPin;
  1728. //ASSERT(m_pCurAudioAMT);
  1729. if(FAILED(pOutPin = FindPinOnFilter(m_pAudioEncoder, NULL)))
  1730. {
  1731. TRACE("cant get outpin of Audio encoder!");
  1732. return E_FAIL;
  1733. }
  1734. IEnumMediaTypes *pEmt;
  1735. if(FAILED(pOutPin->EnumMediaTypes(&pEmt)))
  1736. {
  1737. pOutPin->Release();
  1738. return E_FAIL;
  1739. }
  1740. for(int i = 0; i < pLB->GetCount(); i++)
  1741. HeapFree(GetProcessHeap(), 0, pLB->GetItemDataPtr(i));
  1742. pLB->ResetContent();
  1743. ULONG uFetch;
  1744. AM_MEDIA_TYPE *pamt;
  1745. CString strTemp;
  1746. CString strFormat;
  1747. int liResult = 0;//保存两个当前媒体类型和枚举媒题类型的比较结果
  1748. while(pEmt->Next(1, &pamt, &uFetch) == S_OK)
  1749. {
  1750. if(pamt->formattype == FORMAT_WaveFormatEx)
  1751. {
  1752. WAVEFORMATEX *pw = (WAVEFORMATEX *)(pamt->pbFormat);
  1753. strTemp.Format("%.3fKbits/s, %dHz", (pw->nAvgBytesPerSec*8)/1024.0, pw->nSamplesPerSec);
  1754. if(pw->nChannels == 1)
  1755. strFormat.Format("%s, mono", strTemp);
  1756. else
  1757. strFormat.Format("%s, stereo", strTemp);
  1758. AM_MEDIA_TYPE *pwfe = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
  1759. HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
  1760. sizeof(AM_MEDIA_TYPE) + pamt->cbFormat);
  1761. memcpy(pwfe, pamt, sizeof(AM_MEDIA_TYPE));
  1762. pwfe->pbFormat = (LPBYTE)(pwfe+1);
  1763. memcpy(pwfe->pbFormat, pw, pamt->cbFormat);
  1764. int idx = pLB->AddString(strFormat);
  1765. pLB->SetItemDataPtr(idx, pwfe);
  1766. //Arthur:0806Add
  1767. //当前媒体类型不动,这里只是负责选择,如果当前类型在枚举的时候已经不存在,则依然不动。
  1768. //如果用户选择了新的则改变,否则继续不动。
  1769. if (!m_pCurAudioAMT)
  1770. {
  1771. continue;
  1772. }
  1773. if (m_pCurAudioAMT->cbFormat == pwfe->cbFormat)
  1774. {
  1775. liResult = memcmp(m_pCurAudioAMT, pwfe,sizeof(AM_MEDIA_TYPE) - 4);
  1776. if (!liResult)
  1777. {//如果两者一样就将这项选择
  1778. liResult = memcmp(m_pCurAudioAMT->pbFormat, pwfe->pbFormat,m_pCurAudioAMT->cbFormat);
  1779. if (!liResult)
  1780. {
  1781. pLB->SetCurSel(idx);
  1782. }
  1783. }
  1784. }
  1785. }
  1786. }
  1787. pEmt->Release();
  1788. pOutPin->Release();
  1789. return S_OK;
  1790. }
  1791. void CCaptureGraph::SetAudioWaveformat(AM_MEDIA_TYPE* pamt)// called by selector dlg
  1792. {
  1793. if(pamt)
  1794. {
  1795. //Arthur:0806Modify
  1796. WAVEFORMATEX *pwfe = (WAVEFORMATEX *)pamt;//Arthur:Bug.该指针根本就没用
  1797. //
  1798. if (!m_pCurAudioAMT)
  1799. {
  1800. m_pCurAudioAMT = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
  1801. HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
  1802. sizeof(AM_MEDIA_TYPE) + pamt->cbFormat);
  1803. }
  1804. ZeroMemory(m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
  1805. int iii = sizeof(AM_MEDIA_TYPE);
  1806. memcpy(m_pCurAudioAMT, pamt, sizeof(AM_MEDIA_TYPE));
  1807. BYTE* ii = (LPBYTE)(m_pCurAudioAMT+1);
  1808. m_pCurAudioAMT->pbFormat = (LPBYTE)(m_pCurAudioAMT+1);//arthur:指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
  1809. //赋给pbFormat
  1810. memcpy(m_pCurAudioAMT->pbFormat, pamt->pbFormat, pamt->cbFormat);
  1811. }
  1812. }
  1813. // used to enum fiters in specified catagory
  1814. HRESULT CCaptureGraph::EnumSpeciFilters(IID iidEnumType, CStringArray &strArrayType)
  1815. {
  1816. HRESULT hr;
  1817. IMoniker *pMoniker =NULL;
  1818. ULONG cFetched;
  1819. // Create the system device enumerator
  1820. ICreateDevEnum* pDevEnum = NULL;
  1821. hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
  1822. IID_ICreateDevEnum, (void **) &pDevEnum);
  1823. if (FAILED(hr))
  1824. {
  1825. TRACE1(TEXT("Couldn't create system enumerator!  hr=0x%x"), hr);
  1826. return hr;
  1827. }
  1828. IEnumMoniker *pClassEnum = NULL;
  1829. hr = pDevEnum->CreateClassEnumerator(iidEnumType, &pClassEnum, 0);
  1830. if (FAILED(hr))
  1831. {
  1832. pDevEnum->Release();
  1833. TRACE1(TEXT("Couldn't create class enumerator!  hr=0x%x"), hr);
  1834. return hr;
  1835. }
  1836. if (pClassEnum == NULL)
  1837. {
  1838. pDevEnum->Release();
  1839. return S_OK;
  1840. }
  1841. while (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
  1842. {
  1843. IPropertyBag *pPropBag;
  1844. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
  1845. (void **)&pPropBag);
  1846. if (SUCCEEDED(hr))
  1847. {
  1848. VARIANT varName;
  1849. VariantInit(&varName);
  1850. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1851. if (SUCCEEDED(hr))
  1852. {
  1853. int cch = lstrlenW(varName.bstrVal) + 1;
  1854. CHAR* lpszFilterName = new char[cch * 2];
  1855. if (!lpszFilterName) 
  1856. return E_OUTOFMEMORY;
  1857. WideCharToMultiByte(GetACP(), 0, varName.bstrVal, -1,
  1858. lpszFilterName, cch, NULL, NULL);
  1859. if(iidEnumType == VIDEO_CAP)
  1860.                     strArrayType.Add(lpszFilterName);
  1861.                 else if(iidEnumType == AUDIO_CAP)
  1862.                     strArrayType.Add(lpszFilterName);
  1863. else if(iidEnumType == VIDEO_COMPRESS)
  1864. {
  1865. if(strcmp(lpszFilterName, "Microsoft H.261 Video Codec") != 0 &&
  1866. strcmp(lpszFilterName, "Microsoft H.263 Video Codec") != 0 &&
  1867. strcmp(lpszFilterName, "Microsoft RLE") != 0 && 
  1868. strcmp(lpszFilterName, "ffdshow video encoder") != 0)
  1869. strArrayType.Add(lpszFilterName);
  1870. }
  1871. else if(iidEnumType == AUDIO_COMPRESS)
  1872. {
  1873. if(strcmp(lpszFilterName, "WM Speech Encoder DMO") != 0 &&
  1874. strcmp(lpszFilterName, "ACELP.net") != 0)
  1875. strArrayType.Add(lpszFilterName);
  1876. }
  1877. else
  1878. ASSERT(FALSE);
  1879. delete [] lpszFilterName;
  1880. }
  1881. VariantClear(&varName);
  1882. pPropBag->Release();
  1883. }
  1884. pMoniker->Release();
  1885. }
  1886. pClassEnum->Release();
  1887. pDevEnum->Release();
  1888. return S_OK;
  1889. }
  1890. // used to create filter 
  1891. HRESULT CCaptureGraph::FindFilterByName(LPTSTR strName, IBaseFilter **ppFilter, IID iidEnumType)
  1892. {
  1893. if(ppFilter == NULL)
  1894. return E_INVALIDARG;
  1895. *ppFilter = NULL;
  1896. HRESULT hr;
  1897. IMoniker *pMoniker =NULL;
  1898. ULONG cFetched;
  1899. // Create the system device enumerator
  1900. ICreateDevEnum* pDevEnum = NULL;
  1901. hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
  1902. IID_ICreateDevEnum, (void **) &pDevEnum);
  1903. if (FAILED(hr))
  1904. {
  1905. TRACE1(TEXT("Couldn't create system enumerator!  hr=0x%x"), hr);
  1906. return hr;
  1907. }
  1908. IEnumMoniker *pClassEnum = NULL;
  1909. hr = pDevEnum->CreateClassEnumerator(iidEnumType, &pClassEnum, 0);
  1910. if (FAILED(hr))
  1911. {
  1912. pDevEnum->Release();
  1913. TRACE1(TEXT("Couldn't create class enumerator!  hr=0x%x"), hr);
  1914. return hr;
  1915. }
  1916. if (pClassEnum == NULL)
  1917. {
  1918. pDevEnum->Release();
  1919. return S_OK;
  1920. }
  1921. while (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
  1922. {
  1923. IPropertyBag *pPropBag;
  1924. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
  1925. (void **)&pPropBag);
  1926. if (SUCCEEDED(hr))
  1927. {
  1928. VARIANT varName;
  1929. VariantInit(&varName);
  1930. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  1931. if (SUCCEEDED(hr))
  1932. {
  1933. int cch = lstrlenW(varName.bstrVal) + 1;
  1934. CHAR* lpszFilterName = new char[cch * 2];
  1935. if (!lpszFilterName) 
  1936. return E_OUTOFMEMORY;
  1937. WideCharToMultiByte(GetACP(), 0, varName.bstrVal, -1,
  1938. lpszFilterName, cch, NULL, NULL);
  1939. VariantClear(&varName);
  1940. if(strcmp(lpszFilterName, strName) == 0)
  1941. {
  1942. hr = pMoniker->BindToObject(NULL, NULL, 
  1943. IID_IBaseFilter,
  1944. (VOID**)ppFilter);
  1945. delete [] lpszFilterName;
  1946. pPropBag->Release();
  1947. pMoniker->Release();
  1948. break;
  1949. }
  1950. delete [] lpszFilterName;
  1951. }
  1952. pPropBag->Release();
  1953. }
  1954. pMoniker->Release();
  1955. }
  1956. pClassEnum->Release();
  1957. pDevEnum->Release();
  1958. return S_OK;
  1959. }
  1960. // used to get audio capture device 
  1961. HRESULT CCaptureGraph::GetAudioCaptureDevice()
  1962. {
  1963. HRESULT hr;
  1964. IMoniker *pMoniker =NULL;
  1965. ULONG cFetched;
  1966. // Create the system device enumerator
  1967. ICreateDevEnum* pDevEnum = NULL;
  1968. hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
  1969. IID_ICreateDevEnum, (void **) &pDevEnum);
  1970. if (FAILED(hr))
  1971. {
  1972. TRACE1(TEXT("Couldn't create system enumerator!  hr=0x%x"), hr);
  1973. return hr;
  1974. }
  1975. IEnumMoniker *pClassEnum = NULL;
  1976. hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pClassEnum, 0);
  1977. if (FAILED(hr))
  1978. {
  1979. pDevEnum->Release();
  1980. TRACE1(TEXT("Couldn't create class enumerator!  hr=0x%x"), hr);
  1981. return hr;
  1982. }
  1983. if (pClassEnum == NULL)
  1984. {
  1985. pDevEnum->Release();
  1986. return S_OK;
  1987. }
  1988. pDevEnum->Release();
  1989. hr = pClassEnum->Reset();
  1990. if(S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
  1991. {
  1992. hr = pMoniker->BindToObject(NULL, NULL, 
  1993. IID_IBaseFilter,
  1994. (VOID**)&m_pAudioCapture);
  1995. if(FAILED(hr))
  1996. {
  1997. pMoniker->Release();
  1998. pClassEnum->Release();
  1999. TRACE("Cant find Audio Capture");
  2000. return hr;
  2001. }
  2002. }
  2003. pMoniker->Release();
  2004. pClassEnum->Release();
  2005. return hr;
  2006. }
  2007. // used for filling the m_arryOtherFilter, diff from our 
  2008. // refrenced filters
  2009. BOOL CCaptureGraph::IsFilterInStdFilters(IBaseFilter *pFilter)
  2010. {
  2011. if(m_pVideoCapture == pFilter ||
  2012. m_pAudioCapture == pFilter ||
  2013. m_pVideoEncoder == pFilter ||
  2014. m_pAudioEncoder == pFilter ||
  2015. m_pTVStreamSink == pFilter ||
  2016. m_pVideoSmartTee == pFilter)
  2017. return TRUE;
  2018. else
  2019. return FALSE;
  2020. }
  2021. //得到媒体类型
  2022. bool CCaptureGraph::GetCurMediaType(AM_MEDIA_TYPE** aMTMediaType)
  2023. {
  2024. //Arthur:把当前的媒体类型交出去。重新拷一下,不能直接只拷指针。只拷指针不能访问
  2025. if(m_pCurAudioAMT)
  2026. {
  2027. if (!*aMTMediaType)
  2028. {
  2029. *aMTMediaType = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
  2030. HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
  2031. sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
  2032. if (!*aMTMediaType)
  2033. {
  2034. return false;
  2035. }
  2036. }
  2037. memcpy(*aMTMediaType, m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE));
  2038. (*aMTMediaType)->pbFormat = (LPBYTE)(*aMTMediaType+ 1);//指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
  2039. //赋给pbFormat
  2040. memcpy((*aMTMediaType)->pbFormat, m_pCurAudioAMT->pbFormat, m_pCurAudioAMT->cbFormat);
  2041. int ii = sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat;
  2042. return true;
  2043. }
  2044. return false;
  2045. }
  2046. //设置媒体类型
  2047. bool CCaptureGraph::SetCurMediaType(AM_MEDIA_TYPE *aMTMediaType)
  2048. {
  2049. //设置当前媒体类型的一个指针。
  2050. if(aMTMediaType)
  2051. {
  2052. //如果此时已经有媒体类型则将之释放掉
  2053. if (!m_pCurAudioAMT)
  2054. {
  2055. m_pCurAudioAMT = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
  2056. HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
  2057. sizeof(AM_MEDIA_TYPE) + aMTMediaType->cbFormat);
  2058. if (!m_pCurAudioAMT)
  2059. {
  2060. return false;
  2061. }
  2062. }
  2063. ZeroMemory(m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
  2064. memcpy(m_pCurAudioAMT, aMTMediaType, sizeof(AM_MEDIA_TYPE));
  2065. BYTE* ii = (LPBYTE)(m_pCurAudioAMT+1);
  2066. int iii = sizeof(AM_MEDIA_TYPE);
  2067. m_pCurAudioAMT->pbFormat = (LPBYTE)(m_pCurAudioAMT+1);//arthur:指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
  2068. //赋给pbFormat
  2069. if (m_pCurAudioAMT->pbFormat && aMTMediaType->pbFormat)
  2070. {
  2071. memcpy(m_pCurAudioAMT->pbFormat, aMTMediaType->pbFormat, aMTMediaType->cbFormat);
  2072. }
  2073. return true;
  2074. }
  2075. return false;
  2076. }
  2077. //=========================================
  2078. // Writed by zhuwei 2005-8-12 
  2079. //Show Pin Setting
  2080. void CCaptureGraph::ShowPinSetting(HWND hParent)
  2081. {
  2082. if (NULL == m_pVideoCapture)
  2083. {
  2084. AfxMessageBox("视频采集设备未找到");
  2085. return;
  2086. }
  2087. /*
  2088. * SECOND: prompt user to configure output pin configuration
  2089. */
  2090. HRESULT hr;
  2091. ISpecifyPropertyPages *pSpec;
  2092. WCHAR wstrCaption[256];
  2093. CAUUID cauuid;
  2094. // must be added in the graph this time
  2095. m_pGB->AddFilter(m_pVideoCapture, NULL);
  2096. IAMStreamConfig *pSC;
  2097. IPin *pOutPin = FindPinOnFilter(m_pVideoCapture, NULL);
  2098. hr = pOutPin->QueryInterface(IID_IAMStreamConfig, (void**)(&pSC));
  2099. pOutPin->Release();
  2100. if(FAILED(hr))
  2101. return;
  2102. hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
  2103. if(FAILED(hr))
  2104. {
  2105. pSC->Release();
  2106. return;
  2107. }
  2108. // Popup page
  2109. CString str = CString(_T("Video Capture Configuration 2")); // dlg caption
  2110. pSpec->GetPages(&cauuid);
  2111. if(cauuid.cElems >= 1)
  2112. {
  2113. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
  2114. str.GetBuffer(str.GetLength()), -1, 
  2115. wstrCaption, sizeof(wstrCaption) / sizeof(WCHAR));
  2116. hr = OleCreatePropertyFrame(hParent, 30, 30, wstrCaption, 1,
  2117. (IUnknown **)&pSC, cauuid.cElems,
  2118. (GUID *)cauuid.pElems, 0, 0, NULL);
  2119. if(FAILED(hr))
  2120. {
  2121. CoTaskMemFree(cauuid.pElems);
  2122. pSpec->Release();
  2123. pSC->Release();
  2124. return;
  2125. }
  2126. }
  2127. // Destructor
  2128. CoTaskMemFree(cauuid.pElems);
  2129. pSpec->Release();
  2130. pSC->Release();
  2131. return;
  2132. }
  2133. //Set AVI Filename
  2134. void CCaptureGraph::SetAVIFile( char* szFile )
  2135. {
  2136. if ( szFile[0] )
  2137. {
  2138. this->m_bSave = true;
  2139. strncpy( this->m_szAVIFile, szFile, MAX_PATH);
  2140. }
  2141. }
  2142. HRESULT CCaptureGraph::DVSplitter()
  2143. {
  2144. HRESULT hr;
  2145. if(!m_pVideoCapture)
  2146. {
  2147. AfxMessageBox("No Video Capture Device!");
  2148. return E_FAIL;
  2149. }
  2150. hr = m_pGB->AddFilter(m_pVideoCapture, NULL);
  2151. if(FAILED(hr))
  2152. {
  2153. TRACE("cant add video capture filter to graph");
  2154. return hr;
  2155. }
  2156. hr = AddFilter(CLSID_DVSplitter, &m_pftrDVSpliter);
  2157. //Add DV Splitter Filter
  2158. if(FAILED(hr))
  2159. {
  2160. AfxMessageBox("cant add DV Splitter Filter to graph");
  2161. return hr;
  2162. }
  2163. hr = ConnectAutoPins(m_pVideoCapture, "DV A/V Out", m_pftrDVSpliter, NULL);
  2164. if (FAILED(hr))
  2165. {
  2166. AfxMessageBox("cant ConnectDirect DV Splitter Filter to graph");
  2167. return hr;
  2168. }
  2169. return hr;
  2170. }
  2171. HRESULT CCaptureGraph::BuildDVAudio()
  2172. {
  2173. //DV加音频
  2174. HRESULT hr;
  2175. //Add Audio Encoder
  2176. if(!m_pAudioEncoder)
  2177. {
  2178. AfxMessageBox("No Aduio Compressor available!");
  2179. return E_FAIL;
  2180. }
  2181. hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
  2182. if(FAILED(hr))
  2183. {
  2184. TRACE("cant add audio encoder filter to graph");
  2185. return hr;
  2186. }
  2187. //[DVSplitter] --> [AudioEncoder]
  2188. hr = ConnectAutoPins(m_pftrDVSpliter,"AudOut00", m_pAudioEncoder, NULL);
  2189. if(FAILED(hr))
  2190. {
  2191. AfxMessageBox("不能进行播放,请重新选择音频编码器。");
  2192. return hr;
  2193. }
  2194. //Add AudioSmartTee
  2195. hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
  2196. if(FAILED(hr))
  2197. {
  2198. TRACE("cant add smarttee filter to graph");
  2199. return hr;
  2200. }
  2201. //[AudioEncoder] --> [AudioSmartTee]
  2202. hr = ConnectPins(m_pAudioEncoder, __T("Output"), m_pAudioSmartTee, __T("Input"));
  2203. if(FAILED(hr))
  2204. {
  2205. AfxMessageBox("不能进行播放,请重新选择音频编码器。");
  2206. return E_FAIL;
  2207. }
  2208. //[AudioSmartTee] -> [TVSink]
  2209. hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
  2210. if(FAILED(hr))
  2211. {
  2212. AfxMessageBox("不能进行播放,请重新选择音频编码器。");
  2213. return hr;
  2214. }
  2215. return hr;
  2216. }
  2217. HRESULT CCaptureGraph::AddDVVideoOverlay()
  2218. {
  2219. HRESULT hr;
  2220. hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
  2221. if(FAILED(hr))
  2222. {
  2223. TRACE("cant add Video Overlay to graph");
  2224. return E_FAIL;
  2225. }
  2226. //[DVEncoder] --> [VideoOverlay]
  2227. hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoOverlay, NULL);
  2228. if(FAILED(hr))
  2229. {
  2230. AfxMessageBox("与字幕Filter连接失败");
  2231. return E_FAIL;
  2232. }
  2233. //将字幕Filter和视频编码filter相连
  2234. //Add Video Encoder 
  2235. if(!m_pVideoEncoder)
  2236. {
  2237. AfxMessageBox("No Video Compressor available!");
  2238. return E_FAIL;
  2239. }
  2240. hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
  2241. if(FAILED(hr))
  2242. {
  2243. TRACE("cant add video encoder filter to graph");
  2244. return E_FAIL;
  2245. }
  2246. //如果是DMO组件
  2247. if (IsDMOFilter())
  2248. {
  2249. hr = BuildVideoDMOEncoder();
  2250. if (FAILED(hr))
  2251. {
  2252. return hr;
  2253. }
  2254. }
  2255. else
  2256. {
  2257. //[VideoOverlay] --> [VideoEncoder]
  2258. hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
  2259. if(FAILED(hr))
  2260. {
  2261. AfxMessageBox("不能进行播放,请重新选择视频编码器。");
  2262. return hr;
  2263. }
  2264. }
  2265. return hr;
  2266. }
  2267. //DV视频预览
  2268. HRESULT CCaptureGraph::BuildDVVideoPrview()
  2269. {
  2270. //Get VideoSmartTee's Sencond Output Pin
  2271. IPin *pPreview;
  2272. if(FAILED(pPreview = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"))))
  2273. {
  2274. TRACE("cant get preview outpin of smart tee!");
  2275. return E_FAIL;
  2276. }
  2277. //Render pin
  2278. HRESULT hr;
  2279. hr = m_pGB->Render(pPreview);
  2280. if(FAILED(hr))
  2281. {
  2282. AfxMessageBox("不能进行播放,请重新选择视频编码器。");
  2283. return hr;
  2284. }
  2285. pPreview->Release();
  2286. if ( NULL == m_pVW )
  2287. {
  2288. hr = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);
  2289. if (FAILED(hr))
  2290. {
  2291. TRACE0("ERROR - Could not Get IVideoWindow.");
  2292. return hr;
  2293. }
  2294. }
  2295. m_pVW->put_Owner((OAHWND)m_hWndOwner);
  2296. m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
  2297. CRect rc;
  2298. GetClientRect(m_hWndOwner, &rc);
  2299. m_pVW->put_Top(0);
  2300. m_pVW->put_Left(0);
  2301. m_pVW->put_Width(rc.Width());
  2302. m_pVW->put_Height(rc.Height());
  2303. m_pVW->put_Visible(-1);
  2304. m_pVW->put_AutoShow(-1);
  2305. return hr;
  2306. }
  2307. //构建DV视频链路
  2308. HRESULT CCaptureGraph::BuildDVVideo()
  2309. {
  2310. HRESULT hr;
  2311. hr = AddFilter(CLSID_DVVideoCodec, &m_pDVDecoder);
  2312. if (FAILED(hr))
  2313. {
  2314. TRACE("加载m_pDVDecoder失败");
  2315. return hr;
  2316. }
  2317. //为了解决CPU消耗过高,只减小输出画面
  2318. IIPDVDec* lpDVDec = NULL;
  2319. hr = m_pDVDecoder->QueryInterface(IID_IIPDVDec, (void**)&lpDVDec);
  2320. if (FAILED(hr))
  2321. {
  2322. TRACE("获取IIPDVDec接口失败");
  2323. return hr;
  2324. }
  2325. else
  2326. {
  2327. lpDVDec->put_IPDisplay(DVRESOLUTION_HALF);
  2328. lpDVDec->Release();
  2329. }
  2330. //[DVSpliter] --> [DVVideoCodec]
  2331. hr = ConnectPins(m_pftrDVSpliter, "DVVidOut0", m_pDVDecoder, NULL);
  2332. if(FAILED(hr))
  2333. {
  2334. AfxMessageBox("与m_pDVDecoderFilter连接失败");
  2335. return E_FAIL;
  2336. }
  2337. if (m_pVideoOverlay)//如果字幕filter有则需连字幕filter
  2338. {
  2339. hr = AddDVVideoOverlay();
  2340. }
  2341. else//不需要字幕的情况
  2342. {
  2343. //Add Video Encoder 
  2344. if(!m_pVideoEncoder)
  2345. {
  2346. AfxMessageBox("No Video Compressor available!");
  2347. return E_FAIL;
  2348. }
  2349. hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
  2350. if(FAILED(hr))
  2351. {
  2352. AfxMessageBox("cant add video encoder filter to graph");
  2353. return hr;
  2354. }
  2355. //如果是DMO组件
  2356. if (IsDMOFilter())
  2357. {
  2358. hr = BuildVideoDMOEncoder();
  2359. if (FAILED(hr))
  2360. {
  2361. return hr;
  2362. }
  2363. }
  2364. else
  2365. {
  2366. //[DV Splitter] --> [VideoEncoder]
  2367. hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoEncoder, NULL);
  2368. if(FAILED(hr))
  2369. {
  2370. AfxMessageBox("不能进行自动连接在m_pftrDVSpliter和m_pVideoEncoder之间");
  2371. return E_FAIL;
  2372. }
  2373. }
  2374. }
  2375. //Add VideoSmartTee
  2376. hr = AddFilter(CLSID_InfTee, &m_pVideoSmartTee);
  2377. if(FAILED(hr))
  2378. {
  2379. TRACE("cant add smarttee filter to graph");
  2380. return hr;
  2381. }
  2382. //[VideoEncoder] --> [VideoSmartTee]
  2383. hr = ConnectPins(m_pVideoEncoder, NULL, m_pVideoSmartTee, __T("Input"));
  2384. if(FAILED(hr))
  2385. {
  2386. TRACE("cant connect video encoder and Smart Tee!");
  2387. return E_FAIL;
  2388. }
  2389. //[Video SmartTee] --> [TVSink]
  2390. hr = ConnectPins(m_pVideoSmartTee, __T("Output1"), m_pTVStreamSink, __T("Video"));
  2391. if(FAILED(hr))
  2392. {
  2393. AfxMessageBox("不能进行播放,请重新选择视频编码器。");
  2394. return hr;
  2395. }
  2396. //==================================================================================================
  2397. //预览
  2398. if(m_bIsPreview)
  2399. {
  2400. hr = BuildDVVideoPrview();
  2401. if (FAILED(hr))
  2402. {
  2403. return hr;
  2404. }
  2405. }
  2406. return hr;
  2407. }
  2408. //采集DV
  2409. HRESULT CCaptureGraph::DisplayDV()
  2410. {
  2411. HRESULT hr;
  2412. //分离DV的信号
  2413. hr = DVSplitter();
  2414. if (FAILED(hr))
  2415. {
  2416. return hr;
  2417. }
  2418. //构建DV音频
  2419. hr = BuildDVAudio();
  2420. if (FAILED(hr))
  2421. {
  2422. return hr;
  2423. }
  2424. if (FALSE == m_bIsOnlyAudio)
  2425. {
  2426. hr = BuildDVVideo();
  2427. if (FAILED(hr))
  2428. {
  2429. return hr;
  2430. }
  2431. }
  2432. if (m_bSave)
  2433. {
  2434. hr = BuildSaveGraph();
  2435. if (FAILED(hr))
  2436. {
  2437. return hr;
  2438. }
  2439. }
  2440. return hr;
  2441. }