Support unrar64.dll
[xy_vsfilter.git] / src / apps / mplayerc / FGManager.cpp
bloba589ae337c13cb405b5da7a54dcc4d51fcab10ad
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
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.
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
22 #include "stdafx.h"
23 #include "mplayerc.h"
24 #include "FGManager.h"
25 #include "..\..\DSUtil\DSUtil.h"
26 #include "..\..\Filters\Filters.h"
27 #include "DX7AllocatorPresenter.h"
28 #include "DX9AllocatorPresenter.h"
29 #include "DeinterlacerFilter.h"
30 #include <initguid.h>
31 #include "..\..\..\include\moreuuids.h"
32 #include <dmodshow.h>
33 #include <D3d9.h>
34 #include <Vmr9.h>
37 // CFGManager
40 CFGManager::CFGManager(LPCTSTR pName, LPUNKNOWN pUnk)
41 : CUnknown(pName, pUnk)
42 , m_dwRegister(0)
44 m_pUnkInner.CoCreateInstance(CLSID_FilterGraph, GetOwner());
45 m_pFM.CoCreateInstance(CLSID_FilterMapper2);
48 CFGManager::~CFGManager()
50 CAutoLock cAutoLock(this);
51 while(!m_source.IsEmpty()) delete m_source.RemoveHead();
52 while(!m_transform.IsEmpty()) delete m_transform.RemoveHead();
53 while(!m_override.IsEmpty()) delete m_override.RemoveHead();
54 m_pUnks.RemoveAll();
55 m_pUnkInner.Release();
58 STDMETHODIMP CFGManager::NonDelegatingQueryInterface(REFIID riid, void** ppv)
60 CheckPointer(ppv, E_POINTER);
62 return
63 QI(IFilterGraph)
64 QI(IGraphBuilder)
65 QI(IFilterGraph2)
66 QI(IGraphBuilder2)
67 QI(IGraphBuilderDeadEnd)
68 m_pUnkInner && (riid != IID_IUnknown && SUCCEEDED(m_pUnkInner->QueryInterface(riid, ppv))) ? S_OK :
69 __super::NonDelegatingQueryInterface(riid, ppv);
74 void CFGManager::CStreamPath::Append(IBaseFilter* pBF, IPin* pPin)
76 path_t p;
77 p.clsid = GetCLSID(pBF);
78 p.filter = GetFilterName(pBF);
79 p.pin = GetPinName(pPin);
80 AddTail(p);
83 bool CFGManager::CStreamPath::Compare(const CStreamPath& path)
85 POSITION pos1 = GetHeadPosition();
86 POSITION pos2 = path.GetHeadPosition();
88 while(pos1 && pos2)
90 const path_t& p1 = GetNext(pos1);
91 const path_t& p2 = path.GetNext(pos2);
93 if(p1.filter != p2.filter) return true;
94 else if(p1.pin != p2.pin) return false;
97 return true;
102 bool CFGManager::CheckBytes(HANDLE hFile, CString chkbytes)
104 CAtlList<CString> sl;
105 Explode(chkbytes, sl, ',');
107 if(sl.GetCount() < 4)
108 return false;
110 ASSERT(!(sl.GetCount()&3));
112 LARGE_INTEGER size = {0, 0};
113 size.LowPart = GetFileSize(hFile, (DWORD*)&size.HighPart);
115 POSITION pos = sl.GetHeadPosition();
116 while(sl.GetCount() >= 4)
118 CString offsetstr = sl.RemoveHead();
119 CString cbstr = sl.RemoveHead();
120 CString maskstr = sl.RemoveHead();
121 CString valstr = sl.RemoveHead();
123 long cb = _ttol(cbstr);
125 if(offsetstr.IsEmpty() || cbstr.IsEmpty()
126 || valstr.IsEmpty() || (valstr.GetLength() & 1)
127 || cb*2 != valstr.GetLength())
128 return false;
130 LARGE_INTEGER offset;
131 offset.QuadPart = _ttoi64(offsetstr);
132 if(offset.QuadPart < 0) offset.QuadPart = size.QuadPart - offset.QuadPart;
133 SetFilePointer(hFile, offset.LowPart, &offset.HighPart, FILE_BEGIN);
135 // LAME
136 while(maskstr.GetLength() < valstr.GetLength())
137 maskstr += 'F';
139 CAtlArray<BYTE> mask, val;
140 CStringToBin(maskstr, mask);
141 CStringToBin(valstr, val);
143 for(size_t i = 0; i < val.GetCount(); i++)
145 BYTE b;
146 DWORD r;
147 if(!ReadFile(hFile, &b, 1, &r, NULL) || (b & mask[i]) != val[i])
148 return false;
152 return sl.IsEmpty();
155 HRESULT CFGManager::EnumSourceFilters(LPCWSTR lpcwstrFileName, CFGFilterList& fl)
157 // TODO: use overrides
159 CheckPointer(lpcwstrFileName, E_POINTER);
161 fl.RemoveAll();
163 CStringW fn = CStringW(lpcwstrFileName).TrimLeft();
164 CStringW protocol = fn.Left(fn.Find(':')+1).TrimRight(':').MakeLower();
165 CStringW ext = CPathW(fn).GetExtension().MakeLower();
167 HANDLE hFile = INVALID_HANDLE_VALUE;
169 if(protocol.GetLength() <= 1 || protocol == L"file")
171 hFile = CreateFile(CString(fn), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
173 if(hFile == INVALID_HANDLE_VALUE)
175 return VFW_E_NOT_FOUND;
179 // exceptions first
181 if(ext == _T(".dvr-ms")) // doh, this is stupid
183 fl.Insert(new CFGFilterRegistry(CLSID_StreamBufferSource, MERIT64_PREFERRED), 0);
186 TCHAR buff[256], buff2[256];
187 ULONG len, len2;
189 if(hFile == INVALID_HANDLE_VALUE)
191 // internal / protocol
193 POSITION pos = m_source.GetHeadPosition();
194 while(pos)
196 CFGFilter* pFGF = m_source.GetNext(pos);
197 if(pFGF->m_protocols.Find(CString(protocol)))
198 fl.Insert(pFGF, 0, false, false);
201 else
203 // internal / check bytes
205 POSITION pos = m_source.GetHeadPosition();
206 while(pos)
208 CFGFilter* pFGF = m_source.GetNext(pos);
210 POSITION pos2 = pFGF->m_chkbytes.GetHeadPosition();
211 while(pos2)
213 if(CheckBytes(hFile, pFGF->m_chkbytes.GetNext(pos2)))
215 fl.Insert(pFGF, 1, false, false);
216 break;
222 if(!ext.IsEmpty())
224 // internal / file extension
226 POSITION pos = m_source.GetHeadPosition();
227 while(pos)
229 CFGFilter* pFGF = m_source.GetNext(pos);
230 if(pFGF->m_extensions.Find(CString(ext)))
231 fl.Insert(pFGF, 2, false, false);
236 // internal / the rest
238 POSITION pos = m_source.GetHeadPosition();
239 while(pos)
241 CFGFilter* pFGF = m_source.GetNext(pos);
242 if(pFGF->m_protocols.IsEmpty() && pFGF->m_chkbytes.IsEmpty() && pFGF->m_extensions.IsEmpty())
243 fl.Insert(pFGF, 3, false, false);
247 if(hFile == INVALID_HANDLE_VALUE)
249 // protocol
251 CRegKey key;
252 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, CString(protocol), KEY_READ))
254 CRegKey exts;
255 if(ERROR_SUCCESS == exts.Open(key, _T("Extensions"), KEY_READ))
257 len = countof(buff);
258 if(ERROR_SUCCESS == exts.QueryStringValue(CString(ext), buff, &len))
259 fl.Insert(new CFGFilterRegistry(GUIDFromCString(buff)), 4);
262 len = countof(buff);
263 if(ERROR_SUCCESS == key.QueryStringValue(_T("Source Filter"), buff, &len))
264 fl.Insert(new CFGFilterRegistry(GUIDFromCString(buff)), 5);
267 fl.Insert(new CFGFilterRegistry(CLSID_URLReader), 6);
269 else
271 // check bytes
273 CRegKey key;
274 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Media Type"), KEY_READ))
276 FILETIME ft;
277 len = countof(buff);
278 for(DWORD i = 0; ERROR_SUCCESS == key.EnumKey(i, buff, &len, &ft); i++, len = countof(buff))
280 GUID majortype;
281 if(FAILED(GUIDFromCString(buff, majortype)))
282 continue;
284 CRegKey majorkey;
285 if(ERROR_SUCCESS == majorkey.Open(key, buff, KEY_READ))
287 len = countof(buff);
288 for(DWORD j = 0; ERROR_SUCCESS == majorkey.EnumKey(j, buff, &len, &ft); j++, len = countof(buff))
290 GUID subtype;
291 if(FAILED(GUIDFromCString(buff, subtype)))
292 continue;
294 CRegKey subkey;
295 if(ERROR_SUCCESS == subkey.Open(majorkey, buff, KEY_READ))
297 len = countof(buff);
298 if(ERROR_SUCCESS != subkey.QueryStringValue(_T("Source Filter"), buff, &len))
299 continue;
301 GUID clsid = GUIDFromCString(buff);
303 len = countof(buff);
304 len2 = sizeof(buff2);
305 for(DWORD k = 0, type;
306 clsid != GUID_NULL && ERROR_SUCCESS == RegEnumValue(subkey, k, buff2, &len2, 0, &type, (BYTE*)buff, &len);
307 k++, len = countof(buff), len2 = sizeof(buff2))
309 if(CheckBytes(hFile, CString(buff)))
311 CFGFilter* pFGF = new CFGFilterRegistry(clsid);
312 pFGF->AddType(majortype, subtype);
313 fl.Insert(pFGF, 9);
314 break;
324 if(!ext.IsEmpty())
326 // file extension
328 CRegKey key;
329 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Media Type\\Extensions\\") + CString(ext), KEY_READ))
331 ULONG len = countof(buff);
332 memset(buff, 0, sizeof(buff));
333 LONG ret = key.QueryStringValue(_T("Source Filter"), buff, &len); // QueryStringValue can return ERROR_INVALID_DATA on bogus strings (radlight mpc v1003, fixed in v1004)
334 if(ERROR_SUCCESS == ret || ERROR_INVALID_DATA == ret && GUIDFromCString(buff) != GUID_NULL)
336 GUID clsid = GUIDFromCString(buff);
337 GUID majortype = GUID_NULL;
338 GUID subtype = GUID_NULL;
340 len = countof(buff);
341 if(ERROR_SUCCESS == key.QueryStringValue(_T("Media Type"), buff, &len))
342 majortype = GUIDFromCString(buff);
344 len = countof(buff);
345 if(ERROR_SUCCESS == key.QueryStringValue(_T("Subtype"), buff, &len))
346 subtype = GUIDFromCString(buff);
348 CFGFilter* pFGF = new CFGFilterRegistry(clsid);
349 pFGF->AddType(majortype, subtype);
350 fl.Insert(pFGF, 7);
355 if(hFile != INVALID_HANDLE_VALUE)
357 CloseHandle(hFile);
360 CFGFilter* pFGF = new CFGFilterRegistry(CLSID_AsyncReader);
361 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_NULL);
362 fl.Insert(pFGF, 9);
364 return S_OK;
367 HRESULT CFGManager::AddSourceFilter(CFGFilter* pFGF, LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppBF)
369 TRACE(_T("FGM: AddSourceFilter trying '%s'\n"), CStringFromGUID(pFGF->GetCLSID()));
371 CheckPointer(lpcwstrFileName, E_POINTER);
372 CheckPointer(ppBF, E_POINTER);
374 ASSERT(*ppBF == NULL);
376 HRESULT hr;
378 CComPtr<IBaseFilter> pBF;
379 CInterfaceList<IUnknown, &IID_IUnknown> pUnks;
380 if(FAILED(hr = pFGF->Create(&pBF, pUnks)))
381 return hr;
383 CComQIPtr<IFileSourceFilter> pFSF = pBF;
384 if(!pFSF) return E_NOINTERFACE;
386 if(FAILED(hr = AddFilter(pBF, lpcwstrFilterName)))
387 return hr;
389 const AM_MEDIA_TYPE* pmt = NULL;
391 CMediaType mt;
392 const CAtlList<GUID>& types = pFGF->GetTypes();
393 if(types.GetCount() == 2 && (types.GetHead() != GUID_NULL || types.GetTail() != GUID_NULL))
395 mt.majortype = types.GetHead();
396 mt.subtype = types.GetTail();
397 pmt = &mt;
400 if(FAILED(hr = pFSF->Load(lpcwstrFileName, pmt)))
402 RemoveFilter(pBF);
403 return hr;
406 // doh :P
407 BeginEnumMediaTypes(GetFirstPin(pBF, PINDIR_OUTPUT), pEMT, pmt)
409 if(pmt->subtype == GUIDFromCString(_T("{640999A0-A946-11D0-A520-000000000000}"))
410 || pmt->subtype == GUIDFromCString(_T("{640999A1-A946-11D0-A520-000000000000}"))
411 || pmt->subtype == GUIDFromCString(_T("{D51BD5AE-7548-11CF-A520-0080C77EF58A}")))
413 RemoveFilter(pBF);
414 pFGF = new CFGFilterRegistry(CLSID_NetShowSource);
415 hr = AddSourceFilter(pFGF, lpcwstrFileName, lpcwstrFilterName, ppBF);
416 delete pFGF;
417 return hr;
420 EndEnumMediaTypes(pmt)
422 *ppBF = pBF.Detach();
424 m_pUnks.AddTailList(&pUnks);
426 return S_OK;
429 // IFilterGraph
431 STDMETHODIMP CFGManager::AddFilter(IBaseFilter* pFilter, LPCWSTR pName)
433 if(!m_pUnkInner) return E_UNEXPECTED;
435 CAutoLock cAutoLock(this);
437 HRESULT hr;
439 if(FAILED(hr = CComQIPtr<IFilterGraph2>(m_pUnkInner)->AddFilter(pFilter, pName)))
440 return hr;
442 // TODO
443 hr = pFilter->JoinFilterGraph(NULL, NULL);
444 hr = pFilter->JoinFilterGraph(this, pName);
446 return hr;
449 STDMETHODIMP CFGManager::RemoveFilter(IBaseFilter* pFilter)
451 if(!m_pUnkInner) return E_UNEXPECTED;
453 CAutoLock cAutoLock(this);
455 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->RemoveFilter(pFilter);
458 STDMETHODIMP CFGManager::EnumFilters(IEnumFilters** ppEnum)
460 if(!m_pUnkInner) return E_UNEXPECTED;
462 CAutoLock cAutoLock(this);
464 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->EnumFilters(ppEnum);
467 STDMETHODIMP CFGManager::FindFilterByName(LPCWSTR pName, IBaseFilter** ppFilter)
469 if(!m_pUnkInner) return E_UNEXPECTED;
471 CAutoLock cAutoLock(this);
473 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->FindFilterByName(pName, ppFilter);
476 STDMETHODIMP CFGManager::ConnectDirect(IPin* pPinOut, IPin* pPinIn, const AM_MEDIA_TYPE* pmt)
478 if(!m_pUnkInner) return E_UNEXPECTED;
480 CAutoLock cAutoLock(this);
482 CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinIn);
483 CLSID clsid = GetCLSID(pBF);
485 // TODO: GetUpStreamFilter goes up on the first input pin only
486 for(CComPtr<IBaseFilter> pBFUS = GetFilterFromPin(pPinOut); pBFUS; pBFUS = GetUpStreamFilter(pBFUS))
488 if(pBFUS == pBF) return VFW_E_CIRCULAR_GRAPH;
489 if(GetCLSID(pBFUS) == clsid) return VFW_E_CANNOT_CONNECT;
492 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->ConnectDirect(pPinOut, pPinIn, pmt);
495 STDMETHODIMP CFGManager::Reconnect(IPin* ppin)
497 if(!m_pUnkInner) return E_UNEXPECTED;
499 CAutoLock cAutoLock(this);
501 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->Reconnect(ppin);
504 STDMETHODIMP CFGManager::Disconnect(IPin* ppin)
506 if(!m_pUnkInner) return E_UNEXPECTED;
508 CAutoLock cAutoLock(this);
510 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->Disconnect(ppin);
513 STDMETHODIMP CFGManager::SetDefaultSyncSource()
515 if(!m_pUnkInner) return E_UNEXPECTED;
517 CAutoLock cAutoLock(this);
519 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->SetDefaultSyncSource();
522 // IGraphBuilder
524 STDMETHODIMP CFGManager::Connect(IPin* pPinOut, IPin* pPinIn)
526 CAutoLock cAutoLock(this);
528 CheckPointer(pPinOut, E_POINTER);
530 HRESULT hr;
532 if(S_OK != IsPinDirection(pPinOut, PINDIR_OUTPUT)
533 || pPinIn && S_OK != IsPinDirection(pPinIn, PINDIR_INPUT))
534 return VFW_E_INVALID_DIRECTION;
536 if(S_OK == IsPinConnected(pPinOut)
537 || pPinIn && S_OK == IsPinConnected(pPinIn))
538 return VFW_E_ALREADY_CONNECTED;
540 bool fDeadEnd = true;
542 if(pPinIn)
544 // 1. Try a direct connection between the filters, with no intermediate filters
546 if(SUCCEEDED(hr = ConnectDirect(pPinOut, pPinIn, NULL)))
547 return hr;
549 else
551 // 1. Use IStreamBuilder
553 if(CComQIPtr<IStreamBuilder> pSB = pPinOut)
555 if(SUCCEEDED(hr = pSB->Render(pPinOut, this)))
556 return hr;
558 pSB->Backout(pPinOut, this);
562 // 2. Try cached filters
564 if(CComQIPtr<IGraphConfig> pGC = (IGraphBuilder2*)this)
566 BeginEnumCachedFilters(pGC, pEF, pBF)
568 if(pPinIn && GetFilterFromPin(pPinIn) == pBF)
569 continue;
571 hr = pGC->RemoveFilterFromCache(pBF);
573 // does RemoveFilterFromCache call AddFilter like AddFilterToCache calls RemoveFilter ?
575 if(SUCCEEDED(hr = ConnectFilterDirect(pPinOut, pBF, NULL)))
577 if(!IsStreamEnd(pBF)) fDeadEnd = false;
579 if(SUCCEEDED(hr = ConnectFilter(pBF, pPinIn)))
580 return hr;
583 hr = pGC->AddFilterToCache(pBF);
585 EndEnumCachedFilters
588 // 3. Try filters in the graph
591 CInterfaceList<IBaseFilter> pBFs;
593 BeginEnumFilters(this, pEF, pBF)
595 if(pPinIn && GetFilterFromPin(pPinIn) == pBF
596 || GetFilterFromPin(pPinOut) == pBF)
597 continue;
599 // HACK: ffdshow - audio capture filter
600 if(GetCLSID(pPinOut) == GUIDFromCString(_T("{04FE9017-F873-410E-871E-AB91661A4EF7}"))
601 && GetCLSID(pBF) == GUIDFromCString(_T("{E30629D2-27E5-11CE-875D-00608CB78066}")))
602 continue;
604 pBFs.AddTail(pBF);
606 EndEnumFilters
608 POSITION pos = pBFs.GetHeadPosition();
609 while(pos)
611 IBaseFilter* pBF = pBFs.GetNext(pos);
613 if(SUCCEEDED(hr = ConnectFilterDirect(pPinOut, pBF, NULL)))
615 if(!IsStreamEnd(pBF)) fDeadEnd = false;
617 if(SUCCEEDED(hr = ConnectFilter(pBF, pPinIn)))
618 return hr;
621 EXECUTE_ASSERT(Disconnect(pPinOut));
625 // 4. Look up filters in the registry
628 CFGFilterList fl;
630 CAtlArray<GUID> types;
631 ExtractMediaTypes(pPinOut, types);
633 POSITION pos = m_transform.GetHeadPosition();
634 while(pos)
636 CFGFilter* pFGF = m_transform.GetNext(pos);
637 if(pFGF->GetMerit() < MERIT64_DO_USE || pFGF->CheckTypes(types, false))
638 fl.Insert(pFGF, 0, pFGF->CheckTypes(types, true), false);
641 pos = m_override.GetHeadPosition();
642 while(pos)
644 CFGFilter* pFGF = m_override.GetNext(pos);
645 if(pFGF->GetMerit() < MERIT64_DO_USE || pFGF->CheckTypes(types, false))
646 fl.Insert(pFGF, 0, pFGF->CheckTypes(types, true), false);
649 CComPtr<IEnumMoniker> pEM;
650 if(types.GetCount() > 0
651 && SUCCEEDED(m_pFM->EnumMatchingFilters(
652 &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
653 TRUE, types.GetCount()/2, types.GetData(), NULL, NULL, FALSE,
654 !!pPinIn, 0, NULL, NULL, NULL)))
656 for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
658 CFGFilterRegistry* pFGF = new CFGFilterRegistry(pMoniker);
659 fl.Insert(pFGF, 0, pFGF->CheckTypes(types, true));
663 pos = fl.GetHeadPosition();
664 while(pos)
666 CFGFilter* pFGF = fl.GetNext(pos);
668 TRACE(_T("FGM: Connecting '%s'\n"), pFGF->GetName());
670 CComPtr<IBaseFilter> pBF;
671 CInterfaceList<IUnknown, &IID_IUnknown> pUnks;
672 if(FAILED(pFGF->Create(&pBF, pUnks)))
673 continue;
675 if(FAILED(hr = AddFilter(pBF, pFGF->GetName())))
676 continue;
678 hr = E_FAIL;
680 if(FAILED(hr))
682 hr = ConnectFilterDirect(pPinOut, pBF, NULL);
685 if(FAILED(hr))
687 if(types.GetCount() >= 2 && types[0] == MEDIATYPE_Stream && types[1] != GUID_NULL)
689 CMediaType mt;
691 mt.majortype = types[0];
692 mt.subtype = types[1];
693 mt.formattype = FORMAT_None;
694 if(FAILED(hr)) hr = ConnectFilterDirect(pPinOut, pBF, &mt);
696 mt.formattype = GUID_NULL;
697 if(FAILED(hr)) hr = ConnectFilterDirect(pPinOut, pBF, &mt);
701 if(SUCCEEDED(hr))
703 if(!IsStreamEnd(pBF)) fDeadEnd = false;
705 hr = ConnectFilter(pBF, pPinIn);
707 if(SUCCEEDED(hr))
709 m_pUnks.AddTailList(&pUnks);
711 // maybe the application should do this...
713 POSITION pos = pUnks.GetHeadPosition();
714 while(pos)
716 if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pUnks.GetNext(pos))
717 pMPC->SetAspectRatioMode(AM_ARMODE_STRETCHED);
720 if(CComQIPtr<IVMRAspectRatioControl> pARC = pBF)
721 pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
723 if(CComQIPtr<IVMRAspectRatioControl9> pARC = pBF)
724 pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
726 return hr;
730 EXECUTE_ASSERT(SUCCEEDED(RemoveFilter(pBF)));
732 TRACE(_T("FGM: Connecting '%s' FAILED!\n"), pFGF->GetName());
736 if(fDeadEnd)
738 CAutoPtr<CStreamDeadEnd> psde(new CStreamDeadEnd());
739 psde->AddTailList(&m_streampath);
740 int skip = 0;
741 BeginEnumMediaTypes(pPinOut, pEM, pmt)
743 if(pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_NULL) skip++;
744 psde->mts.AddTail(CMediaType(*pmt));
746 EndEnumMediaTypes(pmt)
747 if(skip < psde->mts.GetCount())
748 m_deadends.Add(psde);
751 return pPinIn ? VFW_E_CANNOT_CONNECT : VFW_E_CANNOT_RENDER;
754 STDMETHODIMP CFGManager::Render(IPin* pPinOut)
756 CAutoLock cAutoLock(this);
758 return RenderEx(pPinOut, 0, NULL);
761 STDMETHODIMP CFGManager::RenderFile(LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrPlayList)
763 CAutoLock cAutoLock(this);
765 m_streampath.RemoveAll();
766 m_deadends.RemoveAll();
768 HRESULT hr;
771 CComPtr<IBaseFilter> pBF;
772 if(FAILED(hr = AddSourceFilter(lpcwstrFile, lpcwstrFile, &pBF)))
773 return hr;
775 return ConnectFilter(pBF, NULL);
778 CFGFilterList fl;
779 if(FAILED(hr = EnumSourceFilters(lpcwstrFileName, fl)))
780 return hr;
782 CAutoPtrArray<CStreamDeadEnd> deadends;
784 hr = VFW_E_CANNOT_RENDER;
786 POSITION pos = fl.GetHeadPosition();
787 while(pos)
789 CComPtr<IBaseFilter> pBF;
791 if(SUCCEEDED(hr = AddSourceFilter(fl.GetNext(pos), lpcwstrFileName, lpcwstrFileName, &pBF)))
793 m_streampath.RemoveAll();
794 m_deadends.RemoveAll();
796 if(SUCCEEDED(hr = ConnectFilter(pBF, NULL)))
797 return hr;
799 NukeDownstream(pBF);
800 RemoveFilter(pBF);
802 deadends.Append(m_deadends);
806 m_deadends.Copy(deadends);
808 return hr;
811 STDMETHODIMP CFGManager::AddSourceFilter(LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter)
813 CAutoLock cAutoLock(this);
815 HRESULT hr;
817 CFGFilterList fl;
818 if(FAILED(hr = EnumSourceFilters(lpcwstrFileName, fl)))
819 return hr;
821 POSITION pos = fl.GetHeadPosition();
822 while(pos)
824 if(SUCCEEDED(hr = AddSourceFilter(fl.GetNext(pos), lpcwstrFileName, lpcwstrFilterName, ppFilter)))
825 return hr;
828 return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
831 STDMETHODIMP CFGManager::SetLogFile(DWORD_PTR hFile)
833 if(!m_pUnkInner) return E_UNEXPECTED;
835 CAutoLock cAutoLock(this);
837 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->SetLogFile(hFile);
840 STDMETHODIMP CFGManager::Abort()
842 if(!m_pUnkInner) return E_UNEXPECTED;
844 CAutoLock cAutoLock(this);
846 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->Abort();
849 STDMETHODIMP CFGManager::ShouldOperationContinue()
851 if(!m_pUnkInner) return E_UNEXPECTED;
853 CAutoLock cAutoLock(this);
855 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->ShouldOperationContinue();
858 // IFilterGraph2
860 STDMETHODIMP CFGManager::AddSourceFilterForMoniker(IMoniker* pMoniker, IBindCtx* pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter)
862 if(!m_pUnkInner) return E_UNEXPECTED;
864 CAutoLock cAutoLock(this);
866 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->AddSourceFilterForMoniker(pMoniker, pCtx, lpcwstrFilterName, ppFilter);
869 STDMETHODIMP CFGManager::ReconnectEx(IPin* ppin, const AM_MEDIA_TYPE* pmt)
871 if(!m_pUnkInner) return E_UNEXPECTED;
873 CAutoLock cAutoLock(this);
875 return CComQIPtr<IFilterGraph2>(m_pUnkInner)->ReconnectEx(ppin, pmt);
878 STDMETHODIMP CFGManager::RenderEx(IPin* pPinOut, DWORD dwFlags, DWORD* pvContext)
880 CAutoLock cAutoLock(this);
882 m_streampath.RemoveAll();
883 m_deadends.RemoveAll();
885 if(!pPinOut || dwFlags > AM_RENDEREX_RENDERTOEXISTINGRENDERERS || pvContext)
886 return E_INVALIDARG;
888 HRESULT hr;
890 if(dwFlags & AM_RENDEREX_RENDERTOEXISTINGRENDERERS)
892 CInterfaceList<IBaseFilter> pBFs;
894 BeginEnumFilters(this, pEF, pBF)
896 if(CComQIPtr<IAMFilterMiscFlags> pAMMF = pBF)
898 if(pAMMF->GetMiscFlags() & AM_FILTER_MISC_FLAGS_IS_RENDERER)
900 pBFs.AddTail(pBF);
903 else
905 BeginEnumPins(pBF, pEP, pPin)
907 CComPtr<IPin> pPinIn;
908 DWORD size = 1;
909 if(SUCCEEDED(pPin->QueryInternalConnections(&pPinIn, &size)) && size == 0)
911 pBFs.AddTail(pBF);
912 break;
915 EndEnumPins
918 EndEnumFilters
920 while(!pBFs.IsEmpty())
922 if(SUCCEEDED(hr = ConnectFilter(pPinOut, pBFs.RemoveHead())))
923 return hr;
926 return VFW_E_CANNOT_RENDER;
929 return Connect(pPinOut, (IPin*)NULL);
932 // IGraphBuilder2
934 STDMETHODIMP CFGManager::IsPinDirection(IPin* pPin, PIN_DIRECTION dir1)
936 CAutoLock cAutoLock(this);
938 CheckPointer(pPin, E_POINTER);
940 PIN_DIRECTION dir2;
941 if(FAILED(pPin->QueryDirection(&dir2)))
942 return E_FAIL;
944 return dir1 == dir2 ? S_OK : S_FALSE;
947 STDMETHODIMP CFGManager::IsPinConnected(IPin* pPin)
949 CAutoLock cAutoLock(this);
951 CheckPointer(pPin, E_POINTER);
953 CComPtr<IPin> pPinTo;
954 return SUCCEEDED(pPin->ConnectedTo(&pPinTo)) && pPinTo ? S_OK : S_FALSE;
957 STDMETHODIMP CFGManager::ConnectFilter(IBaseFilter* pBF, IPin* pPinIn)
959 CAutoLock cAutoLock(this);
961 CheckPointer(pBF, E_POINTER);
963 if(pPinIn && S_OK != IsPinDirection(pPinIn, PINDIR_INPUT))
964 return VFW_E_INVALID_DIRECTION;
966 int nTotal = 0, nRendered = 0;
968 BeginEnumPins(pBF, pEP, pPin)
970 if(GetPinName(pPin)[0] != '~'
971 && S_OK == IsPinDirection(pPin, PINDIR_OUTPUT)
972 && S_OK != IsPinConnected(pPin))
974 m_streampath.Append(pBF, pPin);
976 HRESULT hr = Connect(pPin, pPinIn);
978 if(SUCCEEDED(hr))
980 for(int i = m_deadends.GetCount()-1; i >= 0; i--)
981 if(m_deadends[i]->Compare(m_streampath))
982 m_deadends.RemoveAt(i);
984 nRendered++;
987 nTotal++;
989 m_streampath.RemoveTail();
991 if(SUCCEEDED(hr) && pPinIn)
992 return S_OK;
995 EndEnumPins
997 return
998 nRendered == nTotal ? (nRendered > 0 ? S_OK : S_FALSE) :
999 nRendered > 0 ? VFW_S_PARTIAL_RENDER :
1000 VFW_E_CANNOT_RENDER;
1003 STDMETHODIMP CFGManager::ConnectFilter(IPin* pPinOut, IBaseFilter* pBF)
1005 CAutoLock cAutoLock(this);
1007 CheckPointer(pPinOut, E_POINTER);
1008 CheckPointer(pBF, E_POINTER);
1010 if(S_OK != IsPinDirection(pPinOut, PINDIR_OUTPUT))
1011 return VFW_E_INVALID_DIRECTION;
1013 HRESULT hr;
1015 BeginEnumPins(pBF, pEP, pPin)
1017 if(GetPinName(pPin)[0] != '~'
1018 && S_OK == IsPinDirection(pPin, PINDIR_INPUT)
1019 && S_OK != IsPinConnected(pPin)
1020 && SUCCEEDED(hr = Connect(pPinOut, pPin)))
1021 return hr;
1023 EndEnumPins
1025 return VFW_E_CANNOT_CONNECT;
1028 STDMETHODIMP CFGManager::ConnectFilterDirect(IPin* pPinOut, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt)
1030 CAutoLock cAutoLock(this);
1032 CheckPointer(pPinOut, E_POINTER);
1033 CheckPointer(pBF, E_POINTER);
1035 if(S_OK != IsPinDirection(pPinOut, PINDIR_OUTPUT))
1036 return VFW_E_INVALID_DIRECTION;
1038 HRESULT hr;
1040 BeginEnumPins(pBF, pEP, pPin)
1042 if(GetPinName(pPin)[0] != '~'
1043 && S_OK == IsPinDirection(pPin, PINDIR_INPUT)
1044 && S_OK != IsPinConnected(pPin)
1045 && SUCCEEDED(hr = ConnectDirect(pPinOut, pPin, pmt)))
1046 return hr;
1048 EndEnumPins
1050 return VFW_E_CANNOT_CONNECT;
1053 STDMETHODIMP CFGManager::NukeDownstream(IUnknown* pUnk)
1055 CAutoLock cAutoLock(this);
1057 if(CComQIPtr<IBaseFilter> pBF = pUnk)
1059 BeginEnumPins(pBF, pEP, pPin)
1061 NukeDownstream(pPin);
1063 EndEnumPins
1065 else if(CComQIPtr<IPin> pPin = pUnk)
1067 CComPtr<IPin> pPinTo;
1068 if(S_OK == IsPinDirection(pPin, PINDIR_OUTPUT)
1069 && SUCCEEDED(pPin->ConnectedTo(&pPinTo)) && pPinTo)
1071 if(CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo))
1073 NukeDownstream(pBF);
1074 Disconnect(pPinTo);
1075 Disconnect(pPin);
1076 RemoveFilter(pBF);
1080 else
1082 return E_INVALIDARG;
1085 return S_OK;
1088 STDMETHODIMP CFGManager::FindInterface(REFIID iid, void** ppv, BOOL bRemove)
1090 CAutoLock cAutoLock(this);
1092 CheckPointer(ppv, E_POINTER);
1094 for(POSITION pos = m_pUnks.GetHeadPosition(); pos; m_pUnks.GetNext(pos))
1096 if(SUCCEEDED(m_pUnks.GetAt(pos)->QueryInterface(iid, ppv)))
1098 if(bRemove) m_pUnks.RemoveAt(pos);
1099 return S_OK;
1103 return E_NOINTERFACE;
1106 STDMETHODIMP CFGManager::AddToROT()
1108 CAutoLock cAutoLock(this);
1110 HRESULT hr;
1112 if(m_dwRegister) return S_FALSE;
1114 CComPtr<IRunningObjectTable> pROT;
1115 CComPtr<IMoniker> pMoniker;
1116 WCHAR wsz[256];
1117 swprintf(wsz, L"FilterGraph %08p pid %08x (MPC)", (DWORD_PTR)this, GetCurrentProcessId());
1118 if(SUCCEEDED(hr = GetRunningObjectTable(0, &pROT))
1119 && SUCCEEDED(hr = CreateItemMoniker(L"!", wsz, &pMoniker)))
1120 hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, (IGraphBuilder2*)this, pMoniker, &m_dwRegister);
1122 return hr;
1125 STDMETHODIMP CFGManager::RemoveFromROT()
1127 CAutoLock cAutoLock(this);
1129 HRESULT hr;
1131 if(!m_dwRegister) return S_FALSE;
1133 CComPtr<IRunningObjectTable> pROT;
1134 if(SUCCEEDED(hr = GetRunningObjectTable(0, &pROT))
1135 && SUCCEEDED(hr = pROT->Revoke(m_dwRegister)))
1136 m_dwRegister = 0;
1138 return hr;
1141 // IGraphBuilderDeadEnd
1143 STDMETHODIMP_(size_t) CFGManager::GetCount()
1145 CAutoLock cAutoLock(this);
1147 return m_deadends.GetCount();
1150 STDMETHODIMP CFGManager::GetDeadEnd(int iIndex, CAtlList<CStringW>& path, CAtlList<CMediaType>& mts)
1152 CAutoLock cAutoLock(this);
1154 if(iIndex < 0 || iIndex >= m_deadends.GetCount()) return E_FAIL;
1156 path.RemoveAll();
1157 mts.RemoveAll();
1159 POSITION pos = m_deadends[iIndex]->GetHeadPosition();
1160 while(pos)
1162 const path_t& p = m_deadends[iIndex]->GetNext(pos);
1164 CStringW str;
1165 str.Format(L"%s::%s", p.filter, p.pin);
1166 path.AddTail(str);
1169 mts.AddTailList(&m_deadends[iIndex]->mts);
1171 return S_OK;
1175 // CFGManagerCustom
1178 CFGManagerCustom::CFGManagerCustom(LPCTSTR pName, LPUNKNOWN pUnk, UINT src, UINT tra)
1179 : CFGManager(pName, pUnk)
1181 AppSettings& s = AfxGetAppSettings();
1183 CFGFilter* pFGF;
1185 // Source filters
1187 if(src & SRC_SHOUTCAST)
1189 pFGF = new CFGFilterInternal<CShoutcastSource>();
1190 pFGF->m_protocols.AddTail(_T("http"));
1191 m_source.AddTail(pFGF);
1194 #if (_MSC_VER < 1500)
1195 // if(src & SRC_UDP)
1197 pFGF = new CFGFilterInternal<CUDPReader>();
1198 pFGF->m_protocols.AddTail(_T("udp"));
1199 m_source.AddTail(pFGF);
1201 #endif
1203 if(src & SRC_AVI)
1205 pFGF = new CFGFilterInternal<CAviSourceFilter>();
1206 pFGF->m_chkbytes.AddTail(_T("0,4,,52494646,8,4,,41564920"));
1207 pFGF->m_chkbytes.AddTail(_T("0,4,,52494646,8,4,,41564958"));
1208 m_source.AddTail(pFGF);
1211 if(src & SRC_MP4)
1213 pFGF = new CFGFilterInternal<CMP4SourceFilter>();
1214 pFGF->m_chkbytes.AddTail(_T("4,4,,66747970")); // ftyp
1215 pFGF->m_chkbytes.AddTail(_T("4,4,,6d6f6f76")); // moov
1216 pFGF->m_chkbytes.AddTail(_T("4,4,,6d646174")); // mdat
1217 pFGF->m_chkbytes.AddTail(_T("4,4,,736b6970")); // skip
1218 pFGF->m_chkbytes.AddTail(_T("4,12,ffffffff00000000ffffffff,77696465027fe3706d646174")); // wide ? mdat
1219 pFGF->m_chkbytes.AddTail(_T("3,3,,000001")); // raw mpeg4 video
1220 pFGF->m_extensions.AddTail(_T(".mov"));
1221 m_source.AddTail(pFGF);
1224 if(src & SRC_FLV)
1226 pFGF = new CFGFilterInternal<CFLVSourceFilter>();
1227 pFGF->m_chkbytes.AddTail(_T("0,4,,464C5601")); // FLV (v1)
1228 m_source.AddTail(pFGF);
1231 if(src & SRC_MATROSKA)
1233 pFGF = new CFGFilterInternal<CMatroskaSourceFilter>();
1234 pFGF->m_chkbytes.AddTail(_T("0,4,,1A45DFA3"));
1235 m_source.AddTail(pFGF);
1238 if(src & SRC_REALMEDIA)
1240 pFGF = new CFGFilterInternal<CRealMediaSourceFilter>();
1241 pFGF->m_chkbytes.AddTail(_T("0,4,,2E524D46"));
1242 m_source.AddTail(pFGF);
1245 if(src & SRC_DSM)
1247 pFGF = new CFGFilterInternal<CDSMSourceFilter>();
1248 pFGF->m_chkbytes.AddTail(_T("0,4,,44534D53"));
1249 m_source.AddTail(pFGF);
1252 if(src & SRC_FLIC)
1254 pFGF = new CFGFilterInternal<CFLICSource>();
1255 pFGF->m_chkbytes.AddTail(_T("4,2,,11AF"));
1256 pFGF->m_chkbytes.AddTail(_T("4,2,,12AF"));
1257 pFGF->m_extensions.AddTail(_T(".fli"));
1258 pFGF->m_extensions.AddTail(_T(".flc"));
1259 m_source.AddTail(pFGF);
1262 if(src & SRC_CDDA)
1264 pFGF = new CFGFilterInternal<CCDDAReader>();
1265 pFGF->m_extensions.AddTail(_T(".cda"));
1266 m_source.AddTail(pFGF);
1269 if(src & SRC_CDXA)
1271 pFGF = new CFGFilterInternal<CCDXAReader>();
1272 pFGF->m_chkbytes.AddTail(_T("0,4,,52494646,8,4,,43445841"));
1273 m_source.AddTail(pFGF);
1276 if(src & SRC_VTS)
1278 pFGF = new CFGFilterInternal<CVTSReader>();
1279 pFGF->m_chkbytes.AddTail(_T("0,12,,445644564944454F2D565453"));
1280 m_source.AddTail(pFGF);
1283 __if_exists(CD2VSource)
1285 if(src & SRC_D2V)
1287 pFGF = new CFGFilterInternal<CD2VSource>();
1288 pFGF->m_chkbytes.AddTail(_T("0,18,,4456443241564950726F6A65637446696C65"));
1289 pFGF->m_extensions.AddTail(_T(".d2v"));
1290 m_source.AddTail(pFGF);
1294 __if_exists(CRadGtSourceFilter)
1296 if(src & SRC_RADGT)
1298 pFGF = new CFGFilterInternal<CRadGtSourceFilter>();
1299 pFGF->m_chkbytes.AddTail(_T("0,3,,534D4B"));
1300 pFGF->m_chkbytes.AddTail(_T("0,3,,42494B"));
1301 pFGF->m_extensions.AddTail(_T(".smk"));
1302 pFGF->m_extensions.AddTail(_T(".bik"));
1303 m_source.AddTail(pFGF);
1307 if(src & SRC_ROQ)
1309 pFGF = new CFGFilterInternal<CRoQSourceFilter>();
1310 pFGF->m_chkbytes.AddTail(_T("0,8,,8410FFFFFFFF1E00"));
1311 m_source.AddTail(pFGF);
1314 if(src & SRC_OGG)
1316 pFGF = new CFGFilterInternal<COggSourceFilter>();
1317 pFGF->m_chkbytes.AddTail(_T("0,4,,4F676753"));
1318 m_source.AddTail(pFGF);
1321 __if_exists(CNutSourceFilter)
1323 if(src & SRC_NUT)
1325 pFGF = new CFGFilterInternal<CNutSourceFilter>();
1326 pFGF->m_chkbytes.AddTail(_T("0,8,,F9526A624E55544D"));
1327 m_source.AddTail(pFGF);
1331 __if_exists(CDiracSourceFilter)
1333 if(src & SRC_DIRAC)
1335 pFGF = new CFGFilterInternal<CDiracSourceFilter>();
1336 pFGF->m_chkbytes.AddTail(_T("0,8,,4B572D4449524143"));
1337 m_source.AddTail(pFGF);
1341 if(src & SRC_MPEG)
1343 pFGF = new CFGFilterInternal<CMpegSourceFilter>();
1344 pFGF->m_chkbytes.AddTail(_T("0,16,FFFFFFFFF100010001800001FFFFFFFF,000001BA2100010001800001000001BB"));
1345 pFGF->m_chkbytes.AddTail(_T("0,5,FFFFFFFFC0,000001BA40"));
1346 pFGF->m_chkbytes.AddTail(_T("0,1,,47,188,1,,47,376,1,,47"));
1347 pFGF->m_chkbytes.AddTail(_T("4,1,,47,196,1,,47,388,1,,47"));
1348 pFGF->m_chkbytes.AddTail(_T("0,4,,54467263,1660,1,,47"));
1349 pFGF->m_chkbytes.AddTail(_T("0,8,fffffc00ffe00000,4156000055000000"));
1350 m_source.AddTail(pFGF);
1353 if(src & SRC_DTSAC3)
1355 pFGF = new CFGFilterInternal<CDTSAC3Source>();
1356 pFGF->m_chkbytes.AddTail(_T("0,4,,7FFE8001"));
1357 pFGF->m_chkbytes.AddTail(_T("0,2,,0B77"));
1358 pFGF->m_chkbytes.AddTail(_T("0,2,,770B"));
1359 pFGF->m_extensions.AddTail(_T(".ac3"));
1360 pFGF->m_extensions.AddTail(_T(".dts"));
1361 m_source.AddTail(pFGF);
1364 if(src & SRC_MPA)
1366 pFGF = new CFGFilterInternal<CMpaSourceFilter>();
1367 pFGF->m_chkbytes.AddTail(_T("0,2,FFE0,FFE0"));
1368 pFGF->m_chkbytes.AddTail(_T("0,10,FFFFFF00000080808080,49443300000000000000"));
1369 m_source.AddTail(pFGF);
1372 if(AfxGetAppSettings().fUseWMASFReader)
1374 pFGF = new CFGFilterRegistry(CLSID_WMAsfReader);
1375 pFGF->m_chkbytes.AddTail(_T("0,4,,3026B275"));
1376 pFGF->m_chkbytes.AddTail(_T("0,4,,D129E2D6"));
1377 m_source.AddTail(pFGF);
1380 // Transform filters
1382 pFGF = new CFGFilterInternal<CAVI2AC3Filter>(L"AVI<->AC3/DTS", MERIT64(0x00680000)+1);
1383 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_WAVE_DOLBY_AC3);
1384 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_WAVE_DTS);
1385 m_transform.AddTail(pFGF);
1387 if(src & SRC_MATROSKA) {
1388 pFGF = new CFGFilterInternal<CMatroskaSplitterFilter>(L"Matroska Splitter", MERIT64_ABOVE_DSHOW);
1389 } else {
1390 pFGF = new CFGFilterInternal<CMatroskaSplitterFilter>(L"Matroska Splitter (low merit)", MERIT64_DO_USE);
1392 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Matroska);
1393 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1394 m_transform.AddTail(pFGF);
1396 if(src & SRC_REALMEDIA) {
1397 pFGF = new CFGFilterInternal<CRealMediaSplitterFilter>(L"RealMedia Splitter", MERIT64_ABOVE_DSHOW);
1398 } else {
1399 pFGF = new CFGFilterInternal<CRealMediaSplitterFilter>(L"RealMedia Splitter (low merit)", MERIT64_DO_USE);
1401 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_RealMedia);
1402 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1403 m_transform.AddTail(pFGF);
1405 if(src & SRC_AVI) {
1406 pFGF = new CFGFilterInternal<CAviSplitterFilter>(L"Avi Splitter", MERIT64_ABOVE_DSHOW);
1407 } else {
1408 pFGF = new CFGFilterInternal<CAviSplitterFilter>(L"Avi Splitter (low merit)", MERIT64_DO_USE);
1410 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Avi);
1411 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1412 m_transform.AddTail(pFGF);
1414 __if_exists(CRadGtSplitterFilter)
1416 if(src & SRC_RADGT) {
1417 pFGF = new CFGFilterInternal<CRadGtSplitterFilter>(L"RadGt Splitter", MERIT64_ABOVE_DSHOW);
1418 } else {
1419 pFGF = new CFGFilterInternal<CRadGtSplitterFilter>(L"RadGt Splitter (low merit)", MERIT64_DO_USE);
1421 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Bink);
1422 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Smacker);
1423 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1424 m_transform.AddTail(pFGF);
1427 if(src & SRC_ROQ) {
1428 pFGF = new CFGFilterInternal<CRoQSplitterFilter>(L"RoQ Splitter", MERIT64_ABOVE_DSHOW);
1429 } else {
1430 pFGF = new CFGFilterInternal<CRoQSplitterFilter>(L"RoQ Splitter (low merit)", MERIT64_DO_USE);
1432 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_RoQ);
1433 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1434 m_transform.AddTail(pFGF);
1436 if(src & SRC_OGG) {
1437 pFGF = new CFGFilterInternal<COggSplitterFilter>(L"Ogg Splitter", MERIT64_ABOVE_DSHOW);
1438 } else {
1439 pFGF = new CFGFilterInternal<COggSplitterFilter>(L"Ogg Splitter (low merit)", MERIT64_DO_USE);
1441 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Ogg);
1442 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1443 m_transform.AddTail(pFGF);
1445 __if_exists(CNutSplitterFilter)
1447 if(src & SRC_NUT) {
1448 pFGF = new CFGFilterInternal<CNutSplitterFilter>(L"Nut Splitter", MERIT64_ABOVE_DSHOW);
1449 } else {
1450 pFGF = new CFGFilterInternal<CNutSplitterFilter>(L"Nut Splitter (low merit)", MERIT64_DO_USE);
1452 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Nut);
1453 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1454 m_transform.AddTail(pFGF);
1457 if(src & SRC_MPEG) {
1458 pFGF = new CFGFilterInternal<CMpegSplitterFilter>(L"Mpeg Splitter", MERIT64_ABOVE_DSHOW);
1459 } else {
1460 pFGF = new CFGFilterInternal<CMpegSplitterFilter>(L"Mpeg Splitter (low merit)", MERIT64_DO_USE);
1462 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG1System);
1463 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG2_PROGRAM);
1464 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG2_TRANSPORT);
1465 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG2_PVA);
1466 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1467 m_transform.AddTail(pFGF);
1469 __if_exists(CDiracSplitterFilter)
1471 if(src & SRC_DIRAC) {
1472 pFGF = new CFGFilterInternal<CDiracSplitterFilter>(L"Dirac Splitter", MERIT64_ABOVE_DSHOW);
1473 } else {
1474 pFGF = new CFGFilterInternal<CDiracSplitterFilter>(L"Dirac Splitter (low merit)", MERIT64_DO_USE);
1476 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_Dirac);
1477 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1478 m_transform.AddTail(pFGF);
1481 if(src & SRC_MPA) {
1482 pFGF = new CFGFilterInternal<CMpaSplitterFilter>(L"Mpa Splitter", MERIT64_ABOVE_DSHOW);
1483 } else {
1484 pFGF = new CFGFilterInternal<CMpaSplitterFilter>(L"Mpa Splitter (low merit)", MERIT64_DO_USE);
1486 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG1Audio);
1487 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1488 m_transform.AddTail(pFGF);
1490 if(src & SRC_DSM) {
1491 pFGF = new CFGFilterInternal<CDSMSplitterFilter>(L"DSM Splitter", MERIT64_ABOVE_DSHOW);
1492 } else {
1493 pFGF = new CFGFilterInternal<CDSMSplitterFilter>(L"DSM Splitter (low merit)", MERIT64_DO_USE);
1495 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_DirectShowMedia);
1496 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1497 m_transform.AddTail(pFGF);
1499 if(src & SRC_MP4) {
1500 pFGF = new CFGFilterInternal<CMP4SplitterFilter>(L"MP4 Splitter", MERIT64_ABOVE_DSHOW);
1501 } else {
1502 pFGF = new CFGFilterInternal<CMP4SplitterFilter>(L"MP4 Splitter (low merit)", MERIT64_DO_USE);
1504 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_MP4);
1505 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1506 m_transform.AddTail(pFGF);
1508 if(src & SRC_FLV) {
1509 pFGF = new CFGFilterInternal<CFLVSplitterFilter>(L"FLV Splitter", MERIT64_ABOVE_DSHOW);
1510 } else {
1511 pFGF = new CFGFilterInternal<CFLVSplitterFilter>(L"FLV Splitter (low merit)", MERIT64_DO_USE);
1513 pFGF->AddType(MEDIATYPE_Stream, MEDIASUBTYPE_FLV);
1514 pFGF->AddType(MEDIATYPE_Stream, GUID_NULL);
1515 m_transform.AddTail(pFGF);
1517 pFGF = new CFGFilterInternal<CMpeg2DecFilter>(
1518 (tra & TRA_MPEG1) ? L"MPEG-1 Video Decoder" : L"MPEG-1 Video Decoder (low merit)",
1519 (tra & TRA_MPEG1) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1520 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_MPEG1Packet);
1521 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_MPEG1Payload);
1522 m_transform.AddTail(pFGF);
1524 pFGF = new CFGFilterInternal<CMpeg2DecFilter>(
1525 (tra & TRA_MPEG2) ? L"MPEG-2 Video Decoder" : L"MPEG-2 Video Decoder (low merit)",
1526 (tra & TRA_MPEG2) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1527 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_MPEG2_VIDEO);
1528 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_MPEG2_VIDEO);
1529 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_MPEG2_VIDEO);
1530 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO);
1531 m_transform.AddTail(pFGF);
1533 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1534 (tra & TRA_MPA) ? L"MPEG-1 Audio Decoder" : L"MPEG-1 Audio Decoder (low merit)",
1535 (tra & TRA_MPA) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1536 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MP3);
1537 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG1AudioPayload);
1538 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG1Payload);
1539 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG1Packet);
1540 m_transform.AddTail(pFGF);
1542 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1543 (tra & TRA_MPA) ? L"MPEG-2 Audio Decoder" : L"MPEG-2 Audio Decoder (low merit)",
1544 (tra & TRA_MPA) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1545 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_MPEG2_AUDIO);
1546 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_MPEG2_AUDIO);
1547 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_MPEG2_AUDIO);
1548 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO);
1549 m_transform.AddTail(pFGF);
1551 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1552 (tra & TRA_LPCM) ? L"LPCM Audio Decoder" : L"LPCM Audio Decoder (low merit)",
1553 (tra & TRA_LPCM) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1554 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_DVD_LPCM_AUDIO);
1555 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_DVD_LPCM_AUDIO);
1556 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_DVD_LPCM_AUDIO);
1557 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_DVD_LPCM_AUDIO);
1558 m_transform.AddTail(pFGF);
1560 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1561 (tra & TRA_AC3) ? L"AC3 Audio Decoder" : L"AC3 Audio Decoder (low merit)",
1562 (tra & TRA_AC3) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1563 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_DOLBY_AC3);
1564 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_DOLBY_AC3);
1565 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_DOLBY_AC3);
1566 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3);
1567 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_WAVE_DOLBY_AC3);
1568 m_transform.AddTail(pFGF);
1570 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1571 (tra & TRA_DTS) ? L"DTS Decoder" : L"DTS Decoder (low merit)",
1572 (tra & TRA_DTS) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1573 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_DTS);
1574 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_DTS);
1575 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_DTS);
1576 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_DTS);
1577 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_WAVE_DTS);
1578 m_transform.AddTail(pFGF);
1580 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1581 (tra & TRA_AAC) ? L"AAC Decoder" : L"AAC Decoder (low merit)",
1582 (tra & TRA_AAC) ? MERIT64_ABOVE_DSHOW+1 : MERIT64_DO_USE);
1583 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_AAC);
1584 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_AAC);
1585 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_AAC);
1586 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_AAC);
1587 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_MP4A);
1588 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_MP4A);
1589 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_MP4A);
1590 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_MP4A);
1591 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_mp4a);
1592 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_mp4a);
1593 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_mp4a);
1594 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_mp4a);
1595 m_transform.AddTail(pFGF);
1597 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1598 (tra & TRA_PS2AUD) ? L"PS2 Audio Decoder" : L"PS2 Audio Decoder (low merit)",
1599 (tra & TRA_PS2AUD) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1600 pFGF->AddType(MEDIATYPE_DVD_ENCRYPTED_PACK, MEDIASUBTYPE_PS2_PCM);
1601 pFGF->AddType(MEDIATYPE_MPEG2_PACK, MEDIASUBTYPE_PS2_PCM);
1602 pFGF->AddType(MEDIATYPE_MPEG2_PES, MEDIASUBTYPE_PS2_PCM);
1603 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_PS2_PCM);
1604 m_transform.AddTail(pFGF);
1606 pFGF = new CFGFilterInternal<CRealVideoDecoder>(
1607 (tra & TRA_RV) ? L"RealVideo Decoder" : L"RealVideo Decoder (low merit)",
1608 (tra & TRA_RV) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1609 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_RV10);
1610 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_RV20);
1611 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_RV30);
1612 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_RV40);
1613 m_transform.AddTail(pFGF);
1615 pFGF = new CFGFilterInternal<CRealAudioDecoder>(
1616 (tra & TRA_RA) ? L"RealAudio Decoder" : L"RealAudio Decoder (low merit)",
1617 (tra & TRA_RA) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1618 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_14_4);
1619 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_28_8);
1620 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_ATRC);
1621 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_COOK);
1622 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_DNET);
1623 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_SIPR);
1624 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_RAAC);
1625 m_transform.AddTail(pFGF);
1627 pFGF = new CFGFilterInternal<CMpaDecFilter>(
1628 (tra & TRA_VORBIS) ? L"Vorbis Audio Decoder" : L"Vorbis Audio Decoder (low merit)",
1629 (tra & TRA_VORBIS) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1630 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_Vorbis2);
1631 m_transform.AddTail(pFGF);
1633 pFGF = new CFGFilterInternal<CRoQVideoDecoder>(
1634 (tra & TRA_RV) ? L"RoQ Video Decoder" : L"RoQ Video Decoder (low merit)",
1635 (tra & TRA_RV) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1636 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_RoQV);
1637 m_transform.AddTail(pFGF);
1639 pFGF = new CFGFilterInternal<CRoQAudioDecoder>(
1640 (tra & TRA_RA) ? L"RoQ Audio Decoder" : L"RoQ Audio Decoder (low merit)",
1641 (tra & TRA_RA) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1642 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_RoQA);
1643 m_transform.AddTail(pFGF);
1645 __if_exists(CDiracVideoDecoder)
1647 pFGF = new CFGFilterInternal<CDiracVideoDecoder>(
1648 (tra & TRA_DIRAC) ? L"Dirac Video Decoder" : L"Dirac Video Decoder (low merit)",
1649 (tra & TRA_DIRAC) ? MERIT64_ABOVE_DSHOW : MERIT64_DO_USE);
1650 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_DiracVideo);
1651 m_transform.AddTail(pFGF);
1654 pFGF = new CFGFilterInternal<CNullTextRenderer>(L"NullTextRenderer", MERIT64_DO_USE);
1655 pFGF->AddType(MEDIATYPE_Text, MEDIASUBTYPE_NULL);
1656 pFGF->AddType(MEDIATYPE_ScriptCommand, MEDIASUBTYPE_NULL);
1657 pFGF->AddType(MEDIATYPE_Subtitle, MEDIASUBTYPE_NULL);
1658 pFGF->AddType(MEDIATYPE_Text, MEDIASUBTYPE_NULL);
1659 pFGF->AddType(MEDIATYPE_NULL, MEDIASUBTYPE_DVD_SUBPICTURE);
1660 pFGF->AddType(MEDIATYPE_NULL, MEDIASUBTYPE_CVD_SUBPICTURE);
1661 pFGF->AddType(MEDIATYPE_NULL, MEDIASUBTYPE_SVCD_SUBPICTURE);
1662 m_transform.AddTail(pFGF);
1664 __if_exists(CFLVVideoDecoder)
1666 pFGF = new CFGFilterInternal<CFLVVideoDecoder>(L"FLV4 Video Decoder (low merit)",MERIT64_DO_USE);
1667 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_FLV4);
1668 m_transform.AddTail(pFGF);
1671 // Blocked filters
1673 // "Subtitle Mixer" makes an access violation around the
1674 // 11-12th media type when enumerating them on its output.
1675 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{00A95963-3BE5-48C0-AD9F-3356D67EA09D}")), MERIT64_DO_NOT_USE));
1677 // ISCR suxx
1678 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}")), MERIT64_DO_NOT_USE));
1680 // Samsung's "mpeg-4 demultiplexor" can even open matroska files, amazing...
1681 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{99EC0C72-4D1B-411B-AB1F-D561EE049D94}")), MERIT64_DO_NOT_USE));
1683 // LG Video Renderer (lgvid.ax) just crashes when trying to connect it
1684 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{9F711C60-0668-11D0-94D4-0000C02BA972}")), MERIT64_DO_NOT_USE));
1686 // palm demuxer crashes (even crashes graphedit when dropping an .ac3 onto it)
1687 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{BE2CF8A7-08CE-4A2C-9A25-FD726A999196}")), MERIT64_DO_NOT_USE));
1689 // DCDSPFilter (early versions crash mpc)
1691 CRegKey key;
1693 TCHAR buff[256];
1694 ULONG len = sizeof(buff);
1695 memset(buff, 0, len);
1697 CString clsid = _T("{B38C58A0-1809-11D6-A458-EDAE78F1DF12}");
1699 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("CLSID\\") + clsid + _T("\\InprocServer32"), KEY_READ)
1700 && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len)
1701 && GetFileVersion(buff) < 0x0001000000030000ui64)
1703 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(clsid), MERIT64_DO_NOT_USE));
1707 // NVIDIA Transport Demux crashed for someone, I could not reproduce it
1708 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{735823C1-ACC4-11D3-85AC-006008376FB8}")), MERIT64_DO_NOT_USE));
1710 // mainconcept color space converter
1711 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{272D77A0-A852-4851-ADA4-9091FEAD4C86}")), MERIT64_DO_NOT_USE));
1714 // Block VSFilter when internal subtitle renderer will get used
1715 if(s.fAutoloadSubtitles && s.fBlockVSFilter) {
1716 if(s.iDSVideoRendererType == VIDRNDT_DS_VMR7RENDERLESS || s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS || s.iDSVideoRendererType == VIDRNDT_DS_DXR) {
1717 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{9852A670-F845-491B-9BE6-EBD841B8A613}")), MERIT64_DO_NOT_USE));
1722 // Overrides
1724 WORD merit_low = 1;
1726 POSITION pos = s.filters.GetTailPosition();
1727 while(pos)
1729 FilterOverride* fo = s.filters.GetPrev(pos);
1731 if(fo->fDisabled || fo->type == FilterOverride::EXTERNAL && !CPath(MakeFullPath(fo->path)).FileExists())
1732 continue;
1734 ULONGLONG merit =
1735 fo->iLoadType == FilterOverride::PREFERRED ? MERIT64_ABOVE_DSHOW :
1736 fo->iLoadType == FilterOverride::MERIT ? MERIT64(fo->dwMerit) :
1737 MERIT64_DO_NOT_USE; // fo->iLoadType == FilterOverride::BLOCKED
1739 merit += merit_low++;
1741 CFGFilter* pFGF = NULL;
1743 if(fo->type == FilterOverride::REGISTERED)
1745 pFGF = new CFGFilterRegistry(fo->dispname, merit);
1747 else if(fo->type == FilterOverride::EXTERNAL)
1749 pFGF = new CFGFilterFile(fo->clsid, fo->path, CStringW(fo->name), merit);
1752 if(pFGF)
1754 pFGF->SetTypes(fo->guids);
1755 m_override.AddTail(pFGF);
1760 STDMETHODIMP CFGManagerCustom::AddFilter(IBaseFilter* pBF, LPCWSTR pName)
1762 CAutoLock cAutoLock(this);
1764 HRESULT hr;
1766 if(FAILED(hr = __super::AddFilter(pBF, pName)))
1767 return hr;
1769 AppSettings& s = AfxGetAppSettings();
1771 if(GetCLSID(pBF) == CLSID_DMOWrapperFilter)
1773 if(CComQIPtr<IPropertyBag> pPB = pBF)
1775 CComVariant var(true);
1776 pPB->Write(CComBSTR(L"_HIRESOUTPUT"), &var);
1780 if(CComQIPtr<IAudioSwitcherFilter> pASF = pBF)
1782 pASF->EnableDownSamplingTo441(s.fDownSampleTo441);
1783 pASF->SetSpeakerConfig(s.fCustomChannelMapping, s.pSpeakerToChannelMap);
1784 pASF->SetAudioTimeShift(s.fAudioTimeShift ? 10000i64*s.tAudioTimeShift : 0);
1785 pASF->SetNormalizeBoost(s.fAudioNormalize, s.fAudioNormalizeRecover, s.AudioBoost);
1788 return hr;
1792 // CFGManagerPlayer
1795 CFGManagerPlayer::CFGManagerPlayer(LPCTSTR pName, LPUNKNOWN pUnk, UINT src, UINT tra, HWND hWnd)
1796 : CFGManagerCustom(pName, pUnk, src, tra)
1797 , m_hWnd(hWnd)
1798 , m_vrmerit(MERIT64(MERIT_PREFERRED))
1799 , m_armerit(MERIT64(MERIT_PREFERRED))
1801 CFGFilter* pFGF;
1803 AppSettings& s = AfxGetAppSettings();
1805 if(m_pFM)
1807 CComPtr<IEnumMoniker> pEM;
1809 GUID guids[] = {MEDIATYPE_Video, MEDIASUBTYPE_NULL};
1811 if(SUCCEEDED(m_pFM->EnumMatchingFilters(&pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
1812 TRUE, 1, guids, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL)))
1814 for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
1816 CFGFilterRegistry f(pMoniker);
1817 m_vrmerit = max(m_vrmerit, f.GetMerit());
1821 m_vrmerit += 0x100;
1824 if(m_pFM)
1826 CComPtr<IEnumMoniker> pEM;
1828 GUID guids[] = {MEDIATYPE_Audio, MEDIASUBTYPE_NULL};
1830 if(SUCCEEDED(m_pFM->EnumMatchingFilters(&pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
1831 TRUE, 1, guids, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL)))
1833 for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
1835 CFGFilterRegistry f(pMoniker);
1836 m_armerit = max(m_armerit, f.GetMerit());
1840 BeginEnumSysDev(CLSID_AudioRendererCategory, pMoniker)
1842 CFGFilterRegistry f(pMoniker);
1843 m_armerit = max(m_armerit, f.GetMerit());
1845 EndEnumSysDev
1847 m_armerit += 0x100;
1850 // Switchers
1852 if(s.fEnableAudioSwitcher)
1854 pFGF = new CFGFilterInternal<CAudioSwitcherFilter>(L"Audio Switcher", m_armerit + 0x100);
1855 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_NULL);
1856 m_transform.AddTail(pFGF);
1858 // morgan stream switcher
1859 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}")), MERIT64_DO_NOT_USE));
1862 // Renderers
1864 if(s.iDSVideoRendererType == VIDRNDT_DS_OLDRENDERER)
1865 m_transform.AddTail(new CFGFilterRegistry(CLSID_VideoRenderer, m_vrmerit));
1866 else if(s.iDSVideoRendererType == VIDRNDT_DS_OVERLAYMIXER)
1867 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_OverlayMixer, L"Overlay Mixer", m_vrmerit));
1868 else if(s.iDSVideoRendererType == VIDRNDT_DS_VMR7WINDOWED)
1869 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_VideoMixingRenderer, L"Video Mixing Render 7 (Windowed)", m_vrmerit));
1870 else if(s.iDSVideoRendererType == VIDRNDT_DS_VMR9WINDOWED)
1871 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_VideoMixingRenderer9, L"Video Mixing Render 9 (Windowed)", m_vrmerit));
1872 else if(s.iDSVideoRendererType == VIDRNDT_DS_VMR7RENDERLESS)
1873 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_VMR7AllocatorPresenter, L"Video Mixing Render 7 (Renderless)", m_vrmerit));
1874 else if(s.iDSVideoRendererType == VIDRNDT_DS_VMR9RENDERLESS)
1875 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_VMR9AllocatorPresenter, L"Video Mixing Render 9 (Renderless)", m_vrmerit));
1876 else if(s.iDSVideoRendererType == VIDRNDT_DS_DXR)
1877 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_DXRAllocatorPresenter, L"Haali's Video Renderer", m_vrmerit));
1878 else if(s.iDSVideoRendererType == VIDRNDT_DS_NULL_COMP)
1880 pFGF = new CFGFilterInternal<CNullVideoRenderer>(L"Null Video Renderer (Any)", MERIT64_ABOVE_DSHOW+2);
1881 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_NULL);
1882 m_transform.AddTail(pFGF);
1884 else if(s.iDSVideoRendererType == VIDRNDT_DS_NULL_UNCOMP)
1886 pFGF = new CFGFilterInternal<CNullUVideoRenderer>(L"Null Video Renderer (Uncompressed)", MERIT64_ABOVE_DSHOW+2);
1887 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_NULL);
1888 m_transform.AddTail(pFGF);
1891 if(s.AudioRendererDisplayName == AUDRNDT_NULL_COMP)
1893 pFGF = new CFGFilterInternal<CNullAudioRenderer>(AUDRNDT_NULL_COMP, MERIT64_ABOVE_DSHOW+2);
1894 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_NULL);
1895 m_transform.AddTail(pFGF);
1897 else if(s.AudioRendererDisplayName == AUDRNDT_NULL_UNCOMP)
1899 pFGF = new CFGFilterInternal<CNullUAudioRenderer>(AUDRNDT_NULL_UNCOMP, MERIT64_ABOVE_DSHOW+2);
1900 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_NULL);
1901 m_transform.AddTail(pFGF);
1903 else if(!s.AudioRendererDisplayName.IsEmpty())
1905 pFGF = new CFGFilterRegistry(s.AudioRendererDisplayName, m_armerit);
1906 pFGF->AddType(MEDIATYPE_Audio, MEDIASUBTYPE_NULL);
1907 m_transform.AddTail(pFGF);
1911 STDMETHODIMP CFGManagerPlayer::ConnectDirect(IPin* pPinOut, IPin* pPinIn, const AM_MEDIA_TYPE* pmt)
1913 CAutoLock cAutoLock(this);
1915 if(GetCLSID(pPinOut) == CLSID_MPEG2Demultiplexer)
1917 CComQIPtr<IMediaSeeking> pMS = pPinOut;
1918 REFERENCE_TIME rtDur = 0;
1919 if(!pMS || FAILED(pMS->GetDuration(&rtDur)) || rtDur <= 0)
1920 return E_FAIL;
1923 return __super::ConnectDirect(pPinOut, pPinIn, pmt);
1927 // CFGManagerDVD
1930 CFGManagerDVD::CFGManagerDVD(LPCTSTR pName, LPUNKNOWN pUnk, UINT src, UINT tra, HWND hWnd)
1931 : CFGManagerPlayer(pName, pUnk, src, tra, hWnd)
1933 AppSettings& s = AfxGetAppSettings();
1935 // have to avoid the old video renderer
1936 if(!s.fXpOrBetter && s.iDSVideoRendererType != VIDRNDT_DS_OVERLAYMIXER || s.iDSVideoRendererType == VIDRNDT_DS_OLDRENDERER)
1937 m_transform.AddTail(new CFGFilterVideoRenderer(m_hWnd, CLSID_OverlayMixer, L"Overlay Mixer", m_vrmerit-1));
1939 // elecard's decoder isn't suited for dvd playback (atm)
1940 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{F50B3F13-19C4-11CF-AA9A-02608C9BABA2}")), MERIT64_DO_NOT_USE));
1943 #include "..\..\decss\VobFile.h"
1945 class CResetDVD : public CDVDSession
1947 public:
1948 CResetDVD(LPCTSTR path)
1950 if(Open(path))
1952 if(BeginSession()) {Authenticate(); /*GetDiscKey();*/ EndSession();}
1953 Close();
1958 STDMETHODIMP CFGManagerDVD::RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList)
1960 CAutoLock cAutoLock(this);
1962 HRESULT hr;
1964 CComPtr<IBaseFilter> pBF;
1965 if(FAILED(hr = AddSourceFilter(lpcwstrFile, lpcwstrFile, &pBF)))
1966 return hr;
1968 return ConnectFilter(pBF, NULL);
1971 STDMETHODIMP CFGManagerDVD::AddSourceFilter(LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter)
1973 CAutoLock cAutoLock(this);
1975 CheckPointer(lpcwstrFileName, E_POINTER);
1976 CheckPointer(ppFilter, E_POINTER);
1978 HRESULT hr;
1980 CStringW fn = CStringW(lpcwstrFileName).TrimLeft();
1981 CStringW protocol = fn.Left(fn.Find(':')+1).TrimRight(':').MakeLower();
1982 CStringW ext = CPathW(fn).GetExtension().MakeLower();
1984 GUID clsid = ext == L".ratdvd" ? GUIDFromCString(_T("{482d10b6-376e-4411-8a17-833800A065DB}")) : CLSID_DVDNavigator;
1986 CComPtr<IBaseFilter> pBF;
1987 if(FAILED(hr = pBF.CoCreateInstance(clsid))
1988 || FAILED(hr = AddFilter(pBF, L"DVD Navigator")))
1989 return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
1991 CComQIPtr<IDvdControl2> pDVDC;
1992 CComQIPtr<IDvdInfo2> pDVDI;
1994 if(!((pDVDC = pBF) && (pDVDI = pBF)))
1995 return E_NOINTERFACE;
1997 WCHAR buff[MAX_PATH];
1998 ULONG len;
1999 if((!fn.IsEmpty()
2000 && FAILED(hr = pDVDC->SetDVDDirectory(fn))
2001 && FAILED(hr = pDVDC->SetDVDDirectory(fn + L"VIDEO_TS"))
2002 && FAILED(hr = pDVDC->SetDVDDirectory(fn + L"\\VIDEO_TS")))
2003 || FAILED(hr = pDVDI->GetDVDDirectory(buff, countof(buff), &len)) || len == 0)
2004 return E_INVALIDARG;
2006 pDVDC->SetOption(DVD_ResetOnStop, FALSE);
2007 pDVDC->SetOption(DVD_HMSF_TimeCodeEvents, TRUE);
2009 if(clsid == CLSID_DVDNavigator)
2010 CResetDVD(CString(buff));
2012 *ppFilter = pBF.Detach();
2014 return S_OK;
2018 // CFGManagerCapture
2021 CFGManagerCapture::CFGManagerCapture(LPCTSTR pName, LPUNKNOWN pUnk, UINT src, UINT tra, HWND hWnd)
2022 : CFGManagerPlayer(pName, pUnk, src, tra, hWnd)
2024 AppSettings& s = AfxGetAppSettings();
2026 CFGFilter* pFGF = new CFGFilterInternal<CDeinterlacerFilter>(L"Deinterlacer", m_vrmerit + 0x100);
2027 pFGF->AddType(MEDIATYPE_Video, MEDIASUBTYPE_NULL);
2028 m_transform.AddTail(pFGF);
2030 // morgan stream switcher
2031 m_transform.AddTail(new CFGFilterRegistry(GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}")), MERIT64_DO_NOT_USE));
2035 // CFGManagerMuxer
2038 CFGManagerMuxer::CFGManagerMuxer(LPCTSTR pName, LPUNKNOWN pUnk)
2039 : CFGManagerCustom(pName, pUnk, ~0, ~0)
2041 m_source.AddTail(new CFGFilterInternal<CSubtitleSourceASS>());
2042 m_source.AddTail(new CFGFilterInternal<CSSFSourceFilter>());
2046 // CFGAggregator
2049 CFGAggregator::CFGAggregator(const CLSID& clsid, LPCTSTR pName, LPUNKNOWN pUnk, HRESULT& hr)
2050 : CUnknown(pName, pUnk)
2052 hr = m_pUnkInner.CoCreateInstance(clsid, GetOwner());
2055 CFGAggregator::~CFGAggregator()
2057 m_pUnkInner.Release();
2060 STDMETHODIMP CFGAggregator::NonDelegatingQueryInterface(REFIID riid, void** ppv)
2062 CheckPointer(ppv, E_POINTER);
2064 return
2065 m_pUnkInner && (riid != IID_IUnknown && SUCCEEDED(m_pUnkInner->QueryInterface(riid, ppv))) ? S_OK :
2066 __super::NonDelegatingQueryInterface(riid, ppv);