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 

Generated on Tue Dec 13 14:46:51 2005 for guliverkli by  doxygen 1.4.5