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)
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
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"
31 #include "..\..\..\include\moreuuids.h"
40 CFGManager::CFGManager(LPCTSTR pName
, LPUNKNOWN pUnk
)
41 : CUnknown(pName
, pUnk
)
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();
55 m_pUnkInner
.Release();
58 STDMETHODIMP
CFGManager::NonDelegatingQueryInterface(REFIID riid
, void** ppv
)
60 CheckPointer(ppv
, E_POINTER
);
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
)
77 p
.clsid
= GetCLSID(pBF
);
78 p
.filter
= GetFilterName(pBF
);
79 p
.pin
= GetPinName(pPin
);
83 bool CFGManager::CStreamPath::Compare(const CStreamPath
& path
)
85 POSITION pos1
= GetHeadPosition();
86 POSITION pos2
= path
.GetHeadPosition();
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;
102 bool CFGManager::CheckBytes(HANDLE hFile
, CString chkbytes
)
104 CAtlList
<CString
> sl
;
105 Explode(chkbytes
, sl
, ',');
107 if(sl
.GetCount() < 4)
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())
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
);
136 while(maskstr
.GetLength() < valstr
.GetLength())
139 CAtlArray
<BYTE
> mask
, val
;
140 CStringToBin(maskstr
, mask
);
141 CStringToBin(valstr
, val
);
143 for(size_t i
= 0; i
< val
.GetCount(); i
++)
147 if(!ReadFile(hFile
, &b
, 1, &r
, NULL
) || (b
& mask
[i
]) != val
[i
])
155 HRESULT
CFGManager::EnumSourceFilters(LPCWSTR lpcwstrFileName
, CFGFilterList
& fl
)
157 // TODO: use overrides
159 CheckPointer(lpcwstrFileName
, E_POINTER
);
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
;
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];
189 if(hFile
== INVALID_HANDLE_VALUE
)
191 // internal / protocol
193 POSITION pos
= m_source
.GetHeadPosition();
196 CFGFilter
* pFGF
= m_source
.GetNext(pos
);
197 if(pFGF
->m_protocols
.Find(CString(protocol
)))
198 fl
.Insert(pFGF
, 0, false, false);
203 // internal / check bytes
205 POSITION pos
= m_source
.GetHeadPosition();
208 CFGFilter
* pFGF
= m_source
.GetNext(pos
);
210 POSITION pos2
= pFGF
->m_chkbytes
.GetHeadPosition();
213 if(CheckBytes(hFile
, pFGF
->m_chkbytes
.GetNext(pos2
)))
215 fl
.Insert(pFGF
, 1, false, false);
224 // internal / file extension
226 POSITION pos
= m_source
.GetHeadPosition();
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();
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
)
252 if(ERROR_SUCCESS
== key
.Open(HKEY_CLASSES_ROOT
, CString(protocol
), KEY_READ
))
255 if(ERROR_SUCCESS
== exts
.Open(key
, _T("Extensions"), KEY_READ
))
258 if(ERROR_SUCCESS
== exts
.QueryStringValue(CString(ext
), buff
, &len
))
259 fl
.Insert(new CFGFilterRegistry(GUIDFromCString(buff
)), 4);
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);
274 if(ERROR_SUCCESS
== key
.Open(HKEY_CLASSES_ROOT
, _T("Media Type"), KEY_READ
))
278 for(DWORD i
= 0; ERROR_SUCCESS
== key
.EnumKey(i
, buff
, &len
, &ft
); i
++, len
= countof(buff
))
281 if(FAILED(GUIDFromCString(buff
, majortype
)))
285 if(ERROR_SUCCESS
== majorkey
.Open(key
, buff
, KEY_READ
))
288 for(DWORD j
= 0; ERROR_SUCCESS
== majorkey
.EnumKey(j
, buff
, &len
, &ft
); j
++, len
= countof(buff
))
291 if(FAILED(GUIDFromCString(buff
, subtype
)))
295 if(ERROR_SUCCESS
== subkey
.Open(majorkey
, buff
, KEY_READ
))
298 if(ERROR_SUCCESS
!= subkey
.QueryStringValue(_T("Source Filter"), buff
, &len
))
301 GUID clsid
= GUIDFromCString(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
);
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
;
341 if(ERROR_SUCCESS
== key
.QueryStringValue(_T("Media Type"), buff
, &len
))
342 majortype
= GUIDFromCString(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
);
355 if(hFile
!= INVALID_HANDLE_VALUE
)
360 CFGFilter
* pFGF
= new CFGFilterRegistry(CLSID_AsyncReader
);
361 pFGF
->AddType(MEDIATYPE_Stream
, MEDIASUBTYPE_NULL
);
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
);
378 CComPtr
<IBaseFilter
> pBF
;
379 CInterfaceList
<IUnknown
, &IID_IUnknown
> pUnks
;
380 if(FAILED(hr
= pFGF
->Create(&pBF
, pUnks
)))
383 CComQIPtr
<IFileSourceFilter
> pFSF
= pBF
;
384 if(!pFSF
) return E_NOINTERFACE
;
386 if(FAILED(hr
= AddFilter(pBF
, lpcwstrFilterName
)))
389 const AM_MEDIA_TYPE
* pmt
= NULL
;
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();
400 if(FAILED(hr
= pFSF
->Load(lpcwstrFileName
, pmt
)))
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}")))
414 pFGF
= new CFGFilterRegistry(CLSID_NetShowSource
);
415 hr
= AddSourceFilter(pFGF
, lpcwstrFileName
, lpcwstrFilterName
, ppBF
);
420 EndEnumMediaTypes(pmt
)
422 *ppBF
= pBF
.Detach();
424 m_pUnks
.AddTailList(&pUnks
);
431 STDMETHODIMP
CFGManager::AddFilter(IBaseFilter
* pFilter
, LPCWSTR pName
)
433 if(!m_pUnkInner
) return E_UNEXPECTED
;
435 CAutoLock
cAutoLock(this);
439 if(FAILED(hr
= CComQIPtr
<IFilterGraph2
>(m_pUnkInner
)->AddFilter(pFilter
, pName
)))
443 hr
= pFilter
->JoinFilterGraph(NULL
, NULL
);
444 hr
= pFilter
->JoinFilterGraph(this, pName
);
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();
524 STDMETHODIMP
CFGManager::Connect(IPin
* pPinOut
, IPin
* pPinIn
)
526 CAutoLock
cAutoLock(this);
528 CheckPointer(pPinOut
, E_POINTER
);
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;
544 // 1. Try a direct connection between the filters, with no intermediate filters
546 if(SUCCEEDED(hr
= ConnectDirect(pPinOut
, pPinIn
, NULL
)))
551 // 1. Use IStreamBuilder
553 if(CComQIPtr
<IStreamBuilder
> pSB
= pPinOut
)
555 if(SUCCEEDED(hr
= pSB
->Render(pPinOut
, this)))
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
)
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
)))
583 hr
= pGC
->AddFilterToCache(pBF
);
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
)
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}")))
608 POSITION pos
= pBFs
.GetHeadPosition();
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
)))
621 EXECUTE_ASSERT(Disconnect(pPinOut
));
625 // 4. Look up filters in the registry
630 CAtlArray
<GUID
> types
;
631 ExtractMediaTypes(pPinOut
, types
);
633 POSITION pos
= m_transform
.GetHeadPosition();
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();
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();
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
)))
675 if(FAILED(hr
= AddFilter(pBF
, pFGF
->GetName())))
682 hr
= ConnectFilterDirect(pPinOut
, pBF
, NULL
);
687 if(types.GetCount() >= 2 && types[0] == MEDIATYPE_Stream && types[1] != GUID_NULL)
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);
703 if(!IsStreamEnd(pBF
)) fDeadEnd
= false;
705 hr
= ConnectFilter(pBF
, pPinIn
);
709 m_pUnks
.AddTailList(&pUnks
);
711 // maybe the application should do this...
713 POSITION pos
= pUnks
.GetHeadPosition();
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
);
730 EXECUTE_ASSERT(SUCCEEDED(RemoveFilter(pBF
)));
732 TRACE(_T("FGM: Connecting '%s' FAILED!\n"), pFGF
->GetName());
738 CAutoPtr
<CStreamDeadEnd
> psde(new CStreamDeadEnd());
739 psde
->AddTailList(&m_streampath
);
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();
771 CComPtr<IBaseFilter> pBF;
772 if(FAILED(hr = AddSourceFilter(lpcwstrFile, lpcwstrFile, &pBF)))
775 return ConnectFilter(pBF, NULL);
779 if(FAILED(hr
= EnumSourceFilters(lpcwstrFileName
, fl
)))
782 CAutoPtrArray
<CStreamDeadEnd
> deadends
;
784 hr
= VFW_E_CANNOT_RENDER
;
786 POSITION pos
= fl
.GetHeadPosition();
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
)))
802 deadends
.Append(m_deadends
);
806 m_deadends
.Copy(deadends
);
811 STDMETHODIMP
CFGManager::AddSourceFilter(LPCWSTR lpcwstrFileName
, LPCWSTR lpcwstrFilterName
, IBaseFilter
** ppFilter
)
813 CAutoLock
cAutoLock(this);
818 if(FAILED(hr
= EnumSourceFilters(lpcwstrFileName
, fl
)))
821 POSITION pos
= fl
.GetHeadPosition();
824 if(SUCCEEDED(hr
= AddSourceFilter(fl
.GetNext(pos
), lpcwstrFileName
, lpcwstrFilterName
, ppFilter
)))
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();
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
)
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
)
905 BeginEnumPins(pBF
, pEP
, pPin
)
907 CComPtr
<IPin
> pPinIn
;
909 if(SUCCEEDED(pPin
->QueryInternalConnections(&pPinIn
, &size
)) && size
== 0)
920 while(!pBFs
.IsEmpty())
922 if(SUCCEEDED(hr
= ConnectFilter(pPinOut
, pBFs
.RemoveHead())))
926 return VFW_E_CANNOT_RENDER
;
929 return Connect(pPinOut
, (IPin
*)NULL
);
934 STDMETHODIMP
CFGManager::IsPinDirection(IPin
* pPin
, PIN_DIRECTION dir1
)
936 CAutoLock
cAutoLock(this);
938 CheckPointer(pPin
, E_POINTER
);
941 if(FAILED(pPin
->QueryDirection(&dir2
)))
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
);
980 for(int i
= m_deadends
.GetCount()-1; i
>= 0; i
--)
981 if(m_deadends
[i
]->Compare(m_streampath
))
982 m_deadends
.RemoveAt(i
);
989 m_streampath
.RemoveTail();
991 if(SUCCEEDED(hr
) && pPinIn
)
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
;
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
)))
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
;
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
)))
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
);
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
);
1082 return E_INVALIDARG
;
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
);
1103 return E_NOINTERFACE
;
1106 STDMETHODIMP
CFGManager::AddToROT()
1108 CAutoLock
cAutoLock(this);
1112 if(m_dwRegister
) return S_FALSE
;
1114 CComPtr
<IRunningObjectTable
> pROT
;
1115 CComPtr
<IMoniker
> pMoniker
;
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
);
1125 STDMETHODIMP
CFGManager::RemoveFromROT()
1127 CAutoLock
cAutoLock(this);
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
)))
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
;
1159 POSITION pos
= m_deadends
[iIndex
]->GetHeadPosition();
1162 const path_t
& p
= m_deadends
[iIndex
]->GetNext(pos
);
1165 str
.Format(L
"%s::%s", p
.filter
, p
.pin
);
1169 mts
.AddTailList(&m_deadends
[iIndex
]->mts
);
1178 CFGManagerCustom::CFGManagerCustom(LPCTSTR pName
, LPUNKNOWN pUnk
, UINT src
, UINT tra
)
1179 : CFGManager(pName
, pUnk
)
1181 AppSettings
& s
= AfxGetAppSettings();
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
);
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
);
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
);
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
);
1247 pFGF
= new CFGFilterInternal
<CDSMSourceFilter
>();
1248 pFGF
->m_chkbytes
.AddTail(_T("0,4,,44534D53"));
1249 m_source
.AddTail(pFGF
);
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
);
1264 pFGF
= new CFGFilterInternal
<CCDDAReader
>();
1265 pFGF
->m_extensions
.AddTail(_T(".cda"));
1266 m_source
.AddTail(pFGF
);
1271 pFGF
= new CFGFilterInternal
<CCDXAReader
>();
1272 pFGF
->m_chkbytes
.AddTail(_T("0,4,,52494646,8,4,,43445841"));
1273 m_source
.AddTail(pFGF
);
1278 pFGF
= new CFGFilterInternal
<CVTSReader
>();
1279 pFGF
->m_chkbytes
.AddTail(_T("0,12,,445644564944454F2D565453"));
1280 m_source
.AddTail(pFGF
);
1283 __if_exists(CD2VSource
)
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
)
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
);
1309 pFGF
= new CFGFilterInternal
<CRoQSourceFilter
>();
1310 pFGF
->m_chkbytes
.AddTail(_T("0,8,,8410FFFFFFFF1E00"));
1311 m_source
.AddTail(pFGF
);
1316 pFGF
= new CFGFilterInternal
<COggSourceFilter
>();
1317 pFGF
->m_chkbytes
.AddTail(_T("0,4,,4F676753"));
1318 m_source
.AddTail(pFGF
);
1321 __if_exists(CNutSourceFilter
)
1325 pFGF
= new CFGFilterInternal
<CNutSourceFilter
>();
1326 pFGF
->m_chkbytes
.AddTail(_T("0,8,,F9526A624E55544D"));
1327 m_source
.AddTail(pFGF
);
1331 __if_exists(CDiracSourceFilter
)
1335 pFGF
= new CFGFilterInternal
<CDiracSourceFilter
>();
1336 pFGF
->m_chkbytes
.AddTail(_T("0,8,,4B572D4449524143"));
1337 m_source
.AddTail(pFGF
);
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
);
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
);
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
);
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
);
1406 pFGF
= new CFGFilterInternal
<CAviSplitterFilter
>(L
"Avi Splitter", MERIT64_ABOVE_DSHOW
);
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
);
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
);
1428 pFGF
= new CFGFilterInternal
<CRoQSplitterFilter
>(L
"RoQ Splitter", MERIT64_ABOVE_DSHOW
);
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
);
1437 pFGF
= new CFGFilterInternal
<COggSplitterFilter
>(L
"Ogg Splitter", MERIT64_ABOVE_DSHOW
);
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
)
1448 pFGF
= new CFGFilterInternal
<CNutSplitterFilter
>(L
"Nut Splitter", MERIT64_ABOVE_DSHOW
);
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
);
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
);
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
);
1482 pFGF
= new CFGFilterInternal
<CMpaSplitterFilter
>(L
"Mpa Splitter", MERIT64_ABOVE_DSHOW
);
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
);
1491 pFGF
= new CFGFilterInternal
<CDSMSplitterFilter
>(L
"DSM Splitter", MERIT64_ABOVE_DSHOW
);
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
);
1500 pFGF
= new CFGFilterInternal
<CMP4SplitterFilter
>(L
"MP4 Splitter", MERIT64_ABOVE_DSHOW
);
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
);
1509 pFGF
= new CFGFilterInternal
<CFLVSplitterFilter
>(L
"FLV Splitter", MERIT64_ABOVE_DSHOW
);
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
);
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
));
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)
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
) < 0x0001000000030000ui
64)
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
));
1726 POSITION pos
= s
.filters
.GetTailPosition();
1729 FilterOverride
* fo
= s
.filters
.GetPrev(pos
);
1731 if(fo
->fDisabled
|| fo
->type
== FilterOverride::EXTERNAL
&& !CPath(MakeFullPath(fo
->path
)).FileExists())
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
);
1754 pFGF
->SetTypes(fo
->guids
);
1755 m_override
.AddTail(pFGF
);
1760 STDMETHODIMP
CFGManagerCustom::AddFilter(IBaseFilter
* pBF
, LPCWSTR pName
)
1762 CAutoLock
cAutoLock(this);
1766 if(FAILED(hr
= __super::AddFilter(pBF
, pName
)))
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
);
1795 CFGManagerPlayer::CFGManagerPlayer(LPCTSTR pName
, LPUNKNOWN pUnk
, UINT src
, UINT tra
, HWND hWnd
)
1796 : CFGManagerCustom(pName
, pUnk
, src
, tra
)
1798 , m_vrmerit(MERIT64(MERIT_PREFERRED
))
1799 , m_armerit(MERIT64(MERIT_PREFERRED
))
1803 AppSettings
& s
= AfxGetAppSettings();
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());
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());
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
));
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)
1923 return __super::ConnectDirect(pPinOut
, pPinIn
, pmt
);
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
1948 CResetDVD(LPCTSTR path
)
1952 if(BeginSession()) {Authenticate(); /*GetDiscKey();*/ EndSession();}
1958 STDMETHODIMP
CFGManagerDVD::RenderFile(LPCWSTR lpcwstrFile
, LPCWSTR lpcwstrPlayList
)
1960 CAutoLock
cAutoLock(this);
1964 CComPtr
<IBaseFilter
> pBF
;
1965 if(FAILED(hr
= AddSourceFilter(lpcwstrFile
, lpcwstrFile
, &pBF
)))
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
);
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
];
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();
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
));
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
>());
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
);
2065 m_pUnkInner
&& (riid
!= IID_IUnknown
&& SUCCEEDED(m_pUnkInner
->QueryInterface(riid
, ppv
))) ? S_OK
:
2066 __super::NonDelegatingQueryInterface(riid
, ppv
);