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 "MatroskaSplitter.h"
00025 #include "..\..\..\DSUtil\DSUtil.h"
00026
00027 #include <initguid.h>
00028 #include "..\..\..\..\include\matroska\matroska.h"
00029 #include "..\..\..\..\include\ogg\OggDS.h"
00030 #include "..\..\..\..\include\moreuuids.h"
00031
00032 using namespace MatroskaReader;
00033
00034 #ifdef REGISTER_FILTER
00035
00036 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00037 {
00038 {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska},
00039 {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
00040 };
00041
00042 const AMOVIESETUP_PIN sudpPins[] =
00043 {
00044 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00045 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00046 };
00047
00048 const AMOVIESETUP_FILTER sudFilter[] =
00049 {
00050 {&__uuidof(CMatroskaSplitterFilter), L"Matroska Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
00051 {&__uuidof(CMatroskaSourceFilter), L"Matroska Source", MERIT_NORMAL, 0, NULL},
00052 };
00053
00054 CFactoryTemplate g_Templates[] =
00055 {
00056 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaSplitterFilter>, NULL, &sudFilter[0]},
00057 {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CMatroskaSourceFilter>, NULL, &sudFilter[1]},
00058 };
00059
00060 int g_cTemplates = countof(g_Templates);
00061
00062 STDAPI DllRegisterServer()
00063 {
00064 RegisterSourceFilter(
00065 CLSID_AsyncReader,
00066 MEDIASUBTYPE_Matroska,
00067 _T("0,4,,1A45DFA3"),
00068 _T(".mkv"), _T(".mka"), _T(".mks"), NULL);
00069
00070 return AMovieDllRegisterServer2(TRUE);
00071 }
00072
00073 STDAPI DllUnregisterServer()
00074 {
00075 UnRegisterSourceFilter(MEDIASUBTYPE_Matroska);
00076
00077 return AMovieDllRegisterServer2(FALSE);
00078 }
00079
00080 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00081
00082 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00083 {
00084 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00085 }
00086
00087 #endif
00088
00089
00090
00091
00092
00093 CMatroskaSplitterFilter::CMatroskaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00094 : CBaseSplitterFilter(NAME("CMatroskaSplitterFilter"), pUnk, phr, __uuidof(this))
00095 {
00096 }
00097
00098 CMatroskaSplitterFilter::~CMatroskaSplitterFilter()
00099 {
00100 }
00101
00102 STDMETHODIMP CMatroskaSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00103 {
00104 CheckPointer(ppv, E_POINTER);
00105
00106 return
00107 QI(ITrackInfo)
00108 __super::NonDelegatingQueryInterface(riid, ppv);
00109 }
00110
00111 #include <vector>
00112
00113 HRESULT CMatroskaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00114 {
00115 CheckPointer(pAsyncReader, E_POINTER);
00116
00117 HRESULT hr = E_FAIL;
00118
00119 m_pFile.Free();
00120 m_pTrackEntryMap.RemoveAll();
00121 m_pOrderedTrackArray.RemoveAll();
00122
00123 m_pFile.Attach(new CMatroskaFile(pAsyncReader, hr));
00124 if(!m_pFile) return E_OUTOFMEMORY;
00125 if(FAILED(hr)) {m_pFile.Free(); return hr;}
00126
00127 m_rtNewStart = m_rtCurrent = 0;
00128 m_rtNewStop = m_rtStop = 0;
00129
00130 int iVideo = 1, iAudio = 1, iSubtitle = 1;
00131
00132 POSITION pos = m_pFile->m_segment.Tracks.GetHeadPosition();
00133 while(pos)
00134 {
00135 Track* pT = m_pFile->m_segment.Tracks.GetNext(pos);
00136
00137 POSITION pos2 = pT->TrackEntries.GetHeadPosition();
00138 while(pos2)
00139 {
00140 TrackEntry* pTE = pT->TrackEntries.GetNext(pos2);
00141
00142 if(!pTE->Expand(pTE->CodecPrivate, ContentEncoding::TracksPrivateData))
00143 continue;
00144
00145 CStringA CodecID = pTE->CodecID.ToString();
00146
00147 CStringW Name;
00148 Name.Format(L"Output %I64d", (UINT64)pTE->TrackNumber);
00149
00150 CMediaType mt;
00151 CArray<CMediaType> mts;
00152
00153 mt.SetSampleSize(1);
00154
00155 if(pTE->TrackType == TrackEntry::TypeVideo)
00156 {
00157 Name.Format(L"Video %d", iVideo++);
00158
00159 mt.majortype = MEDIATYPE_Video;
00160
00161 if(CodecID == "V_MS/VFW/FOURCC")
00162 {
00163 mt.formattype = FORMAT_VideoInfo;
00164 VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount() - sizeof(BITMAPINFOHEADER));
00165 memset(mt.Format(), 0, mt.FormatLength());
00166 memcpy(&pvih->bmiHeader, (BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
00167 mt.subtype = FOURCCMap(pvih->bmiHeader.biCompression);
00168 switch(pvih->bmiHeader.biCompression)
00169 {
00170 case BI_RGB: case BI_BITFIELDS: mt.subtype =
00171 pvih->bmiHeader.biBitCount == 1 ? MEDIASUBTYPE_RGB1 :
00172 pvih->bmiHeader.biBitCount == 4 ? MEDIASUBTYPE_RGB4 :
00173 pvih->bmiHeader.biBitCount == 8 ? MEDIASUBTYPE_RGB8 :
00174 pvih->bmiHeader.biBitCount == 16 ? MEDIASUBTYPE_RGB565 :
00175 pvih->bmiHeader.biBitCount == 24 ? MEDIASUBTYPE_RGB24 :
00176 pvih->bmiHeader.biBitCount == 32 ? MEDIASUBTYPE_ARGB32 :
00177 MEDIASUBTYPE_NULL;
00178 break;
00179
00180
00181 }
00182 mts.Add(mt);
00183 }
00184 else if(CodecID == "V_UNCOMPRESSED")
00185 {
00186 }
00187 else if(CodecID.Find("V_MPEG4/ISO/AVC") == 0)
00188 {
00189 if(pTE->CodecPrivate.GetSize() >= 6)
00190 {
00191 BYTE sps = pTE->CodecPrivate[5] & 0x1f;
00192
00193
00194 std::vector<BYTE> avcC;
00195 for(int i = 0, j = pTE->CodecPrivate.GetSize(); i < j; i++)
00196 avcC.push_back(pTE->CodecPrivate[i]);
00197
00198 std::vector<BYTE> sh;
00199
00200 unsigned jj = 6;
00201
00202 while (sps--) {
00203 if (jj + 2 > avcC.size())
00204 goto avcfail;
00205 unsigned spslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
00206 if (jj + 2 + spslen > avcC.size())
00207 goto avcfail;
00208 unsigned cur = sh.size();
00209 sh.resize(cur + spslen + 2, 0);
00210 std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + spslen,sh.begin() + cur);
00211 jj += 2 + spslen;
00212 }
00213
00214 if (jj + 1 > avcC.size())
00215 continue;
00216
00217 unsigned pps = avcC[jj++];
00218
00219 while (pps--) {
00220 if (jj + 2 > avcC.size())
00221 goto avcfail;
00222 unsigned ppslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
00223 if (jj + 2 + ppslen > avcC.size())
00224 goto avcfail;
00225 unsigned cur = sh.size();
00226 sh.resize(cur + ppslen + 2, 0);
00227 std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + ppslen, sh.begin() + cur);
00228 jj += 2 + ppslen;
00229 }
00230
00231 goto avcsuccess;
00232 avcfail:
00233 continue;
00234 avcsuccess:
00235
00236 CArray<BYTE> data;
00237 data.SetSize(sh.size());
00238 std::copy(sh.begin(), sh.end(), (BYTE*)data.GetData());
00239
00240 mt.subtype = FOURCCMap('1CVA');
00241 mt.formattype = FORMAT_MPEG2Video;
00242 MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)mt.AllocFormatBuffer(FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + data.GetSize());
00243 memset(mt.Format(), 0, mt.FormatLength());
00244 pm2vi->hdr.bmiHeader.biSize = sizeof(pm2vi->hdr.bmiHeader);
00245 pm2vi->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00246 pm2vi->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00247 pm2vi->hdr.bmiHeader.biCompression = '1cva';
00248 pm2vi->hdr.bmiHeader.biPlanes = 1;
00249 pm2vi->hdr.bmiHeader.biBitCount = 24;
00250
00251 pm2vi->dwProfile = pTE->CodecPrivate[1];
00252 pm2vi->dwLevel = pTE->CodecPrivate[3];
00253 pm2vi->dwFlags = (pTE->CodecPrivate[4] & 3) + 1;
00254
00255 BYTE* pSequenceHeader = (BYTE*)pm2vi->dwSequenceHeader;
00256 memcpy(pSequenceHeader, data.GetData(), data.GetSize());
00257 pm2vi->cbSequenceHeader = data.GetSize();
00258
00259 mts.Add(mt);
00260
00261 }
00262 }
00263 else if(CodecID.Find("V_MPEG4/") == 0)
00264 {
00265 mt.subtype = FOURCCMap('v4pm');
00266 mt.formattype = FORMAT_VideoInfo;
00267 VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00268 memset(pvih, 0, mt.FormatLength());
00269 pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
00270 pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00271 pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00272 pvih->bmiHeader.biCompression = 'v4pm';
00273 mts.Add(mt);
00274
00275
00276 }
00277 else if(CodecID.Find("V_REAL/RV") == 0)
00278 {
00279 mt.subtype = FOURCCMap('00VR' + ((CodecID[9]-0x30)<<16));
00280 mt.formattype = FORMAT_VideoInfo;
00281 VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount());
00282 memset(mt.Format(), 0, mt.FormatLength());
00283 memcpy(mt.Format() + sizeof(VIDEOINFOHEADER), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00284 pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
00285 pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00286 pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00287 pvih->bmiHeader.biCompression = mt.subtype.Data1;
00288 mts.Add(mt);
00289 }
00290 else if(CodecID == "V_DIRAC")
00291 {
00292 mt.subtype = MEDIASUBTYPE_DiracVideo;
00293 mt.formattype = FORMAT_DiracVideoInfo;
00294 DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)mt.AllocFormatBuffer(FIELD_OFFSET(DIRACINFOHEADER, dwSequenceHeader) + pTE->CodecPrivate.GetSize());
00295 memset(mt.Format(), 0, mt.FormatLength());
00296 dvih->hdr.bmiHeader.biSize = sizeof(dvih->hdr.bmiHeader);
00297 dvih->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00298 dvih->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00299 dvih->hdr.dwPictAspectRatioX = dvih->hdr.bmiHeader.biWidth;
00300 dvih->hdr.dwPictAspectRatioY = dvih->hdr.bmiHeader.biHeight;
00301
00302 BYTE* pSequenceHeader = (BYTE*)dvih->dwSequenceHeader;
00303 memcpy(pSequenceHeader, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
00304 dvih->cbSequenceHeader = pTE->CodecPrivate.GetSize();
00305
00306 mts.Add(mt);
00307 }
00308 else if(CodecID == "V_MPEG2")
00309 {
00310 BYTE* seqhdr = pTE->CodecPrivate.GetData();
00311 DWORD len = pTE->CodecPrivate.GetSize();
00312 int w = pTE->v.PixelWidth;
00313 int h = pTE->v.PixelHeight;
00314
00315 if(MakeMPEG2MediaType(mt, seqhdr, len, w, h))
00316 mts.Add(mt);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 REFERENCE_TIME AvgTimePerFrame = 0;
00331
00332 if(pTE->v.FramePerSec > 0)
00333 AvgTimePerFrame = (REFERENCE_TIME)(10000000i64 / pTE->v.FramePerSec);
00334 else if(pTE->DefaultDuration > 0)
00335 AvgTimePerFrame = (REFERENCE_TIME)pTE->DefaultDuration / 100;
00336
00337 if(AvgTimePerFrame)
00338 {
00339 for(int i = 0; i < mts.GetCount(); i++)
00340 {
00341 if(mts[i].formattype == FORMAT_VideoInfo
00342 || mts[i].formattype == FORMAT_VideoInfo2
00343 || mts[i].formattype == FORMAT_MPEG2Video)
00344 {
00345 ((VIDEOINFOHEADER*)mts[i].Format())->AvgTimePerFrame = AvgTimePerFrame;
00346 }
00347 }
00348 }
00349
00350 if(pTE->v.DisplayWidth != 0 && pTE->v.DisplayHeight != 0)
00351 {
00352 for(int i = 0; i < mts.GetCount(); i++)
00353 {
00354 if(mts[i].formattype == FORMAT_VideoInfo)
00355 {
00356 DWORD vih1 = FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
00357 DWORD vih2 = FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader);
00358 DWORD bmi = mts[i].FormatLength() - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
00359 mt.formattype = FORMAT_VideoInfo2;
00360 mt.AllocFormatBuffer(vih2 + bmi);
00361 memcpy(mt.Format(), mts[i].Format(), vih1);
00362 memset(mt.Format() + vih1, 0, vih2 - vih1);
00363 memcpy(mt.Format() + vih2, mts[i].Format() + vih1, bmi);
00364 ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
00365 ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
00366 mts.InsertAt(i++, mt);
00367 }
00368 else if(mts[i].formattype == FORMAT_MPEG2Video)
00369 {
00370 ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
00371 ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
00372 }
00373 }
00374 }
00375 }
00376 else if(pTE->TrackType == TrackEntry::TypeAudio)
00377 {
00378 Name.Format(L"Audio %d", iAudio++);
00379
00380 mt.majortype = MEDIATYPE_Audio;
00381 mt.formattype = FORMAT_WaveFormatEx;
00382 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX));
00383 memset(pwfe, 0, mt.FormatLength());
00384 pwfe->nChannels = (WORD)pTE->a.Channels;
00385 pwfe->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00386 pwfe->wBitsPerSample = (WORD)pTE->a.BitDepth;
00387 pwfe->nBlockAlign = (WORD)((pwfe->nChannels * pwfe->wBitsPerSample) / 8);
00388 pwfe->nAvgBytesPerSec = pwfe->nSamplesPerSec * pwfe->nBlockAlign;
00389 mt.SetSampleSize(256000);
00390
00391 if(CodecID == "A_VORBIS")
00392 {
00393 BYTE* p = (BYTE*)pTE->CodecPrivate;
00394 CArray<long> sizes;
00395 for(BYTE n = *p++; n > 0; n--)
00396 {
00397 long size = 0;
00398 do {size += *p;} while(*p++ == 0xff);
00399 sizes.Add(size);
00400 }
00401
00402 long totalsize = 0;
00403 for(int i = 0; i < sizes.GetCount(); i++)
00404 totalsize += sizes[i];
00405
00406 sizes.Add(pTE->CodecPrivate.GetSize() - (p - (BYTE*)pTE->CodecPrivate) - totalsize);
00407 totalsize += sizes[sizes.GetCount()-1];
00408
00409 if(sizes.GetCount() == 3)
00410 {
00411 mt.subtype = MEDIASUBTYPE_Vorbis2;
00412 mt.formattype = FORMAT_VorbisFormat2;
00413 VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT2) + totalsize);
00414 memset(pvf2, 0, mt.FormatLength());
00415 pvf2->Channels = (WORD)pTE->a.Channels;
00416 pvf2->SamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00417 pvf2->BitsPerSample = (DWORD)pTE->a.BitDepth;
00418 BYTE* p2 = mt.Format() + sizeof(VORBISFORMAT2);
00419 for(int i = 0; i < sizes.GetCount(); p += sizes[i], p2 += sizes[i], i++)
00420 memcpy(p2, p, pvf2->HeaderSize[i] = sizes[i]);
00421
00422 mts.Add(mt);
00423 }
00424
00425 mt.subtype = MEDIASUBTYPE_Vorbis;
00426 mt.formattype = FORMAT_VorbisFormat;
00427 VORBISFORMAT* pvf = (VORBISFORMAT*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT));
00428 memset(pvf, 0, mt.FormatLength());
00429 pvf->nChannels = (WORD)pTE->a.Channels;
00430 pvf->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00431 pvf->nMinBitsPerSec = pvf->nMaxBitsPerSec = pvf->nAvgBitsPerSec = -1;
00432 mts.Add(mt);
00433 }
00434 else if(CodecID == "A_MPEG/L3")
00435 {
00436 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MP3);
00437 mts.Add(mt);
00438 }
00439 else if(CodecID == "A_MPEG/L2")
00440 {
00441 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MPEG);
00442 mts.Add(mt);
00443
00444 }
00445 else if(CodecID == "A_AC3")
00446 {
00447 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DOLBY_AC3);
00448 mts.Add(mt);
00449 }
00450 else if(CodecID == "A_DTS")
00451 {
00452 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DVD_DTS);
00453 mts.Add(mt);
00454 }
00455 else if(CodecID == "A_FLAC")
00456 {
00457 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_FLAC);
00458 pwfe->cbSize = pTE->CodecPrivate.GetCount();
00459 BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount()) + sizeof(WAVEFORMATEX);
00460 memcpy(pExtra, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00461 mts.Add(mt);
00462
00463 mt.subtype = MEDIASUBTYPE_FLAC_FRAMED;
00464 mts.InsertAt(0, mt);
00465 }
00466 else if(CodecID == "A_TTA1")
00467 {
00468 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_TTA1);
00469 mts.Add(mt);
00470 }
00471 else if(CodecID == "A_MS/ACM")
00472 {
00473 pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(pTE->CodecPrivate.GetCount());
00474 memcpy(pwfe, (WAVEFORMATEX*)(BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
00475 mt.subtype = FOURCCMap(pwfe->wFormatTag);
00476 mts.Add(mt);
00477 }
00478 else if(CodecID == "A_PCM/INT/LIT")
00479 {
00480 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_PCM);
00481 mts.Add(mt);
00482 }
00483 else if(CodecID == "A_PCM/FLOAT/IEEE")
00484 {
00485 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_IEEE_FLOAT);
00486 mts.Add(mt);
00487 }
00488 else if(CodecID.Find("A_AAC/") == 0)
00489 {
00490 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_AAC);
00491 BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX)+5) + sizeof(WAVEFORMATEX);
00492 (pwfe = (WAVEFORMATEX*)mt.pbFormat)->cbSize = 2;
00493
00494 int profile;
00495
00496 if(CodecID.Find("/MAIN") > 0) profile = 0;
00497 else if(CodecID.Find("/SBR") > 0) profile = -1;
00498 else if(CodecID.Find("/LC") > 0) profile = 1;
00499 else if(CodecID.Find("/SSR") > 0) profile = 2;
00500 else if(CodecID.Find("/LTP") > 0) profile = 3;
00501 else continue;
00502
00503 WORD cbSize = MakeAACInitData(pExtra, profile, pwfe->nSamplesPerSec, pTE->a.Channels);
00504
00505 mts.Add(mt);
00506
00507 if(profile < 0)
00508 {
00509 pwfe->cbSize = cbSize;
00510 pwfe->nSamplesPerSec *= 2;
00511 pwfe->nAvgBytesPerSec *= 2;
00512
00513 mts.InsertAt(0, mt);
00514 }
00515 }
00516 else if(CodecID.Find("A_REAL/") == 0 && CodecID.GetLength() >= 11)
00517 {
00518 mt.bTemporalCompression = TRUE;
00519 mt.subtype = FOURCCMap((DWORD)CodecID[7]|((DWORD)CodecID[8]<<8)|((DWORD)CodecID[9]<<16)|((DWORD)CodecID[10]<<24));
00520 BYTE* p = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount());
00521 memcpy(p + sizeof(WAVEFORMATEX), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00522
00523 mts.Add(mt);
00524 }
00525 }
00526 else if(pTE->TrackType == TrackEntry::TypeSubtitle)
00527 {
00528 if(iSubtitle == 1) InstallFonts();
00529
00530 Name.Format(L"Subtitle %d", iSubtitle++);
00531
00532 mt.SetSampleSize(1);
00533
00534 if(CodecID == "S_TEXT/ASCII")
00535 {
00536 mt.majortype = MEDIATYPE_Text;
00537 mt.subtype = MEDIASUBTYPE_NULL;
00538 mt.formattype = FORMAT_None;
00539 mts.Add(mt);
00540 }
00541 else
00542 {
00543 mt.majortype = MEDIATYPE_Subtitle;
00544 mt.formattype = FORMAT_SubtitleInfo;
00545 SUBTITLEINFO* psi = (SUBTITLEINFO*)mt.AllocFormatBuffer(sizeof(SUBTITLEINFO) + pTE->CodecPrivate.GetSize());
00546 memset(psi, 0, mt.FormatLength());
00547 strncpy(psi->IsoLang, pTE->Language, countof(psi->IsoLang)-1);
00548 wcsncpy(psi->TrackName, pTE->Name, countof(psi->TrackName)-1);
00549 memcpy(mt.pbFormat + (psi->dwOffset = sizeof(SUBTITLEINFO)), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
00550
00551 mt.subtype =
00552 CodecID == "S_TEXT/UTF8" ? MEDIASUBTYPE_UTF8 :
00553 CodecID == "S_TEXT/SSA" || CodecID == "S_SSA" ? MEDIASUBTYPE_SSA :
00554 CodecID == "S_TEXT/ASS" || CodecID == "S_ASS" ? MEDIASUBTYPE_ASS :
00555 CodecID == "S_TEXT/USF" || CodecID == "S_USF" ? MEDIASUBTYPE_USF :
00556 CodecID == "S_VOBSUB" ? MEDIASUBTYPE_VOBSUB :
00557 MEDIASUBTYPE_NULL;
00558
00559 if(mt.subtype != MEDIASUBTYPE_NULL)
00560 mts.Add(mt);
00561 }
00562 }
00563
00564 if(mts.IsEmpty())
00565 {
00566 TRACE(_T("CMatroskaSourceFilter: Unsupported TrackType %s (%I64d)\n"), CString(CodecID), (UINT64)pTE->TrackType);
00567 continue;
00568 }
00569
00570 Name = CStringW(pTE->Language.IsEmpty() ? L"English" : CStringW(ISO6392ToLanguage(pTE->Language)))
00571 + (pTE->Name.IsEmpty() ? L"" : L", " + pTE->Name)
00572 + (L" (" + Name + L")");
00573
00574 HRESULT hr;
00575
00576 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CMatroskaSplitterOutputPin((int)pTE->MinCache, pTE->DefaultDuration/100, mts, Name, this, this, &hr));
00577 if(!pTE->Name.IsEmpty()) pPinOut->SetProperty(L"NAME", pTE->Name);
00578 if(pTE->Language.GetLength() == 3) pPinOut->SetProperty(L"LANG", CStringW(CString(pTE->Language)));
00579 AddOutputPin((DWORD)pTE->TrackNumber, pPinOut);
00580
00581 m_pTrackEntryMap[(DWORD)pTE->TrackNumber] = pTE;
00582 m_pOrderedTrackArray.Add(pTE);
00583 }
00584 }
00585
00586 Info& info = m_pFile->m_segment.SegmentInfo;
00587 m_rtNewStart = m_rtCurrent = 0;
00588 m_rtNewStop = m_rtStop = (REFERENCE_TIME)(info.Duration*info.TimeCodeScale/100);
00589
00590 #ifdef DEBUG
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 #endif
00602
00603 SetProperty(L"TITL", info.Title);
00604
00605
00606
00607
00608 {
00609 POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
00610 while(pos)
00611 {
00612 Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
00613
00614 POSITION pos = pA->AttachedFiles.GetHeadPosition();
00615 while(pos)
00616 {
00617 AttachedFile* pF = pA->AttachedFiles.GetNext(pos);
00618
00619 CArray<BYTE> pData;
00620 pData.SetSize(pF->FileDataLen);
00621 m_pFile->Seek(pF->FileDataPos);
00622 if(SUCCEEDED(m_pFile->Read(pData.GetData(), pData.GetSize())))
00623 ResAppend(pF->FileName, pF->FileDescription, CStringW(pF->FileMimeType), pData.GetData(), pData.GetSize());
00624 }
00625 }
00626 }
00627
00628
00629
00630 if(ChapterAtom* caroot = m_pFile->m_segment.FindChapterAtom(0))
00631 {
00632 CStringA str;
00633 str.ReleaseBufferSetLength(GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, str.GetBuffer(3), 3));
00634 CStringA ChapLanguage = CStringA(ISO6391To6392(str));
00635 if(ChapLanguage.GetLength() < 3) ChapLanguage = "eng";
00636
00637 POSITION pos = caroot->ChapterAtoms.GetHeadPosition();
00638 while(pos)
00639 {
00640
00641 if(ChapterAtom* ca = m_pFile->m_segment.FindChapterAtom(caroot->ChapterAtoms.GetNext(pos)->ChapterUID))
00642 {
00643 CStringW name, first;
00644
00645 POSITION pos = ca->ChapterDisplays.GetHeadPosition();
00646 while(pos)
00647 {
00648 ChapterDisplay* cd = ca->ChapterDisplays.GetNext(pos);
00649 if(first.IsEmpty()) first = cd->ChapString;
00650 if(cd->ChapLanguage == ChapLanguage) name = cd->ChapString;
00651 }
00652
00653 ChapAppend(ca->ChapterTimeStart / 100 - m_pFile->m_rtOffset, !name.IsEmpty() ? name : first);
00654 }
00655 }
00656 }
00657
00658 return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00659 }
00660
00661 void CMatroskaSplitterFilter::InstallFonts()
00662 {
00663 POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
00664 while(pos)
00665 {
00666 Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
00667
00668 POSITION p2 = pA->AttachedFiles.GetHeadPosition();
00669 while(p2)
00670 {
00671 AttachedFile* pF = pA->AttachedFiles.GetNext(p2);
00672
00673 if(pF->FileMimeType == "application/x-truetype-font")
00674 {
00675
00676
00677 if(BYTE* pData = new BYTE[(UINT)pF->FileDataLen])
00678 {
00679 m_pFile->Seek(pF->FileDataPos);
00680
00681 if(SUCCEEDED(m_pFile->Read(pData, pF->FileDataLen)))
00682 m_fontinst.InstallFont(pData, (UINT)pF->FileDataLen);
00683
00684 delete [] pData;
00685 }
00686 }
00687 }
00688 }
00689 }
00690
00691 void CMatroskaSplitterFilter::SendVorbisHeaderSample()
00692 {
00693 HRESULT hr;
00694
00695 POSITION pos = m_pTrackEntryMap.GetStartPosition();
00696 while(pos)
00697 {
00698 DWORD TrackNumber = 0;
00699 TrackEntry* pTE = NULL;
00700 m_pTrackEntryMap.GetNextAssoc(pos, TrackNumber, pTE);
00701
00702 CBaseSplitterOutputPin* pPin = GetOutputPin(TrackNumber);
00703
00704 if(!(pTE && pPin && pPin->IsConnected()))
00705 continue;
00706
00707 if(pTE->CodecID.ToString() == "A_VORBIS" && pPin->CurrentMediaType().subtype == MEDIASUBTYPE_Vorbis
00708 && pTE->CodecPrivate.GetSize() > 0)
00709 {
00710 BYTE* ptr = (BYTE*)pTE->CodecPrivate;
00711
00712 CList<long> sizes;
00713 long last = 0;
00714 for(BYTE n = *ptr++; n > 0; n--)
00715 {
00716 long size = 0;
00717 do {size += *ptr;} while(*ptr++ == 0xff);
00718 sizes.AddTail(size);
00719 last += size;
00720 }
00721 sizes.AddTail(pTE->CodecPrivate.GetSize() - (ptr - (BYTE*)pTE->CodecPrivate) - last);
00722
00723 hr = S_OK;
00724
00725 POSITION pos = sizes.GetHeadPosition();
00726 while(pos && SUCCEEDED(hr))
00727 {
00728 long len = sizes.GetNext(pos);
00729
00730 CAutoPtr<Packet> p(new Packet());
00731 p->TrackNumber = (DWORD)pTE->TrackNumber;
00732 p->rtStart = 0; p->rtStop = 1;
00733 p->bSyncPoint = FALSE;
00734 p->pData.SetSize(len);
00735 memcpy(p->pData.GetData(), ptr, len);
00736 ptr += len;
00737
00738 hr = DeliverPacket(p);
00739 }
00740
00741 if(FAILED(hr))
00742 TRACE(_T("ERROR: Vorbis initialization failed for stream %I64d\n"), TrackNumber);
00743 }
00744 }
00745 }
00746
00747 bool CMatroskaSplitterFilter::DemuxInit()
00748 {
00749 CMatroskaNode Root(m_pFile);
00750 if(!m_pFile
00751 || !(m_pSegment = Root.Child(0x18538067))
00752 || !(m_pCluster = m_pSegment->Child(0x1F43B675)))
00753 return(false);
00754
00755
00756
00757 if(m_pFile->m_segment.Cues.GetCount() == 0)
00758 {
00759 m_nOpenProgress = 0;
00760 m_pFile->m_segment.SegmentInfo.Duration.Set(0);
00761
00762 UINT64 TrackNumber = m_pFile->m_segment.GetMasterTrack();
00763
00764 CAutoPtr<Cue> pCue(new Cue());
00765
00766 do
00767 {
00768 Cluster c;
00769 c.ParseTimeCode(m_pCluster);
00770
00771 m_pFile->m_segment.SegmentInfo.Duration.Set((float)c.TimeCode - m_pFile->m_rtOffset/10000);
00772
00773 CAutoPtr<CuePoint> pCuePoint(new CuePoint());
00774 CAutoPtr<CueTrackPosition> pCueTrackPosition(new CueTrackPosition());
00775 pCuePoint->CueTime.Set(c.TimeCode);
00776 pCueTrackPosition->CueTrack.Set(TrackNumber);
00777 pCueTrackPosition->CueClusterPosition.Set(m_pCluster->m_filepos - m_pSegment->m_start);
00778 pCuePoint->CueTrackPositions.AddTail(pCueTrackPosition);
00779 pCue->CuePoints.AddTail(pCuePoint);
00780
00781 m_nOpenProgress = m_pFile->GetPos()*100/m_pFile->GetLength();
00782
00783 DWORD cmd;
00784 if(CheckRequest(&cmd))
00785 {
00786 if(cmd == CMD_EXIT) m_fAbort = true;
00787 else Reply(S_OK);
00788 }
00789 }
00790 while(!m_fAbort && m_pCluster->Next(true));
00791
00792 m_nOpenProgress = 100;
00793
00794 if(!m_fAbort) m_pFile->m_segment.Cues.AddTail(pCue);
00795
00796 m_fAbort = false;
00797 }
00798
00799 m_pCluster.Free();
00800 m_pBlock.Free();
00801
00802 return(true);
00803 }
00804
00805 void CMatroskaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00806 {
00807 m_pCluster = m_pSegment->Child(0x1F43B675);
00808 m_pBlock.Free();
00809
00810 if(rt > 0)
00811 {
00812 rt += m_pFile->m_rtOffset;
00813
00814 QWORD lastCueClusterPosition = -1;
00815
00816 Segment& s = m_pFile->m_segment;
00817
00818 UINT64 TrackNumber = s.GetMasterTrack();
00819
00820 POSITION pos1 = s.Cues.GetHeadPosition();
00821 while(pos1)
00822 {
00823 Cue* pCue = s.Cues.GetNext(pos1);
00824
00825 POSITION pos2 = pCue->CuePoints.GetTailPosition();
00826 while(pos2)
00827 {
00828 CuePoint* pCuePoint = pCue->CuePoints.GetPrev(pos2);
00829
00830 if(rt < s.GetRefTime(pCuePoint->CueTime))
00831 continue;
00832
00833 POSITION pos3 = pCuePoint->CueTrackPositions.GetHeadPosition();
00834 while(pos3)
00835 {
00836 CueTrackPosition* pCueTrackPositions = pCuePoint->CueTrackPositions.GetNext(pos3);
00837
00838 if(TrackNumber != pCueTrackPositions->CueTrack)
00839 continue;
00840
00841 if(lastCueClusterPosition == pCueTrackPositions->CueClusterPosition)
00842 continue;
00843
00844 lastCueClusterPosition = pCueTrackPositions->CueClusterPosition;
00845
00846 m_pCluster->SeekTo(m_pSegment->m_start + pCueTrackPositions->CueClusterPosition);
00847 m_pCluster->Parse();
00848
00849 bool fFoundKeyFrame = false;
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 {
00860 Cluster c;
00861 c.ParseTimeCode(m_pCluster);
00862
00863 if(CAutoPtr<CMatroskaNode> pBlock = m_pCluster->GetFirstBlock())
00864 {
00865 bool fPassedCueTime = false;
00866
00867 do
00868 {
00869 CBlockGroupNode bgn;
00870
00871 if(pBlock->m_id == 0xA0)
00872 {
00873 bgn.Parse(pBlock, true);
00874 }
00875 else if(pBlock->m_id == 0xA3)
00876 {
00877 CAutoPtr<BlockGroup> bg(new BlockGroup());
00878 bg->Block.Parse(pBlock, true);
00879 if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0);
00880 bgn.AddTail(bg);
00881 }
00882
00883 POSITION pos4 = bgn.GetHeadPosition();
00884 while(!fPassedCueTime && pos4)
00885 {
00886 BlockGroup* bg = bgn.GetNext(pos4);
00887
00888 if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && rt < s.GetRefTime(c.TimeCode + bg->Block.TimeCode)
00889 || rt + 5000000i64 < s.GetRefTime(c.TimeCode + bg->Block.TimeCode))
00890 {
00891 fPassedCueTime = true;
00892 }
00893 else if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && !bg->ReferenceBlock.IsValid())
00894 {
00895 fFoundKeyFrame = true;
00896 m_pBlock = pBlock->Copy();
00897 }
00898 }
00899 }
00900 while(!fPassedCueTime && pBlock->NextBlock());
00901 }
00902 }
00903
00904 if(fFoundKeyFrame)
00905 pos1 = pos2 = pos3 = NULL;
00906 }
00907 }
00908 }
00909
00910 if(!m_pBlock)
00911 {
00912 m_pCluster = m_pSegment->Child(0x1F43B675);
00913 }
00914 }
00915 }
00916
00917 bool CMatroskaSplitterFilter::DemuxLoop()
00918 {
00919 HRESULT hr = S_OK;
00920
00921 SendVorbisHeaderSample();
00922
00923 do
00924 {
00925 Cluster c;
00926 c.ParseTimeCode(m_pCluster);
00927
00928 if(!m_pBlock) m_pBlock = m_pCluster->GetFirstBlock();
00929 if(!m_pBlock) continue;
00930
00931 do
00932 {
00933 CBlockGroupNode bgn;
00934
00935 if(m_pBlock->m_id == 0xA0)
00936 {
00937 bgn.Parse(m_pBlock, true);
00938 }
00939 else if(m_pBlock->m_id == 0xA3)
00940 {
00941 CAutoPtr<BlockGroup> bg(new BlockGroup());
00942 bg->Block.Parse(m_pBlock, true);
00943 if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0);
00944 bgn.AddTail(bg);
00945 }
00946
00947 while(bgn.GetCount())
00948 {
00949 CAutoPtr<MatroskaPacket> p(new MatroskaPacket());
00950 p->bg = bgn.RemoveHead();
00951
00952 p->bSyncPoint = !p->bg->ReferenceBlock.IsValid();
00953 p->TrackNumber = (DWORD)p->bg->Block.TrackNumber;
00954
00955 TrackEntry *pTE = m_pTrackEntryMap[p->TrackNumber];
00956 p->rtStart = m_pFile->m_segment.GetRefTime((REFERENCE_TIME)c.TimeCode + p->bg->Block.TimeCode);
00957 p->rtStop = p->rtStart + (p->bg->BlockDuration.IsValid() ? m_pFile->m_segment.GetRefTime(p->bg->BlockDuration) : 1);
00958
00959
00960 if(pTE && (pTE->TrackType == TrackEntry::TypeSubtitle) && (!p->bg->BlockDuration.IsValid()))
00961 {
00962 p->bg->BlockDuration.Set(1);
00963 p->rtStop = p->rtStart;
00964 }
00965
00966 POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
00967 while(pos)
00968 {
00969 CBinary* pb = p->bg->Block.BlockData.GetNext(pos);
00970 m_pTrackEntryMap[p->TrackNumber]->Expand(*pb, ContentEncoding::AllFrameContents);
00971 }
00972
00973
00974 p->rtStart -= m_pFile->m_rtOffset;
00975 p->rtStop -= m_pFile->m_rtOffset;
00976
00977 hr = DeliverPacket(p);
00978 }
00979 }
00980 while(m_pBlock->NextBlock() && SUCCEEDED(hr) && !CheckRequest(NULL));
00981
00982 m_pBlock.Free();
00983 }
00984 while(m_pFile->GetPos() < m_pFile->m_segment.pos + m_pFile->m_segment.len
00985 && m_pCluster->Next(true) && SUCCEEDED(hr) && !CheckRequest(NULL));
00986
00987 m_pCluster.Free();
00988
00989 return(true);
00990 }
00991
00992
00993
00994 STDMETHODIMP CMatroskaSplitterFilter::GetDuration(LONGLONG* pDuration)
00995 {
00996 CheckPointer(pDuration, E_POINTER);
00997 CheckPointer(m_pFile, VFW_E_NOT_CONNECTED);
00998
00999 Segment& s = m_pFile->m_segment;
01000 *pDuration = s.GetRefTime((INT64)s.SegmentInfo.Duration);
01001
01002 return S_OK;
01003 }
01004
01005
01006
01007 STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrameCount(UINT& nKFs)
01008 {
01009 if(!m_pFile) return E_UNEXPECTED;
01010
01011 HRESULT hr = S_OK;
01012
01013 nKFs = 0;
01014
01015 POSITION pos = m_pFile->m_segment.Cues.GetHeadPosition();
01016 while(pos) nKFs += m_pFile->m_segment.Cues.GetNext(pos)->CuePoints.GetCount();
01017
01018 return hr;
01019 }
01020
01021 STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
01022 {
01023 CheckPointer(pFormat, E_POINTER);
01024 CheckPointer(pKFs, E_POINTER);
01025
01026 if(!m_pFile) return E_UNEXPECTED;
01027 if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
01028
01029 UINT nKFsTmp = 0;
01030
01031 POSITION pos1 = m_pFile->m_segment.Cues.GetHeadPosition();
01032 while(pos1 && nKFsTmp < nKFs)
01033 {
01034 Cue* pCue = m_pFile->m_segment.Cues.GetNext(pos1);
01035
01036 POSITION pos2 = pCue->CuePoints.GetHeadPosition();
01037 while(pos2 && nKFsTmp < nKFs)
01038 pKFs[nKFsTmp++] = m_pFile->m_segment.GetRefTime(pCue->CuePoints.GetNext(pos2)->CueTime);
01039 }
01040
01041 nKFs = nKFsTmp;
01042
01043 return S_OK;
01044 }
01045
01046
01047
01048
01049
01050 CMatroskaSourceFilter::CMatroskaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
01051 : CMatroskaSplitterFilter(pUnk, phr)
01052 {
01053 m_clsid = __uuidof(this);
01054 m_pInput.Free();
01055 }
01056
01057
01058
01059
01060
01061 CMatroskaSplitterOutputPin::CMatroskaSplitterOutputPin(
01062 int nMinCache, REFERENCE_TIME rtDefaultDuration,
01063 CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
01064 : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
01065 , m_nMinCache(nMinCache), m_rtDefaultDuration(rtDefaultDuration)
01066 {
01067 m_nMinCache = max(m_nMinCache, 1);
01068 }
01069
01070 CMatroskaSplitterOutputPin::~CMatroskaSplitterOutputPin()
01071 {
01072 }
01073
01074 HRESULT CMatroskaSplitterOutputPin::DeliverEndFlush()
01075 {
01076 {
01077 CAutoLock cAutoLock(&m_csQueue);
01078 m_packets.RemoveAll();
01079 m_rob.RemoveAll();
01080 m_tos.RemoveAll();
01081 }
01082
01083 return __super::DeliverEndFlush();
01084 }
01085
01086 HRESULT CMatroskaSplitterOutputPin::DeliverEndOfStream()
01087 {
01088 CAutoLock cAutoLock(&m_csQueue);
01089
01090
01091
01092 while(m_rob.GetCount())
01093 {
01094 MatroskaPacket* mp = m_rob.RemoveHead();
01095 if(m_rob.GetCount() && !mp->bg->BlockDuration.IsValid())
01096 mp->rtStop = m_rob.GetHead()->rtStart;
01097 else if(m_rob.GetCount() == 0 && m_rtDefaultDuration > 0)
01098 mp->rtStop = mp->rtStart + m_rtDefaultDuration;
01099
01100 timeoverride to = {mp->rtStart, mp->rtStop};
01101 m_tos.AddTail(to);
01102 }
01103
01104 while(m_packets.GetCount())
01105 {
01106 HRESULT hr = DeliverBlock(m_packets.RemoveHead());
01107 if(hr != S_OK) return hr;
01108 }
01109
01110 return __super::DeliverEndOfStream();
01111 }
01112
01113 HRESULT CMatroskaSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
01114 {
01115 MatroskaPacket* mp = dynamic_cast<MatroskaPacket*>(p.m_p);
01116 if(!mp) return __super::DeliverPacket(p);
01117
01118
01119
01120 CAutoLock cAutoLock(&m_csQueue);
01121
01122 CAutoPtr<MatroskaPacket> p2;
01123 p.Detach();
01124 p2.Attach(mp);
01125 m_packets.AddTail(p2);
01126
01127 POSITION pos = m_rob.GetTailPosition();
01128 for(int i = m_nMinCache-1; i > 0 && pos && mp->bg->ReferencePriority < m_rob.GetAt(pos)->bg->ReferencePriority; i--)
01129 m_rob.GetPrev(pos);
01130
01131 if(!pos) m_rob.AddHead(mp);
01132 else m_rob.InsertAfter(pos, mp);
01133
01134 mp = NULL;
01135
01136 if(m_rob.GetCount() == m_nMinCache+1)
01137 {
01138 ASSERT(m_nMinCache > 0);
01139 pos = m_rob.GetHeadPosition();
01140 MatroskaPacket* mp1 = m_rob.GetNext(pos);
01141 MatroskaPacket* mp2 = m_rob.GetNext(pos);
01142 if(!mp1->bg->BlockDuration.IsValid())
01143 {
01144 mp1->bg->BlockDuration.Set(1);
01145
01146 if(mp1->rtStart >= mp2->rtStart)
01147 {
01148
01149
01150
01151
01152
01153 }
01154 else
01155 {
01156 mp1->rtStop = mp2->rtStart;
01157 }
01158 }
01159 }
01160
01161 while(m_packets.GetCount())
01162 {
01163 mp = m_packets.GetHead();
01164 if(!mp->bg->BlockDuration.IsValid()) break;
01165
01166 mp = m_rob.RemoveHead();
01167 timeoverride to = {mp->rtStart, mp->rtStop};
01168 m_tos.AddTail(to);
01169
01170 HRESULT hr = DeliverBlock(m_packets.RemoveHead());
01171 if(hr != S_OK) return hr;
01172 }
01173
01174 return S_OK;
01175 }
01176
01177 HRESULT CMatroskaSplitterOutputPin::DeliverBlock(MatroskaPacket* p)
01178 {
01179 HRESULT hr = S_FALSE;
01180
01181 if(m_tos.GetCount())
01182 {
01183 timeoverride to = m_tos.RemoveHead();
01184
01185 TRACE(_T("(track=%d) %I64d, %I64d -> %I64d, %I64d (buffcnt=%d)\n"),
01186 p->TrackNumber, p->rtStart, p->rtStop, to.rtStart, to.rtStop,
01187 QueueCount());
01188
01189 p->rtStart = to.rtStart;
01190 p->rtStop = to.rtStop;
01191 }
01192
01193 REFERENCE_TIME
01194 rtStart = p->rtStart,
01195 rtDelta = (p->rtStop - p->rtStart) / p->bg->Block.BlockData.GetCount(),
01196 rtStop = p->rtStart + rtDelta;
01197
01198 POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
01199 while(pos)
01200 {
01201 CAutoPtr<Packet> tmp(new Packet());
01202 tmp->TrackNumber = p->TrackNumber;
01203 tmp->bDiscontinuity = p->bDiscontinuity;
01204 tmp->bSyncPoint = p->bSyncPoint;
01205 tmp->rtStart = rtStart;
01206 tmp->rtStop = rtStop;
01207 tmp->pData.Copy(*p->bg->Block.BlockData.GetNext(pos));
01208 if(S_OK != (hr = DeliverPacket(tmp))) break;
01209
01210 rtStart += rtDelta;
01211 rtStop += rtDelta;
01212
01213 p->bSyncPoint = false;
01214 p->bDiscontinuity = false;
01215 }
01216
01217 return hr;
01218 }
01219
01220
01221
01222 TrackEntry* CMatroskaSplitterFilter::GetTrackEntryAt(UINT aTrackIdx)
01223 {
01224 if(aTrackIdx < 0 || aTrackIdx >= m_pOrderedTrackArray.GetCount())
01225 return NULL;
01226 return m_pOrderedTrackArray[aTrackIdx];
01227 }
01228
01229 STDMETHODIMP_(UINT) CMatroskaSplitterFilter::GetTrackCount()
01230 {
01231 return m_pTrackEntryMap.GetCount();
01232 }
01233
01234 STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackInfo(UINT aTrackIdx, struct TrackElement* pStructureToFill)
01235 {
01236 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01237 if(pTE == NULL)
01238 return FALSE;
01239
01240 pStructureToFill->FlagDefault = !!pTE->FlagDefault;
01241 pStructureToFill->FlagLacing = !!pTE->FlagLacing;
01242 strncpy(pStructureToFill->Language, pTE->Language, 3);
01243 if(pStructureToFill->Language[0] == '\0')
01244 strncpy(pStructureToFill->Language, "eng", 3);
01245 pStructureToFill->Language[3] = '\0';
01246 pStructureToFill->MaxCache = (UINT)pTE->MaxCache;
01247 pStructureToFill->MinCache = (UINT)pTE->MinCache;
01248 pStructureToFill->Type = (BYTE)pTE->TrackType;
01249 return TRUE;
01250 }
01251
01252 STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackExtendedInfo(UINT aTrackIdx, void* pStructureToFill)
01253 {
01254 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01255 if(pTE == NULL)
01256 return FALSE;
01257
01258 if(pTE->TrackType == TrackEntry::TypeVideo)
01259 {
01260 TrackExtendedInfoVideo* pTEIV = (TrackExtendedInfoVideo*)pStructureToFill;
01261 pTEIV->AspectRatioType = (BYTE)pTE->v.AspectRatioType;
01262 pTEIV->DisplayUnit = (BYTE)pTE->v.DisplayUnit;
01263 pTEIV->DisplayWidth = (UINT)pTE->v.DisplayWidth;
01264 pTEIV->DisplayHeight = (UINT)pTE->v.DisplayHeight;
01265 pTEIV->Interlaced = !!pTE->v.FlagInterlaced;
01266 pTEIV->PixelWidth = (UINT)pTE->v.PixelWidth;
01267 pTEIV->PixelHeight = (UINT)pTE->v.PixelHeight;
01268 } else if(pTE->TrackType == TrackEntry::TypeAudio) {
01269 TrackExtendedInfoAudio* pTEIA = (TrackExtendedInfoAudio*)pStructureToFill;
01270 pTEIA->BitDepth = (UINT)pTE->a.BitDepth;
01271 pTEIA->Channels = (UINT)pTE->a.Channels;
01272 pTEIA->OutputSamplingFrequency = pTE->a.OutputSamplingFrequency;
01273 pTEIA->SamplingFreq = pTE->a.SamplingFrequency;
01274 } else {
01275 return FALSE;
01276 }
01277
01278 return TRUE;
01279 }
01280
01281 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackName(UINT aTrackIdx)
01282 {
01283 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01284 if(pTE == NULL)
01285 return NULL;
01286 return pTE->Name.AllocSysString();
01287 }
01288
01289 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecID(UINT aTrackIdx)
01290 {
01291 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01292 if(pTE == NULL)
01293 return NULL;
01294 return pTE->CodecID.ToString().AllocSysString();
01295 }
01296
01297 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecName(UINT aTrackIdx)
01298 {
01299 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01300 if(pTE == NULL)
01301 return NULL;
01302 return pTE->CodecName.AllocSysString();
01303 }
01304
01305 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecInfoURL(UINT aTrackIdx)
01306 {
01307 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01308 if(pTE == NULL)
01309 return NULL;
01310 return pTE->CodecInfoURL.AllocSysString();
01311 }
01312
01313 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecDownloadURL(UINT aTrackIdx)
01314 {
01315 TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01316 if(pTE == NULL)
01317 return NULL;
01318 return pTE->CodecDownloadURL.AllocSysString();
01319 }