00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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 , 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
00073
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);
00083 }
00084
00085 #endif
00086
00087
00088
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)
00118 {
00119 CMpegSplitterFile::pshdr h;
00120 if(!m_pFile->Read(h)) return S_FALSE;
00121 }
00122 else if(b == 0xbb)
00123 {
00124 CMpegSplitterFile::pssyshdr h;
00125 if(!m_pFile->Read(h)) return S_FALSE;
00126 }
00127 else if(b >= 0xbd && b < 0xf0)
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))
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
00323
00324 if(rt < 0) break;
00325
00326 REFERENCE_TIME dt = rt - rtmax;
00327 if(dt > 0 && dt == pdt) dt = 10000000i64;
00328
00329
00330
00331 if(rtmin <= rt && rt <= rtmax || pdt > 0 && dt < 0)
00332 {
00333
00334 minseekpos = min(minseekpos, m_pFile->GetPos());
00335
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
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
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);
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
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
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)
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
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 }