- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# MpegSplitter.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 <mmreg.h>
    00024 #include <initguid.h>
    00025 #include "MpegSplitter.h"
    00026 #include "..\..\..\..\include\moreuuids.h"
    00027
    00028 #ifdef REGISTER_FILTER
    00029
    00030 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
    00031 {
    00032         {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System},
    00033 //      {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD}, // cdxa filter should take care of this
    00034         {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_PROGRAM},
    00035         {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_TRANSPORT},
    00036         {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_PVA},
    00037         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
    00038 };
    00039
    00040 const AMOVIESETUP_PIN sudpPins[] =
    00041 {
    00042     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
    00043     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL},
    00044 };
    00045
    00046 const AMOVIESETUP_FILTER sudFilter[] =
    00047 {
    00048         {&__uuidof(CMpegSplitterFilter), L"Mpeg Splitter", MERIT_NORMAL+1 /*MERIT_DO_NOT_USE*/, countof(sudpPins), sudpPins},
    00049         {&__uuidof(CMpegSourceFilter), L"Mpeg Source", MERIT_DO_NOT_USE, 0, NULL},
    00050 };
    00051
    00052 CFactoryTemplate g_Templates[] =
    00053 {
    00054         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMpegSplitterFilter>, NULL, &sudFilter[0]},
    00055         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CMpegSourceFilter>, NULL, &sudFilter[1]},
    00056 };
    00057
    00058 int g_cTemplates = countof(g_Templates);
    00059
    00060 STDAPI DllRegisterServer()
    00061 {
    00062         RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG1System, _T("0,16,FFFFFFFFF100010001800001FFFFFFFF,000001BA2100010001800001000001BB"), NULL);
    00063         RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_PROGRAM, _T("0,5,FFFFFFFFC0,000001BA40"), NULL);
    00064         RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_TRANSPORT, _T("0,4,,47,188,4,,47,376,4,,47"), NULL);
    00065         RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_PVA, _T("0,8,fffffc00ffe00000,4156000055000000"), NULL);
    00066
    00067         return AMovieDllRegisterServer2(TRUE);
    00068 }
    00069
    00070 STDAPI DllUnregisterServer()
    00071 {
    00072 //      UnRegisterSourceFilter(MEDIASUBTYPE_MPEG1System);
    00073 //      UnRegisterSourceFilter(MEDIASUBTYPE_MPEG2_PROGRAM);
    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 // CMpegSplitterFilter
    00089 //
    00090
    00091 CMpegSplitterFilter::CMpegSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr, const CLSID& clsid)
    00092         : CBaseSplitterFilter(NAME("CMpegSplitterFilter"), pUnk, phr, clsid)
    00093 {
    00094 }
    00095
    00096 STDMETHODIMP CMpegSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00097 {
    00098     CheckPointer(ppv, E_POINTER);
    00099
    00100     return
    00101                 QI(IAMStreamSelect)
    00102                 __super::NonDelegatingQueryInterface(riid, ppv);
    00103 }
    00104
    00105 //
    00106
    00107 HRESULT CMpegSplitterFilter::DemuxNextPacket(REFERENCE_TIME rtStartOffset)
    00108 {
    00109         HRESULT hr;
    00110         BYTE b;
    00111
    00112         if(m_pFile->m_type == CMpegSplitterFile::ps || m_pFile->m_type == CMpegSplitterFile::es)
    00113         {
    00114                 if(!m_pFile->NextMpegStartCode(b))
    00115                         return S_FALSE;
    00116
    00117                 if(b == 0xba) // program stream header
    00118                 {
    00119                         CMpegSplitterFile::pshdr h;
    00120                         if(!m_pFile->Read(h)) return S_FALSE;
    00121                 }
    00122                 else if(b == 0xbb) // program stream system header
    00123                 {
    00124                         CMpegSplitterFile::pssyshdr h;
    00125                         if(!m_pFile->Read(h)) return S_FALSE;
    00126                 }
    00127                 else if(b >= 0xbd && b < 0xf0) // pes packet
    00128                 {
    00129                         CMpegSplitterFile::peshdr h;
    00130                         if(!m_pFile->Read(h, b) || !h.len) return S_FALSE;
    00131
    00132                         if(h.type == CMpegSplitterFile::mpeg2 && h.scrambling) {ASSERT(0); return E_FAIL;}
    00133
    00134                         __int64 pos = m_pFile->GetPos();
    00135
    00136                         DWORD TrackNumber = m_pFile->AddStream(0, b, h.len);
    00137
    00138                         if(GetOutputPin(TrackNumber))
    00139                         {
    00140                                 CAutoPtr<Packet> p(new Packet());
    00141                                 p->TrackNumber = TrackNumber;
    00142                                 p->bSyncPoint = !!h.fpts;
    00143                                 p->bAppendable = !h.fpts;
    00144                                 p->rtStart = h.fpts ? (h.pts - rtStartOffset) : Packet::INVALID_TIME;
    00145                                 p->rtStop = p->rtStart+1;
    00146                                 p->pData.SetSize(h.len - (m_pFile->GetPos() - pos));
    00147                                 m_pFile->ByteRead(p->pData.GetData(), h.len - (m_pFile->GetPos() - pos));
    00148                                 hr = DeliverPacket(p);
    00149                         }
    00150
    00151                         m_pFile->Seek(pos + h.len);
    00152                 }
    00153         }
    00154         else if(m_pFile->m_type == CMpegSplitterFile::ts)
    00155         {
    00156                 CMpegSplitterFile::trhdr h;
    00157                 if(!m_pFile->Read(h))
    00158                         return S_FALSE;
    00159
    00160                 if(h.scrambling) {ASSERT(0); return S_FALSE;}
    00161
    00162                 __int64 pos = m_pFile->GetPos();
    00163
    00164                 if(h.payload && h.pid >= 16 && h.pid < 0x1fff)
    00165                 {
    00166                         DWORD TrackNumber = h.pid;
    00167
    00168                         CMpegSplitterFile::peshdr h2;
    00169                         if(h.payloadstart && m_pFile->NextMpegStartCode(b, 4) && m_pFile->Read(h2, b)) // pes packet
    00170                         {
    00171                                 if(h2.type == CMpegSplitterFile::mpeg2 && h2.scrambling) {ASSERT(0); return E_FAIL;}
    00172                                 TrackNumber = m_pFile->AddStream(h.pid, b, h.bytes - (m_pFile->GetPos() - pos));
    00173                         }
    00174
    00175                         if(GetOutputPin(TrackNumber))
    00176                         {
    00177                                 CAutoPtr<Packet> p(new Packet());
    00178                                 p->TrackNumber = TrackNumber;
    00179                                 p->bSyncPoint = !!h2.fpts;
    00180                                 p->bAppendable = !h2.fpts;
    00181                                 p->rtStart = h2.fpts ? (h2.pts - rtStartOffset) : Packet::INVALID_TIME;
    00182                                 p->rtStop = p->rtStart+1;
    00183                                 p->pData.SetSize(h.bytes - (m_pFile->GetPos() - pos));
    00184                                 m_pFile->ByteRead(p->pData.GetData(), h.bytes - (m_pFile->GetPos() - pos));
    00185                                 hr = DeliverPacket(p);
    00186                         }
    00187                 }
    00188
    00189                 m_pFile->Seek(h.next);
    00190         }
    00191         else if(m_pFile->m_type == CMpegSplitterFile::pva)
    00192         {
    00193                 CMpegSplitterFile::pvahdr h;
    00194                 if(!m_pFile->Read(h))
    00195                         return S_FALSE;
    00196
    00197                 DWORD TrackNumber = h.streamid;
    00198
    00199                 __int64 pos = m_pFile->GetPos();
    00200
    00201                 if(GetOutputPin(TrackNumber))
    00202                 {
    00203                         CAutoPtr<Packet> p(new Packet());
    00204                         p->TrackNumber = TrackNumber;
    00205                         p->bSyncPoint = !!h.fpts;
    00206                         p->bAppendable = !h.fpts;
    00207                         p->rtStart = h.fpts ? (h.pts - rtStartOffset) : Packet::INVALID_TIME;
    00208                         p->rtStop = p->rtStart+1;
    00209                         p->pData.SetSize(h.length);
    00210                         m_pFile->ByteRead(p->pData.GetData(), h.length);
    00211                         hr = DeliverPacket(p);
    00212                 }
    00213
    00214                 m_pFile->Seek(pos + h.length);
    00215         }
    00216
    00217         return S_OK;
    00218 }
    00219
    00220 //
    00221
    00222 HRESULT CMpegSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
    00223 {
    00224         CheckPointer(pAsyncReader, E_POINTER);
    00225
    00226         HRESULT hr = E_FAIL;
    00227
    00228         m_pFile.Free();
    00229
    00230         m_pFile.Attach(new CMpegSplitterFile(pAsyncReader, hr));
    00231         if(!m_pFile) return E_OUTOFMEMORY;
    00232         if(FAILED(hr)) {m_pFile.Free(); return hr;}
    00233
    00234         //
    00235
    00236         m_rtNewStart = m_rtCurrent = 0;
    00237         m_rtNewStop = m_rtStop = m_rtDuration = 0;
    00238
    00239         for(int i = 0; i < countof(m_pFile->m_streams); i++)
    00240         {
    00241                 POSITION pos = m_pFile->m_streams[i].GetHeadPosition();
    00242                 while(pos)
    00243                 {
    00244                         CMpegSplitterFile::stream& s = m_pFile->m_streams[i].GetNext(pos);
    00245
    00246                         CArray<CMediaType> mts;
    00247                         mts.Add(s.mt);
    00248
    00249                         CStringW name = CMpegSplitterFile::CStreamList::ToString(i);
    00250
    00251                         HRESULT hr;
    00252                         CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CMpegSplitterOutputPin(mts, name, this, this, &hr));
    00253                         if(S_OK == AddOutputPin(s, pPinOut))
    00254                                 break;
    00255                 }
    00256         }
    00257
    00258         m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->IsStreaming() ? 0 : 10000000i64 * m_pFile->GetLength() / m_pFile->m_rate;
    00259
    00260         return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
    00261 }
    00262
    00263 bool CMpegSplitterFilter::DemuxInit()
    00264 {
    00265         if(!m_pFile) return(false);
    00266
    00267         m_rtStartOffset = 0;
    00268
    00269         return(true);
    00270 }
    00271
    00272 void CMpegSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
    00273 {
    00274         CList<CMpegSplitterFile::stream>* pMasterStream =
    00275                 !m_pFile->m_streams[CMpegSplitterFile::video].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::video] :
    00276                 !m_pFile->m_streams[CMpegSplitterFile::audio].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::audio] :
    00277                 !m_pFile->m_streams[CMpegSplitterFile::subpic].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::subpic] :
    00278                 NULL;
    00279
    00280         if(!pMasterStream) {ASSERT(0); return;}
    00281
    00282         if(m_pFile->IsStreaming())
    00283         {
    00284                 m_pFile->Seek(max(0, m_pFile->GetLength() - 100*1024));
    00285                 m_rtStartOffset = m_pFile->m_rtMin + m_pFile->NextPTS(pMasterStream->GetHead());
    00286                 return;
    00287         }
    00288
    00289         REFERENCE_TIME rtPreroll = 10000000;
    00290
    00291         if(rt <= rtPreroll || m_rtDuration <= 0)
    00292         {
    00293                 m_pFile->Seek(0);
    00294         }
    00295         else
    00296         {
    00297                 __int64 len = m_pFile->GetLength();
    00298                 __int64 seekpos = (__int64)(1.0*rt/m_rtDuration*len);
    00299                 __int64 minseekpos = _I64_MAX;
    00300
    00301                 REFERENCE_TIME rtmax = rt - rtPreroll;
    00302                 REFERENCE_TIME rtmin = rtmax - 5000000;
    00303
    00304                 if(m_rtStartOffset == 0)
    00305                 for(int i = 0; i < countof(m_pFile->m_streams)-1; i++)
    00306                 {
    00307                         POSITION pos = m_pFile->m_streams[i].GetHeadPosition();
    00308                         while(pos)
    00309                         {
    00310                                 DWORD TrackNum = m_pFile->m_streams[i].GetNext(pos);
    00311
    00312                                 CBaseSplitterOutputPin* pPin = GetOutputPin(TrackNum);
    00313                                 if(pPin && pPin->IsConnected())
    00314                                 {
    00315                                         m_pFile->Seek(seekpos);
    00316
    00317                                         REFERENCE_TIME pdt = _I64_MIN;
    00318
    00319                                         for(int j = 0; j < 10; j++)
    00320                                         {
    00321                                                 REFERENCE_TIME rt = m_pFile->NextPTS(TrackNum);
    00322                                                 // TRACE(_T("[%d/%04x]: rt=%I64d, fp=%I64d\n"), i, TrackNum, rt, m_pFile->GetPos());
    00323
    00324                                                 if(rt < 0) break;
    00325
    00326                                                 REFERENCE_TIME dt = rt - rtmax;
    00327                                                 if(dt > 0 && dt == pdt) dt = 10000000i64;
    00328
    00329                                                 // TRACE(_T("dt=%I64d\n"), dt);
    00330
    00331                                                 if(rtmin <= rt && rt <= rtmax || pdt > 0 && dt < 0)
    00332                                                 {
    00333                                                         // TRACE(_T("minseekpos: %I64d -> "), minseekpos);
    00334                                                         minseekpos = min(minseekpos, m_pFile->GetPos());
    00335                                                         // TRACE(_T("%I64d\n"), minseekpos);
    00336                                                         break;
    00337                                                 }
    00338
    00339                                                 m_pFile->Seek(m_pFile->GetPos() - (__int64)(1.0*dt/m_rtDuration*len));
    00340
    00341                                                 pdt = dt;
    00342                                         }
    00343                                 }
    00344                         }
    00345                 }
    00346
    00347                 if(minseekpos != _I64_MAX)
    00348                 {
    00349                         seekpos = minseekpos;
    00350                 }
    00351                 else
    00352                 {
    00353                         // this file is probably screwed up, try plan B, seek simply by bitrate
    00354
    00355                         rt -= rtPreroll;
    00356                         seekpos = (__int64)(1.0*rt/m_rtDuration*len);
    00357                         m_pFile->Seek(seekpos);
    00358                         m_rtStartOffset = m_pFile->m_rtMin + m_pFile->NextPTS(pMasterStream->GetHead()) - rt;
    00359                 }
    00360
    00361                 m_pFile->Seek(seekpos);
    00362         }
    00363 }
    00364
    00365 bool CMpegSplitterFilter::DemuxLoop()
    00366 {
    00367         REFERENCE_TIME rtStartOffset = m_rtStartOffset ? m_rtStartOffset : m_pFile->m_rtMin;
    00368
    00369         HRESULT hr = S_OK;
    00370         while(SUCCEEDED(hr) && !CheckRequest(NULL))
    00371         {
    00372                 if((hr = m_pFile->HasMoreData(1024*500)) == S_OK)
    00373                         if((hr = DemuxNextPacket(rtStartOffset)) == S_FALSE)
    00374                                 Sleep(1);
    00375         }
    00376
    00377         return(true);
    00378 }
    00379
    00380 // IAMStreamSelect
    00381
    00382 STDMETHODIMP CMpegSplitterFilter::Count(DWORD* pcStreams)
    00383 {
    00384         CheckPointer(pcStreams, E_POINTER);
    00385
    00386         *pcStreams = 0;
    00387         for(int i = 0; i < countof(m_pFile->m_streams); i++)
    00388                 (*pcStreams) += m_pFile->m_streams[i].GetCount();
    00389
    00390         return S_OK;
    00391 }
    00392
    00393 STDMETHODIMP CMpegSplitterFilter::Enable(long lIndex, DWORD dwFlags)
    00394 {
    00395         if(!(dwFlags & AMSTREAMSELECTENABLE_ENABLE))
    00396                 return E_NOTIMPL;
    00397
    00398         for(int i = 0, j = 0; i < countof(m_pFile->m_streams); i++)
    00399         {
    00400                 int cnt = m_pFile->m_streams[i].GetCount();
    00401
    00402                 if(lIndex >= j && lIndex < j+cnt)
    00403                 {
    00404                         lIndex -= j;
    00405
    00406                         POSITION pos = m_pFile->m_streams[i].FindIndex(lIndex);
    00407                         if(!pos) return E_UNEXPECTED;
    00408
    00409                         CMpegSplitterFile::stream& to = m_pFile->m_streams[i].GetAt(pos);
    00410
    00411                         pos = m_pFile->m_streams[i].GetHeadPosition();
    00412                         while(pos)
    00413                         {
    00414                                 CMpegSplitterFile::stream& from = m_pFile->m_streams[i].GetNext(pos);
    00415                                 if(GetOutputPin(from))
    00416                                         return RenameOutputPin(from, to, &to.mt);
    00417                         }
    00418                 }
    00419
    00420                 j += cnt;
    00421         }
    00422
    00423         return S_FALSE;
    00424 }
    00425
    00426 STDMETHODIMP CMpegSplitterFilter::Info(long lIndex, AM_MEDIA_TYPE** ppmt, DWORD* pdwFlags, LCID* plcid, DWORD* pdwGroup, WCHAR** ppszName, IUnknown** ppObject, IUnknown** ppUnk)
    00427 {
    00428         for(int i = 0, j = 0; i < countof(m_pFile->m_streams); i++)
    00429         {
    00430                 int cnt = m_pFile->m_streams[i].GetCount();
    00431
    00432                 if(lIndex >= j && lIndex < j+cnt)
    00433                 {
    00434                         lIndex -= j;
    00435
    00436                         POSITION pos = m_pFile->m_streams[i].FindIndex(lIndex);
    00437                         if(!pos) return E_UNEXPECTED;
    00438
    00439                         CMpegSplitterFile::stream& s = m_pFile->m_streams[i].GetAt(pos);
    00440
    00441                         if(ppmt) *ppmt = CreateMediaType(&s.mt);
    00442                         if(pdwFlags) *pdwFlags = GetOutputPin(s) ? (AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE) : 0;
    00443                         if(plcid) *plcid = 0;
    00444                         if(pdwGroup) *pdwGroup = i;
    00445                         if(ppObject) *ppObject = NULL;
    00446                         if(ppUnk) *ppUnk = NULL;
    00447
    00448                         if(ppszName)
    00449                         {
    00450                                 *ppszName = NULL;
    00451
    00452                                 CStringW name = CMpegSplitterFile::CStreamList::ToString(i);
    00453
    00454                                 CStringW str;
    00455                                 str.Format(L"%s (%04x,%02x,%02x)", name, s.pid, s.pesid, s.ps1id); // TODO: make this nicer
    00456
    00457                                 *ppszName = (WCHAR*)CoTaskMemAlloc((str.GetLength()+1)*sizeof(WCHAR));
    00458                                 if(*ppszName == NULL) return E_OUTOFMEMORY;
    00459                                 wcscpy(*ppszName, str);
    00460                         }
    00461                 }
    00462
    00463                 j += cnt;
    00464         }
    00465
    00466         return S_OK;
    00467 }
    00468
    00469 //
    00470 // CMpegSourceFilter
    00471 //
    00472
    00473 CMpegSourceFilter::CMpegSourceFilter(LPUNKNOWN pUnk, HRESULT* phr, const CLSID& clsid)
    00474         : CMpegSplitterFilter(pUnk, phr, clsid)
    00475 {
    00476         m_pInput.Free();
    00477 }
    00478
    00479 //
    00480 // CMpegSplitterOutputPin
    00481 //
    00482
    00483 CMpegSplitterOutputPin::CMpegSplitterOutputPin(CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
    00484         : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
    00485 {
    00486 }
    00487
    00488 CMpegSplitterOutputPin::~CMpegSplitterOutputPin()
    00489 {
    00490 }
    00491
    00492 HRESULT CMpegSplitterOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
    00493 {
    00494         {
    00495                 CAutoLock cAutoLock(this);
    00496                 m_rtPrev = Packet::INVALID_TIME;
    00497                 m_rtOffset = 0;
    00498         }
    00499
    00500         return __super::DeliverNewSegment(tStart, tStop, dRate);
    00501 }
    00502
    00503 HRESULT CMpegSplitterOutputPin::DeliverEndFlush()
    00504 {
    00505         {
    00506                 CAutoLock cAutoLock(this);
    00507                 m_p.Free();
    00508         }
    00509
    00510         return __super::DeliverEndFlush();
    00511 }
    00512
    00513 HRESULT CMpegSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
    00514 {
    00515         CAutoLock cAutoLock(this);
    00516
    00517         if(p->rtStart != Packet::INVALID_TIME)
    00518         {
    00519                 if(p->rtStart + m_rtOffset + 10000000 < m_rtPrev)
    00520                         m_rtOffset += m_rtPrev - (p->rtStart + m_rtOffset);
    00521
    00522                 p->rtStart += m_rtOffset;
    00523                 p->rtStop += m_rtOffset;
    00524
    00525                 m_rtPrev = p->rtStart;
    00526         }
    00527
    00528         if(m_mt.subtype == MEDIASUBTYPE_AAC) // special code for aac, the currently available decoders only like whole frame samples
    00529         {
    00530                 if(m_p && m_p->pData.GetSize() == 1 && m_p->pData[0] == 0xff
    00531                 && !(p->pData.GetSize() > 0 && (p->pData[0]&0xf6) == 0xf0))
    00532                         m_p.Free();
    00533
    00534                 if(!m_p)
    00535                 {
    00536                         BYTE* base = p->pData.GetData();
    00537                         BYTE* s = base;
    00538                         BYTE* e = s + p->pData.GetSize();
    00539
    00540                         for(; s < e; s++)
    00541                         {
    00542                                 if(*s != 0xff) continue;
    00543
    00544                                 if(s == e-1 || (s[1]&0xf6) == 0xf0)
    00545                                 {
    00546                                         memmove(base, s, e - s);
    00547                                         p->pData.SetSize(e - s);
    00548                                         m_p = p;
    00549                                         break;
    00550                                 }
    00551                         }
    00552                 }
    00553                 else
    00554                 {
    00555                         m_p->pData.Append(p->pData);
    00556                 }
    00557
    00558                 while(m_p && m_p->pData.GetSize() > 9)
    00559                 {
    00560                         BYTE* base = m_p->pData.GetData();
    00561                         BYTE* s = base;
    00562                         BYTE* e = s + m_p->pData.GetSize();
    00563                         //bool layer0 = ((s[3]>>1)&3) == 0;
    00564                         int len = ((s[3]&3)<<11)|(s[4]<<3)|(s[5]>>5);
    00565                         bool crc = !(s[3]&1);
    00566                         s += 7; len -= 7;
    00567                         if(crc) s += 2, len -= 2;
    00568
    00569                         if(e - s < len)
    00570                         {
    00571                                 break;
    00572                         }
    00573
    00574                         if(len <= 0 || e - s >= len + 2 && (s[len] != 0xff || (s[len+1]&0xf6) != 0xf0))
    00575                         {
    00576                                 m_p.Free();
    00577                                 break;
    00578                         }
    00579
    00580                         CAutoPtr<Packet> p(new Packet());
    00581                         p->TrackNumber = m_p->TrackNumber;
    00582                         p->bDiscontinuity |= m_p->bDiscontinuity; m_p->bDiscontinuity = false;
    00583                         p->bSyncPoint = m_p->rtStart != Packet::INVALID_TIME;
    00584                         p->rtStart = m_p->rtStart; m_p->rtStart = Packet::INVALID_TIME;
    00585                         p->rtStop = m_p->rtStop; m_p->rtStop = Packet::INVALID_TIME;
    00586                         p->pmt = m_p->pmt; m_p->pmt = NULL;
    00587                         p->pData.SetSize(len);
    00588                         memcpy(p->pData.GetData(), s, len);
    00589                         s += len;
    00590                         memmove(base, s, e - s);
    00591                         m_p->pData.SetSize(e - s);
    00592
    00593                         HRESULT hr = __super::DeliverPacket(p);
    00594                         if(hr != S_OK) return hr;
    00595                 }
    00596
    00597                 if(m_p && p)
    00598                 {
    00599                         if(!m_p->bDiscontinuity) m_p->bDiscontinuity = p->bDiscontinuity;
    00600                         if(!m_p->bSyncPoint) m_p->bSyncPoint = p->bSyncPoint;
    00601                         if(m_p->rtStart == Packet::INVALID_TIME) m_p->rtStart = p->rtStart, m_p->rtStop = p->rtStop;
    00602                         if(m_p->pmt) DeleteMediaType(m_p->pmt); m_p->pmt = p->pmt; p->pmt = NULL;
    00603                 }
    00604
    00605                 return S_OK;
    00606         }
    00607         else
    00608         {
    00609                 m_p.Free();
    00610         }
    00611
    00612         return __super::DeliverPacket(p);
    00613 }