DSMSplitter.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 "DSMSplitter.h"
00024 #include "..\..\..\DSUtil\DSUtil.h"
00025 
00026 #include <initguid.h>
00027 #include "..\..\..\..\include\moreuuids.h"
00028 
00029 #ifdef REGISTER_FILTER
00030 
00031 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00032 {
00033         {&MEDIATYPE_Stream, &MEDIASUBTYPE_DirectShowMedia},
00034         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
00035 };
00036 
00037 const AMOVIESETUP_PIN sudpPins[] =
00038 {
00039         {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00040         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00041 };
00042 
00043 const AMOVIESETUP_FILTER sudFilter[] =
00044 {
00045         {&__uuidof(CDSMSplitterFilter), L"DSM Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
00046         {&__uuidof(CDSMSourceFilter), L"DSM Source", MERIT_NORMAL, 0, NULL},
00047 };
00048 
00049 CFactoryTemplate g_Templates[] =
00050 {
00051         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CDSMSplitterFilter>, NULL, &sudFilter[0]},
00052         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CDSMSourceFilter>, NULL, &sudFilter[1]},
00053 };
00054 
00055 int g_cTemplates = countof(g_Templates);
00056 
00057 STDAPI DllRegisterServer()
00058 {
00059         CString str;
00060         str.Format(_T("0,%d,,%%0%dI64x"), DSMSW_SIZE, DSMSW_SIZE*2);
00061         str.Format(CString(str), DSMSW);
00062 
00063         RegisterSourceFilter(
00064                 CLSID_AsyncReader, 
00065                 MEDIASUBTYPE_DirectShowMedia, 
00066                 str, NULL);
00067 
00068         return AMovieDllRegisterServer2(TRUE);
00069 }
00070 
00071 STDAPI DllUnregisterServer()
00072 {
00073         UnRegisterSourceFilter(MEDIASUBTYPE_DirectShowMedia);
00074 
00075         return AMovieDllRegisterServer2(FALSE);
00076 }
00077 
00078 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00079 
00080 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00081 {
00082     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00083 }
00084 
00085 #endif
00086 
00087 //
00088 // CDSMSplitterFilter
00089 //
00090 
00091 CDSMSplitterFilter::CDSMSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00092         : CBaseSplitterFilter(NAME("CDSMSplitterFilter"), pUnk, phr, __uuidof(this))
00093 {
00094 }
00095 
00096 CDSMSplitterFilter::~CDSMSplitterFilter()
00097 {
00098 }
00099 
00100 static int compare_id(const void* id1, const void* id2) {return (int)*(BYTE*)id1 - (int)*(BYTE*)id2;}
00101 
00102 HRESULT CDSMSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00103 {
00104         CheckPointer(pAsyncReader, E_POINTER);
00105 
00106         HRESULT hr = E_FAIL;
00107 
00108         m_pFile.Free();
00109         m_pFile.Attach(new CDSMSplitterFile(pAsyncReader, hr, *this, *this));
00110         if(!m_pFile) return E_OUTOFMEMORY;
00111         if(FAILED(hr)) {m_pFile.Free(); return hr;}
00112 
00113         m_rtNewStart = m_rtCurrent = 0;
00114         m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->m_rtDuration;
00115 
00116         CArray<BYTE> ids;
00117 
00118         POSITION pos = m_pFile->m_mts.GetStartPosition();
00119         while(pos)
00120         {
00121                 BYTE id;
00122                 CMediaType mt;
00123                 m_pFile->m_mts.GetNextAssoc(pos, id, mt);
00124                 ids.Add(id);
00125         }
00126 
00127         qsort(ids.GetData(), ids.GetCount(), sizeof(BYTE), compare_id);
00128 
00129         for(int i = 0; i < ids.GetCount(); i++)
00130         {
00131                 BYTE id = ids[i];
00132                 CMediaType& mt = m_pFile->m_mts[id];
00133 
00134                 CStringW name, lang;
00135                 name.Format(L"Output %02d", id);
00136 
00137                 CArray<CMediaType> mts;
00138                 mts.Add(mt);
00139 
00140                 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, name, this, this, &hr));
00141         
00142                 name.Empty();
00143 
00144                 pos = m_pFile->m_sim[id].GetStartPosition();
00145                 while(pos)
00146                 {
00147                         CStringA key; CStringW value;
00148                         m_pFile->m_sim[id].GetNextAssoc(pos, key, value);
00149                         pPinOut->SetProperty(CStringW(key), value);
00150 
00151                         if(key == "NAME") name = value;
00152                         if(key == "LANG") if((lang = ISO6392ToLanguage(CStringA(CString(value)))).IsEmpty()) lang = value;
00153                 }
00154 
00155                 if(!name.IsEmpty() || !lang.IsEmpty())
00156                 {
00157                         if(!name.IsEmpty()) {if(!lang.IsEmpty()) name += L" (" + lang + L")";}
00158                         else if(!lang.IsEmpty()) name = lang;
00159                         pPinOut->SetName(name);
00160                 }
00161 
00162                 EXECUTE_ASSERT(SUCCEEDED(AddOutputPin(id, pPinOut)));
00163         }
00164 
00165         pos = m_pFile->m_fim.GetStartPosition();
00166         while(pos)
00167         {
00168                 CStringA key; CStringW value;
00169                 m_pFile->m_fim.GetNextAssoc(pos, key, value);
00170                 SetProperty(CStringW(key), value);
00171         }
00172 
00173         for(int i = 0; i < m_resources.GetCount(); i++)
00174         {
00175                 const CDSMResource& r = m_resources[i];
00176                 if(r.mime == "application/x-truetype-font")
00177                         m_fontinst.InstallFont(r.data);
00178         }
00179 
00180         return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00181 }
00182 
00183 bool CDSMSplitterFilter::DemuxInit()
00184 {
00185         return(true);
00186 }
00187 
00188 void CDSMSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00189 {
00190         m_pFile->Seek(m_pFile->FindSyncPoint(rt));
00191 }
00192 
00193 bool CDSMSplitterFilter::DemuxLoop()
00194 {
00195         HRESULT hr = S_OK;
00196 
00197         while(SUCCEEDED(hr) && !CheckRequest(NULL) && m_pFile->GetPos() < m_pFile->GetLength())
00198         {
00199                 dsmp_t type;
00200                 UINT64 len;
00201 
00202                 if(!m_pFile->Sync(type, len))
00203                         continue;
00204 
00205                 __int64 pos = m_pFile->GetPos();
00206 
00207                 if(type == DSMP_SAMPLE)
00208                 {
00209                         CAutoPtr<Packet> p(new Packet());
00210                         if(m_pFile->Read(len, p))
00211                         {
00212                                 if(p->rtStart != Packet::INVALID_TIME)
00213                                 {
00214                                         p->rtStart -= m_pFile->m_rtFirst;
00215                                         p->rtStop -= m_pFile->m_rtFirst;
00216                                 }
00217 
00218                                 hr = DeliverPacket(p);
00219                         }
00220                 }
00221 
00222                 m_pFile->Seek(pos + len);
00223         }
00224 
00225         return(true);
00226 }
00227 
00228 // IKeyFrameInfo
00229 
00230 STDMETHODIMP CDSMSplitterFilter::GetKeyFrameCount(UINT& nKFs)
00231 {
00232         CheckPointer(m_pFile, E_UNEXPECTED);
00233         nKFs = m_pFile->m_sps.GetCount();
00234         return S_OK;
00235 }
00236 
00237 STDMETHODIMP CDSMSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
00238 {
00239         CheckPointer(pFormat, E_POINTER);
00240         CheckPointer(pKFs, E_POINTER);
00241         CheckPointer(m_pFile, E_UNEXPECTED);
00242 
00243         if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
00244 
00245         // these aren't really the keyframes, but quicky accessable points in the stream
00246         for(nKFs = 0; nKFs < m_pFile->m_sps.GetCount(); nKFs++)
00247                 pKFs[nKFs] = m_pFile->m_sps[nKFs].rt;
00248 
00249         return S_OK;
00250 }
00251 
00252 //
00253 // CDSMSourceFilter
00254 //
00255 
00256 CDSMSourceFilter::CDSMSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
00257         : CDSMSplitterFilter(pUnk, phr)
00258 {
00259         m_clsid = __uuidof(this);
00260         m_pInput.Free();
00261 }

Generated on Tue Dec 13 14:47:18 2005 for guliverkli by  doxygen 1.4.5