MpegSplitter.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:16k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include <mmreg.h>
  23. #include <initguid.h>
  24. #include "MpegSplitter.h"
  25. #include "........includemoreuuids.h"
  26. #ifdef REGISTER_FILTER
  27. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  28. {
  29. {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1System},
  30. // {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1VideoCD}, // cdxa filter should take care of this
  31. {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_PROGRAM},
  32. {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_TRANSPORT},
  33. {&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG2_PVA},
  34. {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
  35. };
  36. const AMOVIESETUP_PIN sudpPins[] =
  37. {
  38.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
  39.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL},
  40. };
  41. const AMOVIESETUP_FILTER sudFilter[] =
  42. {
  43. {&__uuidof(CMpegSplitterFilter), L"Mpeg Splitter", MERIT_NORMAL+1 /*MERIT_DO_NOT_USE*/, countof(sudpPins), sudpPins},
  44. {&__uuidof(CMpegSourceFilter), L"Mpeg Source", MERIT_DO_NOT_USE, 0, NULL},
  45. };
  46. CFactoryTemplate g_Templates[] =
  47. {
  48. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMpegSplitterFilter>, NULL, &sudFilter[0]},
  49. {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CMpegSourceFilter>, NULL, &sudFilter[1]},
  50. };
  51. int g_cTemplates = countof(g_Templates);
  52. STDAPI DllRegisterServer()
  53. {
  54. RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG1System, _T("0,16,FFFFFFFFF100010001800001FFFFFFFF,000001BA2100010001800001000001BB"), NULL);
  55. RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_PROGRAM, _T("0,5,FFFFFFFFC0,000001BA40"), NULL);
  56. RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_TRANSPORT, _T("0,4,,47,188,4,,47,376,4,,47"), NULL);
  57. RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG2_PVA, _T("0,8,fffffc00ffe00000,4156000055000000"), NULL);
  58. return AMovieDllRegisterServer2(TRUE);
  59. }
  60. STDAPI DllUnregisterServer()
  61. {
  62. // UnRegisterSourceFilter(MEDIASUBTYPE_MPEG1System);
  63. // UnRegisterSourceFilter(MEDIASUBTYPE_MPEG2_PROGRAM);
  64. return AMovieDllRegisterServer2(FALSE);
  65. }
  66. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  67. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  68. {
  69.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  70. }
  71. #endif
  72. //
  73. // CMpegSplitterFilter
  74. //
  75. CMpegSplitterFilter::CMpegSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr, const CLSID& clsid)
  76. : CBaseSplitterFilter(NAME("CMpegSplitterFilter"), pUnk, phr, clsid)
  77. {
  78. }
  79. STDMETHODIMP CMpegSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  80. {
  81.     CheckPointer(ppv, E_POINTER);
  82.     return 
  83. QI(IAMStreamSelect)
  84. __super::NonDelegatingQueryInterface(riid, ppv);
  85. }
  86. //
  87. HRESULT CMpegSplitterFilter::DemuxNextPacket(REFERENCE_TIME rtStartOffset)
  88. {
  89. HRESULT hr;
  90. BYTE b;
  91. if(m_pFile->m_type == CMpegSplitterFile::ps || m_pFile->m_type == CMpegSplitterFile::es)
  92. {
  93. if(!m_pFile->NextMpegStartCode(b))
  94. return S_FALSE;
  95. if(b == 0xba) // program stream header
  96. {
  97. CMpegSplitterFile::pshdr h;
  98. if(!m_pFile->Read(h)) return S_FALSE;
  99. }
  100. else if(b == 0xbb) // program stream system header
  101. {
  102. CMpegSplitterFile::pssyshdr h;
  103. if(!m_pFile->Read(h)) return S_FALSE;
  104. }
  105. else if(b >= 0xbd && b < 0xf0) // pes packet
  106. {
  107. CMpegSplitterFile::peshdr h;
  108. if(!m_pFile->Read(h, b) || !h.len) return S_FALSE;
  109. if(h.type == CMpegSplitterFile::mpeg2 && h.scrambling) {ASSERT(0); return E_FAIL;}
  110. __int64 pos = m_pFile->GetPos();
  111. DWORD TrackNumber = m_pFile->AddStream(0, b, h.len);
  112. if(GetOutputPin(TrackNumber))
  113. {
  114. CAutoPtr<Packet> p(new Packet());
  115. p->TrackNumber = TrackNumber;
  116. p->bSyncPoint = !!h.fpts;
  117. p->bAppendable = !h.fpts;
  118. p->rtStart = h.fpts ? (h.pts - rtStartOffset) : Packet::INVALID_TIME;
  119. p->rtStop = p->rtStart+1;
  120. p->pData.SetSize(h.len - (m_pFile->GetPos() - pos));
  121. m_pFile->ByteRead(p->pData.GetData(), h.len - (m_pFile->GetPos() - pos));
  122. hr = DeliverPacket(p);
  123. }
  124. m_pFile->Seek(pos + h.len);
  125. }
  126. }
  127. else if(m_pFile->m_type == CMpegSplitterFile::ts)
  128. {
  129. CMpegSplitterFile::trhdr h;
  130. if(!m_pFile->Read(h)) 
  131. return S_FALSE;
  132. if(h.scrambling) {ASSERT(0); return S_FALSE;}
  133. __int64 pos = m_pFile->GetPos();
  134. if(h.payload && h.pid >= 16 && h.pid < 0x1fff)
  135. {
  136. DWORD TrackNumber = h.pid;
  137. CMpegSplitterFile::peshdr h2;
  138. if(h.payloadstart && m_pFile->NextMpegStartCode(b, 4) && m_pFile->Read(h2, b)) // pes packet
  139. {
  140. if(h2.type == CMpegSplitterFile::mpeg2 && h2.scrambling) {ASSERT(0); return E_FAIL;}
  141. TrackNumber = m_pFile->AddStream(h.pid, b, h.bytes - (m_pFile->GetPos() - pos));
  142. }
  143. if(GetOutputPin(TrackNumber))
  144. {
  145. CAutoPtr<Packet> p(new Packet());
  146. p->TrackNumber = TrackNumber;
  147. p->bSyncPoint = !!h2.fpts;
  148. p->bAppendable = !h2.fpts;
  149. p->rtStart = h2.fpts ? (h2.pts - rtStartOffset) : Packet::INVALID_TIME;
  150. p->rtStop = p->rtStart+1;
  151. p->pData.SetSize(h.bytes - (m_pFile->GetPos() - pos));
  152. m_pFile->ByteRead(p->pData.GetData(), h.bytes - (m_pFile->GetPos() - pos));
  153. hr = DeliverPacket(p);
  154. }
  155. }
  156. m_pFile->Seek(h.next);
  157. }
  158. else if(m_pFile->m_type == CMpegSplitterFile::pva)
  159. {
  160. CMpegSplitterFile::pvahdr h;
  161. if(!m_pFile->Read(h))
  162. return S_FALSE;
  163. DWORD TrackNumber = h.streamid;
  164. __int64 pos = m_pFile->GetPos();
  165. if(GetOutputPin(TrackNumber))
  166. {
  167. CAutoPtr<Packet> p(new Packet());
  168. p->TrackNumber = TrackNumber;
  169. p->bSyncPoint = !!h.fpts;
  170. p->bAppendable = !h.fpts;
  171. p->rtStart = h.fpts ? (h.pts - rtStartOffset) : Packet::INVALID_TIME;
  172. p->rtStop = p->rtStart+1;
  173. p->pData.SetSize(h.length);
  174. m_pFile->ByteRead(p->pData.GetData(), h.length);
  175. hr = DeliverPacket(p);
  176. }
  177. m_pFile->Seek(pos + h.length);
  178. }
  179. return S_OK;
  180. }
  181. //
  182. HRESULT CMpegSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
  183. {
  184. CheckPointer(pAsyncReader, E_POINTER);
  185. HRESULT hr = E_FAIL;
  186. m_pFile.Free();
  187. m_pFile.Attach(new CMpegSplitterFile(pAsyncReader, hr));
  188. if(!m_pFile) return E_OUTOFMEMORY;
  189. if(FAILED(hr)) {m_pFile.Free(); return hr;}
  190. //
  191. m_rtNewStart = m_rtCurrent = 0;
  192. m_rtNewStop = m_rtStop = m_rtDuration = 0;
  193. for(int i = 0; i < countof(m_pFile->m_streams); i++)
  194. {
  195. POSITION pos = m_pFile->m_streams[i].GetHeadPosition();
  196. while(pos)
  197. {
  198. CMpegSplitterFile::stream& s = m_pFile->m_streams[i].GetNext(pos);
  199. CArray<CMediaType> mts;
  200. mts.Add(s.mt);
  201. CStringW name = CMpegSplitterFile::CStreamList::ToString(i);
  202. HRESULT hr;
  203. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CMpegSplitterOutputPin(mts, name, this, this, &hr));
  204. if(S_OK == AddOutputPin(s, pPinOut))
  205. break;
  206. }
  207. }
  208. m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->IsStreaming() ? 0 : 10000000i64 * m_pFile->GetLength() / m_pFile->m_rate;
  209. return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
  210. }
  211. bool CMpegSplitterFilter::DemuxInit()
  212. {
  213. if(!m_pFile) return(false);
  214. m_rtStartOffset = 0;
  215. return(true);
  216. }
  217. void CMpegSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
  218. {
  219. CList<CMpegSplitterFile::stream>* pMasterStream = 
  220. !m_pFile->m_streams[CMpegSplitterFile::video].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::video] :
  221. !m_pFile->m_streams[CMpegSplitterFile::audio].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::audio] :
  222. !m_pFile->m_streams[CMpegSplitterFile::subpic].IsEmpty() ? &m_pFile->m_streams[CMpegSplitterFile::subpic] :
  223. NULL;
  224. if(!pMasterStream) {ASSERT(0); return;}
  225. if(m_pFile->IsStreaming())
  226. {
  227. m_pFile->Seek(max(0, m_pFile->GetLength() - 100*1024));
  228. m_rtStartOffset = m_pFile->m_rtMin + m_pFile->NextPTS(pMasterStream->GetHead());
  229. return;
  230. }
  231. REFERENCE_TIME rtPreroll = 10000000;
  232. if(rt <= rtPreroll || m_rtDuration <= 0)
  233. {
  234. m_pFile->Seek(0);
  235. }
  236. else
  237. {
  238. __int64 len = m_pFile->GetLength();
  239. __int64 seekpos = (__int64)(1.0*rt/m_rtDuration*len);
  240. __int64 minseekpos = _I64_MAX;
  241. REFERENCE_TIME rtmax = rt - rtPreroll;
  242. REFERENCE_TIME rtmin = rtmax - 5000000;
  243. if(m_rtStartOffset == 0)
  244. for(int i = 0; i < countof(m_pFile->m_streams)-1; i++)
  245. {
  246. POSITION pos = m_pFile->m_streams[i].GetHeadPosition();
  247. while(pos)
  248. {
  249. DWORD TrackNum = m_pFile->m_streams[i].GetNext(pos);
  250. CBaseSplitterOutputPin* pPin = GetOutputPin(TrackNum);
  251. if(pPin && pPin->IsConnected())
  252. {
  253. m_pFile->Seek(seekpos);
  254. REFERENCE_TIME pdt = _I64_MIN;
  255. for(int j = 0; j < 10; j++)
  256. {
  257. REFERENCE_TIME rt = m_pFile->NextPTS(TrackNum);
  258. // TRACE(_T("[%d/%04x]: rt=%I64d, fp=%I64dn"), i, TrackNum, rt, m_pFile->GetPos());
  259. if(rt < 0) break;
  260. REFERENCE_TIME dt = rt - rtmax;
  261. if(dt > 0 && dt == pdt) dt = 10000000i64;
  262. // TRACE(_T("dt=%I64dn"), dt);
  263. if(rtmin <= rt && rt <= rtmax || pdt > 0 && dt < 0)
  264. {
  265. // TRACE(_T("minseekpos: %I64d -> "), minseekpos);
  266. minseekpos = min(minseekpos, m_pFile->GetPos());
  267. // TRACE(_T("%I64dn"), minseekpos);
  268. break;
  269. }
  270. m_pFile->Seek(m_pFile->GetPos() - (__int64)(1.0*dt/m_rtDuration*len));
  271. pdt = dt;
  272. }
  273. }
  274. }
  275. }
  276. if(minseekpos != _I64_MAX)
  277. {
  278. seekpos = minseekpos;
  279. }
  280. else
  281. {
  282. // this file is probably screwed up, try plan B, seek simply by bitrate
  283. rt -= rtPreroll;
  284. seekpos = (__int64)(1.0*rt/m_rtDuration*len);
  285. m_pFile->Seek(seekpos);
  286. m_rtStartOffset = m_pFile->m_rtMin + m_pFile->NextPTS(pMasterStream->GetHead()) - rt;
  287. }
  288. m_pFile->Seek(seekpos);
  289. }
  290. }
  291. bool CMpegSplitterFilter::DemuxLoop()
  292. {
  293. REFERENCE_TIME rtStartOffset = m_rtStartOffset ? m_rtStartOffset : m_pFile->m_rtMin;
  294. HRESULT hr = S_OK;
  295. while(SUCCEEDED(hr) && !CheckRequest(NULL))
  296. {
  297. if((hr = m_pFile->HasMoreData(1024*500)) == S_OK)
  298. if((hr = DemuxNextPacket(rtStartOffset)) == S_FALSE)
  299. Sleep(1);
  300. }
  301. return(true);
  302. }
  303. // IAMStreamSelect
  304. STDMETHODIMP CMpegSplitterFilter::Count(DWORD* pcStreams)
  305. {
  306. CheckPointer(pcStreams, E_POINTER);
  307. *pcStreams = 0;
  308. for(int i = 0; i < countof(m_pFile->m_streams); i++)
  309. (*pcStreams) += m_pFile->m_streams[i].GetCount();
  310. return S_OK;
  311. }
  312. STDMETHODIMP CMpegSplitterFilter::Enable(long lIndex, DWORD dwFlags)
  313. {
  314. if(!(dwFlags & AMSTREAMSELECTENABLE_ENABLE))
  315. return E_NOTIMPL;
  316. for(int i = 0, j = 0; i < countof(m_pFile->m_streams); i++)
  317. {
  318. int cnt = m_pFile->m_streams[i].GetCount();
  319. if(lIndex >= j && lIndex < j+cnt)
  320. {
  321. lIndex -= j;
  322. POSITION pos = m_pFile->m_streams[i].FindIndex(lIndex);
  323. if(!pos) return E_UNEXPECTED;
  324. CMpegSplitterFile::stream& to = m_pFile->m_streams[i].GetAt(pos);
  325. pos = m_pFile->m_streams[i].GetHeadPosition();
  326. while(pos)
  327. {
  328. CMpegSplitterFile::stream& from = m_pFile->m_streams[i].GetNext(pos);
  329. if(GetOutputPin(from))
  330. return RenameOutputPin(from, to, &to.mt);
  331. }
  332. }
  333. j += cnt;
  334. }
  335. return S_FALSE;
  336. }
  337. STDMETHODIMP CMpegSplitterFilter::Info(long lIndex, AM_MEDIA_TYPE** ppmt, DWORD* pdwFlags, LCID* plcid, DWORD* pdwGroup, WCHAR** ppszName, IUnknown** ppObject, IUnknown** ppUnk)
  338. {
  339. for(int i = 0, j = 0; i < countof(m_pFile->m_streams); i++)
  340. {
  341. int cnt = m_pFile->m_streams[i].GetCount();
  342. if(lIndex >= j && lIndex < j+cnt)
  343. {
  344. lIndex -= j;
  345. POSITION pos = m_pFile->m_streams[i].FindIndex(lIndex);
  346. if(!pos) return E_UNEXPECTED;
  347. CMpegSplitterFile::stream& s = m_pFile->m_streams[i].GetAt(pos);
  348. if(ppmt) *ppmt = CreateMediaType(&s.mt);
  349. if(pdwFlags) *pdwFlags = GetOutputPin(s) ? (AMSTREAMSELECTINFO_ENABLED|AMSTREAMSELECTINFO_EXCLUSIVE) : 0;
  350. if(plcid) *plcid = 0;
  351. if(pdwGroup) *pdwGroup = i;
  352. if(ppObject) *ppObject = NULL;
  353. if(ppUnk) *ppUnk = NULL;
  354. if(ppszName)
  355. {
  356. *ppszName = NULL;
  357. CStringW name = CMpegSplitterFile::CStreamList::ToString(i);
  358. CStringW str;
  359. str.Format(L"%s (%04x,%02x,%02x)", name, s.pid, s.pesid, s.ps1id); // TODO: make this nicer
  360. *ppszName = (WCHAR*)CoTaskMemAlloc((str.GetLength()+1)*sizeof(WCHAR));
  361. if(*ppszName == NULL) return E_OUTOFMEMORY;
  362. wcscpy(*ppszName, str);
  363. }
  364. }
  365. j += cnt;
  366. }
  367. return S_OK;
  368. }
  369. //
  370. // CMpegSourceFilter
  371. //
  372. CMpegSourceFilter::CMpegSourceFilter(LPUNKNOWN pUnk, HRESULT* phr, const CLSID& clsid)
  373. : CMpegSplitterFilter(pUnk, phr, clsid)
  374. {
  375. m_pInput.Free();
  376. }
  377. //
  378. // CMpegSplitterOutputPin
  379. //
  380. CMpegSplitterOutputPin::CMpegSplitterOutputPin(CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  381. : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
  382. {
  383. }
  384. CMpegSplitterOutputPin::~CMpegSplitterOutputPin()
  385. {
  386. }
  387. HRESULT CMpegSplitterOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  388. {
  389. {
  390. CAutoLock cAutoLock(this);
  391. m_rtPrev = Packet::INVALID_TIME;
  392. m_rtOffset = 0;
  393. }
  394. return __super::DeliverNewSegment(tStart, tStop, dRate);
  395. }
  396. HRESULT CMpegSplitterOutputPin::DeliverEndFlush()
  397. {
  398. {
  399. CAutoLock cAutoLock(this);
  400. m_p.Free();
  401. }
  402. return __super::DeliverEndFlush();
  403. }
  404. HRESULT CMpegSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
  405. {
  406. CAutoLock cAutoLock(this);
  407. if(p->rtStart != Packet::INVALID_TIME)
  408. {
  409. if(p->rtStart + m_rtOffset + 10000000 < m_rtPrev)
  410. m_rtOffset += m_rtPrev - (p->rtStart + m_rtOffset);
  411. p->rtStart += m_rtOffset;
  412. p->rtStop += m_rtOffset;
  413. m_rtPrev = p->rtStart;
  414. }
  415. if(m_mt.subtype == MEDIASUBTYPE_AAC) // special code for aac, the currently available decoders only like whole frame samples
  416. {
  417. if(m_p && m_p->pData.GetSize() == 1 && m_p->pData[0] == 0xff
  418. && !(p->pData.GetSize() > 0 && (p->pData[0]&0xf6) == 0xf0))
  419. m_p.Free();
  420. if(!m_p)
  421. {
  422. BYTE* base = p->pData.GetData();
  423. BYTE* s = base;
  424. BYTE* e = s + p->pData.GetSize();
  425. for(; s < e; s++)
  426. {
  427. if(*s != 0xff) continue;
  428. if(s == e-1 || (s[1]&0xf6) == 0xf0)
  429. {
  430. memmove(base, s, e - s);
  431. p->pData.SetSize(e - s);
  432. m_p = p;
  433. break;
  434. }
  435. }
  436. }
  437. else
  438. {
  439. m_p->pData.Append(p->pData);
  440. }
  441. while(m_p && m_p->pData.GetSize() > 9)
  442. {
  443. BYTE* base = m_p->pData.GetData();
  444. BYTE* s = base;
  445. BYTE* e = s + m_p->pData.GetSize();
  446. //bool layer0 = ((s[3]>>1)&3) == 0;
  447. int len = ((s[3]&3)<<11)|(s[4]<<3)|(s[5]>>5);
  448. bool crc = !(s[3]&1);
  449. s += 7; len -= 7;
  450. if(crc) s += 2, len -= 2;
  451. if(e - s < len)
  452. {
  453. break;
  454. }
  455. if(len <= 0 || e - s >= len + 2 && (s[len] != 0xff || (s[len+1]&0xf6) != 0xf0))
  456. {
  457. m_p.Free();
  458. break;
  459. }
  460. CAutoPtr<Packet> p(new Packet());
  461. p->TrackNumber = m_p->TrackNumber;
  462. p->bDiscontinuity |= m_p->bDiscontinuity; m_p->bDiscontinuity = false;
  463. p->bSyncPoint = m_p->rtStart != Packet::INVALID_TIME;
  464. p->rtStart = m_p->rtStart; m_p->rtStart = Packet::INVALID_TIME;
  465. p->rtStop = m_p->rtStop; m_p->rtStop = Packet::INVALID_TIME;
  466. p->pmt = m_p->pmt; m_p->pmt = NULL;
  467. p->pData.SetSize(len);
  468. memcpy(p->pData.GetData(), s, len);
  469. s += len;
  470. memmove(base, s, e - s);
  471. m_p->pData.SetSize(e - s);
  472. HRESULT hr = __super::DeliverPacket(p);
  473. if(hr != S_OK) return hr;
  474. }
  475. if(m_p && p)
  476. {
  477. if(!m_p->bDiscontinuity) m_p->bDiscontinuity = p->bDiscontinuity;
  478. if(!m_p->bSyncPoint) m_p->bSyncPoint = p->bSyncPoint;
  479. if(m_p->rtStart == Packet::INVALID_TIME) m_p->rtStart = p->rtStart, m_p->rtStop = p->rtStop;
  480. if(m_p->pmt) DeleteMediaType(m_p->pmt); m_p->pmt = p->pmt; p->pmt = NULL;
  481. }
  482. return S_OK;
  483. }
  484. else
  485. {
  486. m_p.Free();
  487. }
  488. return __super::DeliverPacket(p);
  489. }