- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }