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 }

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