FGFilter.cpp
上传用户:tangyu_668
上传日期:2014-02-27
资源大小:678k
文件大小:14k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2006 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 "FGFilter.h"
  23. #include "....DSUtilDSUtil.h"
  24. #include "DX7AllocatorPresenter.h"
  25. #include "DX9AllocatorPresenter.h"
  26. #include "......includemoreuuids.h"
  27. //
  28. // CFGFilter
  29. //
  30. CFGFilter::CFGFilter(const CLSID& clsid, CStringW name, UINT64 merit)
  31. : m_clsid(clsid)
  32. , m_name(name)
  33. {
  34. m_merit.val = merit;
  35. }
  36. const CAtlList<GUID>& CFGFilter::GetTypes() const
  37. {
  38. return m_types;
  39. }
  40. void CFGFilter::SetTypes(const CAtlList<GUID>& types)
  41. {
  42. m_types.RemoveAll();
  43. m_types.AddTailList(&types);
  44. }
  45. void CFGFilter::AddType(const GUID& majortype, const GUID& subtype)
  46. {
  47. m_types.AddTail(majortype);
  48. m_types.AddTail(subtype);
  49. }
  50. bool CFGFilter::CheckTypes(const CAtlArray<GUID>& types, bool fExactMatch)
  51. {
  52. POSITION pos = m_types.GetHeadPosition();
  53. while(pos)
  54. {
  55. const GUID& majortype = m_types.GetNext(pos);
  56. if(!pos) {ASSERT(0); break;}
  57. const GUID& subtype = m_types.GetNext(pos);
  58. for(int i = 0, len = types.GetCount() & ~1; i < len; i += 2)
  59. {
  60. if(fExactMatch)
  61. {
  62. if(majortype == types[i] && majortype != GUID_NULL
  63. && subtype == types[i+1] && subtype != GUID_NULL)
  64.              return true;
  65. }
  66. else
  67. {
  68. if((majortype == GUID_NULL || types[i] == GUID_NULL || majortype == types[i])
  69. && (subtype == GUID_NULL || types[i+1] == GUID_NULL || subtype == types[i+1]))
  70. return true;
  71. }
  72. }
  73. }
  74. return false;
  75. }
  76. //
  77. // CFGFilterRegistry
  78. //
  79. CFGFilterRegistry::CFGFilterRegistry(IMoniker* pMoniker, UINT64 merit) 
  80. : CFGFilter(GUID_NULL, L"", merit)
  81. , m_pMoniker(pMoniker)
  82. {
  83. if(!m_pMoniker) return;
  84. LPOLESTR str = NULL;
  85. if(FAILED(m_pMoniker->GetDisplayName(0, 0, &str))) return;
  86. m_DisplayName = m_name = str;
  87. CoTaskMemFree(str), str = NULL;
  88. CComPtr<IPropertyBag> pPB;
  89. if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
  90. {
  91. CComVariant var;
  92. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
  93. {
  94. m_name = var.bstrVal;
  95. var.Clear();
  96. }
  97. if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
  98. {
  99. CLSIDFromString(var.bstrVal, &m_clsid);
  100. var.Clear();
  101. }
  102. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
  103. {
  104. BSTR* pstr;
  105. if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
  106. {
  107. ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
  108. SafeArrayUnaccessData(var.parray);
  109. }
  110. var.Clear();
  111. }
  112. }
  113. if(merit != MERIT64_DO_USE) m_merit.val = merit;
  114. }
  115. CFGFilterRegistry::CFGFilterRegistry(CStringW DisplayName, UINT64 merit) 
  116. : CFGFilter(GUID_NULL, L"", merit)
  117. , m_DisplayName(DisplayName)
  118. {
  119. if(m_DisplayName.IsEmpty()) return;
  120. CComPtr<IBindCtx> pBC;
  121. CreateBindCtx(0, &pBC);
  122. ULONG chEaten;
  123. if(S_OK != MkParseDisplayName(pBC, CComBSTR(m_DisplayName), &chEaten, &m_pMoniker))
  124. return;
  125. CComPtr<IPropertyBag> pPB;
  126. if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
  127. {
  128. CComVariant var;
  129. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
  130. {
  131. m_name = var.bstrVal;
  132. var.Clear();
  133. }
  134. if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
  135. {
  136. CLSIDFromString(var.bstrVal, &m_clsid);
  137. var.Clear();
  138. }
  139. if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
  140. {
  141. BSTR* pstr;
  142. if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
  143. {
  144. ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
  145. SafeArrayUnaccessData(var.parray);
  146. }
  147. var.Clear();
  148. }
  149. }
  150. if(merit != MERIT64_DO_USE) m_merit.val = merit;
  151. }
  152. CFGFilterRegistry::CFGFilterRegistry(const CLSID& clsid, UINT64 merit) 
  153. : CFGFilter(clsid, L"", merit)
  154. {
  155. if(m_clsid == GUID_NULL) return;
  156. CString guid = CStringFromGUID(m_clsid);
  157. CRegKey key;
  158. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("CLSID\") + guid, KEY_READ))
  159. {
  160. ULONG nChars = 0;
  161. if(ERROR_SUCCESS == key.QueryStringValue(NULL, NULL, &nChars))
  162. {
  163. CString name;
  164. if(ERROR_SUCCESS == key.QueryStringValue(NULL, name.GetBuffer(nChars), &nChars))
  165. {
  166. name.ReleaseBuffer(nChars);
  167. m_name = name;
  168. }
  169. }
  170. key.Close();
  171. }
  172. CRegKey catkey;
  173. if(ERROR_SUCCESS == catkey.Open(HKEY_CLASSES_ROOT, _T("CLSID\{083863F1-70DE-11d0-BD40-00A0C911CE86}\Instance"), KEY_READ))
  174. {
  175. if(ERROR_SUCCESS != key.Open(catkey, guid, KEY_READ))
  176. {
  177. // illiminable pack uses the name of the filter and not the clsid, have to enum all keys to find it...
  178. FILETIME ft;
  179. TCHAR buff[256];
  180. DWORD len = countof(buff);
  181. for(DWORD i = 0; ERROR_SUCCESS == catkey.EnumKey(i, buff, &len, &ft); i++, len = countof(buff))
  182. {
  183. if(ERROR_SUCCESS == key.Open(catkey, buff, KEY_READ))
  184. {
  185. TCHAR clsid[256];
  186. len = countof(clsid);
  187. if(ERROR_SUCCESS == key.QueryStringValue(_T("CLSID"), clsid, &len) && GUIDFromCString(clsid) == m_clsid)
  188. break;
  189. key.Close();
  190. }
  191. }
  192. }
  193. if(key)
  194. {
  195. ULONG nChars = 0;
  196. if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), NULL, &nChars))
  197. {
  198. CString name;
  199. if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), name.GetBuffer(nChars), &nChars))
  200. {
  201. name.ReleaseBuffer(nChars);
  202. m_name = name;
  203. }
  204. }
  205. ULONG nBytes = 0;
  206. if(ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), NULL, &nBytes))
  207. {
  208. CAutoVectorPtr<BYTE> buff;
  209. if(buff.Allocate(nBytes) && ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), buff, &nBytes))
  210. {
  211. ExtractFilterData(buff, nBytes);
  212. }
  213. }
  214. key.Close();
  215. }
  216. }
  217. if(merit != MERIT64_DO_USE) m_merit.val = merit;
  218. }
  219. HRESULT CFGFilterRegistry::Create(IBaseFilter** ppBF, CInterfaceList<IUnknown, &IID_IUnknown>& pUnks)
  220. {
  221. CheckPointer(ppBF, E_POINTER);
  222. HRESULT hr = E_FAIL;
  223. if(m_pMoniker)
  224. {
  225. if(SUCCEEDED(hr = m_pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppBF)))
  226. {
  227. m_clsid = ::GetCLSID(*ppBF);
  228. }
  229. }
  230. else if(m_clsid != GUID_NULL)
  231. {
  232. CComQIPtr<IBaseFilter> pBF;
  233. if(FAILED(pBF.CoCreateInstance(m_clsid))) 
  234. return E_FAIL;
  235. *ppBF = pBF.Detach();
  236. hr = S_OK;
  237. }
  238. return hr;
  239. };
  240. [uuid("97f7c4d4-547b-4a5f-8332-536430ad2e4d")]
  241. interface IAMFilterData : public IUnknown
  242. {
  243. STDMETHOD (ParseFilterData) (BYTE* rgbFilterData, ULONG cb, BYTE** prgbRegFilter2) PURE;
  244. STDMETHOD (CreateFilterData) (REGFILTER2* prf2, BYTE** prgbFilterData, ULONG* pcb) PURE;
  245. };
  246. void CFGFilterRegistry::ExtractFilterData(BYTE* p, UINT len)
  247. {
  248. CComPtr<IAMFilterData> pFD;
  249. BYTE* ptr = NULL;
  250. if(SUCCEEDED(pFD.CoCreateInstance(CLSID_FilterMapper2))
  251. && SUCCEEDED(pFD->ParseFilterData(p, len, (BYTE**)&ptr)))
  252. {
  253. REGFILTER2* prf = (REGFILTER2*)*(DWORD*)ptr; // this is f*cked up
  254. m_merit.mid = prf->dwMerit;
  255. if(prf->dwVersion == 1)
  256. {
  257. for(UINT i = 0; i < prf->cPins; i++)
  258. {
  259. if(prf->rgPins[i].bOutput)
  260. continue;
  261. for(UINT j = 0; j < prf->rgPins[i].nMediaTypes; j++)
  262. {
  263. if(!prf->rgPins[i].lpMediaType[j].clsMajorType || !prf->rgPins[i].lpMediaType[j].clsMinorType)
  264. break;
  265. const REGPINTYPES& rpt = prf->rgPins[i].lpMediaType[j];
  266. AddType(*rpt.clsMajorType, *rpt.clsMinorType);
  267. }
  268. }
  269. }
  270. else if(prf->dwVersion == 2)
  271. {
  272. for(UINT i = 0; i < prf->cPins2; i++)
  273. {
  274. if(prf->rgPins2[i].dwFlags&REG_PINFLAG_B_OUTPUT)
  275. continue;
  276. for(UINT j = 0; j < prf->rgPins2[i].nMediaTypes; j++)
  277. {
  278. if(!prf->rgPins2[i].lpMediaType[j].clsMajorType || !prf->rgPins2[i].lpMediaType[j].clsMinorType)
  279. break;
  280. const REGPINTYPES& rpt = prf->rgPins2[i].lpMediaType[j];
  281. AddType(*rpt.clsMajorType, *rpt.clsMinorType);
  282. }
  283. }
  284. }
  285. CoTaskMemFree(prf);
  286. }
  287. else
  288. {
  289. BYTE* base = p;
  290. #define ChkLen(size) if(p - base + size > (int)len) return;
  291. ChkLen(4)
  292. if(*(DWORD*)p != 0x00000002) return; // only version 2 supported, no samples found for 1
  293. p += 4;
  294. ChkLen(4)
  295. m_merit.mid = *(DWORD*)p; p += 4;
  296. m_types.RemoveAll();
  297. ChkLen(8)
  298. DWORD nPins = *(DWORD*)p; p += 8;
  299. while(nPins-- > 0)
  300. {
  301. ChkLen(1)
  302. BYTE n = *p-0x30; p++;
  303. ChkLen(2)
  304. WORD pi = *(WORD*)p; p += 2;
  305. ASSERT(pi == 'ip');
  306. ChkLen(1)
  307. BYTE x33 = *p; p++;
  308. ASSERT(x33 == 0x33);
  309. ChkLen(8)
  310. bool fOutput = !!(*p&REG_PINFLAG_B_OUTPUT);
  311. p += 8;
  312. ChkLen(12)
  313. DWORD nTypes = *(DWORD*)p; p += 12;
  314. while(nTypes-- > 0)
  315. {
  316. ChkLen(1)
  317. BYTE n = *p-0x30; p++;
  318. ChkLen(2)
  319. WORD ty = *(WORD*)p; p += 2;
  320. ASSERT(ty == 'yt');
  321. ChkLen(5)
  322. BYTE x33 = *p; p++;
  323. ASSERT(x33 == 0x33);
  324. p += 4;
  325. ChkLen(8)
  326. if(*(DWORD*)p < (p-base+8) || *(DWORD*)p >= len 
  327. || *(DWORD*)(p+4) < (p-base+8) || *(DWORD*)(p+4) >= len)
  328. {
  329. p += 8;
  330. continue;
  331. }
  332. GUID majortype, subtype;
  333. memcpy(&majortype, &base[*(DWORD*)p], sizeof(GUID)); p += 4;
  334. if(!fOutput) AddType(majortype, subtype); 
  335. }
  336. }
  337. #undef ChkLen
  338. }
  339. }
  340. //
  341. // CFGFilterFile
  342. //
  343. CFGFilterFile::CFGFilterFile(const CLSID& clsid, CString path, CStringW name, UINT64 merit)
  344. : CFGFilter(clsid, name, merit)
  345. , m_path(path)
  346. , m_hInst(NULL)
  347. {
  348. }
  349. HRESULT CFGFilterFile::Create(IBaseFilter** ppBF, CInterfaceList<IUnknown, &IID_IUnknown>& pUnks)
  350. {
  351. CheckPointer(ppBF, E_POINTER);
  352. return LoadExternalFilter(m_path, m_clsid, ppBF);
  353. }
  354. //
  355. // CFGFilterVideoRenderer
  356. //
  357. CFGFilterVideoRenderer::CFGFilterVideoRenderer(HWND hWnd, const CLSID& clsid, CStringW name, UINT64 merit) 
  358. : CFGFilter(clsid, name, merit)
  359. , m_hWnd(hWnd)
  360. {
  361. AddType(MEDIATYPE_Video, MEDIASUBTYPE_NULL);
  362. }
  363. HRESULT CFGFilterVideoRenderer::Create(IBaseFilter** ppBF, CInterfaceList<IUnknown, &IID_IUnknown>& pUnks)
  364. {
  365. CheckPointer(ppBF, E_POINTER);
  366. HRESULT hr = S_OK;
  367. CComPtr<ISubPicAllocatorPresenter> pCAP;
  368. if(m_clsid == CLSID_VMR7AllocatorPresenter 
  369. || m_clsid == CLSID_VMR9AllocatorPresenter 
  370. || m_clsid == CLSID_DXRAllocatorPresenter)
  371. {
  372. if(SUCCEEDED(CreateAP7(m_clsid, m_hWnd, &pCAP))
  373. || SUCCEEDED(CreateAP9(m_clsid, m_hWnd, &pCAP)))
  374. {
  375. CComPtr<IUnknown> pRenderer;
  376. if(SUCCEEDED(hr = pCAP->CreateRenderer(&pRenderer)))
  377. {
  378. *ppBF = CComQIPtr<IBaseFilter>(pRenderer).Detach();
  379. pUnks.AddTail(pCAP);
  380. }
  381. }
  382. }
  383. else
  384. {
  385. CComPtr<IBaseFilter> pBF;
  386. if(SUCCEEDED(pBF.CoCreateInstance(m_clsid)))
  387. {
  388. BeginEnumPins(pBF, pEP, pPin)
  389. {
  390. if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pPin)
  391. {
  392. pUnks.AddTail(pMPC);
  393. break;
  394. }
  395. }
  396. EndEnumPins
  397. *ppBF = pBF.Detach();
  398. }
  399. }
  400. if(!*ppBF) hr = E_FAIL;
  401. return hr;
  402. }
  403. //
  404. // CFGFilterList
  405. //
  406. CFGFilterList::CFGFilterList()
  407. {
  408. }
  409. CFGFilterList::~CFGFilterList()
  410. {
  411. RemoveAll();
  412. }
  413. void CFGFilterList::RemoveAll()
  414. {
  415. while(!m_filters.IsEmpty())
  416. {
  417. const filter_t& f = m_filters.RemoveHead();
  418. if(f.autodelete) delete f.pFGF;
  419. }
  420. m_sortedfilters.RemoveAll();
  421. }
  422. void CFGFilterList::Insert(CFGFilter* pFGF, int group, bool exactmatch, bool autodelete)
  423. {
  424. if(CFGFilterRegistry* f1r = dynamic_cast<CFGFilterRegistry*>(pFGF))
  425. {
  426. POSITION pos = m_filters.GetHeadPosition();
  427. while(pos)
  428. {
  429. filter_t& f2 = m_filters.GetNext(pos);
  430. if(group != f2.group) continue;
  431. if(CFGFilterRegistry* f2r = dynamic_cast<CFGFilterRegistry*>(f2.pFGF))
  432. {
  433. if(f1r->GetMoniker() && f2r->GetMoniker() && S_OK == f1r->GetMoniker()->IsEqual(f2r->GetMoniker())
  434. || f1r->GetCLSID() != GUID_NULL && f1r->GetCLSID() == f2r->GetCLSID())
  435. {
  436. TRACE(_T("FGM: Inserting %d %d %016I64x '%s' NOT!n"), 
  437. group, exactmatch, pFGF->GetMerit(),
  438. pFGF->GetName().IsEmpty() ? CStringFromGUID(pFGF->GetCLSID()) : CString(pFGF->GetName()));
  439. if(autodelete) delete pFGF;
  440. return;
  441. }
  442. }
  443. }
  444. }
  445. POSITION pos = m_filters.GetHeadPosition();
  446. while(pos)
  447. {
  448. if(m_filters.GetNext(pos).pFGF == pFGF)
  449. {
  450. TRACE(_T("FGM: Inserting %d %d %016I64x '%s' DUP!n"), 
  451. group, exactmatch, pFGF->GetMerit(),
  452. pFGF->GetName().IsEmpty() ? CStringFromGUID(pFGF->GetCLSID()) : CString(pFGF->GetName()));
  453. if(autodelete) delete pFGF;
  454. return;
  455. }
  456. }
  457. TRACE(_T("FGM: Inserting %d %d %016I64x '%s'n"), 
  458. group, exactmatch, pFGF->GetMerit(),
  459. pFGF->GetName().IsEmpty() ? CStringFromGUID(pFGF->GetCLSID()) : CString(pFGF->GetName()));
  460. filter_t f = {m_filters.GetCount(), pFGF, group, exactmatch, autodelete};
  461. m_filters.AddTail(f);
  462. m_sortedfilters.RemoveAll();
  463. }
  464. POSITION CFGFilterList::GetHeadPosition()
  465. {
  466. if(m_sortedfilters.IsEmpty())
  467. {
  468. CAtlArray<filter_t> sort;
  469. sort.SetCount(m_filters.GetCount());
  470. POSITION pos = m_filters.GetHeadPosition();
  471. for(int i = 0; pos; i++) sort[i] = m_filters.GetNext(pos);
  472. qsort(&sort[0], sort.GetCount(), sizeof(sort[0]), filter_cmp);
  473. for(size_t i = 0; i < sort.GetCount(); i++) 
  474. if(sort[i].pFGF->GetMerit() >= MERIT64_DO_USE) 
  475. m_sortedfilters.AddTail(sort[i].pFGF);
  476. }
  477. TRACE(_T("FGM: Sorting filtersn"));
  478. POSITION pos = m_sortedfilters.GetHeadPosition();
  479. while(pos)
  480. {
  481. CFGFilter* pFGF = m_sortedfilters.GetNext(pos);
  482. TRACE(_T("FGM: - %016I64x '%s'n"), pFGF->GetMerit(), pFGF->GetName().IsEmpty() ? CStringFromGUID(pFGF->GetCLSID()) : CString(pFGF->GetName()));
  483. }
  484. return m_sortedfilters.GetHeadPosition();
  485. }
  486. CFGFilter* CFGFilterList::GetNext(POSITION& pos)
  487. {
  488. return m_sortedfilters.GetNext(pos);
  489. }
  490. int CFGFilterList::filter_cmp(const void* a, const void* b)
  491. {
  492. filter_t* fa = (filter_t*)a;
  493. filter_t* fb = (filter_t*)b;
  494. if(fa->group < fb->group) return -1;
  495. if(fa->group > fb->group) return +1;
  496. if(fa->pFGF->GetCLSID() == fb->pFGF->GetCLSID())
  497. {
  498. CFGFilterFile* fgfa = dynamic_cast<CFGFilterFile*>(fa->pFGF);
  499. CFGFilterFile* fgfb = dynamic_cast<CFGFilterFile*>(fb->pFGF);
  500. if(fgfa && !fgfb) return -1;
  501. if(!fgfa && fgfb) return +1;
  502. }
  503. if(fa->pFGF->GetMerit() > fb->pFGF->GetMerit()) return -1;
  504. if(fa->pFGF->GetMerit() < fb->pFGF->GetMerit()) return +1;
  505. if(fa->exactmatch && !fb->exactmatch) return -1;
  506. if(!fa->exactmatch && fb->exactmatch) return +1;
  507. if(fa->index < fb->index) return -1;
  508. if(fa->index > fb->index) return +1;
  509. return 0;
  510. }