- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# GraphBuilder.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include "mplayerc.h"
    00024 #include "GraphBuilder.h"
    00025 #include "..\..\DSUtil\DSUtil.h"
    00026 #include "..\..\filters\filters.h"
    00027 #include "..\..\..\include\moreuuids.h"
    00028 #include "..\..\..\include\Ogg\OggDS.h"
    00029 #include "..\..\..\include\matroska\matroska.h"
    00030 #include "DX7AllocatorPresenter.h"
    00031 #include "DX9AllocatorPresenter.h"
    00032 #include "DeinterlacerFilter.h"
    00033
    00034 #include <initguid.h>
    00035 #include <dmodshow.h>
    00036
    00037 #include <D3d9.h>
    00038 #include <Vmr9.h>
    00039
    00040 static void CheckStupidSharedFilesourceFilter()
    00041 {
    00042         CRegKey key;
    00043         CString str(_T("CLSID\\{E436EBB5-524F-11CE-9F53-0020AF0BA770}\\InprocServer32"));
    00044
    00045         if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
    00046         {
    00047                 ULONG nChars = 0;
    00048                 if(ERROR_SUCCESS == key.QueryStringValue(NULL, NULL, &nChars))
    00049                 {
    00050                         CString dll;
    00051                         if(ERROR_SUCCESS == key.QueryStringValue(NULL, dll.GetBuffer(nChars), &nChars))
    00052                         {
    00053                                 dll.ReleaseBuffer(nChars);
    00054                                 dll.MakeLower();
    00055                                 if(dll.Find(_T("shared_filesource.ax")) >= 0
    00056                                 || dll.Find(_T("shared~1.ax")) >= 0)
    00057                                 {
    00058                                         if(IDYES == AfxMessageBox(
    00059                                                 _T("Warning: MPC has detected that DirectShow's \"File Source (async)\" filter\n")
    00060                                                 _T("was replaced by shared_filesource.ax. Please run \"regsvr32.exe quartz.dll\"\n")
    00061                                                 _T("in your system folder to restore it. If you are a user with administrator\n")
    00062                                                 _T("rights, MPC can also do this for you. Do you want to re-register quartz.dll now?"),
    00063                                                 MB_YESNO|MB_ICONEXCLAMATION))
    00064                                         {
    00065                                                 TCHAR buff[MAX_PATH+1];
    00066                                                 GetSystemDirectory(buff, sizeof(buff));
    00067
    00068                                                 CString path = CString(buff) + _T("\\quartz.dll");
    00069
    00070                                                 HRESULT hr = E_FAIL;
    00071
    00072                                                 if(HMODULE hModule = LoadLibrary(path))
    00073                                                 {
    00074                                                         typedef HRESULT (__stdcall * PDllRegisterServer)();
    00075                                                         if(PDllRegisterServer p = (PDllRegisterServer)GetProcAddress(hModule, "DllRegisterServer"))
    00076                                                                 hr = p();
    00077                                                 }
    00078
    00079                                                 if(SUCCEEDED(hr))
    00080                                                         AfxMessageBox(_T("Successfully re-registered quartz.dll, you may need to restart the player now."), MB_OK);
    00081                                                 else
    00082                                                         AfxMessageBox(_T("Failed to re-register quartz.dll!"), MB_OK|MB_ICONEXCLAMATION);
    00083                                         }
    00084                                 }
    00085                         }
    00086                 }
    00087         }
    00088 }
    00089
    00090 //
    00091 // CGraphBuilder
    00092 //
    00093
    00094 CGraphBuilder::CGraphBuilder(IGraphBuilder* pGB, HWND hWnd)
    00095         : m_pGB(pGB), m_hWnd(hWnd)
    00096         , m_nTotalStreams(0)
    00097         , m_nCurrentStream(0)
    00098         , m_VRMerit(LMERIT(MERIT_PREFERRED+1)+0x100)
    00099         , m_ARMerit(LMERIT(MERIT_PREFERRED+1)+0x100)
    00100 {
    00101         AppSettings& s = AfxGetAppSettings();
    00102
    00103         m_pFM.CoCreateInstance(CLSID_FilterMapper2);
    00104         if(!m_pFM) return;
    00105
    00106         {
    00107                 CArray<GUID> guids;
    00108                 CComPtr<IEnumMoniker> pEM;
    00109
    00110                 m_VRMerit = LMERIT(MERIT_PREFERRED);
    00111
    00112                 guids.Add(MEDIATYPE_Video);
    00113                 guids.Add(MEDIASUBTYPE_NULL);
    00114                 if(guids.GetCount() > 0
    00115                 && SUCCEEDED(m_pFM->EnumMatchingFilters(
    00116                         &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
    00117                         TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, TRUE,
    00118                         FALSE, 0, NULL, NULL, NULL)))
    00119                 {
    00120                         for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
    00121                         {
    00122                                 CGraphRegFilter gf(pMoniker);
    00123                                 m_VRMerit = max(m_VRMerit, gf.GetMerit());
    00124                         }
    00125                 }
    00126                 guids.RemoveAll();
    00127                 pEM = NULL;
    00128
    00129                 m_VRMerit += 0x100;
    00130
    00131                 m_ARMerit = LMERIT(MERIT_PREFERRED);
    00132
    00133                 guids.Add(MEDIATYPE_Audio);
    00134                 guids.Add(MEDIASUBTYPE_NULL);
    00135                 if(guids.GetCount() > 0
    00136                 && SUCCEEDED(m_pFM->EnumMatchingFilters(
    00137                         &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
    00138                         TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, TRUE,
    00139                         FALSE, 0, NULL, NULL, NULL)))
    00140                 {
    00141                         for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
    00142                         {
    00143                                 CGraphRegFilter gf(pMoniker);
    00144                                 m_ARMerit = max(m_ARMerit, gf.GetMerit());
    00145                         }
    00146                 }
    00147
    00148                 BeginEnumSysDev(CLSID_AudioRendererCategory, pMoniker)
    00149                 {
    00150                         CGraphRegFilter gf(pMoniker);
    00151                         m_ARMerit = max(m_ARMerit, gf.GetMerit());
    00152                 }
    00153                 EndEnumSysDev
    00154
    00155                 guids.RemoveAll();
    00156                 pEM = NULL;
    00157
    00158                 m_ARMerit += 0x100;
    00159         }
    00160
    00161         // transform filters
    00162
    00163         CList<GUID> guids;
    00164
    00165         guids.AddTail(MEDIATYPE_Audio);
    00166         guids.AddTail(MEDIASUBTYPE_WAVE_DOLBY_AC3);
    00167         guids.AddTail(MEDIATYPE_Audio);
    00168         guids.AddTail(MEDIASUBTYPE_WAVE_DTS);
    00169         AddFilter(new CGraphCustomFilter(__uuidof(CAVI2AC3Filter), guids, L"AVI<->AC3/DTS", LMERIT(0x00680000)+1));
    00170         guids.RemoveAll();
    00171
    00172         {
    00173                 guids.AddTail(MEDIATYPE_Stream);
    00174                 guids.AddTail(MEDIASUBTYPE_Matroska);
    00175                 AddFilter(new CGraphCustomFilter(__uuidof(CMatroskaSplitterFilter), guids,
    00176                         (s.SrcFilters&SRC_MATROSKA) ? L"Matroska Splitter" : L"Matroska Splitter (low merit)",
    00177                         (s.SrcFilters&SRC_MATROSKA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00178                 guids.RemoveAll();
    00179         }
    00180
    00181         {
    00182                 guids.AddTail(MEDIATYPE_Stream);
    00183                 guids.AddTail(MEDIASUBTYPE_RealMedia);
    00184                 AddFilter(new CGraphCustomFilter(__uuidof(CRealMediaSplitterFilter), guids,
    00185                         (s.SrcFilters&SRC_REALMEDIA) ? L"RealMedia Splitter" : L"RealMedia Splitter (low merit)",
    00186                         (s.SrcFilters&SRC_REALMEDIA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00187                 guids.RemoveAll();
    00188         }
    00189
    00190         {
    00191                 guids.AddTail(MEDIATYPE_Stream);
    00192                 guids.AddTail(MEDIASUBTYPE_Avi);
    00193                 AddFilter(new CGraphCustomFilter(__uuidof(CAviSplitterFilter), guids,
    00194                         (s.SrcFilters&SRC_AVI) ? L"Avi Splitter" : L"Avi Splitter (low merit)",
    00195                         (s.SrcFilters&SRC_AVI) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00196                 guids.RemoveAll();
    00197         }
    00198
    00199         __if_exists(CRadGtSplitterFilter)
    00200         {
    00201                 guids.AddTail(MEDIATYPE_Stream);
    00202                 guids.AddTail(MEDIASUBTYPE_Bink);
    00203                 guids.AddTail(MEDIATYPE_Stream);
    00204                 guids.AddTail(MEDIASUBTYPE_Smacker);
    00205                 AddFilter(new CGraphCustomFilter(__uuidof(CRadGtSplitterFilter), guids,
    00206                         (s.SrcFilters&SRC_RADGT) ? L"RadGt Splitter" : L"RadGt Splitter (low merit)",
    00207                         (s.SrcFilters&SRC_RADGT) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00208                 guids.RemoveAll();
    00209         }
    00210
    00211         {
    00212                 guids.AddTail(MEDIATYPE_Stream);
    00213                 guids.AddTail(MEDIASUBTYPE_RoQ);
    00214                 AddFilter(new CGraphCustomFilter(__uuidof(CRoQSplitterFilter), guids,
    00215                         (s.SrcFilters&SRC_ROQ) ? L"RoQ Splitter" : L"RoQ Splitter (low merit)",
    00216                         (s.SrcFilters&SRC_ROQ) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00217                 guids.RemoveAll();
    00218         }
    00219
    00220         {
    00221                 guids.AddTail(MEDIATYPE_Stream);
    00222                 guids.AddTail(MEDIASUBTYPE_Ogg);
    00223                 AddFilter(new CGraphCustomFilter(__uuidof(COggSplitterFilter), guids,
    00224                         (s.SrcFilters&SRC_OGG) ? L"Ogg Splitter" : L"Ogg Splitter (low merit)",
    00225                         (s.SrcFilters&SRC_OGG) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00226                 guids.RemoveAll();
    00227         }
    00228
    00229         {
    00230                 guids.AddTail(MEDIATYPE_Stream);
    00231                 guids.AddTail(MEDIASUBTYPE_Nut);
    00232                 AddFilter(new CGraphCustomFilter(__uuidof(CNutSplitterFilter), guids,
    00233                         (s.SrcFilters&SRC_NUT) ? L"Nut Splitter" : L"Nut Splitter (low merit)",
    00234                         (s.SrcFilters&SRC_NUT) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00235                 guids.RemoveAll();
    00236         }
    00237
    00238         {
    00239                 guids.AddTail(MEDIATYPE_Stream);
    00240                 guids.AddTail(MEDIASUBTYPE_MPEG1System);
    00241                 guids.AddTail(MEDIATYPE_Stream);
    00242                 guids.AddTail(MEDIASUBTYPE_MPEG2_PROGRAM);
    00243                 guids.AddTail(MEDIATYPE_Stream);
    00244                 guids.AddTail(MEDIASUBTYPE_MPEG2_TRANSPORT);
    00245                 guids.AddTail(MEDIATYPE_Stream);
    00246                 guids.AddTail(MEDIASUBTYPE_MPEG2_PVA);
    00247                 AddFilter(new CGraphCustomFilter(__uuidof(CMpegSplitterFilter), guids,
    00248                         (s.SrcFilters&SRC_MPEG) ? L"Mpeg Splitter" : L"Mpeg Splitter (low merit)",
    00249                         (s.SrcFilters&SRC_MPEG) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00250                 guids.RemoveAll();
    00251         }
    00252
    00253         {
    00254                 guids.AddTail(MEDIATYPE_Video);
    00255                 guids.AddTail(MEDIASUBTYPE_MPEG1Packet);
    00256                 guids.AddTail(MEDIATYPE_Video);
    00257                 guids.AddTail(MEDIASUBTYPE_MPEG1Payload);
    00258                 AddFilter(new CGraphCustomFilter(__uuidof(CMpeg2DecFilter), guids,
    00259                         (s.TraFilters&TRA_MPEG1) ? L"MPEG-1 Video Decoder" : L"MPEG-1 Video Decoder (low merit)",
    00260                         (s.TraFilters&TRA_MPEG1) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00261                 guids.RemoveAll();
    00262         }
    00263
    00264         {
    00265                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00266                 guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
    00267                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00268                 guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
    00269                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00270                 guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
    00271                 guids.AddTail(MEDIATYPE_Video);
    00272                 guids.AddTail(MEDIASUBTYPE_MPEG2_VIDEO);
    00273                 AddFilter(new CGraphCustomFilter(__uuidof(CMpeg2DecFilter), guids,
    00274                         (s.TraFilters&TRA_MPEG2) ? L"MPEG-2 Video Decoder" : L"MPEG-2 Video Decoder (low merit)",
    00275                         (s.TraFilters&TRA_MPEG2) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00276                 guids.RemoveAll();
    00277         }
    00278
    00279         {
    00280                 guids.AddTail(MEDIATYPE_Audio);
    00281                 guids.AddTail(MEDIASUBTYPE_MP3);
    00282                 guids.AddTail(MEDIATYPE_Audio);
    00283                 guids.AddTail(MEDIASUBTYPE_MPEG1AudioPayload);
    00284                 guids.AddTail(MEDIATYPE_Audio);
    00285                 guids.AddTail(MEDIASUBTYPE_MPEG1Payload);
    00286                 guids.AddTail(MEDIATYPE_Audio);
    00287                 guids.AddTail(MEDIASUBTYPE_MPEG1Packet);
    00288                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00289                         (s.TraFilters&TRA_MPA) ? L"MPEG-1 Audio Decoder" : L"MPEG-1 Audio Decoder (low merit)",
    00290                         (s.TraFilters&TRA_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00291                 guids.RemoveAll();
    00292         }
    00293
    00294         {
    00295                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00296                 guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
    00297                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00298                 guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
    00299                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00300                 guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
    00301                 guids.AddTail(MEDIATYPE_Audio);
    00302                 guids.AddTail(MEDIASUBTYPE_MPEG2_AUDIO);
    00303                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00304                         (s.TraFilters&TRA_MPA) ? L"MPEG-2 Audio Decoder" : L"MPEG-2 Audio Decoder (low merit)",
    00305                         (s.TraFilters&TRA_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00306                 guids.RemoveAll();
    00307         }
    00308
    00309         {
    00310                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00311                 guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
    00312                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00313                 guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
    00314                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00315                 guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
    00316                 guids.AddTail(MEDIATYPE_Audio);
    00317                 guids.AddTail(MEDIASUBTYPE_DVD_LPCM_AUDIO);
    00318                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00319                         (s.TraFilters&TRA_LPCM) ? L"LPCM Audio Decoder" : L"LPCM Audio Decoder (low merit)",
    00320                         (s.TraFilters&TRA_LPCM) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00321                 guids.RemoveAll();
    00322         }
    00323
    00324         {
    00325                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00326                 guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
    00327                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00328                 guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
    00329                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00330                 guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
    00331                 guids.AddTail(MEDIATYPE_Audio);
    00332                 guids.AddTail(MEDIASUBTYPE_DOLBY_AC3);
    00333                 guids.AddTail(MEDIATYPE_Audio);
    00334                 guids.AddTail(MEDIASUBTYPE_WAVE_DOLBY_AC3);
    00335                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00336                         (s.TraFilters&TRA_AC3) ? L"AC3 Audio Decoder" : L"AC3 Audio Decoder (low merit)",
    00337                         (s.TraFilters&TRA_AC3) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00338                 guids.RemoveAll();
    00339         }
    00340
    00341         {
    00342                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00343                 guids.AddTail(MEDIASUBTYPE_DTS);
    00344                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00345                 guids.AddTail(MEDIASUBTYPE_DTS);
    00346                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00347                 guids.AddTail(MEDIASUBTYPE_DTS);
    00348                 guids.AddTail(MEDIATYPE_Audio);
    00349                 guids.AddTail(MEDIASUBTYPE_DTS);
    00350                 guids.AddTail(MEDIATYPE_Audio);
    00351                 guids.AddTail(MEDIASUBTYPE_WAVE_DTS);
    00352                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00353                         (s.TraFilters&TRA_DTS) ? L"DTS Decoder" : L"DTS Decoder (low merit)",
    00354                         (s.TraFilters&TRA_DTS) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00355                 guids.RemoveAll();
    00356         }
    00357
    00358         {
    00359                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00360                 guids.AddTail(MEDIASUBTYPE_AAC);
    00361                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00362                 guids.AddTail(MEDIASUBTYPE_AAC);
    00363                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00364                 guids.AddTail(MEDIASUBTYPE_AAC);
    00365                 guids.AddTail(MEDIATYPE_Audio);
    00366                 guids.AddTail(MEDIASUBTYPE_AAC);
    00367                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00368                 guids.AddTail(MEDIASUBTYPE_MP4A);
    00369                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00370                 guids.AddTail(MEDIASUBTYPE_MP4A);
    00371                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00372                 guids.AddTail(MEDIASUBTYPE_MP4A);
    00373                 guids.AddTail(MEDIATYPE_Audio);
    00374                 guids.AddTail(MEDIASUBTYPE_MP4A);
    00375                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00376                         (s.TraFilters&TRA_AAC) ? L"AAC Decoder" : L"AAC Decoder (low merit)",
    00377                         (s.TraFilters&TRA_AAC) ? LMERIT_ABOVE_DSHOW+1 : LMERIT_DO_USE));
    00378                 guids.RemoveAll();
    00379         }
    00380
    00381         {
    00382                 guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    00383                 guids.AddTail(MEDIASUBTYPE_PS2_PCM);
    00384                 guids.AddTail(MEDIATYPE_MPEG2_PACK);
    00385                 guids.AddTail(MEDIASUBTYPE_PS2_PCM);
    00386                 guids.AddTail(MEDIATYPE_MPEG2_PES);
    00387                 guids.AddTail(MEDIASUBTYPE_PS2_PCM);
    00388                 guids.AddTail(MEDIATYPE_Audio);
    00389                 guids.AddTail(MEDIASUBTYPE_PS2_PCM);
    00390                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaDecFilter), guids,
    00391                         (s.TraFilters&TRA_PS2AUD) ? L"PS2 Audio Decoder" : L"PS2 Audio Decoder (low merit)",
    00392                         (s.TraFilters&TRA_PS2AUD) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00393                 guids.RemoveAll();
    00394         }
    00395
    00396         {
    00397                 guids.AddTail(MEDIATYPE_Video);
    00398                 guids.AddTail(MEDIASUBTYPE_RV10);
    00399                 guids.AddTail(MEDIATYPE_Video);
    00400                 guids.AddTail(MEDIASUBTYPE_RV20);
    00401                 guids.AddTail(MEDIATYPE_Video);
    00402                 guids.AddTail(MEDIASUBTYPE_RV30);
    00403                 guids.AddTail(MEDIATYPE_Video);
    00404                 guids.AddTail(MEDIASUBTYPE_RV40);
    00405                 AddFilter(new CGraphCustomFilter(__uuidof(CRealVideoDecoder), guids,
    00406                         (s.TraFilters&TRA_RV) ? L"RealVideo Decoder" : L"RealVideo Decoder (low merit)",
    00407                         (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00408                 guids.RemoveAll();
    00409         }
    00410
    00411         {
    00412                 guids.AddTail(MEDIATYPE_Audio);
    00413                 guids.AddTail(MEDIASUBTYPE_14_4);
    00414                 guids.AddTail(MEDIATYPE_Audio);
    00415                 guids.AddTail(MEDIASUBTYPE_28_8);
    00416                 guids.AddTail(MEDIATYPE_Audio);
    00417                 guids.AddTail(MEDIASUBTYPE_ATRC);
    00418                 guids.AddTail(MEDIATYPE_Audio);
    00419                 guids.AddTail(MEDIASUBTYPE_COOK);
    00420                 guids.AddTail(MEDIATYPE_Audio);
    00421                 guids.AddTail(MEDIASUBTYPE_DNET);
    00422                 guids.AddTail(MEDIATYPE_Audio);
    00423                 guids.AddTail(MEDIASUBTYPE_SIPR);
    00424                 guids.AddTail(MEDIATYPE_Audio);
    00425                 guids.AddTail(MEDIASUBTYPE_RAAC);
    00426                 AddFilter(new CGraphCustomFilter(__uuidof(CRealAudioDecoder), guids,
    00427                         (s.TraFilters&TRA_RA) ? L"RealAudio Decoder" : L"RealAudio Decoder (low merit)",
    00428                         (s.TraFilters&TRA_RA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00429                 guids.RemoveAll();
    00430         }
    00431
    00432         {
    00433                 guids.AddTail(MEDIATYPE_Video);
    00434                 guids.AddTail(MEDIASUBTYPE_RoQV);
    00435                 AddFilter(new CGraphCustomFilter(__uuidof(CRoQVideoDecoder), guids,
    00436                         (s.TraFilters&TRA_RV) ? L"RoQ Video Decoder" : L"RoQ Video Decoder (low merit)",
    00437                         (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00438                 guids.RemoveAll();
    00439         }
    00440
    00441         {
    00442                 guids.AddTail(MEDIATYPE_Audio);
    00443                 guids.AddTail(MEDIASUBTYPE_RoQA);
    00444                 AddFilter(new CGraphCustomFilter(__uuidof(CRoQAudioDecoder), guids,
    00445                         (s.TraFilters&TRA_RV) ? L"RoQ Audio Decoder" : L"RoQ Audio Decoder (low merit)",
    00446                         (s.TraFilters&TRA_RV) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00447                 guids.RemoveAll();
    00448         }
    00449
    00450         {
    00451                 guids.AddTail(MEDIATYPE_Stream);
    00452                 guids.AddTail(MEDIASUBTYPE_Dirac);
    00453                 AddFilter(new CGraphCustomFilter(__uuidof(CDiracSplitterFilter), guids,
    00454                         (s.SrcFilters&SRC_DIRAC) ? L"Dirac Splitter" : L"Dirac Splitter (low merit)",
    00455                         (s.SrcFilters&SRC_DIRAC) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00456                 guids.RemoveAll();
    00457         }
    00458
    00459         {
    00460                 guids.AddTail(MEDIATYPE_Video);
    00461                 guids.AddTail(MEDIASUBTYPE_DiracVideo);
    00462                 AddFilter(new CGraphCustomFilter(__uuidof(CDiracVideoDecoder), guids,
    00463                         (s.TraFilters&TRA_DIRAC) ? L"Dirac Video Decoder" : L"Dirac Video Decoder (low merit)",
    00464                         (s.TraFilters&TRA_DIRAC) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00465                 guids.RemoveAll();
    00466         }
    00467
    00468         {
    00469                 guids.AddTail(MEDIATYPE_Stream);
    00470                 guids.AddTail(MEDIASUBTYPE_MPEG1Audio);
    00471                 AddFilter(new CGraphCustomFilter(__uuidof(CMpaSplitterFilter), guids,
    00472                         (s.SrcFilters&SRC_MPA) ? L"Mpa Splitter" : L"Mpa Splitter (low merit)",
    00473                         (s.SrcFilters&SRC_MPA) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00474                 guids.RemoveAll();
    00475         }
    00476
    00477         {
    00478                 guids.AddTail(MEDIATYPE_Stream);
    00479                 guids.AddTail(MEDIASUBTYPE_DirectShowMedia);
    00480                 AddFilter(new CGraphCustomFilter(__uuidof(CDSMSplitterFilter), guids,
    00481                         (s.SrcFilters&SRC_DSM) ? L"DSM Splitter" : L"DSM Splitter (low merit)",
    00482                         (s.SrcFilters&SRC_DSM) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00483                 guids.RemoveAll();
    00484         }
    00485
    00486         {
    00487                 guids.AddTail(MEDIATYPE_Stream);
    00488                 guids.AddTail(MEDIASUBTYPE_MP4);
    00489                 AddFilter(new CGraphCustomFilter(__uuidof(CMP4SplitterFilter), guids,
    00490                         (s.SrcFilters&SRC_MP4) ? L"MP4 Splitter" : L"MP4 Splitter (low merit)",
    00491                         (s.SrcFilters&SRC_MP4) ? LMERIT_ABOVE_DSHOW : LMERIT_DO_USE));
    00492                 guids.RemoveAll();
    00493         }
    00494
    00495         // renderer filters
    00496
    00497         switch(s.iDSVideoRendererType)
    00498         {
    00499                 default:
    00500                 case VIDRNDT_DS_DEFAULT:
    00501                         break;
    00502                 case VIDRNDT_DS_OLDRENDERER:
    00503                         AddFilter(new CGraphRegFilter(CLSID_VideoRenderer, m_VRMerit));
    00504                         break;
    00505                 case VIDRNDT_DS_OVERLAYMIXER:
    00506                         AddFilter(new CGraphRendererFilter(CLSID_OverlayMixer, m_hWnd, L"Overlay Mixer", m_VRMerit));
    00507                         break;
    00508                 case VIDRNDT_DS_VMR7WINDOWED:
    00509                         AddFilter(new CGraphRendererFilter(CLSID_VideoMixingRenderer, m_hWnd, L"Video Mixing Render 7 (Windowed)", m_VRMerit));
    00510                         break;
    00511                 case VIDRNDT_DS_VMR9WINDOWED:
    00512                         AddFilter(new CGraphRendererFilter(CLSID_VideoMixingRenderer9, m_hWnd, L"Video Mixing Render 9 (Windowed)", m_VRMerit));
    00513                         break;
    00514                 case VIDRNDT_DS_VMR7RENDERLESS:
    00515                         AddFilter(new CGraphRendererFilter(CLSID_VMR7AllocatorPresenter, m_hWnd, L"Video Mixing Render 7 (Renderless)", m_VRMerit));
    00516                         break;
    00517                 case VIDRNDT_DS_VMR9RENDERLESS:
    00518                         AddFilter(new CGraphRendererFilter(CLSID_VMR9AllocatorPresenter, m_hWnd, L"Video Mixing Render 9 (Renderless)", m_VRMerit));
    00519                         break;
    00520                 case VIDRNDT_DS_NULL_COMP:
    00521                         guids.AddTail(MEDIATYPE_Video);
    00522                         guids.AddTail(MEDIASUBTYPE_NULL);
    00523                         AddFilter(new CGraphCustomFilter(__uuidof(CNullVideoRenderer), guids, L"Null Video Renderer (Any)", LMERIT_ABOVE_DSHOW+2));
    00524                         guids.RemoveAll();
    00525                         break;
    00526                 case VIDRNDT_DS_NULL_UNCOMP:
    00527                         guids.AddTail(MEDIATYPE_Video);
    00528                         guids.AddTail(MEDIASUBTYPE_NULL);
    00529                         AddFilter(new CGraphCustomFilter(__uuidof(CNullUVideoRenderer), guids, L"Null Video Renderer (Uncompressed)", LMERIT_ABOVE_DSHOW+2));
    00530                         guids.RemoveAll();
    00531                         break;
    00532         }
    00533
    00534         if(s.AudioRendererDisplayName == AUDRNDT_NULL_COMP)
    00535         {
    00536                 guids.AddTail(MEDIATYPE_Audio);
    00537                 guids.AddTail(MEDIASUBTYPE_NULL);
    00538                 AddFilter(new CGraphCustomFilter(__uuidof(CNullAudioRenderer), guids, AUDRNDT_NULL_COMP, LMERIT_ABOVE_DSHOW+2));
    00539                 guids.RemoveAll();
    00540         }
    00541         else if(s.AudioRendererDisplayName == AUDRNDT_NULL_UNCOMP)
    00542         {
    00543                 guids.AddTail(MEDIATYPE_Audio);
    00544                 guids.AddTail(MEDIASUBTYPE_NULL);
    00545                 AddFilter(new CGraphCustomFilter(__uuidof(CNullUAudioRenderer), guids, AUDRNDT_NULL_UNCOMP, LMERIT_ABOVE_DSHOW+2));
    00546                 guids.RemoveAll();
    00547         }
    00548         else if(!s.AudioRendererDisplayName.IsEmpty())
    00549         {
    00550                 AddFilter(new CGraphRegFilter(s.AudioRendererDisplayName, m_ARMerit));
    00551         }
    00552
    00553         WORD lowmerit = 1;
    00554         POSITION pos = s.filters.GetTailPosition();
    00555         while(pos)
    00556         {
    00557                 Filter* f = s.filters.GetPrev(pos);
    00558
    00559                 if(f->fDisabled
    00560                 || f->type == Filter::EXTERNAL && !CPath(MakeFullPath(f->path)).FileExists())
    00561                         continue;
    00562
    00563                 ULONGLONG merit =
    00564                         f->iLoadType == Filter::PREFERRED ? LMERIT_ABOVE_DSHOW :
    00565                         f->iLoadType == Filter::MERIT ? LMERIT(f->dwMerit) :
    00566                         LMERIT_DO_NOT_USE; // f->iLoadType == Filter::BLOCKED
    00567
    00568                 merit += lowmerit++;
    00569
    00570                 CGraphFilter* gf = NULL;
    00571
    00572                 if(f->type == Filter::REGISTERED)
    00573                 {
    00574                         gf = new CGraphRegFilter(f->dispname, merit);
    00575                 }
    00576                 else if(f->type == Filter::EXTERNAL)
    00577                 {
    00578                         gf = new CGraphFileFilter(f->clsid, f->guids, f->path, CStringW(f->name), merit);
    00579                 }
    00580
    00581                 if(gf)
    00582                 {
    00583                         gf->SetGUIDs(f->guids);
    00584                         AddFilter(gf);
    00585                 }
    00586         }
    00587
    00588         guids.AddTail(MEDIATYPE_Text);
    00589         guids.AddTail(MEDIASUBTYPE_NULL);
    00590         guids.AddTail(MEDIATYPE_ScriptCommand);
    00591         guids.AddTail(MEDIASUBTYPE_NULL);
    00592         guids.AddTail(MEDIATYPE_Subtitle);
    00593         guids.AddTail(MEDIASUBTYPE_NULL);
    00594         guids.AddTail(MEDIATYPE_NULL);
    00595         guids.AddTail(MEDIASUBTYPE_DVD_SUBPICTURE);
    00596         guids.AddTail(MEDIATYPE_NULL);
    00597         guids.AddTail(MEDIASUBTYPE_CVD_SUBPICTURE);
    00598         guids.AddTail(MEDIATYPE_NULL);
    00599         guids.AddTail(MEDIASUBTYPE_SVCD_SUBPICTURE);
    00600
    00601         AddFilter(new CGraphCustomFilter(__uuidof(CNullTextRenderer), guids, L"NullTextRenderer", LMERIT_DO_USE));
    00602         guids.RemoveAll();
    00603
    00604         // FIXME: "Subtitle Mixer" makes an access violation around
    00605         // the 11-12th media type when enumerating them on its output.
    00606         CLSID CLSID_SubtitlerMixer = GUIDFromCString(_T("{00A95963-3BE5-48C0-AD9F-3356D67EA09D}"));
    00607         AddFilter(new CGraphRegFilter(CLSID_SubtitlerMixer, LMERIT_DO_NOT_USE));
    00608
    00609         // ISCR suxx
    00610         AddFilter(new CGraphRegFilter(GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}")), LMERIT_DO_NOT_USE));
    00611 }
    00612
    00613 CGraphBuilder::~CGraphBuilder()
    00614 {
    00615 }
    00616 /*
    00617 void CGraphBuilder::LOG(LPCTSTR fmt, ...)
    00618 {
    00619         va_list args;
    00620         va_start(args, fmt);
    00621         if(TCHAR* buff = new TCHAR[_vsctprintf(fmt, args) + 1])
    00622         {
    00623                 _vstprintf(buff, fmt, args);
    00624                 m_log.AddTail(buff);
    00625                 TRACE(_T("GraphBuilder: Stream[%d]: %s\n"), m_iStream, buff);
    00626                 if(FILE* f = _tfopen(_T("c:\\mpcgb.txt"), _T("at")))
    00627                 {
    00628                         fseek(f, 0, 2);
    00629                         _ftprintf(f, _T("Stream[%d]: %s\n"), m_iStream, buff);
    00630                         fclose(f);
    00631                 }
    00632                 delete [] buff;
    00633         }
    00634         va_end(args);
    00635 }
    00636 */
    00637
    00638 void CGraphBuilder::ExtractMediaTypes(IPin* pPin, CArray<GUID>& guids)
    00639 {
    00640         guids.RemoveAll();
    00641
    00642     BeginEnumMediaTypes(pPin, pEM, pmt)
    00643         {
    00644                 bool fFound = false;
    00645
    00646                 for(int i = 0; !fFound && i < guids.GetCount(); i += 2)
    00647                 {
    00648                         if(guids[i] == pmt->majortype && guids[i+1] == pmt->subtype)
    00649                                 fFound = true;
    00650                 }
    00651
    00652                 if(!fFound)
    00653                 {
    00654                         guids.Add(pmt->majortype);
    00655                         guids.Add(pmt->subtype);
    00656                 }
    00657         }
    00658         EndEnumMediaTypes(pmt)
    00659 }
    00660
    00661 void CGraphBuilder::ExtractMediaTypes(IPin* pPin, CList<CMediaType>& mts)
    00662 {
    00663         mts.RemoveAll();
    00664
    00665     BeginEnumMediaTypes(pPin, pEM, pmt)
    00666         {
    00667                 bool fFound = false;
    00668
    00669                 POSITION pos = mts.GetHeadPosition();
    00670                 while(!fFound && pos)
    00671                 {
    00672                         CMediaType& mt = mts.GetNext(pos);
    00673                         if(mt.majortype == pmt->majortype && mt.subtype == pmt->subtype)
    00674                                 fFound = true;
    00675                 }
    00676
    00677                 if(!fFound)
    00678                 {
    00679                         mts.AddTail(CMediaType(*pmt));
    00680                 }
    00681         }
    00682         EndEnumMediaTypes(pmt)
    00683 }
    00684
    00685 void CGraphBuilder::SaveFilters(CInterfaceList<IBaseFilter>& bfl)
    00686 {
    00687         bfl.RemoveAll();
    00688         BeginEnumFilters(m_pGB, pEF, pBF)
    00689                 bfl.AddTail(pBF);
    00690         EndEnumFilters
    00691 }
    00692
    00693 void CGraphBuilder::RestoreFilters(CInterfaceList<IBaseFilter>& bfl)
    00694 {
    00695         BeginEnumFilters(m_pGB, pEF, pBF)
    00696                 if(!bfl.Find(pBF)) {m_pGB->RemoveFilter(pBF); pEF->Reset();}
    00697         EndEnumFilters
    00698 }
    00699
    00700 HRESULT CGraphBuilder::SafeAddFilter(IBaseFilter* pBF, LPCWSTR pName)
    00701 {
    00702         if(!m_pGB || !pBF)
    00703                 return E_FAIL;
    00704
    00705         bool fFound = false;
    00706         BeginEnumFilters(m_pGB, pEF, pBF2)
    00707                 if(pBF == pBF2) fFound = true;
    00708         EndEnumFilters
    00709         if(fFound) return S_OK;
    00710
    00711         CFilterInfo fi;
    00712         if(SUCCEEDED(pBF->QueryFilterInfo(&fi)))
    00713         {
    00714                 if(!fi.pGraph) // not in graph yet?
    00715                 {
    00716                         CStringW name;
    00717
    00718                         if(pName && wcslen(pName) > 0)
    00719                         {
    00720                                 name = pName;
    00721                         }
    00722                         else
    00723                         {
    00724                                 if(CComQIPtr<IFileSourceFilter> pFSF = pBF)
    00725                                 {
    00726                                         CMediaType mt;
    00727                                         LPOLESTR str = NULL;
    00728                                         if(SUCCEEDED(pFSF->GetCurFile(&str, &mt))) name = str;
    00729                                         if(str) CoTaskMemFree(str);
    00730                                 }
    00731
    00732                                 if(name.IsEmpty())
    00733                                 {
    00734                                         CLSID clsid = GetCLSID(pBF);
    00735                                         name = clsid == GUID_NULL ? L"Unknown Filter" : CStringFromGUID(clsid);
    00736                                 }
    00737                         }
    00738
    00739                         if(FAILED(m_pGB->AddFilter(pBF, name)))
    00740                         {
    00741                                 return E_FAIL;
    00742                         }
    00743                 }
    00744
    00745                 return S_OK;
    00746         }
    00747
    00748         return E_FAIL;
    00749 }
    00750
    00751 void CGraphBuilder::Reset()
    00752 {
    00753         m_nTotalStreams = 0;
    00754         m_nCurrentStream = 0;
    00755         m_pUnks.RemoveAll();
    00756         m_DeadEnds.RemoveAll();
    00757 //      m_log.RemoveAll();
    00758 }
    00759
    00760 HRESULT CGraphBuilder::AddSourceFilter(LPCTSTR lpsz, IBaseFilter** ppBF, UINT SrcFilters)
    00761 {
    00762         CheckPointer(lpsz, E_POINTER);
    00763         CheckPointer(ppBF, E_POINTER);
    00764
    00765         if(!m_pGB) return E_UNEXPECTED;
    00766
    00767         CString fn = CString(lpsz).Trim();
    00768         if(fn.IsEmpty()) return E_FAIL;
    00769         CStringW fnw = fn;
    00770         CString ext = CPath(fn).GetExtension().MakeLower();
    00771
    00772         HRESULT hr;
    00773
    00774         CComQIPtr<IBaseFilter> pBF;
    00775
    00776         CComQIPtr<IGraphEngine> pGE = m_pGB;
    00777         if(!pGE || pGE->GetEngine() == DirectShow)
    00778         {
    00779 /*
    00780                 if(!pBF && fn.Find(_T("://")) > 0)
    00781                 {
    00782                         CList<CString> mms;
    00783                         CString ct = GetContentType(fn, &mms); // TODO: if there are more to check, do GetContentType only once
    00784                         if(ct == _T("video/x-ms-asf") || ct == _T("video/x-ms-wmv")
    00785                         || ct == _T("video/x-ms-wvx") || ct == _T("video/x-ms-wax")
    00786                         || ct == _T("video/x-ms-wmp"))
    00787                         {
    00788                                 if(!mms.IsEmpty()) fnw = mms.GetHead();
    00789                                 fnw.Replace(L"&MSWMExt=.asf", L"");
    00790
    00791                                 CComPtr<IFileSourceFilter> pReader;
    00792                                 hr = pReader.CoCreateInstance(CLSID_NetShowSource);
    00793                                 if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00794                                         pBF = pReader;
    00795                         }
    00796                 }
    00797 */
    00798                 if((SrcFilters&SRC_SUBS) && !pBF)
    00799                 {
    00800                         hr = S_OK;
    00801                         CComPtr<IFileSourceFilter> pReader = new CSubtitleSourceASS(NULL, &hr);
    00802                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00803                                 pBF = pReader;
    00804                 }
    00805
    00806                 if((SrcFilters&SRC_CDDA) && !pBF && ext == _T(".cda"))
    00807                 {
    00808                         hr = S_OK;
    00809                         CComPtr<IFileSourceFilter> pReader = new CCDDAReader(NULL, &hr);
    00810                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00811                                 pBF = pReader;
    00812                 }
    00813
    00814                 if((SrcFilters&SRC_CDXA) && !pBF)
    00815                 {
    00816                         hr = S_OK;
    00817                         CComPtr<IFileSourceFilter> pReader = new CCDXAReader(NULL, &hr);
    00818                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00819                                 pBF = pReader;
    00820                 }
    00821
    00822                 if((SrcFilters&SRC_VTS) && !pBF) //&& ext == _T(".ifo"))
    00823                 {
    00824                         hr = S_OK;
    00825                         CComPtr<IFileSourceFilter> pReader = new CVTSReader(NULL, &hr);
    00826                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00827                                 pBF = pReader;
    00828                 }
    00829
    00830                 if((SrcFilters&SRC_FLIC) && !pBF) //&& (ext == _T(".fli") || ext == _T(".flc")))
    00831                 {
    00832                         hr = S_OK;
    00833                         CComPtr<IFileSourceFilter> pReader = new CFLICSource(NULL, &hr);
    00834                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00835                                 pBF = pReader;
    00836                 }
    00837
    00838                 if((SrcFilters&SRC_D2V) && !pBF) //&& ext == _T(".d2v"))
    00839                 {
    00840                         hr = S_OK;
    00841                         CComPtr<IFileSourceFilter> pReader = new CD2VSource(NULL, &hr);
    00842                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00843                                 pBF = pReader;
    00844                 }
    00845
    00846                 if((SrcFilters&SRC_DTSAC3) && !pBF) //&& (ext == _T(".dts") || ext == _T(".ac3")))
    00847                 {
    00848                         hr = S_OK;
    00849                         CComPtr<IFileSourceFilter> pReader = new CDTSAC3Source(NULL, &hr);
    00850                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00851                                 pBF = pReader;
    00852                 }
    00853
    00854                 if((SrcFilters&SRC_SHOUTCAST) && !pBF && fn.Find(_T("://")) >= 0)
    00855                 {
    00856                         hr = S_OK;
    00857                         CComPtr<IFileSourceFilter> pReader = new CShoutcastSource(NULL, &hr);
    00858                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00859                                 pBF = pReader;
    00860                 }
    00861
    00862                 if((SrcFilters&SRC_MATROSKA) && !pBF) //&& (ext == _T(".mkv") || ext == _T(".mka") || ext == _T(".mks")))
    00863                 {
    00864                         hr = S_OK;
    00865                         CComPtr<IFileSourceFilter> pReader = new CMatroskaSourceFilter(NULL, &hr);
    00866                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00867                                 pBF = pReader;
    00868                 }
    00869
    00870                 if((SrcFilters&SRC_REALMEDIA) && !pBF)
    00871                 {
    00872                         hr = S_OK;
    00873                         CComPtr<IFileSourceFilter> pReader = new CRealMediaSourceFilter(NULL, &hr);
    00874                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00875                                 pBF = pReader;
    00876                 }
    00877
    00878                 if((SrcFilters&SRC_AVI) && !pBF)
    00879                 {
    00880                         hr = S_OK;
    00881                         CComPtr<IFileSourceFilter> pReader = new CAviSourceFilter(NULL, &hr);
    00882                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00883                                 pBF = pReader;
    00884                 }
    00885
    00886                 __if_exists(CRadGtSplitterFilter)
    00887                 {
    00888                 if((SrcFilters&SRC_RADGT) && !pBF)
    00889                 {
    00890                         hr = S_OK;
    00891                         CComPtr<IFileSourceFilter> pReader = new CRadGtSourceFilter(NULL, &hr);
    00892                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00893                                 pBF = pReader;
    00894                 }
    00895                 }
    00896
    00897                 if((SrcFilters&SRC_ROQ) && !pBF)
    00898                 {
    00899                         hr = S_OK;
    00900                         CComPtr<IFileSourceFilter> pReader = new CRoQSourceFilter(NULL, &hr);
    00901                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00902                                 pBF = pReader;
    00903                 }
    00904
    00905                 if((SrcFilters&SRC_OGG) && !pBF)
    00906                 {
    00907                         hr = S_OK;
    00908                         CComPtr<IFileSourceFilter> pReader = new COggSourceFilter(NULL, &hr);
    00909                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00910                                 pBF = pReader;
    00911                 }
    00912
    00913                 if((SrcFilters&SRC_NUT) && !pBF)
    00914                 {
    00915                         hr = S_OK;
    00916                         CComPtr<IFileSourceFilter> pReader = new CNutSourceFilter(NULL, &hr);
    00917                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00918                                 pBF = pReader;
    00919                 }
    00920
    00921                 if((SrcFilters&SRC_MPEG) && !pBF)
    00922                 {
    00923                         hr = S_OK;
    00924                         CComPtr<IFileSourceFilter> pReader = new CMpegSourceFilter(NULL, &hr);
    00925                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00926                                 pBF = pReader;
    00927                 }
    00928
    00929                 if((SrcFilters&SRC_DIRAC) && !pBF)
    00930                 {
    00931                         hr = S_OK;
    00932                         CComPtr<IFileSourceFilter> pReader = new CDiracSourceFilter(NULL, &hr);
    00933                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00934                                 pBF = pReader;
    00935                 }
    00936
    00937                 if((SrcFilters&SRC_MPA) && !pBF)
    00938                 {
    00939                         hr = S_OK;
    00940                         CComPtr<IFileSourceFilter> pReader = new CMpaSourceFilter(NULL, &hr);
    00941                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00942                                 pBF = pReader;
    00943                 }
    00944
    00945                 if((SrcFilters&SRC_DSM) && !pBF)
    00946                 {
    00947                         hr = S_OK;
    00948                         CComPtr<IFileSourceFilter> pReader = new CDSMSourceFilter(NULL, &hr);
    00949                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00950                                 pBF = pReader;
    00951                 }
    00952
    00953                 if((SrcFilters&SRC_MP4) && !pBF)
    00954                 {
    00955                         hr = S_OK;
    00956                         CComPtr<IFileSourceFilter> pReader = new CMP4SourceFilter(NULL, &hr);
    00957                         if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00958                                 pBF = pReader;
    00959                 }
    00960
    00961                 if(!pBF && fn.Find(_T("://")) < 0)
    00962                 {
    00963                         bool fWindowsMedia = (ext == _T(".asf") || ext == _T(".wmv") || ext == _T(".wma"));
    00964
    00965                         if(!fWindowsMedia)
    00966                         {
    00967                                 CFile f;
    00968                                 if(f.Open(fn, CFile::modeRead))
    00969                                 {
    00970                                         BYTE buff[4];
    00971                                         memset(buff, 0, sizeof(buff));
    00972                                         f.Read(buff, sizeof(buff));
    00973                                         if(*(DWORD*)buff == 0x75b22630)
    00974                                                 fWindowsMedia = true;
    00975                                 }
    00976                         }
    00977
    00978                         if(fWindowsMedia)
    00979                         {
    00980                                 CComPtr<IFileSourceFilter> pReader;
    00981                                 hr = pReader.CoCreateInstance(AfxGetAppSettings().fUseWMASFReader ? CLSID_WMAsfReader : CLSID_NetShowSource);
    00982                                 if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    00983                                         pBF = pReader;
    00984                         }
    00985                 }
    00986 /*
    00987                 if(!pBF && fn.Find(_T("://")) < 0)
    00988                 {
    00989                         CFile f;
    00990                         if(f.Open(fn, CFile::modeRead|CFile::shareDenyWrite))
    00991                         {
    00992                                 ULONGLONG len = f.GetLength();
    00993                                 BYTE buff[12];
    00994                                 memset(buff, 0, sizeof(buff));
    00995                                 f.Read(buff, sizeof(buff));
    00996                                 if(*((DWORD*)&buff[0]) == 'FFIR' && *((DWORD*)&buff[8]) == ' IVA')
    00997                                 {
    00998                                         if(len < *((DWORD*)&buff[4])+8)
    00999                                         {
    01000                                                 MessageBeep(-1);
    01001
    01002                                                 CComPtr<IFileSourceFilter> pReader;
    01003                                                 hr = pReader.CoCreateInstance(CLSID_AVIDoc);
    01004                                                 if(SUCCEEDED(hr) && SUCCEEDED(pReader->Load(fnw, NULL)))
    01005                                                         pBF = pReader;
    01006                                         }
    01007                                 }
    01008                         }
    01009                 }
    01010 */
    01011         }
    01012
    01013         if(!pBF)
    01014         {
    01015                 CheckStupidSharedFilesourceFilter();
    01016
    01017                 if(FAILED(hr = m_pGB->AddSourceFilter(fnw, fnw, &pBF)))
    01018                         return hr;
    01019
    01020                 if(SUCCEEDED(hr) && !pBF) // custom graphs don't need filters
    01021                         return hr;
    01022         }
    01023
    01024         ASSERT(pBF);
    01025
    01026         if(FAILED(SafeAddFilter(pBF, NULL)))
    01027                 return E_FAIL;
    01028
    01029         *ppBF = pBF.Detach();
    01030
    01031         return S_OK;
    01032 }
    01033
    01034 HRESULT CGraphBuilder::Render(LPCTSTR lpsz)
    01035 {
    01036         CComPtr<IBaseFilter> pBF;
    01037
    01038         HRESULT hr = AddSourceFilter(lpsz, &pBF, AfxGetAppSettings().SrcFilters & ~SRC_SUBS);
    01039         if(FAILED(hr)) return hr;
    01040
    01041         return pBF ? Render(pBF) : S_OK;
    01042 }
    01043
    01044 HRESULT CGraphBuilder::Render(IBaseFilter* pBF)
    01045 {
    01046         if(!m_pGB || !m_pFM || !pBF)
    01047                 return E_FAIL;
    01048
    01049         if(FAILED(SafeAddFilter(pBF, NULL)))
    01050                 return E_FAIL;
    01051
    01052         CInterfaceList<IPin> pOutputs;
    01053         BeginEnumPins(pBF, pEP, pPin)
    01054         {
    01055                 PIN_DIRECTION dir;
    01056                 CComPtr<IPin> pTmp;
    01057                 CPinInfo pi;
    01058                 if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT   // not an output?
    01059                 || SUCCEEDED(pPin->ConnectedTo(&pTmp))                                          // already connected?
    01060                 || FAILED(pPin->QueryPinInfo(&pi)) || pi.achName[0] == '~')             // hidden?
    01061                         continue;
    01062
    01063                 pOutputs.AddTail(pPin);
    01064         }
    01065         EndEnumPins
    01066
    01067         int nRendered = 0;
    01068
    01069         if(pOutputs.GetCount() > 0)
    01070         {
    01071                 POSITION pos = pOutputs.GetHeadPosition();
    01072                 while(pos)
    01073                 {
    01074                         if(SUCCEEDED(Render(pOutputs.GetNext(pos)))) nRendered++;
    01075                         if(pOutputs.GetCount() > 1) m_nCurrentStream++;
    01076                 }
    01077         }
    01078         else
    01079         {
    01080                 m_nTotalStreams++;
    01081
    01082                 for(int i = 0; i < m_DeadEnds.GetCount(); i++)
    01083                 {
    01084                         if(m_DeadEnds[i]->nStream == m_nCurrentStream)
    01085                                 m_DeadEnds.RemoveAt(i--);
    01086                 }
    01087         }
    01088
    01089         return
    01090                 nRendered == pOutputs.GetCount() ? (nRendered > 0 ? S_OK : S_FALSE) :
    01091                 nRendered > 0 ? VFW_S_PARTIAL_RENDER :
    01092                 VFW_E_CANNOT_RENDER;
    01093 }
    01094
    01095 typedef struct {CGraphFilter* pFilter; bool fExactMatch;} SortFilter;
    01096
    01097 static int compare(const void* arg1, const void* arg2)
    01098 {
    01099         SortFilter* sf1 = (SortFilter*)arg1;
    01100         SortFilter* sf2 = (SortFilter*)arg2;
    01101 /*
    01102         if(sf1->pFilter->GetMerit() < LMERIT(MERIT_PREFERRED) && sf2->pFilter->GetMerit() < LMERIT(MERIT_PREFERRED))
    01103         {
    01104                 if(!sf1->fExactMatch && sf2->fExactMatch) return 1;
    01105                 else if(sf1->fExactMatch && !sf2->fExactMatch) return -1;
    01106         }
    01107 */
    01108         if(sf1->pFilter->GetCLSID() == sf2->pFilter->GetCLSID())
    01109         {
    01110                 // prefer externals
    01111                 CGraphFileFilter* f1 = dynamic_cast<CGraphFileFilter*>(sf1->pFilter);
    01112                 CGraphFileFilter* f2 = dynamic_cast<CGraphFileFilter*>(sf2->pFilter);
    01113                 if(!f1 && f2) return 1;
    01114                 if(f1 && !f2) return -1;
    01115         }
    01116
    01117         if(sf1->pFilter->GetMerit() < sf2->pFilter->GetMerit()) return 1;
    01118         else if(sf1->pFilter->GetMerit() > sf2->pFilter->GetMerit()) return -1;
    01119
    01120         if(!sf1->fExactMatch && sf2->fExactMatch) return 1;
    01121         else if(sf1->fExactMatch && !sf2->fExactMatch) return -1;
    01122
    01123         return 0;
    01124 }
    01125
    01126 HRESULT CGraphBuilder::Render(IPin* pPin)
    01127 {
    01128         if(!m_pGB || !m_pFM || !pPin)
    01129                 return E_FAIL;
    01130
    01131         PIN_DIRECTION dir;
    01132         CComPtr<IPin> pPinTmp;
    01133         if(FAILED(pPin->QueryDirection(&dir)) || dir != PINDIR_OUTPUT
    01134         || SUCCEEDED(pPin->ConnectedTo(&pPinTmp)))
    01135                 return E_UNEXPECTED;
    01136
    01137         if(GetCLSID(pPin) == CLSID_MPEG2Demultiplexer)
    01138         {
    01139                 CComQIPtr<IMediaSeeking> pMS = pPin;
    01140                 if(!pMS) return E_FAIL;
    01141                 REFERENCE_TIME rtDur = 0;
    01142                 if(FAILED(pMS->GetDuration(&rtDur)) || rtDur <= 0)
    01143                          return E_FAIL;
    01144                 rtDur = rtDur;
    01145         }
    01146
    01147         bool fDeadEnd = true;
    01148
    01149         // 1. stream builder interface
    01150
    01151         if(CComQIPtr<IStreamBuilder> pSB = pPin)
    01152         {
    01153                 CInterfaceList<IBaseFilter> bfl;
    01154                 SaveFilters(bfl);
    01155
    01156                 if(SUCCEEDED(pSB->Render(pPin, m_pGB)))
    01157                         return S_OK;
    01158
    01159                 pSB->Backout(pPin, m_pGB);
    01160
    01161                 RestoreFilters(bfl);
    01162         }
    01163
    01164         // 2. filter cache
    01165
    01166         if(CComQIPtr<IGraphConfig> pGC = m_pGB)
    01167         {
    01168                 CComPtr<IEnumFilters> pEF;
    01169                 if(SUCCEEDED(pGC->EnumCacheFilter(&pEF)))
    01170                 {
    01171                         for(CComPtr<IBaseFilter> pBF; S_OK == pEF->Next(1, &pBF, NULL); pBF = NULL)
    01172                         {
    01173                                 CInterfaceList<IBaseFilter> bfl;
    01174                                 SaveFilters(bfl);
    01175
    01176                                 pGC->RemoveFilterFromCache(pBF);
    01177
    01178                                 if(SUCCEEDED(ConnectDirect(pPin, pBF)))
    01179                                 {
    01180                                         fDeadEnd = false;
    01181
    01182                                         HRESULT hr;
    01183                                         if(SUCCEEDED(hr = Render(pBF)))
    01184                                                 return hr;
    01185                                 }
    01186
    01187                                 pGC->AddFilterToCache(pBF);
    01188
    01189                                 RestoreFilters(bfl);
    01190                         }
    01191                 }
    01192         }
    01193
    01194         // 3. disconnected inputs
    01195
    01196         CInterfaceList<IBaseFilter> pFilters;
    01197         SaveFilters(pFilters);
    01198
    01199         POSITION pos;
    01200
    01201         // FIXME: ffdshow likes to connect to the audio capture filter's fake input pins
    01202         if(!dynamic_cast<CGraphBuilderCapture*>(this))
    01203         {
    01204         pos = pFilters.GetHeadPosition();
    01205         while(pos)
    01206         {
    01207                 CComPtr<IBaseFilter> pBF = pFilters.GetNext(pos);
    01208
    01209                 if(SUCCEEDED(ConnectDirect(pPin, pBF)))
    01210                 {
    01211                         fDeadEnd = false;
    01212
    01213                         HRESULT hr;
    01214                         if(SUCCEEDED(hr = Render(pBF)))
    01215                                 return hr;
    01216                 }
    01217         }
    01218         }
    01219
    01220         // 4. registry+internal+external
    01221
    01222         // TODO: try media types one-by-one and pass pmt to ConnectDirect (this may not be better than the current!!!)
    01223
    01224         CArray<GUID> guids;
    01225     ExtractMediaTypes(pPin, guids);
    01226
    01227         if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Stream && guids[1] == MEDIASUBTYPE_NULL)
    01228         {
    01229                 if(CComQIPtr<IAsyncReader> pReader = pPin)
    01230                 {
    01231                         BYTE buff[4];
    01232                         if(S_OK == pReader->SyncRead(0, 4, buff) && *(DWORD*)buff == 'SggO')
    01233                                 guids[1] = MEDIASUBTYPE_Ogg;
    01234                 }
    01235         }
    01236         else if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Video && guids[1] == FOURCCMap('MGXD'))
    01237         {
    01238                 guids[1] = FOURCCMap('XVID');
    01239         }
    01240
    01241         CAutoPtrList<CGraphFilter> autogfs;
    01242         CArray<CGraphFilter*> gfs;
    01243
    01244         CComPtr<IEnumMoniker> pEM;
    01245         if(guids.GetCount() > 0
    01246         && SUCCEEDED(m_pFM->EnumMatchingFilters(
    01247                 &pEM, 0, FALSE, MERIT_DO_NOT_USE+1,
    01248                 TRUE, guids.GetCount()/2, guids.GetData(), NULL, NULL, FALSE,
    01249                 FALSE, 0, NULL, NULL, NULL)))
    01250         {
    01251                 for(CComPtr<IMoniker> pMoniker; S_OK == pEM->Next(1, &pMoniker, NULL); pMoniker = NULL)
    01252                 {
    01253                         CAutoPtr<CGraphFilter> pGraphFilter(new CGraphRegFilter(pMoniker));
    01254
    01255                         if(pGraphFilter)
    01256                         {
    01257                                 POSITION pos = m_pMoreFilters.GetHeadPosition();
    01258                                 while(pos)
    01259                                 {
    01260                                         CGraphRegFilter* f = dynamic_cast<CGraphRegFilter*>((CGraphFilter*)m_pMoreFilters.GetNext(pos));
    01261                                         if(!f) continue;
    01262
    01263                                         if(f->GetMoniker() && S_OK == pMoniker->IsEqual(f->GetMoniker())
    01264                                         || f->GetCLSID() != GUID_NULL && f->GetCLSID() == pGraphFilter->GetCLSID())
    01265                                         {
    01266                                                 pGraphFilter.Free();
    01267                                                 break;
    01268                                         }
    01269                                 }
    01270                         }
    01271
    01272                         if(pGraphFilter)
    01273                         {
    01274                                 autogfs.AddTail(pGraphFilter);
    01275                         }
    01276                 }
    01277         }
    01278
    01279         pos = autogfs.GetHeadPosition();
    01280         while(pos)
    01281         {
    01282                 CGraphFilter* f = autogfs.GetNext(pos);
    01283
    01284                 bool fFound = false;
    01285
    01286                 POSITION pos2 = m_chain.GetHeadPosition();
    01287                 while(pos2)
    01288                 {
    01289                         if(f->GetCLSID() == m_chain.GetNext(pos2)->GetCLSID())
    01290                         {
    01291                                 fFound = true;
    01292                                 break;
    01293                         }
    01294                 }
    01295
    01296                 if(!fFound)
    01297                         gfs.Add(f);
    01298         }
    01299
    01300         pos = m_pMoreFilters.GetHeadPosition();
    01301         while(pos)
    01302         {
    01303                 CGraphFilter* f = m_pMoreFilters.GetNext(pos);
    01304                 if(f->GetMerit() >= LMERIT_DO_USE && !m_chain.Find(f) && f->IsCompatible(guids))
    01305                         gfs.Add(f);
    01306         }
    01307
    01308         CArray<SortFilter> sfs;
    01309         sfs.SetSize(gfs.GetCount());
    01310         for(int i = 0; i < gfs.GetCount(); i++)
    01311         {
    01312                 sfs[i].pFilter = gfs[i];
    01313                 sfs[i].fExactMatch = gfs[i]->IsExactMatch(guids);
    01314         }
    01315         if(sfs.GetCount() > 1) qsort(sfs.GetData(), sfs.GetCount(), sizeof(SortFilter), compare);
    01316
    01317         for(int i = 0; i < sfs.GetCount(); i++)
    01318         {
    01319                 CGraphFilter* gf = sfs[i].pFilter;
    01320                 if(!gf) continue;
    01321
    01322                 CComPtr<IBaseFilter> pBF;
    01323                 CComPtr<IUnknown> pUnk;
    01324                 if(FAILED(gf->Create(&pBF, &pUnk)))
    01325                         continue;
    01326
    01327                 CInterfaceList<IBaseFilter> bfl;
    01328                 SaveFilters(bfl);
    01329
    01330                 if(FAILED(SafeAddFilter(pBF, gf->GetName())))
    01331                         continue;
    01332
    01333                 if(gf->GetCLSID() == CLSID_DMOWrapperFilter)
    01334                 {
    01335                         if(CComQIPtr<IPropertyBag> pPBag = pBF)
    01336                         {
    01337                                 CComVariant var(true);
    01338                                 pPBag->Write(CComBSTR(L"_HIRESOUTPUT"), &var);
    01339                         }
    01340                 }
    01341
    01342                 if(CComQIPtr<IMpeg2DecFilter> m_pMpeg2DecFilter = pBF)
    01343                 {
    01344                         AppSettings& s = AfxGetAppSettings();
    01345                         m_pMpeg2DecFilter->SetDeinterlaceMethod((ditype)s.mpegdi);
    01346                         m_pMpeg2DecFilter->SetBrightness(s.mpegbright);
    01347                         m_pMpeg2DecFilter->SetContrast(s.mpegcont);
    01348                         m_pMpeg2DecFilter->SetHue(s.mpeghue);
    01349                         m_pMpeg2DecFilter->SetSaturation(s.mpegsat);
    01350                         m_pMpeg2DecFilter->EnableForcedSubtitles(s.mpegforcedsubs);
    01351                         m_pMpeg2DecFilter->EnablePlanarYUV(s.mpegplanaryuv);
    01352                 }
    01353
    01354                 if(CComQIPtr<IMpaDecFilter> m_pMpaDecFilter = pBF)
    01355                 {
    01356                         AppSettings& s = AfxGetAppSettings();
    01357                         m_pMpaDecFilter->SetSampleFormat((SampleFormat)s.mpasf);
    01358                         m_pMpaDecFilter->SetNormalize(s.mpanormalize);
    01359                         m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::ac3, s.ac3sc);
    01360                         m_pMpaDecFilter->SetDynamicRangeControl(IMpaDecFilter::ac3, s.ac3drc);
    01361                         m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::dts, s.dtssc);
    01362                         m_pMpaDecFilter->SetDynamicRangeControl(IMpaDecFilter::dts, s.dtsdrc);
    01363                         m_pMpaDecFilter->SetSpeakerConfig(IMpaDecFilter::aac, s.aacsc);
    01364                         m_pMpaDecFilter->SetBoost(s.mpaboost);
    01365                 }
    01366
    01367                 HRESULT hr = E_FAIL;
    01368
    01369                 if(guids.GetCount() == 2 && guids[0] == MEDIATYPE_Stream && guids[1] != MEDIATYPE_NULL)
    01370                 {
    01371                         CMediaType mt;
    01372                         mt.majortype = guids[0];
    01373                         mt.subtype = guids[1];
    01374                         mt.formattype = FORMAT_None;
    01375                         hr = ConnectDirect(pPin, pBF, &mt);
    01376
    01377                         if(FAILED(hr))
    01378                         {
    01379                                 mt.formattype = GUID_NULL;
    01380                                 hr = ConnectDirect(pPin, pBF, &mt);
    01381                         }
    01382                 }
    01383
    01384                 if(SUCCEEDED(hr) || SUCCEEDED(ConnectDirect(pPin, pBF, NULL)))
    01385                 {
    01386                         fDeadEnd = false;
    01387
    01388                         int nCurrentStream = m_nCurrentStream;
    01389
    01390                         m_chain.AddTail(gf);
    01391
    01392                         hr = Render(pBF);
    01393
    01394                         m_chain.RemoveTail();
    01395
    01396                         if(SUCCEEDED(hr))
    01397                         {
    01398                                 if(pUnk) m_pUnks.AddTail(pUnk);
    01399
    01400                                 // maybe the application should do this...
    01401                                 if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pUnk)
    01402                                         pMPC->SetAspectRatioMode(AM_ARMODE_STRETCHED);
    01403                                 if(CComQIPtr<IVMRAspectRatioControl> pARC = pBF)
    01404                                         pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
    01405                                 if(CComQIPtr<IVMRAspectRatioControl9> pARC = pBF)
    01406                                         pARC->SetAspectRatioMode(VMR_ARMODE_NONE);
    01407
    01408                                 return hr;
    01409                         }
    01410
    01411                         m_nCurrentStream = nCurrentStream;
    01412                 }
    01413
    01414                 m_pGB->RemoveFilter(pBF);
    01415
    01416                 RestoreFilters(bfl);
    01417         }
    01418
    01419         // 5. record filter/pin/mts if this was the end of a chain
    01420
    01421         if(fDeadEnd)
    01422         {
    01423                 CAutoPtr<DeadEnd> de(new DeadEnd);
    01424                 de->nStream = m_nCurrentStream;
    01425                 de->clsid = CStringFromGUID(GetCLSID(pPin));
    01426                 de->filter = GetFilterName(GetFilterFromPin(pPin));
    01427                 de->pin = GetPinName(pPin);
    01428                 ExtractMediaTypes(pPin, de->mts);
    01429                 if(!(m_chain.GetCount() == 0 && de->mts.GetCount() == 1
    01430                 && de->mts.GetHead().majortype == MEDIATYPE_Stream && de->mts.GetHead().subtype == MEDIASUBTYPE_NULL))
    01431                 {
    01432                         CString str;
    01433                         str.Format(_T("Stream %d"), m_nCurrentStream);
    01434                         de->path.AddTail(str);
    01435                         POSITION pos = m_chain.GetHeadPosition();
    01436                         while(pos) de->path.AddTail(CString(m_chain.GetNext(pos)->GetName()));
    01437                         m_DeadEnds.Add(de);
    01438                 }
    01439         }
    01440
    01441         return E_FAIL;
    01442 }
    01443
    01444 HRESULT CGraphBuilder::ConnectDirect(IPin* pPin, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt)
    01445 {
    01446         if(!pPin || !pBF)
    01447                 return E_INVALIDARG;
    01448
    01449         if(FAILED(SafeAddFilter(pBF, NULL)))
    01450                 return E_FAIL;
    01451
    01452         BeginEnumPins(pBF, pEP, pPinTo)
    01453         {
    01454                 PIN_DIRECTION dir;
    01455                 CComPtr<IPin> pTmp;
    01456                 if(FAILED(pPinTo->QueryDirection(&dir)) || dir != PINDIR_INPUT
    01457                 || SUCCEEDED(pPinTo->ConnectedTo(&pTmp)))
    01458                         continue;
    01459
    01460                 if(SUCCEEDED(m_pGB->ConnectDirect(pPin, pPinTo, pmt)))
    01461                         return S_OK;
    01462         }
    01463         EndEnumPins
    01464
    01465         return VFW_E_CANNOT_CONNECT;
    01466 }
    01467
    01468 HRESULT CGraphBuilder::FindInterface(REFIID iid, void** ppv)
    01469 {
    01470         CheckPointer(ppv, E_POINTER);
    01471
    01472         POSITION pos = m_pUnks.GetHeadPosition();
    01473         while(pos)
    01474         {
    01475                 IUnknown* pUnk = m_pUnks.GetNext(pos);
    01476                 HRESULT hr;
    01477                 if(SUCCEEDED(hr = pUnk->QueryInterface(iid, ppv)))
    01478                         return hr;
    01479         }
    01480
    01481         return E_NOINTERFACE;
    01482 }
    01483
    01484 //
    01485 // CGraphBuilderFile
    01486 //
    01487
    01488 CGraphBuilderFile::CGraphBuilderFile(IGraphBuilder* pGB, HWND hWnd)
    01489         : CGraphBuilder(pGB, hWnd)
    01490 {
    01491         CList<GUID> guids;
    01492
    01493         if(AfxGetAppSettings().fEnableAudioSwitcher)
    01494         {
    01495                 guids.AddTail(MEDIATYPE_Audio);
    01496                 guids.AddTail(MEDIASUBTYPE_NULL);
    01497                 AddFilter(new CGraphCustomFilter(__uuidof(CAudioSwitcherFilter), guids, L"Audio Switcher", m_ARMerit + 0x100));
    01498                 guids.RemoveAll();
    01499
    01500                 CLSID CLSID_MorganStreamSwitcher = GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}"));
    01501                 AddFilter(new CGraphRegFilter(CLSID_MorganStreamSwitcher, LMERIT_DO_NOT_USE));
    01502         }
    01503 }
    01504
    01505 //
    01506 // CGraphBuilderDVD
    01507 //
    01508
    01509 CGraphBuilderDVD::CGraphBuilderDVD(IGraphBuilder* pGB, HWND hWnd)
    01510         : CGraphBuilderFile(pGB, hWnd)
    01511 {
    01512         CList<GUID> guids;
    01513 /*
    01514         // there wasn't much use of this and the users were just
    01515         // confused by "decss" being in the report after a failed
    01516         // dvd nav pin rendering
    01517
    01518         guids.AddTail(MEDIATYPE_DVD_ENCRYPTED_PACK);
    01519         guids.AddTail(MEDIASUBTYPE_NULL);
    01520         AddFilter(new CGraphCustomFilter(__uuidof(CDeCSSFilter), guids, L"DeCSS", LMERIT_UNLIKELY));
    01521         guids.RemoveAll();
    01522 */
    01523         DWORD ver = ::GetVersion();
    01524         bool m_fXp = (int)ver >= 0 && (((ver<<8)&0xff00)|((ver>>8)&0xff)) >= 0x0501;
    01525
    01526         AppSettings& s = AfxGetAppSettings();
    01527         if(!m_fXp && s.iDSVideoRendererType != VIDRNDT_DS_OVERLAYMIXER
    01528         || s.iDSVideoRendererType == VIDRNDT_DS_OLDRENDERER)
    01529         AddFilter(new CGraphRendererFilter(CLSID_OverlayMixer, m_hWnd, L"Overlay Mixer", m_VRMerit-1));
    01530
    01531         // this filter just simply sucks for dvd playback (atm)
    01532         CLSID CLSID_ElecardMpeg2 = GUIDFromCString(_T("{F50B3F13-19C4-11CF-AA9A-02608C9BABA2}"));
    01533         AddFilter(new CGraphRegFilter(CLSID_ElecardMpeg2, LMERIT_DO_NOT_USE));
    01534 }
    01535
    01536 #include "..\..\decss\VobFile.h"
    01537
    01538 class CResetDVD : public CDVDSession
    01539 {
    01540 public:
    01541         CResetDVD(LPCTSTR path)
    01542         {
    01543                 if(Open(path))
    01544                 {
    01545                         if(BeginSession())
    01546                         {
    01547                                 Authenticate();
    01548                                 // GetDiscKey();
    01549                                 EndSession();
    01550                         }
    01551
    01552                         Close();
    01553                 }
    01554         }
    01555 };
    01556
    01557 [uuid("482d10b6-376e-4411-8a17-833800A065DB")]
    01558 class ratDVDNavigator {};
    01559
    01560 HRESULT CGraphBuilderDVD::Render(CString fn, CString& path)
    01561 {
    01562         if(!m_pGB) return E_INVALIDARG;
    01563
    01564         HRESULT hr;
    01565
    01566         GUID clsid = CLSID_DVDNavigator;
    01567         if(fn.MakeLower().Find(_T(".ratdvd")) >= 0)
    01568                 clsid = __uuidof(ratDVDNavigator);
    01569
    01570         CComPtr<IBaseFilter> pBF;
    01571         if(FAILED(hr = pBF.CoCreateInstance(clsid)))
    01572                 return E_FAIL;
    01573
    01574         if(FAILED(hr = m_pGB->AddFilter(pBF, L"DVD Navigator")))
    01575                 return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
    01576
    01577         CComQIPtr<IDvdControl2> pDVDC;
    01578         CComQIPtr<IDvdInfo2> pDVDI;
    01579
    01580         if(!((pDVDC = pBF) && (pDVDI = pBF)))
    01581                 return E_NOINTERFACE;
    01582
    01583         WCHAR buff[MAX_PATH];
    01584         ULONG len;
    01585         if((!fn.IsEmpty()
    01586                 && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn)))
    01587                 && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn + _T("VIDEO_TS"))))
    01588                 && FAILED(hr = pDVDC->SetDVDDirectory(CStringW(fn + _T("\\VIDEO_TS")))))
    01589         || FAILED(hr = pDVDI->GetDVDDirectory(buff, MAX_PATH, &len)) || len == 0)
    01590                 return VFW_E_CANNOT_LOAD_SOURCE_FILTER;
    01591
    01592         path = buff;
    01593
    01594         pDVDC->SetOption(DVD_ResetOnStop, FALSE);
    01595         pDVDC->SetOption(DVD_HMSF_TimeCodeEvents, TRUE);
    01596
    01597         m_pUnks.AddTail(pDVDC);
    01598         m_pUnks.AddTail(pDVDI);
    01599
    01600         if(clsid == CLSID_DVDNavigator)
    01601                 CResetDVD tmp(path);
    01602
    01603         return __super::Render(pBF);
    01604 }
    01605
    01606 //
    01607 // CGraphBuilderCapture
    01608 //
    01609
    01610 CGraphBuilderCapture::CGraphBuilderCapture(IGraphBuilder* pGB, HWND hWnd)
    01611         : CGraphBuilderFile(pGB, hWnd)
    01612 {
    01613         CList<GUID> guids;
    01614
    01615         // if(AfxGetAppSettings().fEnableDeinterlacer)
    01616         {
    01617                 guids.AddTail(MEDIATYPE_Video);
    01618                 guids.AddTail(MEDIASUBTYPE_NULL);
    01619                 AddFilter(new CGraphCustomFilter(__uuidof(CDeinterlacerFilter), guids, L"Deinterlacer", m_VRMerit + 0x100));
    01620                 guids.RemoveAll();
    01621         }
    01622
    01623         CLSID CLSID_MorganStreamSwitcher = GUIDFromCString(_T("{D3CD7858-971A-4838-ACEC-40CA5D529DC8}"));
    01624         AddFilter(new CGraphRegFilter(CLSID_MorganStreamSwitcher, LMERIT_DO_NOT_USE));
    01625 }
    01626
    01627 //
    01628 // CGraphFilter
    01629 //
    01630
    01631 CGraphFilter::CGraphFilter(CStringW name, ULONGLONG merit)
    01632         : m_name(name), m_clsid(GUID_NULL)
    01633 {
    01634         m_merit.val = merit;
    01635 }
    01636
    01637 bool CGraphFilter::IsExactMatch(CArray<GUID>& guids)
    01638 {
    01639         POSITION pos = m_guids.GetHeadPosition();
    01640         while(pos)
    01641         {
    01642                 GUID& major = m_guids.GetNext(pos);
    01643                 if(!pos) {ASSERT(0); break;}
    01644                 GUID& sub = m_guids.GetNext(pos);
    01645
    01646                 for(int i = 0; i < (guids.GetCount()&~1); i += 2)
    01647                 {
    01648                         if(major == guids[i] && major != GUID_NULL
    01649                         && sub == guids[i+1] && sub != GUID_NULL)
    01650                 return(true);
    01651                 }
    01652         }
    01653
    01654         return(false);
    01655 }
    01656
    01657 bool CGraphFilter::IsCompatible(CArray<GUID>& guids)
    01658 {
    01659         POSITION pos = m_guids.GetHeadPosition();
    01660         while(pos)
    01661         {
    01662                 GUID& major = m_guids.GetNext(pos);
    01663                 if(!pos) {ASSERT(0); break;}
    01664                 GUID& sub = m_guids.GetNext(pos);
    01665
    01666                 for(int i = 0; i < (guids.GetCount()&~1); i += 2)
    01667                 {
    01668                         if((major == GUID_NULL || guids[i] == GUID_NULL || major == guids[i])
    01669                         && (sub == GUID_NULL || guids[i+1] == GUID_NULL || sub == guids[i+1]))
    01670                 return(true);
    01671                 }
    01672         }
    01673
    01674         return(false);
    01675 }
    01676
    01677 //
    01678 // CGraphRegFilter
    01679 //
    01680
    01681 CGraphRegFilter::CGraphRegFilter(IMoniker* pMoniker, ULONGLONG merit)
    01682         : CGraphFilter(L"", merit), m_pMoniker(pMoniker)
    01683 {
    01684         if(!m_pMoniker) return;
    01685
    01686         LPOLESTR str = NULL;
    01687         if(FAILED(m_pMoniker->GetDisplayName(0, 0, &str))) return;
    01688         m_dispname = m_name = str;
    01689         CoTaskMemFree(str), str = NULL;
    01690
    01691         CComPtr<IPropertyBag> pPB;
    01692         if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
    01693         {
    01694                 CComVariant var;
    01695                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
    01696                 {
    01697                         m_name = var.bstrVal;
    01698                         var.Clear();
    01699                 }
    01700
    01701                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
    01702                 {
    01703                         CLSIDFromString(var.bstrVal, &m_clsid);
    01704                         var.Clear();
    01705                 }
    01706
    01707                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
    01708                 {
    01709                         BSTR* pstr;
    01710                         if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
    01711                         {
    01712                                 ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
    01713                                 SafeArrayUnaccessData(var.parray);
    01714                         }
    01715                         var.Clear();
    01716                 }
    01717         }
    01718
    01719         if(merit != LMERIT_DO_USE) m_merit.val = merit;
    01720 }
    01721
    01722 CGraphRegFilter::CGraphRegFilter(CStringW m_dispname, ULONGLONG merit)
    01723         : CGraphFilter(L"", merit), m_dispname(m_dispname)
    01724 {
    01725         if(m_dispname.IsEmpty()) return;
    01726
    01727         CComPtr<IBindCtx> pBC;
    01728         CreateBindCtx(0, &pBC);
    01729
    01730         ULONG chEaten;
    01731         if(S_OK != MkParseDisplayName(pBC, CComBSTR(m_dispname), &chEaten, &m_pMoniker))
    01732                 return;
    01733
    01734         CComPtr<IPropertyBag> pPB;
    01735         if(SUCCEEDED(m_pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPB)))
    01736         {
    01737                 CComVariant var;
    01738                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("FriendlyName")), &var, NULL)))
    01739                 {
    01740                         m_name = var.bstrVal;
    01741                         var.Clear();
    01742                 }
    01743
    01744                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("CLSID")), &var, NULL)))
    01745                 {
    01746                         CLSIDFromString(var.bstrVal, &m_clsid);
    01747                         var.Clear();
    01748                 }
    01749
    01750                 if(SUCCEEDED(pPB->Read(CComBSTR(_T("FilterData")), &var, NULL)))
    01751                 {
    01752                         BSTR* pstr;
    01753                         if(SUCCEEDED(SafeArrayAccessData(var.parray, (void**)&pstr)))
    01754                         {
    01755                                 ExtractFilterData((BYTE*)pstr, var.parray->cbElements*(var.parray->rgsabound[0].cElements));
    01756                                 SafeArrayUnaccessData(var.parray);
    01757                         }
    01758                         var.Clear();
    01759                 }
    01760         }
    01761
    01762         if(merit != LMERIT_DO_USE) m_merit.val = merit;
    01763 }
    01764
    01765 CGraphRegFilter::CGraphRegFilter(const CLSID& clsid, ULONGLONG merit)
    01766         : CGraphFilter(L"", merit)
    01767 {
    01768         if((m_clsid = clsid) == GUID_NULL) return;
    01769
    01770         CString guid = CStringFromGUID(m_clsid);
    01771         CString str = CString(_T("CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\Instance\\")) + guid;
    01772         CString str2 = CString(_T("CLSID\\")) + guid;
    01773
    01774         CRegKey key;
    01775
    01776         if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str2, KEY_READ))
    01777         {
    01778                 ULONG nChars = 0;
    01779                 if(ERROR_SUCCESS == key.QueryStringValue(NULL, NULL, &nChars))
    01780                 {
    01781                         CString name;
    01782                         if(ERROR_SUCCESS == key.QueryStringValue(NULL, name.GetBuffer(nChars), &nChars))
    01783                         {
    01784                                 name.ReleaseBuffer(nChars);
    01785                                 m_name = name;
    01786                         }
    01787                 }
    01788
    01789                 key.Close();
    01790         }
    01791
    01792         if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, str, KEY_READ))
    01793         {
    01794                 ULONG nChars = 0;
    01795                 if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), NULL, &nChars))
    01796                 {
    01797                         CString name;
    01798                         if(ERROR_SUCCESS == key.QueryStringValue(_T("FriendlyName"), name.GetBuffer(nChars), &nChars))
    01799                         {
    01800                                 name.ReleaseBuffer(nChars);
    01801                                 m_name = name;
    01802                         }
    01803                 }
    01804
    01805                 ULONG nBytes = 0;
    01806                 if(ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), NULL, &nBytes))
    01807                 {
    01808                         CAutoVectorPtr<BYTE> buff;
    01809                         if(buff.Allocate(nBytes) && ERROR_SUCCESS == key.QueryBinaryValue(_T("FilterData"), buff, &nBytes))
    01810                         {
    01811                                 ExtractFilterData(buff, nBytes);
    01812                         }
    01813                 }
    01814
    01815                 key.Close();
    01816         }
    01817
    01818         if(merit != LMERIT_DO_USE) m_merit.val = merit;
    01819 }
    01820
    01821 [uuid("97f7c4d4-547b-4a5f-8332-536430ad2e4d")]
    01822 interface IAMFilterData : public IUnknown
    01823 {
    01824         STDMETHOD (ParseFilterData) (BYTE* rgbFilterData, ULONG cb, BYTE** prgbRegFilter2) PURE;
    01825         STDMETHOD (CreateFilterData) (REGFILTER2* prf2, BYTE** prgbFilterData, ULONG* pcb) PURE;
    01826 };
    01827
    01828 void CGraphRegFilter::ExtractFilterData(BYTE* p, UINT len)
    01829 {
    01830         CComPtr<IAMFilterData> pFD;
    01831         BYTE* ptr = NULL;
    01832
    01833         if(SUCCEEDED(pFD.CoCreateInstance(CLSID_FilterMapper2))
    01834         && SUCCEEDED(pFD->ParseFilterData(p, len, (BYTE**)&ptr)))
    01835         {
    01836                 REGFILTER2* prf = (REGFILTER2*)*(DWORD*)ptr; // this is f*cked up
    01837
    01838                 m_merit.mid = prf->dwMerit;
    01839
    01840                 if(prf->dwVersion == 1)
    01841                 {
    01842                         for(UINT i = 0; i < prf->cPins; i++)
    01843                         {
    01844                                 if(prf->rgPins[i].bOutput)
    01845                                         continue;
    01846
    01847                                 for(UINT j = 0; j < prf->rgPins[i].nMediaTypes; j++)
    01848                                 {
    01849                                         if(!prf->rgPins[i].lpMediaType[j].clsMajorType || !prf->rgPins[i].lpMediaType[j].clsMinorType)
    01850                                                 break;
    01851                                         m_guids.AddTail(*(GUID*)prf->rgPins[i].lpMediaType[j].clsMajorType);
    01852                                         m_guids.AddTail(*(GUID*)prf->rgPins[i].lpMediaType[j].clsMinorType);
    01853                                 }
    01854                         }
    01855                 }
    01856                 else if(prf->dwVersion == 2)
    01857                 {
    01858                         for(UINT i = 0; i < prf->cPins2; i++)
    01859                         {
    01860                                 if(prf->rgPins2[i].dwFlags&REG_PINFLAG_B_OUTPUT)
    01861                                         continue;
    01862
    01863                                 for(UINT j = 0; j < prf->rgPins2[i].nMediaTypes; j++)
    01864                                 {
    01865                                         if(!prf->rgPins2[i].lpMediaType[j].clsMajorType || !prf->rgPins2[i].lpMediaType[j].clsMinorType)
    01866                                                 break;
    01867                                         m_guids.AddTail(*(GUID*)prf->rgPins2[i].lpMediaType[j].clsMajorType);
    01868                                         m_guids.AddTail(*(GUID*)prf->rgPins2[i].lpMediaType[j].clsMinorType);
    01869                                 }
    01870                         }
    01871                 }
    01872
    01873                 CoTaskMemFree(prf);
    01874         }
    01875         else
    01876         {
    01877                 BYTE* base = p;
    01878
    01879 #define ChkLen(size) if(p - base + size > (int)len) return;
    01880
    01881 ChkLen(4)
    01882                 if(*(DWORD*)p != 0x00000002) return; // only version 2 supported, no samples found for 1
    01883                 p += 4;
    01884
    01885 ChkLen(4)
    01886                 m_merit.mid = *(DWORD*)p; p += 4;
    01887
    01888                 m_guids.RemoveAll();
    01889
    01890 ChkLen(8)
    01891                 DWORD nPins = *(DWORD*)p; p += 8;
    01892                 while(nPins-- > 0)
    01893                 {
    01894 ChkLen(1)
    01895                         BYTE n = *p-0x30; p++;
    01896 ChkLen(2)
    01897                         WORD pi = *(WORD*)p; p += 2;
    01898                         ASSERT(pi == 'ip');
    01899 ChkLen(1)
    01900                         BYTE x33 = *p; p++;
    01901                         ASSERT(x33 == 0x33);
    01902 ChkLen(8)
    01903                         bool fOutput = !!(*p&REG_PINFLAG_B_OUTPUT);
    01904                         p += 8;
    01905 ChkLen(12)
    01906                         DWORD nTypes = *(DWORD*)p; p += 12;
    01907                         while(nTypes-- > 0)
    01908                         {
    01909 ChkLen(1)
    01910                                 BYTE n = *p-0x30; p++;
    01911 ChkLen(2)
    01912                                 WORD ty = *(WORD*)p; p += 2;
    01913                                 ASSERT(ty == 'yt');
    01914 ChkLen(5)
    01915                                 BYTE x33 = *p; p++;
    01916                                 ASSERT(x33 == 0x33);
    01917                                 p += 4;
    01918
    01919 ChkLen(8)
    01920                                 if(*(DWORD*)p < (p-base+8) || *(DWORD*)p >= len
    01921                                 || *(DWORD*)(p+4) < (p-base+8) || *(DWORD*)(p+4) >= len)
    01922                                 {
    01923                                         p += 8;
    01924                                         continue;
    01925                                 }
    01926
    01927                                 GUID guid;
    01928                                 memcpy(&guid, &base[*(DWORD*)p], sizeof(GUID)); p += 4;
    01929                                 if(!fOutput) m_guids.AddTail(guid);
    01930                                 memcpy(&guid, &base[*(DWORD*)p], sizeof(GUID)); p += 4;
    01931                                 if(!fOutput) m_guids.AddTail(guid);
    01932                         }
    01933                 }
    01934
    01935 #undef ChkLen
    01936
    01937         }
    01938 /*
    01939         if(CLSID_MMSPLITTER == m_clsid && m_merit.val == LMERIT(MERIT_NORMAL-1))
    01940         {
    01941                 m_merit.val = LMERIT(MERIT_NORMAL)+1; // take this mpeg2 demux...
    01942         }
    01943 */
    01944 }
    01945
    01946 HRESULT CGraphRegFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
    01947 {
    01948         CheckPointer(ppBF, E_POINTER);
    01949
    01950         if(ppUnk) *ppUnk = NULL;
    01951
    01952         HRESULT hr = E_FAIL;
    01953
    01954
    01955         if(m_pMoniker)
    01956         {
    01957                 if(SUCCEEDED(hr = m_pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppBF)))
    01958                         m_clsid = ::GetCLSID(*ppBF);
    01959         }
    01960         else if(m_clsid != GUID_NULL)
    01961         {
    01962                 CComPtr<IBaseFilter> pBF;
    01963                 if(FAILED(pBF.CoCreateInstance(m_clsid))) return E_FAIL;
    01964                 *ppBF = pBF.Detach();
    01965                 hr = S_OK;
    01966         }
    01967
    01968         return hr;
    01969 };
    01970
    01971 //
    01972 // CGraphCustomFilter
    01973 //
    01974
    01975 CGraphCustomFilter::CGraphCustomFilter(const CLSID& clsid, CList<GUID>& guids, CStringW name, ULONGLONG merit)
    01976         : CGraphFilter(name, merit)
    01977 {
    01978         m_clsid = clsid;
    01979         ASSERT(guids.GetCount() > 0);
    01980         m_guids.AddTail(&guids);
    01981 }
    01982
    01983 HRESULT CGraphCustomFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
    01984 {
    01985         CheckPointer(ppBF, E_POINTER);
    01986
    01987         if(ppUnk) *ppUnk = NULL;
    01988
    01989         HRESULT hr = S_OK;
    01990
    01991         *ppBF =
    01992                 m_clsid == __uuidof(CAVI2AC3Filter) ? (IBaseFilter*)new CAVI2AC3Filter(NULL, &hr) :
    01993                 m_clsid == __uuidof(CDeCSSFilter) ? (IBaseFilter*)new CDeCSSFilter(NULL, &hr) :
    01994                 m_clsid == __uuidof(CAudioSwitcherFilter) ? (IBaseFilter*)new CAudioSwitcherFilter(NULL, &hr) :
    01995                 m_clsid == __uuidof(CMatroskaSplitterFilter) ? (IBaseFilter*)new CMatroskaSplitterFilter(NULL, &hr) :
    01996                 m_clsid == __uuidof(CRealMediaSplitterFilter) ? (IBaseFilter*)new CRealMediaSplitterFilter(NULL, &hr) :
    01997                 m_clsid == __uuidof(CRealVideoDecoder) ? (IBaseFilter*)new CRealVideoDecoder(NULL, &hr) :
    01998                 m_clsid == __uuidof(CRealAudioDecoder) ? (IBaseFilter*)new CRealAudioDecoder(NULL, &hr) :
    01999                 m_clsid == __uuidof(CRoQVideoDecoder) ? (IBaseFilter*)new CRoQVideoDecoder(NULL, &hr) :
    02000                 m_clsid == __uuidof(CRoQAudioDecoder) ? (IBaseFilter*)new CRoQAudioDecoder(NULL, &hr) :
    02001                 m_clsid == __uuidof(CAviSplitterFilter) ? (IBaseFilter*)new CAviSplitterFilter(NULL, &hr) :
    02002                 m_clsid == __uuidof(CRoQSplitterFilter) ? (IBaseFilter*)new CRoQSplitterFilter(NULL, &hr) :
    02003                 m_clsid == __uuidof(COggSplitterFilter) ? (IBaseFilter*)new COggSplitterFilter(NULL, &hr) :
    02004                 m_clsid == __uuidof(CNutSplitterFilter) ? (IBaseFilter*)new CNutSplitterFilter(NULL, &hr) :
    02005                 m_clsid == __uuidof(CMpegSplitterFilter) ? (IBaseFilter*)new CMpegSplitterFilter(NULL, &hr) :
    02006                 m_clsid == __uuidof(CMpeg2DecFilter) ? (IBaseFilter*)new CMpeg2DecFilter(NULL, &hr) :
    02007                 m_clsid == __uuidof(CDiracSplitterFilter) ? (IBaseFilter*)new CDiracSplitterFilter(NULL, &hr) :
    02008                 m_clsid == __uuidof(CDiracVideoDecoder) ? (IBaseFilter*)new CDiracVideoDecoder(NULL, &hr) :
    02009                 m_clsid == __uuidof(CMpaSplitterFilter) ? (IBaseFilter*)new CMpaSplitterFilter(NULL, &hr) :
    02010                 m_clsid == __uuidof(CMpaDecFilter) ? (IBaseFilter*)new CMpaDecFilter(NULL, &hr) :
    02011                 m_clsid == __uuidof(CDSMSplitterFilter) ? (IBaseFilter*)new CDSMSplitterFilter(NULL, &hr) :
    02012                 m_clsid == __uuidof(CMP4SplitterFilter) ? (IBaseFilter*)new CMP4SplitterFilter(NULL, &hr) :
    02013                 m_clsid == __uuidof(CNullVideoRenderer) ? (IBaseFilter*)new CNullVideoRenderer() :
    02014                 m_clsid == __uuidof(CNullAudioRenderer) ? (IBaseFilter*)new CNullAudioRenderer() :
    02015                 m_clsid == __uuidof(CNullUVideoRenderer) ? (IBaseFilter*)new CNullUVideoRenderer() :
    02016                 m_clsid == __uuidof(CNullUAudioRenderer) ? (IBaseFilter*)new CNullUAudioRenderer() :
    02017                 m_clsid == __uuidof(CNullTextRenderer) ? (IBaseFilter*)new CNullTextRenderer(NULL, &hr) :
    02018                 m_clsid == __uuidof(CDeinterlacerFilter) ? (IBaseFilter*)new CDeinterlacerFilter(NULL, &hr) :
    02019                 NULL;
    02020
    02021         __if_exists(CRadGtSplitterFilter)
    02022         {
    02023                 if(*ppBF == NULL && m_clsid == __uuidof(CRadGtSplitterFilter))
    02024                          *ppBF = (IBaseFilter*)new CRadGtSplitterFilter(NULL, &hr);
    02025         }
    02026
    02027         if(!*ppBF) hr = E_FAIL;
    02028         else (*ppBF)->AddRef();
    02029
    02030         if(!*ppBF)
    02031         {
    02032                 CComPtr<IBaseFilter> pBF;
    02033                 if(SUCCEEDED(hr = pBF.CoCreateInstance(m_clsid)))
    02034                         *ppBF = pBF.Detach();
    02035         }
    02036
    02037         if(SUCCEEDED(hr) && ppUnk)
    02038         {
    02039                 if(m_clsid == __uuidof(CAudioSwitcherFilter))
    02040                 {
    02041                         *ppUnk = (IUnknown*)CComQIPtr<IAudioSwitcherFilter>(*ppBF).Detach();
    02042                         CComQIPtr<IAudioSwitcherFilter> pASF = *ppUnk;
    02043
    02044                         if(pASF)
    02045                         {
    02046                                 AppSettings& s = AfxGetAppSettings();
    02047                                 pASF->SetSpeakerConfig(s.fCustomChannelMapping, s.pSpeakerToChannelMap);
    02048                                 pASF->EnableDownSamplingTo441(s.fDownSampleTo441);
    02049                                 pASF->SetAudioTimeShift(s.fAudioTimeShift ? 10000i64*s.tAudioTimeShift : 0);
    02050                         }
    02051                 }
    02052         }
    02053
    02054         return hr;
    02055 }
    02056
    02057 //
    02058 // CGraphFileFilter
    02059 //
    02060
    02061 CGraphFileFilter::CGraphFileFilter(const CLSID& clsid, CList<GUID>& guids, CString path, CStringW name, ULONGLONG merit)
    02062         : CGraphCustomFilter(clsid, guids, name, merit), m_path(path), m_hInst(NULL)
    02063 {
    02064 }
    02065
    02066 HRESULT CGraphFileFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
    02067 {
    02068         CheckPointer(ppBF, E_POINTER);
    02069
    02070         if(ppUnk) *ppUnk = NULL;
    02071
    02072         HRESULT hr = S_OK;
    02073
    02074         if(SUCCEEDED(hr = __super::Create(ppBF, ppUnk)))
    02075                 return hr;
    02076
    02077         return LoadExternalFilter(m_path, m_clsid, ppBF);
    02078 }
    02079
    02080 //
    02081 // CGraphRendererFilter
    02082 //
    02083
    02084 CGraphRendererFilter::CGraphRendererFilter(const CLSID& clsid, HWND hWnd, CStringW name, ULONGLONG merit)
    02085         : CGraphFilter(name, merit), m_clsid(clsid), m_hWnd(hWnd)
    02086 {
    02087         m_guids.AddTail(MEDIATYPE_Video);
    02088         m_guids.AddTail(MEDIASUBTYPE_NULL);
    02089 }
    02090
    02091 HRESULT CGraphRendererFilter::Create(IBaseFilter** ppBF, IUnknown** ppUnk)
    02092 {
    02093         CheckPointer(ppBF, E_POINTER);
    02094
    02095         HRESULT hr = S_OK;
    02096
    02097         if(m_clsid == CLSID_OverlayMixer)
    02098         {
    02099                 CComPtr<IBaseFilter> pBF;
    02100                 if(SUCCEEDED(pBF.CoCreateInstance(CLSID_OverlayMixer)))
    02101                 {
    02102                         BeginEnumPins(pBF, pEP, pPin)
    02103                         {
    02104                                 if(CComQIPtr<IMixerPinConfig, &IID_IMixerPinConfig> pMPC = pPin)
    02105                                 {
    02106                                         if(ppUnk) *ppUnk = pMPC.Detach();
    02107                                         break;
    02108                                 }
    02109                         }
    02110                         EndEnumPins
    02111
    02112                         *ppBF = pBF.Detach();
    02113                 }
    02114         }
    02115         else if(m_clsid == CLSID_VideoMixingRenderer)
    02116         {
    02117                 CComPtr<IBaseFilter> pBF;
    02118                 if(SUCCEEDED(pBF.CoCreateInstance(CLSID_VideoMixingRenderer)))
    02119                         *ppBF = pBF.Detach();
    02120         }
    02121         else if(m_clsid == CLSID_VideoMixingRenderer9)
    02122         {
    02123                 CComPtr<IBaseFilter> pBF;
    02124                 if(SUCCEEDED(pBF.CoCreateInstance(CLSID_VideoMixingRenderer9)))
    02125                         *ppBF = pBF.Detach();
    02126         }
    02127         else if(m_clsid == CLSID_VMR7AllocatorPresenter)
    02128         {
    02129                 CComPtr<ISubPicAllocatorPresenter> pCAP;
    02130                 CComPtr<IUnknown> pRenderer;
    02131                 if(SUCCEEDED(hr = CreateAP7(CLSID_VMR7AllocatorPresenter, m_hWnd, &pCAP))
    02132                 && SUCCEEDED(hr = pCAP->CreateRenderer(&pRenderer)))
    02133                 {
    02134                         *ppBF = CComQIPtr<IBaseFilter>(pRenderer).Detach();
    02135                         if(ppUnk) *ppUnk = (IUnknown*)pCAP.Detach();
    02136                 }
    02137         }
    02138         else if(m_clsid == CLSID_VMR9AllocatorPresenter)
    02139         {
    02140                 CComPtr<ISubPicAllocatorPresenter> pCAP;
    02141                 CComPtr<IUnknown> pRenderer;
    02142                 if(SUCCEEDED(hr = CreateAP9(CLSID_VMR9AllocatorPresenter, m_hWnd, &pCAP))
    02143                 && SUCCEEDED(hr = pCAP->CreateRenderer(&pRenderer)))
    02144                 {
    02145                         *ppBF = CComQIPtr<IBaseFilter>(pRenderer).Detach();
    02146                         if(ppUnk) *ppUnk = (IUnknown*)pCAP.Detach();
    02147                 }
    02148         }
    02149
    02150         if(!*ppBF) hr = E_FAIL;
    02151
    02152         return hr;
    02153 }
    02154