GraphBuilder.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:60k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "mplayerc.h"
  23. #include "GraphBuilder.h"
  24. #include "....DSUtilDSUtil.h"
  25. #include "....filtersfilters.h"
  26. #include "......includemoreuuids.h"
  27. #include "......includeOggOggDS.h"
  28. #include "......includematroskamatroska.h"
  29. #include "DX7AllocatorPresenter.h"
  30. #include "DX9AllocatorPresenter.h"
  31. #include "DeinterlacerFilter.h"
  32. #include <initguid.h>
  33. #include <dmodshow.h>
  34. #include <D3d9.h>
  35. #include <Vmr9.h>
  36. static void CheckStupidSharedFilesourceFilter()
  37. {
  38. CRegKey key;
  39. CString str(_T("CLSID\{E436EBB5-524F-11CE-9F53-0020AF0BA770}\InprocServer32"));
  40. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
  41. {
  42. ULONG nChars = 0;
  43. if(ERROR_SUCCESS == key.QueryStringValue(NULL, NULL, &nChars))
  44. {
  45. CString dll;
  46. if(ERROR_SUCCESS == key.QueryStringValue(NULL, dll.GetBuffer(nChars), &nChars))
  47. {
  48. dll.ReleaseBuffer(nChars);
  49. dll.MakeLower();
  50. if(dll.Find(_T("shared_filesource.ax")) >= 0
  51. || dll.Find(_T("shared~1.ax")) >= 0)
  52. {
  53. if(IDYES == AfxMessageBox(
  54. _T("Warning: MPC has detected that DirectShow's "File Source (async)" filtern")
  55. _T("was replaced by shared_filesource.ax. Please run "regsvr32.exe quartz.dll"n")
  56. _T("in your system folder to restore it. If you are a user with administratorn")
  57. _T("rights, MPC can also do this for you. Do you want to re-register quartz.dll now?"), 
  58. MB_YESNO|MB_ICONEXCLAMATION))
  59. {
  60. TCHAR buff[MAX_PATH+1];
  61. GetSystemDirectory(buff, sizeof(buff));
  62. CString path = CString(buff) + _T("\quartz.dll");
  63. HRESULT hr = E_FAIL;
  64. if(HMODULE hModule = LoadLibrary(path))
  65. {
  66. typedef HRESULT (__stdcall * PDllRegisterServer)();
  67. if(PDllRegisterServer p = (PDllRegisterServer)GetProcAddress(hModule, "DllRegisterServer"))
  68. hr = p();
  69. }
  70. if(SUCCEEDED(hr))
  71. AfxMessageBox(_T("Successfully re-registered quartz.dll, you may need to restart the player now."), MB_OK);
  72. else
  73. AfxMessageBox(_T("Failed to re-register quartz.dll!"), MB_OK|MB_ICONEXCLAMATION);
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. //
  81. // CGraphBuilder
  82. //
  83. CGraphBuilder::CGraphBuilder(IGraphBuilder* pGB, HWND hWnd)
  84. : m_pGB(pGB), m_hWnd(hWnd)
  85. , m_nTotalStreams(0)
  86. , m_nCurrentStream(0)
  87. , m_VRMerit(LMERIT(MERIT_PREFERRED+1)+0x100)
  88. , m_ARMerit(LMERIT(MERIT_PREFERRED+1)+0x100)
  89. {
  90. AppSettings& s = AfxGetAppSettings();
  91. m_pFM.CoCreateInstance(CLSID_FilterMapper2);
  92. if(!m_pFM) return;
  93. {
  94. CArray<GUID> guids;
  95. CComPtr<IEnumMoniker> pEM;
  96. m_VRMerit = LMERIT(MERIT_PREFERRED);
  97. guids.Add(MEDIATYPE_Video);
  98. guids.Add(MEDIASUBTYPE_NULL);
  99. if(guids.GetCount() > 0
  100. && SUCCEEDED(m_pFM->EnumMatchingFilters(
  101. &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
  102. TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, TRUE,
  103. FALSE, 0, NULL, NULL, NULL)))
  104. {
  105. for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
  106. {
  107. CGraphRegFilter gf(pMoniker);
  108. m_VRMerit = max(m_VRMerit, gf.GetMerit());
  109. }
  110. }
  111. guids.RemoveAll();
  112. pEM = NULL;
  113. m_VRMerit += 0x100;
  114. m_ARMerit = LMERIT(MERIT_PREFERRED);
  115. guids.Add(MEDIATYPE_Audio);
  116. guids.Add(MEDIASUBTYPE_NULL);
  117. if(guids.GetCount() > 0
  118. && SUCCEEDED(m_pFM->EnumMatchingFilters(
  119. &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
  120. TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, TRUE,
  121. FALSE, 0, NULL, NULL, NULL)))
  122. {
  123. for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
  124. {
  125. CGraphRegFilter gf(pMoniker);
  126. m_ARMerit = max(m_ARMerit, gf.GetMerit());
  127. }
  128. }
  129. BeginEnumSysDev(CLSID_AudioRendererCategory, pMoniker)
  130. {
  131. CGraphRegFilter gf(pMoniker);
  132. m_ARMerit = max(m_ARMerit, gf.GetMerit());
  133. }
  134. EndEnumSysDev
  135. guids.RemoveAll();
  136. pEM = NULL;
  137. m_ARMerit += 0x100;
  138. }
  139. // transform filters
  140. CList<GUID> guids;
  141. guids.AddTail(MEDIATYPE_Audio);
  142. guids.AddTail(MEDIASUBTYPE_WAVE_DOLBY_AC3);
  143. guids.AddTail(MEDIATYPE_Audio);
  144. guids.AddTail(MEDIASUBTYPE_WAVE_DTS);
  145. AddFilter(new CGraphCustomFilter(__uuidof(CAVI2AC3Filter), guids, L"AVI<->AC3/DTS", LMERIT(0x00680000)+1));
  146. guids.RemoveAll();
  147. {
  148. guids.AddTail(MEDIATYPE_Stream);
  149. guids.AddTail(MEDIASUBTYPE_Matroska);
  150. AddFilter(new CGraphCustomFilter(__uuidof(CMatroskaSplitterFilter), guids, 
  151. (s.SrcFilters&SRC_MATROSKA) ? L"Matroska Splitter" : L"Matroska Splitter (low merit)", 
  152. (s.SrcFilters&SRC_MATROSKA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  153. guids.RemoveAll();
  154. }
  155. {
  156. guids.AddTail(MEDIATYPE_Stream);
  157. guids.AddTail(MEDIASUBTYPE_RealMedia);
  158. AddFilter(new CGraphCustomFilter(__uuidof(CRealMediaSplitterFilter), guids, 
  159. (s.SrcFilters&SRC_REALMEDIA) ? L"RealMedia Splitter" : L"RealMedia Splitter (low merit)", 
  160. (s.SrcFilters&SRC_REALMEDIA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  161. guids.RemoveAll();
  162. }
  163. {
  164. guids.AddTail(MEDIATYPE_Stream);
  165. guids.AddTail(MEDIASUBTYPE_Avi);
  166. AddFilter(new CGraphCustomFilter(__uuidof(CAviSplitterFilter), guids, 
  167. (s.SrcFilters&SRC_AVI) ? L"Avi Splitter" : L"Avi Splitter (low merit)",
  168. (s.SrcFilters&SRC_AVI) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  169. guids.RemoveAll();
  170. }
  171. __if_exists(CRadGtSplitterFilter)
  172. {
  173. guids.AddTail(MEDIATYPE_Stream);
  174. guids.AddTail(MEDIASUBTYPE_Bink);
  175. guids.AddTail(MEDIATYPE_Stream);
  176. guids.AddTail(MEDIASUBTYPE_Smacker);
  177. AddFilter(new CGraphCustomFilter(__uuidof(CRadGtSplitterFilter), guids, 
  178. (s.SrcFilters&SRC_RADGT) ? L"RadGt Splitter" : L"RadGt Splitter (low merit)",
  179. (s.SrcFilters&SRC_RADGT) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  180. guids.RemoveAll();
  181. }
  182. {
  183. guids.AddTail(MEDIATYPE_Stream);
  184. guids.AddTail(MEDIASUBTYPE_RoQ);
  185. AddFilter(new CGraphCustomFilter(__uuidof(CRoQSplitterFilter), guids, 
  186. (s.SrcFilters&SRC_ROQ) ? L"RoQ Splitter" : L"RoQ Splitter (low merit)",
  187. (s.SrcFilters&SRC_ROQ) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  188. guids.RemoveAll();
  189. }
  190. {
  191. guids.AddTail(MEDIATYPE_Stream);
  192. guids.AddTail(MEDIASUBTYPE_Ogg);
  193. AddFilter(new CGraphCustomFilter(__uuidof(COggSplitterFilter), guids, 
  194. (s.SrcFilters&SRC_OGG) ? L"Ogg Splitter" : L"Ogg Splitter (low merit)",
  195. (s.SrcFilters&SRC_OGG) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  196. guids.RemoveAll();
  197. }
  198. {
  199. guids.AddTail(MEDIATYPE_Stream);
  200. guids.AddTail(MEDIASUBTYPE_Nut);
  201. AddFilter(new CGraphCustomFilter(__uuidof(CNutSplitterFilter), guids, 
  202. (s.SrcFilters&SRC_NUT) ? L"Nut Splitter" : L"Nut Splitter (low merit)",
  203. (s.SrcFilters&SRC_NUT) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  204. guids.RemoveAll();
  205. }
  206. {
  207. guids.AddTail(MEDIATYPE_Stream);
  208. guids.AddTail(MEDIASUBTYPE_MPEG1System);
  209. guids.AddTail(MEDIATYPE_Stream);
  210. guids.AddTail(MEDIASUBTYPE_MPEG2_PROGRAM);
  211. guids.AddTail(MEDIATYPE_Stream);
  212. guids.AddTail(MEDIASUBTYPE_MPEG2_TRANSPORT);
  213. guids.AddTail(MEDIATYPE_Stream);
  214. guids.AddTail(MEDIASUBTYPE_MPEG2_PVA);
  215. AddFilter(new CGraphCustomFilter(__uuidof(CMpegSplitterFilter), guids, 
  216. (s.SrcFilters&SRC_MPEG) ? L"Mpeg Splitter" : L"Mpeg Splitter (low merit)",
  217. (s.SrcFilters&SRC_MPEG) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  218. guids.RemoveAll();
  219. }
  220. {
  221. guids.AddTail(MEDIATYPE_Video);
  222. guids.AddTail(MEDIASUBTYPE_MPEG1Packet);
  223. guids.AddTail(MEDIATYPE_Video);
  224. guids.AddTail(MEDIASUBTYPE_MPEG1Payload);
  225. AddFilter(new CGraphCustomFilter(__uuidof(CMpeg2DecFilter), guids, 
  226. (s.TraFilters&TRA_MPEG1) ? L"MPEG-1 Video Decoder" : L"MPEG-1 Video Decoder (low merit)", 
  227. (s.TraFilters&TRA_MPEG1) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  228. guids.RemoveAll();
  229. }
  230. {
  231. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  232. guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
  233. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  234. guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
  235. guids.AddTail(MEDIATYPE_MPEG2_PES);
  236. guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
  237. guids.AddTail(MEDIATYPE_Video);
  238. guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
  239. AddFilter(new CGraphCustomFilter(__uuidof(CMpeg2DecFilter), guids,
  240. (s.TraFilters&TRA_MPEG2) ? L"MPEG-2 Video Decoder" : L"MPEG-2 Video Decoder (low merit)", 
  241. (s.TraFilters&TRA_MPEG2) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  242. guids.RemoveAll();
  243. }
  244. {
  245. guids.AddTail(MEDIATYPE_Audio);
  246. guids.AddTail(MEDIASUBTYPE_MP3);
  247. guids.AddTail(MEDIATYPE_Audio);
  248. guids.AddTail(MEDIASUBTYPE_MPEG1AudioPayload);
  249. guids.AddTail(MEDIATYPE_Audio);
  250. guids.AddTail(MEDIASUBTYPE_MPEG1Payload);
  251. guids.AddTail(MEDIATYPE_Audio);
  252. guids.AddTail(MEDIASUBTYPE_MPEG1Packet);
  253. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  254. (s.TraFilters&TRA_MPA) ? L"MPEG-1 Audio Decoder" : L"MPEG-1 Audio Decoder (low merit)",
  255. (s.TraFilters&TRA_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  256. guids.RemoveAll();
  257. }
  258. {
  259. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  260. guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
  261. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  262. guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
  263. guids.AddTail(MEDIATYPE_MPEG2_PES);
  264. guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
  265. guids.AddTail(MEDIATYPE_Audio);
  266. guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
  267. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  268. (s.TraFilters&TRA_MPA) ? L"MPEG-2 Audio Decoder" : L"MPEG-2 Audio Decoder (low merit)",
  269. (s.TraFilters&TRA_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  270. guids.RemoveAll();
  271. }
  272. {
  273. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  274. guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
  275. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  276. guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
  277. guids.AddTail(MEDIATYPE_MPEG2_PES);
  278. guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
  279. guids.AddTail(MEDIATYPE_Audio);
  280. guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
  281. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  282. (s.TraFilters&TRA_LPCM) ? L"LPCM Audio Decoder" : L"LPCM Audio Decoder (low merit)",
  283. (s.TraFilters&TRA_LPCM) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  284. guids.RemoveAll();
  285. }
  286. {
  287. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  288. guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
  289. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  290. guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
  291. guids.AddTail(MEDIATYPE_MPEG2_PES);
  292. guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
  293. guids.AddTail(MEDIATYPE_Audio);
  294. guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
  295. guids.AddTail(MEDIATYPE_Audio);
  296. guids.AddTail(MEDIASUBTYPE_WAVE_DOLBY_AC3);
  297. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  298. (s.TraFilters&TRA_AC3) ? L"AC3 Audio Decoder" : L"AC3 Audio Decoder (low merit)",
  299. (s.TraFilters&TRA_AC3) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  300. guids.RemoveAll();
  301. }
  302. {
  303. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  304. guids.AddTail(MEDIASUBTYPE_DTS);
  305. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  306. guids.AddTail(MEDIASUBTYPE_DTS);
  307. guids.AddTail(MEDIATYPE_MPEG2_PES);
  308. guids.AddTail(MEDIASUBTYPE_DTS);
  309. guids.AddTail(MEDIATYPE_Audio);
  310. guids.AddTail(MEDIASUBTYPE_DTS);
  311. guids.AddTail(MEDIATYPE_Audio);
  312. guids.AddTail(MEDIASUBTYPE_WAVE_DTS);
  313. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  314. (s.TraFilters&TRA_DTS) ? L"DTS Decoder" : L"DTS Decoder (low merit)",
  315. (s.TraFilters&TRA_DTS) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  316. guids.RemoveAll();
  317. }
  318. {
  319. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  320. guids.AddTail(MEDIASUBTYPE_AAC);
  321. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  322. guids.AddTail(MEDIASUBTYPE_AAC);
  323. guids.AddTail(MEDIATYPE_MPEG2_PES);
  324. guids.AddTail(MEDIASUBTYPE_AAC);
  325. guids.AddTail(MEDIATYPE_Audio);
  326. guids.AddTail(MEDIASUBTYPE_AAC);
  327. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  328. guids.AddTail(MEDIASUBTYPE_MP4A);
  329. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  330. guids.AddTail(MEDIASUBTYPE_MP4A);
  331. guids.AddTail(MEDIATYPE_MPEG2_PES);
  332. guids.AddTail(MEDIASUBTYPE_MP4A);
  333. guids.AddTail(MEDIATYPE_Audio);
  334. guids.AddTail(MEDIASUBTYPE_MP4A);
  335. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  336. (s.TraFilters&TRA_AAC) ? L"AAC Decoder" : L"AAC Decoder (low merit)",
  337. (s.TraFilters&TRA_AAC) ? LMERIT_ABOVE_DSHOW+1 : LMERIT_DO_USE));
  338. guids.RemoveAll();
  339. }
  340. {
  341. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  342. guids.AddTail(MEDIASUBTYPE_PS2_PCM);
  343. guids.AddTail(MEDIATYPE_MPEG2_PACK);
  344. guids.AddTail(MEDIASUBTYPE_PS2_PCM);
  345. guids.AddTail(MEDIATYPE_MPEG2_PES);
  346. guids.AddTail(MEDIASUBTYPE_PS2_PCM);
  347. guids.AddTail(MEDIATYPE_Audio);
  348. guids.AddTail(MEDIASUBTYPE_PS2_PCM);
  349. AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids, 
  350. (s.TraFilters&TRA_PS2AUD) ? L"PS2 Audio Decoder" : L"PS2 Audio Decoder (low merit)",
  351. (s.TraFilters&TRA_PS2AUD) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  352. guids.RemoveAll();
  353. }
  354. {
  355. guids.AddTail(MEDIATYPE_Video);
  356. guids.AddTail(MEDIASUBTYPE_RV10);
  357. guids.AddTail(MEDIATYPE_Video);
  358. guids.AddTail(MEDIASUBTYPE_RV20);
  359. guids.AddTail(MEDIATYPE_Video);
  360. guids.AddTail(MEDIASUBTYPE_RV30);
  361. guids.AddTail(MEDIATYPE_Video);
  362. guids.AddTail(MEDIASUBTYPE_RV40);
  363. AddFilter(new CGraphCustomFilter(__uuidof(CRealVideoDecoder), guids,
  364. (s.TraFilters&TRA_RV) ? L"RealVideo Decoder" : L"RealVideo Decoder (low merit)",
  365. (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  366. guids.RemoveAll();
  367. }
  368. {
  369. guids.AddTail(MEDIATYPE_Audio);
  370. guids.AddTail(MEDIASUBTYPE_14_4);
  371. guids.AddTail(MEDIATYPE_Audio);
  372. guids.AddTail(MEDIASUBTYPE_28_8);
  373. guids.AddTail(MEDIATYPE_Audio);
  374. guids.AddTail(MEDIASUBTYPE_ATRC);
  375. guids.AddTail(MEDIATYPE_Audio);
  376. guids.AddTail(MEDIASUBTYPE_COOK);
  377. guids.AddTail(MEDIATYPE_Audio);
  378. guids.AddTail(MEDIASUBTYPE_DNET);
  379. guids.AddTail(MEDIATYPE_Audio);
  380. guids.AddTail(MEDIASUBTYPE_SIPR);
  381. guids.AddTail(MEDIATYPE_Audio);
  382. guids.AddTail(MEDIASUBTYPE_RAAC);
  383. AddFilter(new CGraphCustomFilter(__uuidof(CRealAudioDecoder), guids, 
  384. (s.TraFilters&TRA_RA) ? L"RealAudio Decoder" : L"RealAudio Decoder (low merit)",
  385. (s.TraFilters&TRA_RA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  386. guids.RemoveAll();
  387. }
  388. {
  389. guids.AddTail(MEDIATYPE_Video);
  390. guids.AddTail(MEDIASUBTYPE_RoQV);
  391. AddFilter(new CGraphCustomFilter(__uuidof(CRoQVideoDecoder), guids,
  392. (s.TraFilters&TRA_RV) ? L"RoQ Video Decoder" : L"RoQ Video Decoder (low merit)",
  393. (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  394. guids.RemoveAll();
  395. }
  396. {
  397. guids.AddTail(MEDIATYPE_Audio);
  398. guids.AddTail(MEDIASUBTYPE_RoQA);
  399. AddFilter(new CGraphCustomFilter(__uuidof(CRoQAudioDecoder), guids,
  400. (s.TraFilters&TRA_RV) ? L"RoQ Audio Decoder" : L"RoQ Audio Decoder (low merit)",
  401. (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  402. guids.RemoveAll();
  403. }
  404. {
  405. guids.AddTail(MEDIATYPE_Stream);
  406. guids.AddTail(MEDIASUBTYPE_Dirac);
  407. AddFilter(new CGraphCustomFilter(__uuidof(CDiracSplitterFilter), guids, 
  408. (s.SrcFilters&SRC_DIRAC) ? L"Dirac Splitter" : L"Dirac Splitter (low merit)",
  409. (s.SrcFilters&SRC_DIRAC) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  410. guids.RemoveAll();
  411. }
  412. {
  413. guids.AddTail(MEDIATYPE_Video);
  414. guids.AddTail(MEDIASUBTYPE_DiracVideo);
  415. AddFilter(new CGraphCustomFilter(__uuidof(CDiracVideoDecoder), guids,
  416. (s.TraFilters&TRA_DIRAC) ? L"Dirac Video Decoder" : L"Dirac Video Decoder (low merit)",
  417. (s.TraFilters&TRA_DIRAC) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  418. guids.RemoveAll();
  419. }
  420. {
  421. guids.AddTail(MEDIATYPE_Stream);
  422. guids.AddTail(MEDIASUBTYPE_MPEG1Audio);
  423. AddFilter(new CGraphCustomFilter(__uuidof(CMpaSplitterFilter), guids, 
  424. (s.SrcFilters&SRC_MPA) ? L"Mpa Splitter" : L"Mpa Splitter (low merit)",
  425. (s.SrcFilters&SRC_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  426. guids.RemoveAll();
  427. }
  428. {
  429. guids.AddTail(MEDIATYPE_Stream);
  430. guids.AddTail(MEDIASUBTYPE_DirectShowMedia);
  431. AddFilter(new CGraphCustomFilter(__uuidof(CDSMSplitterFilter), guids, 
  432. (s.SrcFilters&SRC_DSM) ? L"DSM Splitter" : L"DSM Splitter (low merit)",
  433. (s.SrcFilters&SRC_DSM) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  434. guids.RemoveAll();
  435. }
  436. {
  437. guids.AddTail(MEDIATYPE_Stream);
  438. guids.AddTail(MEDIASUBTYPE_MP4);
  439. AddFilter(new CGraphCustomFilter(__uuidof(CMP4SplitterFilter), guids, 
  440. (s.SrcFilters&SRC_MP4) ? L"MP4 Splitter" : L"MP4 Splitter (low merit)",
  441. (s.SrcFilters&SRC_MP4) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
  442. guids.RemoveAll();
  443. }
  444. // renderer filters
  445. switch(s.iDSVideoRendererType)
  446. {
  447. default: 
  448. case VIDRNDT_DS_DEFAULT: 
  449. break;
  450. case VIDRNDT_DS_OLDRENDERER: 
  451. AddFilter(new CGraphRegFilter(CLSID_VideoRenderer, m_VRMerit));
  452. break;
  453. case VIDRNDT_DS_OVERLAYMIXER:
  454. AddFilter(new CGraphRendererFilter(CLSID_OverlayMixer, m_hWnd, L"Overlay Mixer", m_VRMerit));
  455. break;
  456. case VIDRNDT_DS_VMR7WINDOWED:
  457. AddFilter(new CGraphRendererFilter(CLSID_VideoMixingRenderer, m_hWnd, L"Video Mixing Render 7 (Windowed)", m_VRMerit));
  458. break;
  459. case VIDRNDT_DS_VMR9WINDOWED:
  460. AddFilter(new CGraphRendererFilter(CLSID_VideoMixingRenderer9, m_hWnd, L"Video Mixing Render 9 (Windowed)", m_VRMerit));
  461. break;
  462. case VIDRNDT_DS_VMR7RENDERLESS:
  463. AddFilter(new CGraphRendererFilter(CLSID_VMR7AllocatorPresenter, m_hWnd, L"Video Mixing Render 7 (Renderless)", m_VRMerit));
  464. break;
  465. case VIDRNDT_DS_VMR9RENDERLESS:
  466. AddFilter(new CGraphRendererFilter(CLSID_VMR9AllocatorPresenter, m_hWnd, L"Video Mixing Render 9 (Renderless)", m_VRMerit));
  467. break;
  468. case VIDRNDT_DS_NULL_COMP:
  469. guids.AddTail(MEDIATYPE_Video);
  470. guids.AddTail(MEDIASUBTYPE_NULL);
  471. AddFilter(new CGraphCustomFilter(__uuidof(CNullVideoRenderer), guids, L"Null Video Renderer (Any)", LMERIT_ABOVE_DSHOW+2));
  472. guids.RemoveAll();
  473. break;
  474. case VIDRNDT_DS_NULL_UNCOMP:
  475. guids.AddTail(MEDIATYPE_Video);
  476. guids.AddTail(MEDIASUBTYPE_NULL);
  477. AddFilter(new CGraphCustomFilter(__uuidof(CNullUVideoRenderer), guids, L"Null Video Renderer (Uncompressed)", LMERIT_ABOVE_DSHOW+2));
  478. guids.RemoveAll();
  479. break;
  480. }
  481. if(s.AudioRendererDisplayName == AUDRNDT_NULL_COMP)
  482. {
  483. guids.AddTail(MEDIATYPE_Audio);
  484. guids.AddTail(MEDIASUBTYPE_NULL);
  485. AddFilter(new CGraphCustomFilter(__uuidof(CNullAudioRenderer), guids, AUDRNDT_NULL_COMP, LMERIT_ABOVE_DSHOW+2));
  486. guids.RemoveAll();
  487. }
  488. else if(s.AudioRendererDisplayName == AUDRNDT_NULL_UNCOMP)
  489. {
  490. guids.AddTail(MEDIATYPE_Audio);
  491. guids.AddTail(MEDIASUBTYPE_NULL);
  492. AddFilter(new CGraphCustomFilter(__uuidof(CNullUAudioRenderer), guids, AUDRNDT_NULL_UNCOMP, LMERIT_ABOVE_DSHOW+2));
  493. guids.RemoveAll();
  494. }
  495. else if(!s.AudioRendererDisplayName.IsEmpty())
  496. {
  497. AddFilter(new CGraphRegFilter(s.AudioRendererDisplayName, m_ARMerit));
  498. }
  499. WORD lowmerit = 1;
  500. POSITION pos = s.filters.GetTailPosition();
  501. while(pos)
  502. {
  503. Filter* f = s.filters.GetPrev(pos);
  504. if(f->fDisabled
  505. || f->type == Filter::EXTERNAL && !CPath(MakeFullPath(f->path)).FileExists()) 
  506. continue;
  507. ULONGLONG merit = 
  508. f->iLoadType == Filter::PREFERRED ? LMERIT_ABOVE_DSHOW : 
  509. f->iLoadType == Filter::MERIT ? LMERIT(f->dwMerit) : 
  510. LMERIT_DO_NOT_USE; // f->iLoadType == Filter::BLOCKED
  511. merit += lowmerit++;
  512. CGraphFilter* gf = NULL;
  513. if(f->type == Filter::REGISTERED)
  514. {
  515. gf = new CGraphRegFilter(f->dispname, merit);
  516. }
  517. else if(f->type == Filter::EXTERNAL)
  518. {
  519. gf = new CGraphFileFilter(f->clsid, f->guids, f->path, CStringW(f->name), merit);
  520. }
  521. if(gf)
  522. {
  523. gf->SetGUIDs(f->guids);
  524. AddFilter(gf);
  525. }
  526. }
  527. guids.AddTail(MEDIATYPE_Text);
  528. guids.AddTail(MEDIASUBTYPE_NULL);
  529. guids.AddTail(MEDIATYPE_ScriptCommand);
  530. guids.AddTail(MEDIASUBTYPE_NULL);
  531. guids.AddTail(MEDIATYPE_Subtitle);
  532. guids.AddTail(MEDIASUBTYPE_NULL);
  533. guids.AddTail(MEDIATYPE_NULL);
  534. guids.AddTail(MEDIASUBTYPE_DVD_SUBPICTURE);
  535. guids.AddTail(MEDIATYPE_NULL);
  536. guids.AddTail(MEDIASUBTYPE_CVD_SUBPICTURE);
  537. guids.AddTail(MEDIATYPE_NULL);
  538. guids.AddTail(MEDIASUBTYPE_SVCD_SUBPICTURE);
  539. AddFilter(new CGraphCustomFilter(__uuidof(CNullTextRenderer), guids, L"NullTextRenderer", LMERIT_DO_USE));
  540. guids.RemoveAll();
  541. // FIXME: "Subtitle Mixer" makes an access violation around 
  542. // the 11-12th media type when enumerating them on its output.
  543. CLSID CLSID_SubtitlerMixer = GUIDFromCString(_T("{00A95963-3BE5-48C0-AD9F-3356D67EA09D}"));
  544. AddFilter(new CGraphRegFilter(CLSID_SubtitlerMixer, LMERIT_DO_NOT_USE));
  545. // ISCR suxx
  546. AddFilter(new CGraphRegFilter(GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}")), LMERIT_DO_NOT_USE));
  547. }
  548. CGraphBuilder::~CGraphBuilder()
  549. {
  550. }
  551. /*
  552. void CGraphBuilder::LOG(LPCTSTR fmt, ...)
  553. {
  554. va_list args;
  555. va_start(args, fmt);
  556. if(TCHAR* buff = new TCHAR[_vsctprintf(fmt, args) + 1])
  557. {
  558. _vstprintf(buff, fmt, args);
  559. m_log.AddTail(buff);
  560. TRACE(_T("GraphBuilder: Stream[%d]: %sn"), m_iStream, buff);
  561. if(FILE* f = _tfopen(_T("c:\mpcgb.txt"), _T("at")))
  562. {
  563. fseek(f, 0, 2);
  564. _ftprintf(f, _T("Stream[%d]: %sn"), m_iStream, buff);
  565. fclose(f);
  566. }
  567. delete [] buff;
  568. }
  569. va_end(args);
  570. }
  571. */
  572. void CGraphBuilder::ExtractMediaTypes(IPin* pPin, CArray<GUID>& guids)
  573. {
  574. guids.RemoveAll();
  575.     BeginEnumMediaTypes(pPin, pEM, pmt)
  576. {
  577. bool fFound = false;
  578. for(int i = 0; !fFound && i < guids.GetCount(); i += 2)
  579. {
  580. if(guids[i] == pmt->majortype && guids[i+1] == pmt->subtype)
  581. fFound = true;
  582. }
  583. if(!fFound)
  584. {
  585. guids.Add(pmt->majortype);
  586. guids.Add(pmt->subtype);
  587. }
  588. }
  589. EndEnumMediaTypes(pmt)
  590. }
  591. void CGraphBuilder::ExtractMediaTypes(IPin* pPin, CList<CMediaType>& mts)
  592. {
  593. mts.RemoveAll();
  594.     BeginEnumMediaTypes(pPin, pEM, pmt)
  595. {
  596. bool fFound = false;
  597. POSITION pos = mts.GetHeadPosition();
  598. while(!fFound && pos)
  599. {
  600. CMediaType& mt = mts.GetNext(pos);
  601. if(mt.majortype == pmt->majortype && mt.subtype == pmt->subtype)
  602. fFound = true;
  603. }
  604. if(!fFound)
  605. {
  606. mts.AddTail(CMediaType(*pmt));
  607. }
  608. }
  609. EndEnumMediaTypes(pmt)
  610. }
  611. void CGraphBuilder::SaveFilters(CInterfaceList<IBaseFilter>& bfl)
  612. {
  613. bfl.RemoveAll();
  614. BeginEnumFilters(m_pGB, pEF, pBF)
  615. bfl.AddTail(pBF);
  616. EndEnumFilters
  617. }
  618. void CGraphBuilder::RestoreFilters(CInterfaceList<IBaseFilter>& bfl)
  619. {
  620. BeginEnumFilters(m_pGB, pEF, pBF)
  621. if(!bfl.Find(pBF)) {m_pGB->RemoveFilter(pBF); pEF->Reset();}
  622. EndEnumFilters
  623. }
  624. HRESULT CGraphBuilder::SafeAddFilter(IBaseFilter* pBF, LPCWSTR pName)
  625. {
  626. if(!m_pGB || !pBF)
  627. return E_FAIL;
  628. bool fFound = false;
  629. BeginEnumFilters(m_pGB, pEF, pBF2)
  630. if(pBF == pBF2) fFound = true;
  631. EndEnumFilters
  632. if(fFound) return S_OK;
  633. CFilterInfo fi;
  634. if(SUCCEEDED(pBF->QueryFilterInfo(&fi)))
  635. {
  636. if(!fi.pGraph) // not in graph yet?
  637. {
  638. CStringW name;
  639. if(pName && wcslen(pName) > 0)
  640. {
  641. name = pName;
  642. }
  643. else
  644. {
  645. if(CComQIPtr<IFileSourceFilter> pFSF = pBF)
  646. {
  647. CMediaType mt;
  648. LPOLESTR str = NULL;
  649. if(SUCCEEDED(pFSF->GetCurFile(&str, &mt))) name = str;
  650. if(str) CoTaskMemFree(str);
  651. }
  652. if(name.IsEmpty())
  653. {
  654. CLSID clsid = GetCLSID(pBF);
  655. name = clsid == GUID_NULL ? L"Unknown Filter" : CStringFromGUID(clsid);
  656. }
  657. }
  658. if(FAILED(m_pGB->AddFilter(pBF, name)))
  659. {
  660. return E_FAIL;
  661. }
  662. }
  663. return S_OK;
  664. }
  665. return E_FAIL;
  666. }
  667. void CGraphBuilder::Reset()
  668. {
  669. m_nTotalStreams = 0;
  670. m_nCurrentStream = 0;
  671. m_pUnks.RemoveAll();
  672. m_DeadEnds.RemoveAll();
  673. // m_log.RemoveAll();
  674. }
  675. HRESULT CGraphBuilder::AddSourceFilter(LPCTSTR lpsz, IBaseFilter** ppBF, UINT SrcFilters)
  676. {
  677. CheckPointer(lpsz, E_POINTER);
  678. CheckPointer(ppBF, E_POINTER);
  679. if(!m_pGB) return E_UNEXPECTED;
  680. CString fn = CString(lpsz).Trim();
  681. if(fn.IsEmpty()) return E_FAIL;
  682. CStringW fnw = fn;
  683. CString ext = CPath(fn).GetExtension().MakeLower();
  684. HRESULT hr;
  685. CComQIPtr<IBaseFilter> pBF;
  686. CComQIPtr<IGraphEngine> pGE = m_pGB;
  687. if(!pGE || pGE->GetEngine() == DirectShow)
  688. {
  689. /*
  690. if(!pBF && fn.Find(_T("://")) > 0)
  691. {
  692. CList<CString> mms;
  693. CString ct = GetContentType(fn, &mms); // TODO: if there are more to check, do GetContentType only once
  694. if(ct == _T("video/x-ms-asf") || ct == _T("video/x-ms-wmv")
  695. || ct == _T("video/x-ms-wvx") || ct == _T("video/x-ms-wax")
  696. || ct == _T("video/x-ms-wmp"))
  697. {
  698. if(!mms.IsEmpty()) fnw = mms.GetHead();
  699. fnw.Replace(L"&MSWMExt=.asf", L"");
  700. CComPtr<IFileSourceFilter> pReader;
  701. hr = pReader.CoCreateInstance(CLSID_NetShowSource);
  702. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  703. pBF = pReader;
  704. }
  705. }
  706. */
  707. if((SrcFilters&SRC_SUBS) && !pBF)
  708. {
  709. hr = S_OK;
  710. CComPtr<IFileSourceFilter> pReader = new CSubtitleSourceASS(NULL, &hr);
  711. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  712. pBF = pReader;
  713. }
  714. if((SrcFilters&SRC_CDDA) && !pBF && ext == _T(".cda"))
  715. {
  716. hr = S_OK;
  717. CComPtr<IFileSourceFilter> pReader = new CCDDAReader(NULL, &hr);
  718. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  719. pBF = pReader;
  720. }
  721. if((SrcFilters&SRC_CDXA) && !pBF)
  722. {
  723. hr = S_OK;
  724. CComPtr<IFileSourceFilter> pReader = new CCDXAReader(NULL, &hr);
  725. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  726. pBF = pReader;
  727. }
  728. if((SrcFilters&SRC_VTS) && !pBF) //&& ext == _T(".ifo"))
  729. {
  730. hr = S_OK;
  731. CComPtr<IFileSourceFilter> pReader = new CVTSReader(NULL, &hr);
  732. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  733. pBF = pReader;
  734. }
  735. if((SrcFilters&SRC_FLIC) && !pBF) //&& (ext == _T(".fli") || ext == _T(".flc")))
  736. {
  737. hr = S_OK;
  738. CComPtr<IFileSourceFilter> pReader = new CFLICSource(NULL, &hr);
  739. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  740. pBF = pReader;
  741. }
  742. if((SrcFilters&SRC_D2V) && !pBF) //&& ext == _T(".d2v"))
  743. {
  744. hr = S_OK;
  745. CComPtr<IFileSourceFilter> pReader = new CD2VSource(NULL, &hr);
  746. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  747. pBF = pReader;
  748. }
  749. if((SrcFilters&SRC_DTSAC3) && !pBF) //&& (ext == _T(".dts") || ext == _T(".ac3")))
  750. {
  751. hr = S_OK;
  752. CComPtr<IFileSourceFilter> pReader = new CDTSAC3Source(NULL, &hr);
  753. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  754. pBF = pReader;
  755. }
  756. if((SrcFilters&SRC_SHOUTCAST) && !pBF && fn.Find(_T("://")) >= 0)
  757. {
  758. hr = S_OK;
  759. CComPtr<IFileSourceFilter> pReader = new CShoutcastSource(NULL, &hr);
  760. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  761. pBF = pReader;
  762. }
  763. if((SrcFilters&SRC_MATROSKA) && !pBF) //&& (ext == _T(".mkv") || ext == _T(".mka") || ext == _T(".mks")))
  764. {
  765. hr = S_OK;
  766. CComPtr<IFileSourceFilter> pReader = new CMatroskaSourceFilter(NULL, &hr);
  767. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  768. pBF = pReader;
  769. }
  770. if((SrcFilters&SRC_REALMEDIA) && !pBF)
  771. {
  772. hr = S_OK;
  773. CComPtr<IFileSourceFilter> pReader = new CRealMediaSourceFilter(NULL, &hr);
  774. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  775. pBF = pReader;
  776. }
  777. if((SrcFilters&SRC_AVI) && !pBF)
  778. {
  779. hr = S_OK;
  780. CComPtr<IFileSourceFilter> pReader = new CAviSourceFilter(NULL, &hr);
  781. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  782. pBF = pReader;
  783. }
  784. __if_exists(CRadGtSplitterFilter)
  785. {
  786. if((SrcFilters&SRC_RADGT) && !pBF)
  787. {
  788. hr = S_OK;
  789. CComPtr<IFileSourceFilter> pReader = new CRadGtSourceFilter(NULL, &hr);
  790. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  791. pBF = pReader;
  792. }
  793. }
  794. if((SrcFilters&SRC_ROQ) && !pBF)
  795. {
  796. hr = S_OK;
  797. CComPtr<IFileSourceFilter> pReader = new CRoQSourceFilter(NULL, &hr);
  798. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  799. pBF = pReader;
  800. }
  801. if((SrcFilters&SRC_OGG) && !pBF)
  802. {
  803. hr = S_OK;
  804. CComPtr<IFileSourceFilter> pReader = new COggSourceFilter(NULL, &hr);
  805. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  806. pBF = pReader;
  807. }
  808. if((SrcFilters&SRC_NUT) && !pBF)
  809. {
  810. hr = S_OK;
  811. CComPtr<IFileSourceFilter> pReader = new CNutSourceFilter(NULL, &hr);
  812. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  813. pBF = pReader;
  814. }
  815. if((SrcFilters&SRC_MPEG) && !pBF)
  816. {
  817. hr = S_OK;
  818. CComPtr<IFileSourceFilter> pReader = new CMpegSourceFilter(NULL, &hr);
  819. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  820. pBF = pReader;
  821. }
  822. if((SrcFilters&SRC_DIRAC) && !pBF)
  823. {
  824. hr = S_OK;
  825. CComPtr<IFileSourceFilter> pReader = new CDiracSourceFilter(NULL, &hr);
  826. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  827. pBF = pReader;
  828. }
  829. if((SrcFilters&SRC_MPA) && !pBF)
  830. {
  831. hr = S_OK;
  832. CComPtr<IFileSourceFilter> pReader = new CMpaSourceFilter(NULL, &hr);
  833. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  834. pBF = pReader;
  835. }
  836. if((SrcFilters&SRC_DSM) && !pBF)
  837. {
  838. hr = S_OK;
  839. CComPtr<IFileSourceFilter> pReader = new CDSMSourceFilter(NULL, &hr);
  840. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  841. pBF = pReader;
  842. }
  843. if((SrcFilters&SRC_MP4) && !pBF)
  844. {
  845. hr = S_OK;
  846. CComPtr<IFileSourceFilter> pReader = new CMP4SourceFilter(NULL, &hr);
  847. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  848. pBF = pReader;
  849. }
  850. if(!pBF && fn.Find(_T("://")) < 0)
  851. {
  852. bool fWindowsMedia = (ext == _T(".asf") || ext == _T(".wmv") || ext == _T(".wma"));
  853. if(!fWindowsMedia)
  854. {
  855. CFile f;
  856. if(f.Open(fn, CFile::modeRead))
  857. {
  858. BYTE buff[4];
  859. memset(buff, 0, sizeof(buff));
  860. f.Read(buff, sizeof(buff));
  861. if(*(DWORD*)buff == 0x75b22630)
  862. fWindowsMedia = true;
  863. }
  864. }
  865. if(fWindowsMedia)
  866. {
  867. CComPtr<IFileSourceFilter> pReader;
  868. hr = pReader.CoCreateInstance(AfxGetAppSettings().fUseWMASFReader ? CLSID_WMAsfReader : CLSID_NetShowSource);
  869. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  870. pBF = pReader;
  871. }
  872. }
  873. /*
  874. if(!pBF && fn.Find(_T("://")) < 0)
  875. {
  876. CFile f;
  877. if(f.Open(fn, CFile::modeRead|CFile::shareDenyWrite))
  878. {
  879. ULONGLONG len = f.GetLength();
  880. BYTE buff[12];
  881. memset(buff, 0, sizeof(buff));
  882. f.Read(buff, sizeof(buff));
  883. if(*((DWORD*)&buff[0]) == 'FFIR' && *((DWORD*)&buff[8]) == ' IVA')
  884. {
  885. if(len < *((DWORD*)&buff[4])+8)
  886. {
  887. MessageBeep(-1);
  888. CComPtr<IFileSourceFilter> pReader;
  889. hr = pReader.CoCreateInstance(CLSID_AVIDoc);
  890. if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
  891. pBF = pReader;
  892. }
  893. }
  894. }
  895. }
  896. */
  897. }
  898. if(!pBF)
  899. {
  900. CheckStupidSharedFilesourceFilter();
  901. if(FAILED(hr = m_pGB->AddSourceFilter(fnw, fnw, &pBF)))
  902. return hr;
  903. if(SUCCEEDED(hr) && !pBF) // custom graphs don't need filters
  904. return hr;
  905. }
  906. ASSERT(pBF);
  907. if(FAILED(SafeAddFilter(pBF, NULL)))
  908. return E_FAIL;
  909. *ppBF = pBF.Detach();
  910. return S_OK;
  911. }
  912. HRESULT CGraphBuilder::Render(LPCTSTR lpsz)
  913. {
  914. CComPtr<IBaseFilter> pBF;
  915. HRESULT hr = AddSourceFilter(lpsz, &pBF, AfxGetAppSettings().SrcFilters & ~SRC_SUBS);
  916. if(FAILED(hr)) return hr;
  917. return pBF ? Render(pBF) : S_OK;
  918. }
  919. HRESULT CGraphBuilder::Render(IBaseFilter* pBF)
  920. {
  921. if(!m_pGB || !m_pFM || !pBF)
  922. return E_FAIL;
  923. if(FAILED(SafeAddFilter(pBF, NULL)))
  924. return E_FAIL;
  925. CInterfaceList<IPin> pOutputs;
  926. BeginEnumPins(pBF, pEP, pPin)
  927. {
  928. PIN_DIRECTION dir;
  929. CComPtr<IPin> pTmp;
  930. CPinInfo pi;
  931. if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT // not an output?
  932. || SUCCEEDED(pPin->ConnectedTo(&pTmp)) // already connected?
  933. || FAILED(pPin->QueryPinInfo(&pi)) || pi.achName[0] == '~') // hidden?
  934. continue;
  935. pOutputs.AddTail(pPin);
  936. }
  937. EndEnumPins
  938. int nRendered = 0;
  939. if(pOutputs.GetCount() > 0)
  940. {
  941. POSITION pos = pOutputs.GetHeadPosition();
  942. while(pos)
  943. {
  944. if(SUCCEEDED(Render(pOutputs.GetNext(pos)))) nRendered++;
  945. if(pOutputs.GetCount() > 1) m_nCurrentStream++;
  946. }
  947. }
  948. else
  949. {
  950. m_nTotalStreams++;
  951. for(int i = 0; i < m_DeadEnds.GetCount(); i++)
  952. {
  953. if(m_DeadEnds[i]->nStream == m_nCurrentStream)
  954. m_DeadEnds.RemoveAt(i--);
  955. }
  956. }
  957. return 
  958. nRendered == pOutputs.GetCount() ? (nRendered > 0 ? S_OK : S_FALSE) :
  959. nRendered > 0 ? VFW_S_PARTIAL_RENDER :
  960. VFW_E_CANNOT_RENDER;
  961. }
  962. typedef struct {CGraphFilter* pFilter; bool fExactMatch;} SortFilter;
  963. static int compare(const void* arg1, const void* arg2)
  964. {
  965. SortFilter* sf1 = (SortFilter*)arg1;
  966. SortFilter* sf2 = (SortFilter*)arg2;
  967. /*
  968. if(sf1->pFilter->GetMerit() < LMERIT(MERIT_PREFERRED) && sf2->pFilter->GetMerit() < LMERIT(MERIT_PREFERRED))
  969. {
  970. if(!sf1->fExactMatch && sf2->fExactMatch) return 1;
  971. else if(sf1->fExactMatch && !sf2->fExactMatch) return -1;
  972. }
  973. */
  974. if(sf1->pFilter->GetCLSID() == sf2->pFilter->GetCLSID())
  975. {
  976. // prefer externals
  977. CGraphFileFilter* f1 = dynamic_cast<CGraphFileFilter*>(sf1->pFilter);
  978. CGraphFileFilter* f2 = dynamic_cast<CGraphFileFilter*>(sf2->pFilter);
  979. if(!f1 && f2) return 1;
  980. if(f1 && !f2) return -1;
  981. }
  982. if(sf1->pFilter->GetMerit() < sf2->pFilter->GetMerit()) return 1;
  983. else if(sf1->pFilter->GetMerit() > sf2->pFilter->GetMerit()) return -1;
  984. if(!sf1->fExactMatch && sf2->fExactMatch) return 1;
  985. else if(sf1->fExactMatch && !sf2->fExactMatch) return -1;
  986. return 0;
  987. }
  988. HRESULT CGraphBuilder::Render(IPin* pPin)
  989. {
  990. if(!m_pGB || !m_pFM || !pPin)
  991. return E_FAIL;
  992. PIN_DIRECTION dir;
  993. CComPtr<IPin> pPinTmp;
  994. if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT
  995. || SUCCEEDED(pPin->ConnectedTo(&pPinTmp)))
  996. return E_UNEXPECTED;
  997. if(GetCLSID(pPin) == CLSID_MPEG2Demultiplexer)
  998. {
  999. CComQIPtr<IMediaSeeking> pMS = pPin;
  1000. if(!pMS) return E_FAIL;
  1001. REFERENCE_TIME rtDur = 0;
  1002. if(FAILED(pMS->GetDuration(&rtDur)) || rtDur <= 0)
  1003.  return E_FAIL;
  1004. rtDur = rtDur;
  1005. }
  1006. bool fDeadEnd = true;
  1007. // 1. stream builder interface
  1008. if(CComQIPtr<IStreamBuilder> pSB = pPin)
  1009. {
  1010. CInterfaceList<IBaseFilter> bfl;
  1011. SaveFilters(bfl);
  1012. if(SUCCEEDED(pSB->Render(pPin, m_pGB)))
  1013. return S_OK;
  1014. pSB->Backout(pPin, m_pGB);
  1015. RestoreFilters(bfl);
  1016. }
  1017. // 2. filter cache
  1018. if(CComQIPtr<IGraphConfig> pGC = m_pGB)
  1019. {
  1020. CComPtr<IEnumFilters> pEF;
  1021. if(SUCCEEDED(pGC->EnumCacheFilter(&pEF)))
  1022. {
  1023. for(CComPtr<IBaseFilter> pBF; S_OK == pEF->Next(1, &pBF, NULL); pBF = NULL)
  1024. {
  1025. CInterfaceList<IBaseFilter> bfl;
  1026. SaveFilters(bfl);
  1027. pGC->RemoveFilterFromCache(pBF);
  1028. if(SUCCEEDED(ConnectDirect(pPin, pBF)))
  1029. {
  1030. fDeadEnd = false;
  1031. HRESULT hr;
  1032. if(SUCCEEDED(hr = Render(pBF)))
  1033. return hr;
  1034. }
  1035. pGC->AddFilterToCache(pBF);
  1036. RestoreFilters(bfl);
  1037. }
  1038. }
  1039. }
  1040. // 3. disconnected inputs
  1041. CInterfaceList<IBaseFilter> pFilters;
  1042. SaveFilters(pFilters);
  1043. POSITION pos;
  1044. // FIXME: ffdshow likes to connect to the audio capture filter's fake input pins
  1045. if(!dynamic_cast<CGraphBuilderCapture*>(this))
  1046. {
  1047. pos = pFilters.GetHeadPosition();
  1048. while(pos)
  1049. {
  1050. CComPtr<IBaseFilter> pBF = pFilters.GetNext(pos);
  1051. if(SUCCEEDED(ConnectDirect(pPin, pBF)))
  1052. {
  1053. fDeadEnd = false;
  1054. HRESULT hr;
  1055. if(SUCCEEDED(hr = Render(pBF)))
  1056. return hr;
  1057. }
  1058. }
  1059. }
  1060. // 4. registry+internal+external
  1061. // TODO: try media types one-by-one and pass pmt to ConnectDirect (this may not be better than the current!!!)
  1062. CArray<GUID> guids;
  1063.     ExtractMediaTypes(pPin, guids);
  1064. if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Stream && guids[1] == MEDIASUBTYPE_NULL)
  1065. {
  1066. if(CComQIPtr<IAsyncReader> pReader = pPin)
  1067. {
  1068. BYTE buff[4];
  1069. if(S_OK == pReader->SyncRead(0, 4, buff) && *(DWORD*)buff == 'SggO')
  1070. guids[1] = MEDIASUBTYPE_Ogg;
  1071. }
  1072. }
  1073. else if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Video && guids[1] == FOURCCMap('MGXD'))
  1074. {
  1075. guids[1] = FOURCCMap('XVID');
  1076. }
  1077. CAutoPtrList<CGraphFilter> autogfs;
  1078. CArray<CGraphFilter*> gfs;
  1079. CComPtr<IEnumMoniker> pEM;
  1080. if(guids.GetCount() > 0 
  1081. && SUCCEEDED(m_pFM->EnumMatchingFilters(
  1082. &pEM, 0, FALSE, MERIT_DO_NOT_USE+1, 
  1083. TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, FALSE,
  1084. FALSE, 0, NULL, NULL, NULL)))
  1085. {
  1086. for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
  1087. {
  1088. CAutoPtr<CGraphFilter> pGraphFilter(new CGraphRegFilter(pMoniker));
  1089. if(pGraphFilter)
  1090. {
  1091. POSITION pos = m_pMoreFilters.GetHeadPosition();
  1092. while(pos)
  1093. {
  1094. CGraphRegFilter* f = dynamic_cast<CGraphRegFilter*>((CGraphFilter*)m_pMoreFilters.GetNext(pos));
  1095. if(!f) continue;
  1096. if(f->GetMoniker() && S_OK == pMoniker->IsEqual(f->GetMoniker())
  1097. || f->GetCLSID() != GUID_NULL && f->GetCLSID() == pGraphFilter->GetCLSID())
  1098. {
  1099. pGraphFilter.Free();
  1100. break;
  1101. }
  1102. }
  1103. }
  1104. if(pGraphFilter)
  1105. {
  1106. autogfs.AddTail(pGraphFilter);
  1107. }
  1108. }
  1109. }
  1110. pos = autogfs.GetHeadPosition();
  1111. while(pos)
  1112. {
  1113. CGraphFilter* f = autogfs.GetNext(pos);
  1114. bool fFound = false;
  1115. POSITION pos2 = m_chain.GetHeadPosition();
  1116. while(pos2)
  1117. {
  1118. if(f->GetCLSID() == m_chain.GetNext(pos2)->GetCLSID())
  1119. {
  1120. fFound = true;
  1121. break;
  1122. }
  1123. }
  1124. if(!fFound)
  1125. gfs.Add(f);
  1126. }
  1127. pos = m_pMoreFilters.GetHeadPosition();
  1128. while(pos)
  1129. {
  1130. CGraphFilter* f = m_pMoreFilters.GetNext(pos);
  1131. if(f->GetMerit() >= LMERIT_DO_USE && !m_chain.Find(f) && f->IsCompatible(guids))
  1132. gfs.Add(f);
  1133. }
  1134. CArray<SortFilter> sfs;
  1135. sfs.SetSize(gfs.GetCount());
  1136. for(int i = 0; i < gfs.GetCount(); i++)
  1137. {
  1138. sfs[i].pFilter = gfs[i];
  1139. sfs[i].fExactMatch = gfs[i]->IsExactMatch(guids);
  1140. }
  1141. if(sfs.GetCount() > 1) qsort(sfs.GetData(), sfs.GetCount(), sizeof(SortFilter), compare);
  1142. for(int i = 0; i < sfs.GetCount(); i++)
  1143. {
  1144. CGraphFilter* gf = sfs[i].pFilter;
  1145. if(!gf) continue;
  1146. CComPtr<IBaseFilter> pBF;
  1147. CComPtr<IUnknown> pUnk;
  1148. if(FAILED(gf->Create(&pBF, &pUnk)))
  1149. continue;
  1150. CInterfaceList<IBaseFilter> bfl;
  1151. SaveFilters(bfl);
  1152. if(FAILED(SafeAddFilter(pBF, gf->GetName())))
  1153. continue;
  1154. if(gf->GetCLSID() == CLSID_DMOWrapperFilter)
  1155. {
  1156. if(CComQIPtr<IPropertyBag> pPBag = pBF)
  1157. {
  1158. CComVariant var(true);
  1159. pPBag->Write(CComBSTR(L"_HIRESOUTPUT"), &var);
  1160. }
  1161. }
  1162. if(CComQIPtr<IMpeg2DecFilter> m_pMpeg2DecFilter = pBF)
  1163. {
  1164. AppSettings& s = AfxGetAppSettings();
  1165. m_pMpeg2DecFilter->SetDeinterlaceMethod((ditype)s.mpegdi);
  1166. m_pMpeg2DecFilter->SetBrightness(s.mpegbright);
  1167. m_pMpeg2DecFilter->SetContrast(s.mpegcont);
  1168. m_pMpeg2DecFilter->SetHue(s.mpeghue);
  1169. m_pMpeg2DecFilter->SetSaturation(s.mpegsat);
  1170. m_pMpeg2DecFilter->EnableForcedSubtitles(s.mpegforcedsubs);
  1171. m_pMpeg2DecFilter->EnablePlanarYUV(s.mpegplanaryuv);
  1172. }
  1173. if(CComQIPtr<IMpaDecFilter> m_pMpaDecFilter = pBF)
  1174. {
  1175. AppSettings& s = AfxGetAppSettings();
  1176. m_pMpaDecFilter->SetSampleFormat((SampleFormat)s.mpasf);
  1177. m_pMpaDecFilter->SetNormalize(s.mpanormalize);
  1178. m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::ac3, s.ac3sc);
  1179. m_pMpaDecFilter->SetDynamicRangeControl(IMpaDecFilter::ac3, s.ac3drc);
  1180. m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::dts, s.dtssc);
  1181. m_pMpaDecFilter->SetDynamicRangeControl(IMpaDecFilter::dts, s.dtsdrc);
  1182. m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::aac, s.aacsc);
  1183. m_pMpaDecFilter->SetBoost(s.mpaboost);
  1184. }
  1185. HRESULT hr = E_FAIL;
  1186. if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Stream && guids[1] != MEDIATYPE_NULL)
  1187. {
  1188. CMediaType mt;
  1189. mt.majortype = guids[0];
  1190. mt.subtype = guids[1];
  1191. mt.formattype = FORMAT_None;
  1192. hr = ConnectDirect(pPin, pBF, &mt);
  1193. if(FAILED(hr))
  1194. {
  1195. mt.formattype = GUID_NULL;
  1196. hr = ConnectDirect(pPin, pBF, &mt);
  1197. }
  1198. }
  1199. if(SUCCEEDED(hr) || SUCCEEDED(ConnectDirect(pPin, pBF, NULL)))
  1200. {
  1201. fDeadEnd = false;
  1202. int nCurrentStream = m_nCurrentStream;
  1203. m_chain.AddTail(gf);
  1204. hr = Render(pBF);
  1205. m_chain.RemoveTail();
  1206. if(SUCCEEDED(hr))
  1207. {
  1208. if(pUnk) m_pUnks.AddTail(pUnk);
  1209. // maybe the application should do this...
  1210. if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pUnk)
  1211. pMPC->SetAspectRatioMode(AM_ARMODE_STRETCHED);
  1212. if(CComQIPtr<IVMRAspectRatioControl> pARC = pBF)
  1213. pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
  1214. if(CComQIPtr<IVMRAspectRatioControl9> pARC = pBF)
  1215. pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
  1216. return hr;
  1217. }
  1218. m_nCurrentStream = nCurrentStream;
  1219. }
  1220. m_pGB->RemoveFilter(pBF);
  1221. RestoreFilters(bfl);
  1222. }
  1223. // 5. record filter/pin/mts if this was the end of a chain
  1224. if(fDeadEnd)
  1225. {
  1226. CAutoPtr<DeadEnd> de(new DeadEnd);
  1227. de->nStream = m_nCurrentStream;
  1228. de->clsid = CStringFromGUID(GetCLSID(pPin));
  1229. de->filter = GetFilterName(GetFilterFromPin(pPin));
  1230. de->pin = GetPinName(pPin);
  1231. ExtractMediaTypes(pPin, de->mts);
  1232. if(!(m_chain.GetCount() == 0 && de->mts.GetCount() == 1
  1233. && de->mts.GetHead().majortype == MEDIATYPE_Stream && de->mts.GetHead().subtype == MEDIASUBTYPE_NULL))
  1234. {
  1235. CString str;
  1236. str.Format(_T("Stream %d"), m_nCurrentStream);
  1237. de->path.AddTail(str);
  1238. POSITION pos = m_chain.GetHeadPosition();
  1239. while(pos) de->path.AddTail(CString(m_chain.GetNext(pos)->GetName()));
  1240. m_DeadEnds.Add(de);
  1241. }
  1242. }
  1243. return E_FAIL;
  1244. }
  1245. HRESULT CGraphBuilder::ConnectDirect(IPin* pPin, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt)
  1246. {
  1247. if(!pPin || !pBF)
  1248. return E_INVALIDARG;
  1249. if(FAILED(SafeAddFilter(pBF, NULL)))
  1250. return E_FAIL;
  1251. BeginEnumPins(pBF, pEP, pPinTo)
  1252. {
  1253. PIN_DIRECTION dir;
  1254. CComPtr<IPin> pTmp;
  1255. if(FAILED(pPinTo->QueryDirection(&dir)) || dir != PINDIR_INPUT
  1256. || SUCCEEDED(pPinTo->ConnectedTo(&pTmp)))
  1257. continue;
  1258. if(SUCCEEDED(m_pGB->ConnectDirect(pPin, pPinTo, pmt)))
  1259. return S_OK;
  1260. }
  1261. EndEnumPins
  1262. return VFW_E_CANNOT_CONNECT;
  1263. }
  1264. HRESULT CGraphBuilder::FindInterface(REFIID iid, void** ppv)
  1265. {
  1266. CheckPointer(ppv, E_POINTER);
  1267. POSITION pos = m_pUnks.GetHeadPosition();
  1268. while(pos)
  1269. {
  1270. IUnknown* pUnk = m_pUnks.GetNext(pos);
  1271. HRESULT hr;
  1272. if(SUCCEEDED(hr = pUnk->QueryInterface(iid, ppv)))
  1273. return hr;
  1274. }
  1275. return E_NOINTERFACE;
  1276. }
  1277. //
  1278. // CGraphBuilderFile
  1279. //
  1280. CGraphBuilderFile::CGraphBuilderFile(IGraphBuilder* pGB, HWND hWnd)
  1281. : CGraphBuilder(pGB, hWnd)
  1282. {
  1283. CList<GUID> guids;
  1284. if(AfxGetAppSettings().fEnableAudioSwitcher)
  1285. {
  1286. guids.AddTail(MEDIATYPE_Audio);
  1287. guids.AddTail(MEDIASUBTYPE_NULL);
  1288. AddFilter(new CGraphCustomFilter(__uuidof(CAudioSwitcherFilter), guids, L"Audio Switcher", m_ARMerit + 0x100));
  1289. guids.RemoveAll();
  1290. CLSID CLSID_MorganStreamSwitcher = GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}"));
  1291. AddFilter(new CGraphRegFilter(CLSID_MorganStreamSwitcher, LMERIT_DO_NOT_USE));
  1292. }
  1293. }
  1294. //
  1295. // CGraphBuilderDVD
  1296. //
  1297. CGraphBuilderDVD::CGraphBuilderDVD(IGraphBuilder* pGB, HWND hWnd)
  1298. : CGraphBuilderFile(pGB, hWnd)
  1299. {
  1300. CList<GUID> guids;
  1301. /*
  1302. // there wasn't much use of this and the users were just 
  1303. // confused by "decss" being in the report after a failed 
  1304. // dvd nav pin rendering
  1305. guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
  1306. guids.AddTail(MEDIASUBTYPE_NULL);
  1307. AddFilter(new CGraphCustomFilter(__uuidof(CDeCSSFilter), guids, L"DeCSS", LMERIT_UNLIKELY));
  1308. guids.RemoveAll();
  1309. */
  1310. DWORD ver = ::GetVersion();
  1311. bool m_fXp = (int)ver >= 0 && (((ver<<8)&0xff00)|((ver>>8)&0xff)) >= 0x0501;
  1312. AppSettings& s = AfxGetAppSettings();
  1313. if(!m_fXp && s.iDSVideoRendererType != VIDRNDT_DS_OVERLAYMIXER 
  1314. || s.iDSVideoRendererType == VIDRNDT_DS_OLDRENDERER)
  1315.         AddFilter(new CGraphRendererFilter(CLSID_OverlayMixer, m_hWnd, L"Overlay Mixer", m_VRMerit-1));
  1316. // this filter just simply sucks for dvd playback (atm)
  1317. CLSID CLSID_ElecardMpeg2 = GUIDFromCString(_T("{F50B3F13-19C4-11CF-AA9A-02608C9BABA2}"));
  1318. AddFilter(new CGraphRegFilter(CLSID_ElecardMpeg2, LMERIT_DO_NOT_USE));
  1319. }
  1320. #include "....decssVobFile.h"
  1321. class CResetDVD : public CDVDSession
  1322. {
  1323. public:
  1324. CResetDVD(LPCTSTR path)
  1325. {
  1326. if(Open(path))
  1327. {
  1328. if(BeginSession())
  1329. {
  1330. Authenticate();
  1331. // GetDiscKey();
  1332. EndSession();
  1333. }
  1334. Close();
  1335. }
  1336. }
  1337. };
  1338. [uuid("482d10b6-376e-4411-8a17-833800A065DB")]
  1339. class ratDVDNavigator {};
  1340. HRESULT CGraphBuilderDVD::Render(CString fn, CString& path)
  1341. {
  1342. if(!m_pGB) return E_INVALIDARG;
  1343. HRESULT hr;
  1344. GUID clsid = CLSID_DVDNavigator;
  1345. if(fn.MakeLower().Find(_T(".ratdvd")) >= 0)
  1346. clsid = __uuidof(ratDVDNavigator);
  1347. CComPtr<IBaseFilter> pBF;
  1348. if(FAILED(hr = pBF.CoCreateInstance(clsid)))
  1349.   return E_FAIL;
  1350. if(FAILED(hr = m_pGB->AddFilter(pBF, L"DVD Navigator")))
  1351. return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
  1352. CComQIPtr<IDvdControl2> pDVDC;
  1353. CComQIPtr<IDvdInfo2> pDVDI;
  1354. if(!((pDVDC = pBF) && (pDVDI = pBF)))
  1355. return E_NOINTERFACE;
  1356. WCHAR buff[MAX_PATH];
  1357. ULONG len;
  1358. if((!fn.IsEmpty()
  1359. && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn)))
  1360. && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn + _T("VIDEO_TS"))))
  1361. && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn + _T("\VIDEO_TS")))))
  1362. || FAILED(hr = pDVDI->GetDVDDirectory(buff, MAX_PATH, &len)) || len == 0)
  1363. return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
  1364. path = buff;
  1365. pDVDC->SetOption(DVD_ResetOnStop, FALSE);
  1366. pDVDC->SetOption(DVD_HMSF_TimeCodeEvents, TRUE);
  1367. m_pUnks.AddTail(pDVDC);
  1368. m_pUnks.AddTail(pDVDI);
  1369. if(clsid == CLSID_DVDNavigator)
  1370. CResetDVD tmp(path);
  1371. return __super::Render(pBF);
  1372. }
  1373. //
  1374. // CGraphBuilderCapture
  1375. //
  1376. CGraphBuilderCapture::CGraphBuilderCapture(IGraphBuilder* pGB, HWND hWnd)
  1377. : CGraphBuilderFile(pGB, hWnd)
  1378. {
  1379. CList<GUID> guids;
  1380. // if(AfxGetAppSettings().fEnableDeinterlacer)
  1381. {
  1382. guids.AddTail(MEDIATYPE_Video);
  1383. guids.AddTail(MEDIASUBTYPE_NULL);
  1384. AddFilter(new CGraphCustomFilter(__uuidof(CDeinterlacerFilter), guids, L"Deinterlacer", m_VRMerit + 0x100));
  1385. guids.RemoveAll();
  1386. }
  1387. /**/
  1388. CLSID CLSID_MorganStreamSwitcher = GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}"));
  1389. AddFilter(new CGraphRegFilter(CLSID_MorganStreamSwitcher, LMERIT_DO_NOT_USE));
  1390. }
  1391. //
  1392. // CGraphFilter
  1393. //
  1394. CGraphFilter::CGraphFilter(CStringW name, ULONGLONG merit)
  1395. : m_name(name), m_clsid(GUID_NULL)
  1396. {
  1397. m_merit.val = merit;
  1398. }
  1399. bool CGraphFilter::IsExactMatch(CArray<GUID>& guids)
  1400. {
  1401. POSITION pos = m_guids.GetHeadPosition();
  1402. while(pos)
  1403. {
  1404. GUID& major = m_guids.GetNext(pos);
  1405. if(!pos) {ASSERT(0); break;}
  1406. GUID& sub = m_guids.GetNext(pos);
  1407. for(int i = 0; i < (guids.GetCount()&~1); i += 2)
  1408. {
  1409. if(major == guids[i] && major != GUID_NULL
  1410. && sub == guids[i+1] && sub != GUID_NULL)
  1411.              return(true);
  1412. }
  1413. }
  1414. return(false);
  1415. }
  1416. bool CGraphFilter::IsCompatible(CArray<GUID>& guids)
  1417. {
  1418. POSITION pos = m_guids.GetHeadPosition();
  1419. while(pos)
  1420. {
  1421. GUID& major = m_guids.GetNext(pos);
  1422. if(!pos) {ASSERT(0); break;}
  1423. GUID& sub = m_guids.GetNext(pos);
  1424. for(int i = 0; i < (guids.GetCount()&~1); i += 2)
  1425. {
  1426. if((major == GUID_NULL || guids[i] == GUID_NULL || major == guids[i])
  1427. && (sub == GUID_NULL || guids[i+1] == GUID_NULL || sub == guids[i+1]))
  1428.              return(true);
  1429. }
  1430. }
  1431. return(false);
  1432. }
  1433. //
  1434. // CGraphRegFilter
  1435. //
  1436. CGraphRegFilter::CGraphRegFilter(IMoniker* pMoniker, ULONGLONG merit) 
  1437. : CGraphFilter(L"", merit), m_pMoniker(pMoniker)
  1438. {
  1439. if(!m_pMoniker) return;
  1440. LPOLESTR str = NULL;
  1441. if(FAILED(m_pMoniker->GetDisplayName(0, 0, &str))) return;
  1442. m_dispname = m_name = str;
  1443. CoTaskMemFree(str), str = NULL;
  1444. CComPtr<IPropertyBag> pPB;
  1445. if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
  1446. {
  1447. CComVariant var;
  1448. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
  1449. {
  1450. m_name = var.bstrVal;
  1451. var.Clear();
  1452. }
  1453. if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
  1454. {
  1455. CLSIDFromString(var.bstrVal, &m_clsid);
  1456. var.Clear();
  1457. }
  1458. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
  1459. {
  1460. BSTR* pstr;
  1461. if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
  1462. {
  1463. ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
  1464. SafeArrayUnaccessData(var.parray);
  1465. }
  1466. var.Clear();
  1467. }
  1468. }
  1469. if(merit != LMERIT_DO_USE) m_merit.val = merit;
  1470. }
  1471. CGraphRegFilter::CGraphRegFilter(CStringW m_dispname, ULONGLONG merit) 
  1472. : CGraphFilter(L"", merit), m_dispname(m_dispname)
  1473. {
  1474. if(m_dispname.IsEmpty()) return;
  1475. CComPtr<IBindCtx> pBC;
  1476. CreateBindCtx(0, &pBC);
  1477. ULONG chEaten;
  1478. if(S_OK != MkParseDisplayName(pBC, CComBSTR(m_dispname), &chEaten, &m_pMoniker))
  1479. return;
  1480. CComPtr<IPropertyBag> pPB;
  1481. if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
  1482. {
  1483. CComVariant var;
  1484. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
  1485. {
  1486. m_name = var.bstrVal;
  1487. var.Clear();
  1488. }
  1489. if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
  1490. {
  1491. CLSIDFromString(var.bstrVal, &m_clsid);
  1492. var.Clear();
  1493. }
  1494. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
  1495. {
  1496. BSTR* pstr;
  1497. if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
  1498. {
  1499. ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
  1500. SafeArrayUnaccessData(var.parray);
  1501. }
  1502. var.Clear();
  1503. }
  1504. }
  1505. if(merit != LMERIT_DO_USE) m_merit.val = merit;
  1506. }
  1507. CGraphRegFilter::CGraphRegFilter(const CLSID& clsid, ULONGLONG merit) 
  1508. : CGraphFilter(L"", merit)
  1509. {
  1510. if((m_clsid = clsid) == GUID_NULL) return;
  1511. CString guid = CStringFromGUID(m_clsid);
  1512. CString str = CString(_T("CLSID\{083863F1-70DE-11d0-BD40-00A0C911CE86}\Instance\")) + guid;
  1513. CString str2 = CString(_T("CLSID\")) + guid;
  1514. CRegKey key;
  1515. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str2, KEY_READ))
  1516. {
  1517. ULONG nChars = 0;
  1518. if(ERROR_SUCCESS == key.QueryStringValue(NULL, NULL, &nChars))
  1519. {
  1520. CString name;
  1521. if(ERROR_SUCCESS == key.QueryStringValue(NULL, name.GetBuffer(nChars), &nChars))
  1522. {
  1523. name.ReleaseBuffer(nChars);
  1524. m_name = name;
  1525. }
  1526. }
  1527. key.Close();
  1528. }
  1529. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
  1530. {
  1531. ULONG nChars = 0;
  1532. if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), NULL, &nChars))
  1533. {
  1534. CString name;
  1535. if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), name.GetBuffer(nChars), &nChars))
  1536. {
  1537. name.ReleaseBuffer(nChars);
  1538. m_name = name;
  1539. }
  1540. }
  1541. ULONG nBytes = 0;
  1542. if(ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), NULL, &nBytes))
  1543. {
  1544. CAutoVectorPtr<BYTE> buff;
  1545. if(buff.Allocate(nBytes) && ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), buff, &nBytes))
  1546. {
  1547. ExtractFilterData(buff, nBytes);
  1548. }
  1549. }
  1550. key.Close();
  1551. }
  1552. if(merit != LMERIT_DO_USE) m_merit.val = merit;
  1553. }
  1554. [uuid("97f7c4d4-547b-4a5f-8332-536430ad2e4d")]
  1555. interface IAMFilterData : public IUnknown
  1556. {
  1557. STDMETHOD (ParseFilterData) (BYTE* rgbFilterData, ULONG cb, BYTE** prgbRegFilter2) PURE;
  1558. STDMETHOD (CreateFilterData) (REGFILTER2* prf2, BYTE** prgbFilterData, ULONG* pcb) PURE;
  1559. };
  1560. void CGraphRegFilter::ExtractFilterData(BYTE* p, UINT len)
  1561. {
  1562. CComPtr<IAMFilterData> pFD;
  1563. BYTE* ptr = NULL;
  1564. if(SUCCEEDED(pFD.CoCreateInstance(CLSID_FilterMapper2))
  1565. && SUCCEEDED(pFD->ParseFilterData(p, len, (BYTE**)&ptr)))
  1566. {
  1567. REGFILTER2* prf = (REGFILTER2*)*(DWORD*)ptr; // this is f*cked up
  1568. m_merit.mid = prf->dwMerit;
  1569. if(prf->dwVersion == 1)
  1570. {
  1571. for(UINT i = 0; i < prf->cPins; i++)
  1572. {
  1573. if(prf->rgPins[i].bOutput)
  1574. continue;
  1575. for(UINT j = 0; j < prf->rgPins[i].nMediaTypes; j++)
  1576. {
  1577. if(!prf->rgPins[i].lpMediaType[j].clsMajorType || !prf->rgPins[i].lpMediaType[j].clsMinorType)
  1578. break;
  1579. m_guids.AddTail(*(GUID*)prf->rgPins[i].lpMediaType[j].clsMajorType);
  1580. m_guids.AddTail(*(GUID*)prf->rgPins[i].lpMediaType[j].clsMinorType);
  1581. }
  1582. }
  1583. }
  1584. else if(prf->dwVersion == 2)
  1585. {
  1586. for(UINT i = 0; i < prf->cPins2; i++)
  1587. {
  1588. if(prf->rgPins2[i].dwFlags&REG_PINFLAG_B_OUTPUT)
  1589. continue;
  1590. for(UINT j = 0; j < prf->rgPins2[i].nMediaTypes; j++)
  1591. {
  1592. if(!prf->rgPins2[i].lpMediaType[j].clsMajorType || !prf->rgPins2[i].lpMediaType[j].clsMinorType)
  1593. break;
  1594. m_guids.AddTail(*(GUID*)prf->rgPins2[i].lpMediaType[j].clsMajorType);
  1595. m_guids.AddTail(*(GUID*)prf->rgPins2[i].lpMediaType[j].clsMinorType);
  1596. }
  1597. }
  1598. }
  1599. CoTaskMemFree(prf);
  1600. }
  1601. else
  1602. {
  1603. BYTE* base = p;
  1604. #define ChkLen(size) if(p - base + size > (int)len) return;
  1605. ChkLen(4)
  1606. if(*(DWORD*)p != 0x00000002) return; // only version 2 supported, no samples found for 1
  1607. p += 4;
  1608. ChkLen(4)
  1609. m_merit.mid = *(DWORD*)p; p += 4;
  1610. m_guids.RemoveAll();
  1611. ChkLen(8)
  1612. DWORD nPins = *(DWORD*)p; p += 8;
  1613. while(nPins-- > 0)
  1614. {
  1615. ChkLen(1)
  1616. BYTE n = *p-0x30; p++;
  1617. ChkLen(2)
  1618. WORD pi = *(WORD*)p; p += 2;
  1619. ASSERT(pi == 'ip');
  1620. ChkLen(1)
  1621. BYTE x33 = *p; p++;
  1622. ASSERT(x33 == 0x33);
  1623. ChkLen(8)
  1624. bool fOutput = !!(*p&REG_PINFLAG_B_OUTPUT);
  1625. p += 8;
  1626. ChkLen(12)
  1627. DWORD nTypes = *(DWORD*)p; p += 12;
  1628. while(nTypes-- > 0)
  1629. {
  1630. ChkLen(1)
  1631. BYTE n = *p-0x30; p++;
  1632. ChkLen(2)
  1633. WORD ty = *(WORD*)p; p += 2;
  1634. ASSERT(ty == 'yt');
  1635. ChkLen(5)
  1636. BYTE x33 = *p; p++;
  1637. ASSERT(x33 == 0x33);
  1638. p += 4;
  1639. ChkLen(8)
  1640. if(*(DWORD*)p < (p-base+8) || *(DWORD*)p >= len 
  1641. || *(DWORD*)(p+4) < (p-base+8) || *(DWORD*)(p+4) >= len)
  1642. {
  1643. p += 8;
  1644. continue;
  1645. }
  1646. GUID guid;
  1647. memcpy(&guid, &base[*(DWORD*)p], sizeof(GUID)); p += 4;
  1648. if(!fOutput) m_guids.AddTail(guid); 
  1649. memcpy(&guid, &base[*(DWORD*)p], sizeof(GUID)); p += 4;
  1650. if(!fOutput) m_guids.AddTail(guid); 
  1651. }
  1652. }
  1653. #undef ChkLen
  1654. }
  1655. /*
  1656. if(CLSID_MMSPLITTER == m_clsid && m_merit.val == LMERIT(MERIT_NORMAL-1))
  1657. {
  1658. m_merit.val = LMERIT(MERIT_NORMAL)+1; // take this mpeg2 demux...
  1659. }
  1660. */
  1661. }
  1662. HRESULT CGraphRegFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
  1663. {
  1664. CheckPointer(ppBF, E_POINTER);
  1665. if(ppUnk) *ppUnk = NULL;
  1666. HRESULT hr = E_FAIL;
  1667. if(m_pMoniker)
  1668. {
  1669. if(SUCCEEDED(hr = m_pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppBF)))
  1670. m_clsid = ::GetCLSID(*ppBF);
  1671. }
  1672. else if(m_clsid != GUID_NULL)
  1673. {
  1674. CComPtr<IBaseFilter> pBF;
  1675. if(FAILED(pBF.CoCreateInstance(m_clsid))) return E_FAIL;
  1676. *ppBF = pBF.Detach();
  1677. hr = S_OK;
  1678. }
  1679. return hr;
  1680. };
  1681. //
  1682. // CGraphCustomFilter
  1683. //
  1684. CGraphCustomFilter::CGraphCustomFilter(const CLSID& clsid, CList<GUID>& guids, CStringW name, ULONGLONG merit) 
  1685. : CGraphFilter(name, merit)
  1686. {
  1687. m_clsid = clsid;
  1688. ASSERT(guids.GetCount() > 0);
  1689. m_guids.AddTail(&guids);
  1690. }
  1691. HRESULT CGraphCustomFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
  1692. {
  1693. CheckPointer(ppBF, E_POINTER);
  1694. if(ppUnk) *ppUnk = NULL;
  1695. HRESULT hr = S_OK;
  1696. *ppBF = 
  1697. m_clsid == __uuidof(CAVI2AC3Filter) ? (IBaseFilter*)new CAVI2AC3Filter(NULL, &hr) : 
  1698. m_clsid == __uuidof(CDeCSSFilter) ? (IBaseFilter*)new CDeCSSFilter(NULL, &hr) : 
  1699. m_clsid == __uuidof(CAudioSwitcherFilter) ? (IBaseFilter*)new CAudioSwitcherFilter(NULL, &hr) :
  1700. m_clsid == __uuidof(CMatroskaSplitterFilter) ? (IBaseFilter*)new CMatroskaSplitterFilter(NULL, &hr) :
  1701. m_clsid == __uuidof(CRealMediaSplitterFilter) ? (IBaseFilter*)new CRealMediaSplitterFilter(NULL, &hr) :
  1702. m_clsid == __uuidof(CRealVideoDecoder) ? (IBaseFilter*)new CRealVideoDecoder(NULL, &hr) :
  1703. m_clsid == __uuidof(CRealAudioDecoder) ? (IBaseFilter*)new CRealAudioDecoder(NULL, &hr) :
  1704. m_clsid == __uuidof(CRoQVideoDecoder) ? (IBaseFilter*)new CRoQVideoDecoder(NULL, &hr) :
  1705. m_clsid == __uuidof(CRoQAudioDecoder) ? (IBaseFilter*)new CRoQAudioDecoder(NULL, &hr) :
  1706. m_clsid == __uuidof(CAviSplitterFilter) ? (IBaseFilter*)new CAviSplitterFilter(NULL, &hr) :
  1707. m_clsid == __uuidof(CRoQSplitterFilter) ? (IBaseFilter*)new CRoQSplitterFilter(NULL, &hr) :
  1708. m_clsid == __uuidof(COggSplitterFilter) ? (IBaseFilter*)new COggSplitterFilter(NULL, &hr) :
  1709. m_clsid == __uuidof(CNutSplitterFilter) ? (IBaseFilter*)new CNutSplitterFilter(NULL, &hr) :
  1710. m_clsid == __uuidof(CMpegSplitterFilter) ? (IBaseFilter*)new CMpegSplitterFilter(NULL, &hr) :
  1711. m_clsid == __uuidof(CMpeg2DecFilter) ? (IBaseFilter*)new CMpeg2DecFilter(NULL, &hr) :
  1712. m_clsid == __uuidof(CDiracSplitterFilter) ? (IBaseFilter*)new CDiracSplitterFilter(NULL, &hr) :
  1713. m_clsid == __uuidof(CDiracVideoDecoder) ? (IBaseFilter*)new CDiracVideoDecoder(NULL, &hr) :
  1714. m_clsid == __uuidof(CMpaSplitterFilter) ? (IBaseFilter*)new CMpaSplitterFilter(NULL, &hr) :
  1715. m_clsid == __uuidof(CMpaDecFilter) ? (IBaseFilter*)new CMpaDecFilter(NULL, &hr) :
  1716. m_clsid == __uuidof(CDSMSplitterFilter) ? (IBaseFilter*)new CDSMSplitterFilter(NULL, &hr) :
  1717. m_clsid == __uuidof(CMP4SplitterFilter) ? (IBaseFilter*)new CMP4SplitterFilter(NULL, &hr) :
  1718. m_clsid == __uuidof(CNullVideoRenderer) ? (IBaseFilter*)new CNullVideoRenderer() :
  1719. m_clsid == __uuidof(CNullAudioRenderer) ? (IBaseFilter*)new CNullAudioRenderer() :
  1720. m_clsid == __uuidof(CNullUVideoRenderer) ? (IBaseFilter*)new CNullUVideoRenderer() :
  1721. m_clsid == __uuidof(CNullUAudioRenderer) ? (IBaseFilter*)new CNullUAudioRenderer() :
  1722. m_clsid == __uuidof(CNullTextRenderer) ? (IBaseFilter*)new CNullTextRenderer(NULL, &hr) :
  1723. m_clsid == __uuidof(CDeinterlacerFilter) ? (IBaseFilter*)new CDeinterlacerFilter(NULL, &hr) :
  1724. NULL;
  1725. __if_exists(CRadGtSplitterFilter)
  1726. {
  1727. if(*ppBF == NULL && m_clsid == __uuidof(CRadGtSplitterFilter))
  1728.  *ppBF = (IBaseFilter*)new CRadGtSplitterFilter(NULL, &hr);
  1729. }
  1730. if(!*ppBF) hr = E_FAIL;
  1731. else (*ppBF)->AddRef();
  1732. if(!*ppBF)
  1733. {
  1734. CComPtr<IBaseFilter> pBF;
  1735. if(SUCCEEDED(hr = pBF.CoCreateInstance(m_clsid)))
  1736. *ppBF = pBF.Detach();
  1737. }
  1738. if(SUCCEEDED(hr) && ppUnk)
  1739. {
  1740. if(m_clsid == __uuidof(CAudioSwitcherFilter))
  1741. {
  1742. *ppUnk = (IUnknown*)CComQIPtr<IAudioSwitcherFilter>(*ppBF).Detach();
  1743. CComQIPtr<IAudioSwitcherFilter> pASF = *ppUnk;
  1744. if(pASF)
  1745. {
  1746. AppSettings& s = AfxGetAppSettings();
  1747. pASF->SetSpeakerConfig(s.fCustomChannelMapping, s.pSpeakerToChannelMap);
  1748. pASF->EnableDownSamplingTo441(s.fDownSampleTo441);
  1749. pASF->SetAudioTimeShift(s.fAudioTimeShift ? 10000i64*s.tAudioTimeShift : 0);
  1750. }
  1751. }
  1752. }
  1753. return hr;
  1754. }
  1755. //
  1756. // CGraphFileFilter
  1757. //
  1758. CGraphFileFilter::CGraphFileFilter(const CLSID& clsid, CList<GUID>& guids, CString path, CStringW name, ULONGLONG merit)
  1759. : CGraphCustomFilter(clsid, guids, name, merit), m_path(path), m_hInst(NULL)
  1760. {
  1761. }
  1762. HRESULT CGraphFileFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
  1763. {
  1764. CheckPointer(ppBF, E_POINTER);
  1765. if(ppUnk) *ppUnk = NULL;
  1766. HRESULT hr = S_OK;
  1767. if(SUCCEEDED(hr = __super::Create(ppBF, ppUnk)))
  1768. return hr;
  1769. return LoadExternalFilter(m_path, m_clsid, ppBF);
  1770. }
  1771. //
  1772. // CGraphRendererFilter
  1773. //
  1774. CGraphRendererFilter::CGraphRendererFilter(const CLSID& clsid, HWND hWnd, CStringW name, ULONGLONG merit) 
  1775. : CGraphFilter(name, merit), m_clsid(clsid), m_hWnd(hWnd)
  1776. {
  1777. m_guids.AddTail(MEDIATYPE_Video);
  1778. m_guids.AddTail(MEDIASUBTYPE_NULL);
  1779. }
  1780. HRESULT CGraphRendererFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
  1781. {
  1782. CheckPointer(ppBF, E_POINTER);
  1783. HRESULT hr = S_OK;
  1784. if(m_clsid == CLSID_OverlayMixer)
  1785. {
  1786. CComPtr<IBaseFilter> pBF;
  1787. if(SUCCEEDED(pBF.CoCreateInstance(CLSID_OverlayMixer)))
  1788. {
  1789. BeginEnumPins(pBF, pEP, pPin)
  1790. {
  1791. if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pPin)
  1792. {
  1793. if(ppUnk) *ppUnk = pMPC.Detach();
  1794. break;
  1795. }
  1796. }
  1797. EndEnumPins
  1798. *ppBF = pBF.Detach();
  1799. }
  1800. }
  1801. else if(m_clsid == CLSID_VideoMixingRenderer)
  1802. {
  1803. CComPtr<IBaseFilter> pBF;
  1804. if(SUCCEEDED(pBF.CoCreateInstance(CLSID_VideoMixingRenderer)))
  1805. *ppBF = pBF.Detach();
  1806. }
  1807. else if(m_clsid == CLSID_VideoMixingRenderer9)
  1808. {
  1809. CComPtr<IBaseFilter> pBF;
  1810. if(SUCCEEDED(pBF.CoCreateInstance(CLSID_VideoMixingRenderer9)))
  1811. *ppBF = pBF.Detach();
  1812. }
  1813. else if(m_clsid == CLSID_VMR7AllocatorPresenter)
  1814. {
  1815. CComPtr<ISubPicAllocatorPresenter> pCAP;
  1816. CComPtr<IUnknown> pRenderer;
  1817. if(SUCCEEDED(hr = CreateAP7(CLSID_VMR7AllocatorPresenter, m_hWnd, &pCAP))
  1818. && SUCCEEDED(hr = pCAP->CreateRenderer(&pRenderer)))
  1819. {
  1820. *ppBF = CComQIPtr<IBaseFilter>(pRenderer).Detach();
  1821. if(ppUnk) *ppUnk = (IUnknown*)pCAP.Detach();
  1822. }
  1823. }
  1824. else if(m_clsid == CLSID_VMR9AllocatorPresenter)
  1825. {
  1826. CComPtr<ISubPicAllocatorPresenter> pCAP;
  1827. CComPtr<IUnknown> pRenderer;
  1828. if(SUCCEEDED(hr = CreateAP9(CLSID_VMR9AllocatorPresenter, m_hWnd, &pCAP))
  1829. && SUCCEEDED(hr = pCAP->CreateRenderer(&pRenderer)))
  1830. {
  1831. *ppBF = CComQIPtr<IBaseFilter>(pRenderer).Detach();
  1832. if(ppUnk) *ppUnk = (IUnknown*)pCAP.Detach();
  1833. }
  1834. }
  1835. if(!*ppBF) hr = E_FAIL;
  1836. return hr;
  1837. }