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

多媒体编程

开发平台:

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 "MatroskaSplitter.h"
  24. #include "......DSUtilDSUtil.h"
  25. #include <initguid.h>
  26. #include "........includematroskamatroska.h"
  27. #include "........includeoggOggDS.h"
  28. #include "........includemoreuuids.h"
  29. using namespace MatroskaReader;
  30. #ifdef REGISTER_FILTER
  31. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  32. {
  33. {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska},
  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(CMatroskaSplitterFilter), L"Matroska Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
  44. {&__uuidof(CMatroskaSourceFilter), L"Matroska Source", MERIT_NORMAL, 0, NULL},
  45. };
  46. CFactoryTemplate g_Templates[] =
  47. {
  48. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaSplitterFilter>, NULL, &sudFilter[0]},
  49. {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CMatroskaSourceFilter>, NULL, &sudFilter[1]},
  50. };
  51. int g_cTemplates = countof(g_Templates);
  52. STDAPI DllRegisterServer()
  53. {
  54. RegisterSourceFilter(
  55. CLSID_AsyncReader, 
  56. MEDIASUBTYPE_Matroska, 
  57. _T("0,4,,1A45DFA3"), 
  58. _T(".mkv"), _T(".mka"), _T(".mks"), NULL);
  59. return AMovieDllRegisterServer2(TRUE);
  60. }
  61. STDAPI DllUnregisterServer()
  62. {
  63. UnRegisterSourceFilter(MEDIASUBTYPE_Matroska);
  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. // CMatroskaSplitterFilter
  74. //
  75. CMatroskaSplitterFilter::CMatroskaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
  76. : CBaseSplitterFilter(NAME("CMatroskaSplitterFilter"), pUnk, phr, __uuidof(this))
  77. {
  78. }
  79. CMatroskaSplitterFilter::~CMatroskaSplitterFilter()
  80. {
  81. }
  82. STDMETHODIMP CMatroskaSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  83. {
  84. CheckPointer(ppv, E_POINTER);
  85. return 
  86. QI(ITrackInfo)
  87. __super::NonDelegatingQueryInterface(riid, ppv);
  88. }
  89. #include <vector>
  90. HRESULT CMatroskaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
  91. {
  92. CheckPointer(pAsyncReader, E_POINTER);
  93. HRESULT hr = E_FAIL;
  94. m_pFile.Free();
  95. m_pTrackEntryMap.RemoveAll();
  96. m_pOrderedTrackArray.RemoveAll();
  97. m_pFile.Attach(new CMatroskaFile(pAsyncReader, hr));
  98. if(!m_pFile) return E_OUTOFMEMORY;
  99. if(FAILED(hr)) {m_pFile.Free(); return hr;}
  100. m_rtNewStart = m_rtCurrent = 0;
  101. m_rtNewStop = m_rtStop = 0;
  102. int iVideo = 1, iAudio = 1, iSubtitle = 1;
  103. POSITION pos = m_pFile->m_segment.Tracks.GetHeadPosition();
  104. while(pos)
  105. {
  106. Track* pT = m_pFile->m_segment.Tracks.GetNext(pos);
  107. POSITION pos2 = pT->TrackEntries.GetHeadPosition();
  108. while(pos2)
  109. {
  110. TrackEntry* pTE = pT->TrackEntries.GetNext(pos2);
  111. if(!pTE->Expand(pTE->CodecPrivate, ContentEncoding::TracksPrivateData))
  112. continue;
  113. CStringA CodecID = pTE->CodecID.ToString();
  114. CStringW Name;
  115. Name.Format(L"Output %I64d", (UINT64)pTE->TrackNumber);
  116. CMediaType mt;
  117. CArray<CMediaType> mts;
  118. mt.SetSampleSize(1);
  119. if(pTE->TrackType == TrackEntry::TypeVideo)
  120. {
  121. Name.Format(L"Video %d", iVideo++);
  122. mt.majortype = MEDIATYPE_Video;
  123. if(CodecID == "V_MS/VFW/FOURCC")
  124. {
  125. mt.formattype = FORMAT_VideoInfo;
  126. VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount() - sizeof(BITMAPINFOHEADER));
  127. memset(mt.Format(), 0, mt.FormatLength());
  128. memcpy(&pvih->bmiHeader, (BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
  129. mt.subtype = FOURCCMap(pvih->bmiHeader.biCompression);
  130. switch(pvih->bmiHeader.biCompression)
  131. {
  132. case BI_RGB: case BI_BITFIELDS: mt.subtype = 
  133. pvih->bmiHeader.biBitCount == 1 ? MEDIASUBTYPE_RGB1 :
  134. pvih->bmiHeader.biBitCount == 4 ? MEDIASUBTYPE_RGB4 :
  135. pvih->bmiHeader.biBitCount == 8 ? MEDIASUBTYPE_RGB8 :
  136. pvih->bmiHeader.biBitCount == 16 ? MEDIASUBTYPE_RGB565 :
  137. pvih->bmiHeader.biBitCount == 24 ? MEDIASUBTYPE_RGB24 :
  138. pvih->bmiHeader.biBitCount == 32 ? MEDIASUBTYPE_ARGB32 :
  139. MEDIASUBTYPE_NULL;
  140. break;
  141. // case BI_RLE8: mt.subtype = MEDIASUBTYPE_RGB8; break;
  142. // case BI_RLE4: mt.subtype = MEDIASUBTYPE_RGB4; break;
  143. }
  144. mts.Add(mt);
  145. }
  146. else if(CodecID == "V_UNCOMPRESSED")
  147. {
  148. }
  149. else if(CodecID.Find("V_MPEG4/ISO/AVC") == 0)
  150. {
  151. if(pTE->CodecPrivate.GetSize() >= 6)
  152. {
  153. BYTE sps = pTE->CodecPrivate[5] & 0x1f;
  154. std::vector<BYTE> avcC;
  155. for(int i = 0, j = pTE->CodecPrivate.GetSize(); i < j; i++)
  156. avcC.push_back(pTE->CodecPrivate[i]);
  157. std::vector<BYTE> sh;
  158. unsigned jj = 6;
  159. while (sps--) {
  160.   if (jj + 2 > avcC.size())
  161.     goto avcfail;
  162.   unsigned spslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
  163.   if (jj + 2 + spslen > avcC.size())
  164.     goto avcfail;
  165.   unsigned cur = sh.size();
  166.   sh.resize(cur + spslen + 2, 0);
  167.   std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + spslen,sh.begin() + cur);
  168.   jj += 2 + spslen;
  169. }
  170. if (jj + 1 > avcC.size())
  171.   continue;
  172. unsigned pps = avcC[jj++];
  173. while (pps--) {
  174.   if (jj + 2 > avcC.size())
  175.     goto avcfail;
  176.   unsigned ppslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
  177.   if (jj + 2 + ppslen > avcC.size())
  178.     goto avcfail;
  179.   unsigned cur = sh.size();
  180.   sh.resize(cur + ppslen + 2, 0);
  181.   std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + ppslen, sh.begin() + cur);
  182.   jj += 2 + ppslen;
  183. }
  184. goto avcsuccess;
  185. avcfail:
  186. continue;
  187. avcsuccess:
  188. CArray<BYTE> data;
  189. data.SetSize(sh.size());
  190. std::copy(sh.begin(), sh.end(), (BYTE*)data.GetData());
  191. mt.subtype = FOURCCMap('1CVA');
  192. mt.formattype = FORMAT_MPEG2Video;
  193. MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)mt.AllocFormatBuffer(FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + data.GetSize());
  194. memset(mt.Format(), 0, mt.FormatLength());
  195. pm2vi->hdr.bmiHeader.biSize = sizeof(pm2vi->hdr.bmiHeader);
  196. pm2vi->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
  197. pm2vi->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
  198. pm2vi->hdr.bmiHeader.biCompression = '1cva';
  199. pm2vi->hdr.bmiHeader.biPlanes = 1;
  200. pm2vi->hdr.bmiHeader.biBitCount = 24;
  201. pm2vi->dwProfile = pTE->CodecPrivate[1];
  202. pm2vi->dwLevel = pTE->CodecPrivate[3];
  203. pm2vi->dwFlags = (pTE->CodecPrivate[4] & 3) + 1;
  204. BYTE* pSequenceHeader = (BYTE*)pm2vi->dwSequenceHeader;
  205. memcpy(pSequenceHeader, data.GetData(), data.GetSize());
  206. pm2vi->cbSequenceHeader = data.GetSize();
  207. mts.Add(mt);
  208. }
  209. }
  210. else if(CodecID.Find("V_MPEG4/") == 0) // TODO: find out which V_MPEG4/*/* ids can be mapped to 'mp4v'
  211. {
  212. mt.subtype = FOURCCMap('v4pm');
  213. mt.formattype = FORMAT_VideoInfo;
  214. VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  215. memset(pvih, 0, mt.FormatLength());
  216. pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
  217. pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
  218. pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
  219. pvih->bmiHeader.biCompression = 'v4pm';
  220. mts.Add(mt);
  221. // TODO: add (-1,0) dummy frame to timeoverride when it is /asp (that is having b-frames almost certainly)
  222. }
  223. else if(CodecID.Find("V_REAL/RV") == 0)
  224. {
  225. mt.subtype = FOURCCMap('00VR' + ((CodecID[9]-0x30)<<16));
  226. mt.formattype = FORMAT_VideoInfo;
  227. VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount());
  228. memset(mt.Format(), 0, mt.FormatLength());
  229. memcpy(mt.Format() + sizeof(VIDEOINFOHEADER), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
  230. pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
  231. pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
  232. pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
  233. pvih->bmiHeader.biCompression = mt.subtype.Data1;
  234. mts.Add(mt);
  235. }
  236. else if(CodecID == "V_DIRAC")
  237. {
  238. mt.subtype = MEDIASUBTYPE_DiracVideo;
  239. mt.formattype = FORMAT_DiracVideoInfo;
  240. DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)mt.AllocFormatBuffer(FIELD_OFFSET(DIRACINFOHEADER, dwSequenceHeader) + pTE->CodecPrivate.GetSize());
  241. memset(mt.Format(), 0, mt.FormatLength());
  242. dvih->hdr.bmiHeader.biSize = sizeof(dvih->hdr.bmiHeader);
  243. dvih->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
  244. dvih->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
  245. dvih->hdr.dwPictAspectRatioX = dvih->hdr.bmiHeader.biWidth;
  246. dvih->hdr.dwPictAspectRatioY = dvih->hdr.bmiHeader.biHeight;
  247. BYTE* pSequenceHeader = (BYTE*)dvih->dwSequenceHeader;
  248. memcpy(pSequenceHeader, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
  249. dvih->cbSequenceHeader = pTE->CodecPrivate.GetSize();
  250. mts.Add(mt);
  251. }
  252. else if(CodecID == "V_MPEG2")
  253. {
  254. BYTE* seqhdr = pTE->CodecPrivate.GetData();
  255. DWORD len = pTE->CodecPrivate.GetSize();
  256. int w = pTE->v.PixelWidth;
  257. int h = pTE->v.PixelHeight;
  258. if(MakeMPEG2MediaType(mt, seqhdr, len, w, h))
  259. mts.Add(mt);
  260. }
  261. /*
  262. else if(CodecID == "V_DSHOW/MPEG1VIDEO") // V_MPEG1
  263. {
  264. mt.majortype = MEDIATYPE_Video;
  265. mt.subtype = MEDIASUBTYPE_MPEG1Payload;
  266. mt.formattype = FORMAT_MPEGVideo;
  267. MPEG1VIDEOINFO* pm1vi = (MPEG1VIDEOINFO*)mt.AllocFormatBuffer(pTE->CodecPrivate.GetSize());
  268. memcpy(pm1vi, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
  269. mt.SetSampleSize(pm1vi->hdr.bmiHeader.biWidth*pm1vi->hdr.bmiHeader.biHeight*4);
  270. mts.Add(mt);
  271. }
  272. */
  273. REFERENCE_TIME AvgTimePerFrame = 0;
  274.                 if(pTE->v.FramePerSec > 0)
  275. AvgTimePerFrame = (REFERENCE_TIME)(10000000i64 / pTE->v.FramePerSec);
  276. else if(pTE->DefaultDuration > 0)
  277. AvgTimePerFrame = (REFERENCE_TIME)pTE->DefaultDuration / 100;
  278. if(AvgTimePerFrame)
  279. {
  280. for(int i = 0; i < mts.GetCount(); i++)
  281. {
  282. if(mts[i].formattype == FORMAT_VideoInfo
  283. || mts[i].formattype == FORMAT_VideoInfo2
  284. || mts[i].formattype == FORMAT_MPEG2Video)
  285. {
  286. ((VIDEOINFOHEADER*)mts[i].Format())->AvgTimePerFrame = AvgTimePerFrame;
  287. }
  288. }
  289. }
  290. if(pTE->v.DisplayWidth != 0 && pTE->v.DisplayHeight != 0)
  291. {
  292. for(int i = 0; i < mts.GetCount(); i++)
  293. {
  294. if(mts[i].formattype == FORMAT_VideoInfo)
  295. {
  296. DWORD vih1 = FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
  297. DWORD vih2 = FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader);
  298. DWORD bmi = mts[i].FormatLength() - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
  299. mt.formattype = FORMAT_VideoInfo2;
  300. mt.AllocFormatBuffer(vih2 + bmi);
  301. memcpy(mt.Format(), mts[i].Format(), vih1);
  302. memset(mt.Format() + vih1, 0, vih2 - vih1);
  303. memcpy(mt.Format() + vih2, mts[i].Format() + vih1, bmi);
  304. ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
  305. ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
  306. mts.InsertAt(i++, mt);
  307. }
  308. else if(mts[i].formattype == FORMAT_MPEG2Video)
  309. {
  310. ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
  311. ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
  312. }
  313. }
  314. }
  315. }
  316. else if(pTE->TrackType == TrackEntry::TypeAudio)
  317. {
  318. Name.Format(L"Audio %d", iAudio++);
  319. mt.majortype = MEDIATYPE_Audio;
  320. mt.formattype = FORMAT_WaveFormatEx;
  321. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX));
  322. memset(pwfe, 0, mt.FormatLength());
  323. pwfe->nChannels = (WORD)pTE->a.Channels;
  324. pwfe->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
  325. pwfe->wBitsPerSample = (WORD)pTE->a.BitDepth;
  326. pwfe->nBlockAlign = (WORD)((pwfe->nChannels * pwfe->wBitsPerSample) / 8);
  327. pwfe->nAvgBytesPerSec = pwfe->nSamplesPerSec * pwfe->nBlockAlign;
  328. mt.SetSampleSize(256000);
  329. if(CodecID == "A_VORBIS")
  330. {
  331. BYTE* p = (BYTE*)pTE->CodecPrivate;
  332. CArray<long> sizes;
  333. for(BYTE n = *p++; n > 0; n--)
  334. {
  335. long size = 0;
  336. do {size += *p;} while(*p++ == 0xff);
  337. sizes.Add(size);
  338. }
  339. long totalsize = 0;
  340. for(int i = 0; i < sizes.GetCount(); i++)
  341. totalsize += sizes[i];
  342. sizes.Add(pTE->CodecPrivate.GetSize() - (p - (BYTE*)pTE->CodecPrivate) - totalsize);
  343. totalsize += sizes[sizes.GetCount()-1];
  344. if(sizes.GetCount() == 3)
  345. {
  346. mt.subtype = MEDIASUBTYPE_Vorbis2;
  347. mt.formattype = FORMAT_VorbisFormat2;
  348. VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT2) + totalsize);
  349. memset(pvf2, 0, mt.FormatLength());
  350. pvf2->Channels = (WORD)pTE->a.Channels;
  351. pvf2->SamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
  352. pvf2->BitsPerSample = (DWORD)pTE->a.BitDepth;
  353. BYTE* p2 = mt.Format() + sizeof(VORBISFORMAT2);
  354. for(int i = 0; i < sizes.GetCount(); p += sizes[i], p2 += sizes[i], i++)
  355. memcpy(p2, p, pvf2->HeaderSize[i] = sizes[i]);
  356. mts.Add(mt);
  357. }
  358. mt.subtype = MEDIASUBTYPE_Vorbis;
  359. mt.formattype = FORMAT_VorbisFormat;
  360. VORBISFORMAT* pvf = (VORBISFORMAT*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT));
  361. memset(pvf, 0, mt.FormatLength());
  362. pvf->nChannels = (WORD)pTE->a.Channels;
  363. pvf->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
  364. pvf->nMinBitsPerSec = pvf->nMaxBitsPerSec = pvf->nAvgBitsPerSec = -1;
  365. mts.Add(mt);
  366. }
  367. else if(CodecID == "A_MPEG/L3")
  368. {
  369. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MP3);
  370. mts.Add(mt);
  371. }
  372. else if(CodecID == "A_MPEG/L2")
  373. {
  374. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MPEG);
  375. mts.Add(mt);
  376. // TODO : add MPEG1WAVEFORMAT
  377. }
  378. else if(CodecID == "A_AC3")
  379. {
  380. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DOLBY_AC3);
  381. mts.Add(mt);
  382. }
  383. else if(CodecID == "A_DTS")
  384. {
  385. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DVD_DTS);
  386. mts.Add(mt);
  387. }
  388. else if(CodecID == "A_FLAC")
  389. {
  390. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_FLAC);
  391. pwfe->cbSize = pTE->CodecPrivate.GetCount();
  392. BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount()) + sizeof(WAVEFORMATEX);
  393. memcpy(pExtra, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
  394. mts.Add(mt);
  395. mt.subtype = MEDIASUBTYPE_FLAC_FRAMED;
  396. mts.InsertAt(0, mt);
  397. }
  398. else if(CodecID == "A_TTA1")
  399. {
  400. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_TTA1);
  401. mts.Add(mt);
  402. }
  403. else if(CodecID == "A_MS/ACM")
  404. {
  405. pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(pTE->CodecPrivate.GetCount());
  406. memcpy(pwfe, (WAVEFORMATEX*)(BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
  407. mt.subtype = FOURCCMap(pwfe->wFormatTag);
  408. mts.Add(mt);
  409. }
  410. else if(CodecID == "A_PCM/INT/LIT")
  411. {
  412. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_PCM);
  413. mts.Add(mt);
  414. }
  415. else if(CodecID == "A_PCM/FLOAT/IEEE")
  416. {
  417. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_IEEE_FLOAT);
  418. mts.Add(mt);
  419. }
  420. else if(CodecID.Find("A_AAC/") == 0)
  421. {
  422. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_AAC);
  423. BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX)+5) + sizeof(WAVEFORMATEX);
  424. (pwfe = (WAVEFORMATEX*)mt.pbFormat)->cbSize = 2;
  425. int profile;
  426. if(CodecID.Find("/MAIN") > 0) profile = 0;
  427. else if(CodecID.Find("/SBR") > 0) profile = -1;
  428. else if(CodecID.Find("/LC") > 0) profile = 1;
  429. else if(CodecID.Find("/SSR") > 0) profile = 2;
  430. else if(CodecID.Find("/LTP") > 0) profile = 3;
  431. else continue;
  432. WORD cbSize = MakeAACInitData(pExtra, profile, pwfe->nSamplesPerSec, pTE->a.Channels);
  433. mts.Add(mt);
  434. if(profile < 0)
  435. {
  436. pwfe->cbSize = cbSize;
  437. pwfe->nSamplesPerSec *= 2;
  438. pwfe->nAvgBytesPerSec *= 2;
  439. mts.InsertAt(0, mt);
  440. }
  441. }
  442. else if(CodecID.Find("A_REAL/") == 0 && CodecID.GetLength() >= 11)
  443. {
  444. mt.bTemporalCompression = TRUE;
  445. mt.subtype = FOURCCMap((DWORD)CodecID[7]|((DWORD)CodecID[8]<<8)|((DWORD)CodecID[9]<<16)|((DWORD)CodecID[10]<<24));
  446. BYTE* p = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount());
  447. memcpy(p + sizeof(WAVEFORMATEX), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
  448. mts.Add(mt);
  449. }
  450. }
  451. else if(pTE->TrackType == TrackEntry::TypeSubtitle)
  452. {
  453. if(iSubtitle == 1) InstallFonts();
  454. Name.Format(L"Subtitle %d", iSubtitle++);
  455. mt.SetSampleSize(1);
  456. if(CodecID == "S_TEXT/ASCII")
  457. {
  458. mt.majortype = MEDIATYPE_Text;
  459. mt.subtype = MEDIASUBTYPE_NULL;
  460. mt.formattype = FORMAT_None;
  461. mts.Add(mt);
  462. }
  463. else
  464. {
  465. mt.majortype = MEDIATYPE_Subtitle;
  466. mt.formattype = FORMAT_SubtitleInfo;
  467. SUBTITLEINFO* psi = (SUBTITLEINFO*)mt.AllocFormatBuffer(sizeof(SUBTITLEINFO) + pTE->CodecPrivate.GetSize());
  468. memset(psi, 0, mt.FormatLength());
  469. strncpy(psi->IsoLang, pTE->Language, countof(psi->IsoLang)-1);
  470. wcsncpy(psi->TrackName, pTE->Name, countof(psi->TrackName)-1);
  471. memcpy(mt.pbFormat + (psi->dwOffset = sizeof(SUBTITLEINFO)), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
  472. mt.subtype = 
  473. CodecID == "S_TEXT/UTF8" ? MEDIASUBTYPE_UTF8 :
  474. CodecID == "S_TEXT/SSA" || CodecID == "S_SSA" ? MEDIASUBTYPE_SSA :
  475. CodecID == "S_TEXT/ASS" || CodecID == "S_ASS" ? MEDIASUBTYPE_ASS :
  476. CodecID == "S_TEXT/USF" || CodecID == "S_USF" ? MEDIASUBTYPE_USF :
  477. CodecID == "S_VOBSUB" ? MEDIASUBTYPE_VOBSUB :
  478. MEDIASUBTYPE_NULL;
  479. if(mt.subtype != MEDIASUBTYPE_NULL)
  480. mts.Add(mt);
  481. }
  482. }
  483. if(mts.IsEmpty())
  484. {
  485. TRACE(_T("CMatroskaSourceFilter: Unsupported TrackType %s (%I64d)n"), CString(CodecID), (UINT64)pTE->TrackType);
  486. continue;
  487. }
  488. Name = CStringW(pTE->Language.IsEmpty() ? L"English" : CStringW(ISO6392ToLanguage(pTE->Language)))
  489. + (pTE->Name.IsEmpty() ? L"" : L", " + pTE->Name)
  490. + (L" (" + Name + L")");
  491. HRESULT hr;
  492. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CMatroskaSplitterOutputPin((int)pTE->MinCache, pTE->DefaultDuration/100, mts, Name, this, this, &hr));
  493. if(!pTE->Name.IsEmpty()) pPinOut->SetProperty(L"NAME", pTE->Name);
  494. if(pTE->Language.GetLength() == 3) pPinOut->SetProperty(L"LANG", CStringW(CString(pTE->Language)));
  495. AddOutputPin((DWORD)pTE->TrackNumber, pPinOut);
  496. m_pTrackEntryMap[(DWORD)pTE->TrackNumber] = pTE;
  497. m_pOrderedTrackArray.Add(pTE);
  498. }
  499. }
  500. Info& info = m_pFile->m_segment.SegmentInfo;
  501. m_rtNewStart = m_rtCurrent = 0;
  502. m_rtNewStop = m_rtStop = (REFERENCE_TIME)(info.Duration*info.TimeCodeScale/100);
  503. #ifdef DEBUG
  504. /*
  505. for(int i = 1, j = GetChapterCount(CHAPTER_ROOT_ID); i <= j; i++)
  506. {
  507. UINT id = GetChapterId(CHAPTER_ROOT_ID, i);
  508. struct ChapterElement ce;
  509. BOOL b = GetChapterInfo(id, &ce);
  510. BSTR bstr = GetChapterStringInfo(id, "eng", "");
  511. if(bstr) ::SysFreeString(bstr);
  512. }
  513. */
  514. #endif
  515. SetProperty(L"TITL", info.Title);
  516. // TODO
  517. // resources
  518. {
  519. POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
  520. while(pos)
  521. {
  522. Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
  523. POSITION pos = pA->AttachedFiles.GetHeadPosition();
  524. while(pos)
  525. {
  526. AttachedFile* pF = pA->AttachedFiles.GetNext(pos);
  527. CArray<BYTE> pData;
  528. pData.SetSize(pF->FileDataLen);
  529. m_pFile->Seek(pF->FileDataPos);
  530. if(SUCCEEDED(m_pFile->Read(pData.GetData(), pData.GetSize())))
  531. ResAppend(pF->FileName, pF->FileDescription, CStringW(pF->FileMimeType), pData.GetData(), pData.GetSize());
  532. }
  533. }
  534. }
  535. // chapters
  536. if(ChapterAtom* caroot = m_pFile->m_segment.FindChapterAtom(0))
  537. {
  538. CStringA str;
  539. str.ReleaseBufferSetLength(GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, str.GetBuffer(3), 3));
  540. CStringA ChapLanguage = CStringA(ISO6391To6392(str));
  541. if(ChapLanguage.GetLength() < 3) ChapLanguage = "eng";
  542. POSITION pos = caroot->ChapterAtoms.GetHeadPosition();
  543. while(pos)
  544. {
  545. // ca == caroot->ChapterAtoms.GetNext(pos) ?
  546. if(ChapterAtom* ca = m_pFile->m_segment.FindChapterAtom(caroot->ChapterAtoms.GetNext(pos)->ChapterUID))
  547. {
  548. CStringW name, first;
  549. POSITION pos = ca->ChapterDisplays.GetHeadPosition();
  550. while(pos)
  551. {
  552. ChapterDisplay* cd = ca->ChapterDisplays.GetNext(pos);
  553. if(first.IsEmpty()) first = cd->ChapString;
  554. if(cd->ChapLanguage == ChapLanguage) name = cd->ChapString;
  555. }
  556. ChapAppend(ca->ChapterTimeStart / 100 - m_pFile->m_rtOffset, !name.IsEmpty() ? name : first);
  557. }
  558. }
  559. }
  560. return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
  561. }
  562. void CMatroskaSplitterFilter::InstallFonts()
  563. {
  564. POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
  565. while(pos)
  566. {
  567. Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
  568. POSITION p2 = pA->AttachedFiles.GetHeadPosition();
  569. while(p2)
  570. {
  571. AttachedFile* pF = pA->AttachedFiles.GetNext(p2);
  572. if(pF->FileMimeType == "application/x-truetype-font")
  573. {
  574. // assume this is a font resource
  575. if(BYTE* pData = new BYTE[(UINT)pF->FileDataLen])
  576. {
  577. m_pFile->Seek(pF->FileDataPos);
  578. if(SUCCEEDED(m_pFile->Read(pData, pF->FileDataLen)))
  579. m_fontinst.InstallFont(pData, (UINT)pF->FileDataLen);
  580. delete [] pData;
  581. }
  582. }
  583. }
  584. }
  585. }
  586. void CMatroskaSplitterFilter::SendVorbisHeaderSample()
  587. {
  588. HRESULT hr;
  589. POSITION pos = m_pTrackEntryMap.GetStartPosition();
  590. while(pos)
  591. {
  592. DWORD TrackNumber = 0;
  593. TrackEntry* pTE = NULL;
  594. m_pTrackEntryMap.GetNextAssoc(pos, TrackNumber, pTE);
  595. CBaseSplitterOutputPin* pPin = GetOutputPin(TrackNumber);
  596. if(!(pTE && pPin && pPin->IsConnected()))
  597. continue;
  598. if(pTE->CodecID.ToString() == "A_VORBIS" && pPin->CurrentMediaType().subtype == MEDIASUBTYPE_Vorbis
  599. && pTE->CodecPrivate.GetSize() > 0)
  600. {
  601. BYTE* ptr = (BYTE*)pTE->CodecPrivate;
  602. CList<long> sizes;
  603. long last = 0;
  604. for(BYTE n = *ptr++; n > 0; n--)
  605. {
  606. long size = 0;
  607. do {size += *ptr;} while(*ptr++ == 0xff);
  608. sizes.AddTail(size);
  609. last += size;
  610. }
  611. sizes.AddTail(pTE->CodecPrivate.GetSize() - (ptr - (BYTE*)pTE->CodecPrivate) - last);
  612. hr = S_OK;
  613. POSITION pos = sizes.GetHeadPosition();
  614. while(pos && SUCCEEDED(hr))
  615. {
  616. long len = sizes.GetNext(pos);
  617. CAutoPtr<Packet> p(new Packet());
  618. p->TrackNumber = (DWORD)pTE->TrackNumber;
  619. p->rtStart = 0; p->rtStop = 1;
  620. p->bSyncPoint = FALSE;
  621. p->pData.SetSize(len);
  622. memcpy(p->pData.GetData(), ptr, len);
  623. ptr += len;
  624. hr = DeliverPacket(p);
  625. }
  626. if(FAILED(hr))
  627. TRACE(_T("ERROR: Vorbis initialization failed for stream %I64dn"), TrackNumber);
  628. }
  629. }
  630. }
  631. bool CMatroskaSplitterFilter::DemuxInit()
  632. {
  633. CMatroskaNode Root(m_pFile);
  634. if(!m_pFile
  635. || !(m_pSegment = Root.Child(0x18538067))
  636. || !(m_pCluster = m_pSegment->Child(0x1F43B675)))
  637. return(false);
  638. // reindex if needed
  639. if(m_pFile->m_segment.Cues.GetCount() == 0)
  640. {
  641. m_nOpenProgress = 0;
  642. m_pFile->m_segment.SegmentInfo.Duration.Set(0);
  643. UINT64 TrackNumber = m_pFile->m_segment.GetMasterTrack();
  644. CAutoPtr<Cue> pCue(new Cue());
  645. do
  646. {
  647. Cluster c;
  648. c.ParseTimeCode(m_pCluster);
  649. m_pFile->m_segment.SegmentInfo.Duration.Set((float)c.TimeCode - m_pFile->m_rtOffset/10000);
  650. CAutoPtr<CuePoint> pCuePoint(new CuePoint());
  651. CAutoPtr<CueTrackPosition> pCueTrackPosition(new CueTrackPosition());
  652. pCuePoint->CueTime.Set(c.TimeCode);
  653. pCueTrackPosition->CueTrack.Set(TrackNumber);
  654. pCueTrackPosition->CueClusterPosition.Set(m_pCluster->m_filepos - m_pSegment->m_start);
  655. pCuePoint->CueTrackPositions.AddTail(pCueTrackPosition);
  656. pCue->CuePoints.AddTail(pCuePoint);
  657. m_nOpenProgress = m_pFile->GetPos()*100/m_pFile->GetLength();
  658. DWORD cmd;
  659. if(CheckRequest(&cmd))
  660. {
  661. if(cmd == CMD_EXIT) m_fAbort = true;
  662. else Reply(S_OK);
  663. }
  664. }
  665. while(!m_fAbort && m_pCluster->Next(true));
  666. m_nOpenProgress = 100;
  667. if(!m_fAbort) m_pFile->m_segment.Cues.AddTail(pCue);
  668. m_fAbort = false;
  669. }
  670. m_pCluster.Free();
  671. m_pBlock.Free();
  672. return(true);
  673. }
  674. void CMatroskaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
  675. {
  676. m_pCluster = m_pSegment->Child(0x1F43B675);
  677. m_pBlock.Free();
  678. if(rt > 0)
  679. {
  680. rt += m_pFile->m_rtOffset;
  681. QWORD lastCueClusterPosition = -1;
  682. Segment& s = m_pFile->m_segment;
  683. UINT64 TrackNumber = s.GetMasterTrack();
  684. POSITION pos1 = s.Cues.GetHeadPosition();
  685. while(pos1)
  686. {
  687. Cue* pCue = s.Cues.GetNext(pos1);
  688. POSITION pos2 = pCue->CuePoints.GetTailPosition();
  689. while(pos2)
  690. {
  691. CuePoint* pCuePoint = pCue->CuePoints.GetPrev(pos2);
  692. if(rt < s.GetRefTime(pCuePoint->CueTime))
  693. continue;
  694. POSITION pos3 = pCuePoint->CueTrackPositions.GetHeadPosition();
  695. while(pos3)
  696. {
  697. CueTrackPosition* pCueTrackPositions = pCuePoint->CueTrackPositions.GetNext(pos3);
  698. if(TrackNumber != pCueTrackPositions->CueTrack)
  699. continue;
  700. if(lastCueClusterPosition == pCueTrackPositions->CueClusterPosition)
  701. continue;
  702. lastCueClusterPosition = pCueTrackPositions->CueClusterPosition;
  703. m_pCluster->SeekTo(m_pSegment->m_start + pCueTrackPositions->CueClusterPosition);
  704. m_pCluster->Parse();
  705. bool fFoundKeyFrame = false;
  706. /*
  707. if(pCueTrackPositions->CueBlockNumber > 0)
  708. {
  709. // TODO: CueBlockNumber only tells the block num of the track and not for all mixed in the cluster
  710. m_nLastBlock = (int)pCueTrackPositions->CueBlockNumber;
  711. fFoundKeyFrame = true;
  712. }
  713. else
  714. */
  715. {
  716. Cluster c;
  717. c.ParseTimeCode(m_pCluster);
  718. if(CAutoPtr<CMatroskaNode> pBlock = m_pCluster->GetFirstBlock())
  719. {
  720. bool fPassedCueTime = false;
  721. do
  722. {
  723. CBlockGroupNode bgn;
  724. if(pBlock->m_id == 0xA0)
  725. {
  726. bgn.Parse(pBlock, true);
  727. }
  728. else if(pBlock->m_id == 0xA3)
  729. {
  730. CAutoPtr<BlockGroup> bg(new BlockGroup());
  731. bg->Block.Parse(pBlock, true);
  732. if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0); // not a kf
  733. bgn.AddTail(bg);
  734. }
  735. POSITION pos4 = bgn.GetHeadPosition();
  736. while(!fPassedCueTime && pos4)
  737. {
  738. BlockGroup* bg = bgn.GetNext(pos4);
  739. if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && rt < s.GetRefTime(c.TimeCode + bg->Block.TimeCode)
  740. || rt + 5000000i64 < s.GetRefTime(c.TimeCode + bg->Block.TimeCode)) // allow 500ms difference between tracks, just in case intreleaving wasn't that much precise
  741. {
  742. fPassedCueTime = true;
  743. }
  744. else if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && !bg->ReferenceBlock.IsValid())
  745. {
  746. fFoundKeyFrame = true;
  747. m_pBlock = pBlock->Copy();
  748. }
  749. }
  750. }
  751. while(!fPassedCueTime && pBlock->NextBlock());
  752. }
  753. }
  754. if(fFoundKeyFrame)
  755. pos1 = pos2 = pos3 = NULL;
  756. }
  757. }
  758. }
  759. if(!m_pBlock)
  760. {
  761. m_pCluster = m_pSegment->Child(0x1F43B675);
  762. }
  763. }
  764. }
  765. bool CMatroskaSplitterFilter::DemuxLoop()
  766. {
  767. HRESULT hr = S_OK;
  768. SendVorbisHeaderSample(); // HACK: init vorbis decoder with the headers
  769. do
  770. {
  771. Cluster c;
  772. c.ParseTimeCode(m_pCluster);
  773. if(!m_pBlock) m_pBlock = m_pCluster->GetFirstBlock();
  774. if(!m_pBlock) continue;
  775. do
  776. {
  777. CBlockGroupNode bgn;
  778. if(m_pBlock->m_id == 0xA0)
  779. {
  780. bgn.Parse(m_pBlock, true);
  781. }
  782. else if(m_pBlock->m_id == 0xA3)
  783. {
  784. CAutoPtr<BlockGroup> bg(new BlockGroup());
  785. bg->Block.Parse(m_pBlock, true);
  786. if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0); // not a kf
  787. bgn.AddTail(bg);
  788. }
  789. while(bgn.GetCount())
  790. {
  791. CAutoPtr<MatroskaPacket> p(new MatroskaPacket());
  792. p->bg = bgn.RemoveHead();
  793. p->bSyncPoint = !p->bg->ReferenceBlock.IsValid();
  794. p->TrackNumber = (DWORD)p->bg->Block.TrackNumber;
  795. TrackEntry *pTE = m_pTrackEntryMap[p->TrackNumber];
  796. p->rtStart = m_pFile->m_segment.GetRefTime((REFERENCE_TIME)c.TimeCode + p->bg->Block.TimeCode);
  797. p->rtStop = p->rtStart + (p->bg->BlockDuration.IsValid() ? m_pFile->m_segment.GetRefTime(p->bg->BlockDuration) : 1);
  798. // Fix subtitle with duration = 0
  799. if(pTE && (pTE->TrackType == TrackEntry::TypeSubtitle) && (!p->bg->BlockDuration.IsValid()))
  800. {
  801. p->bg->BlockDuration.Set(1); // just setting it to be valid
  802. p->rtStop = p->rtStart;
  803. }
  804. POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
  805. while(pos)
  806. {
  807. CBinary* pb = p->bg->Block.BlockData.GetNext(pos);
  808. m_pTrackEntryMap[p->TrackNumber]->Expand(*pb, ContentEncoding::AllFrameContents);
  809. }
  810. // HACK
  811. p->rtStart -= m_pFile->m_rtOffset;
  812. p->rtStop -= m_pFile->m_rtOffset;
  813. hr = DeliverPacket(p);
  814. }
  815. }
  816. while(m_pBlock->NextBlock() && SUCCEEDED(hr) && !CheckRequest(NULL));
  817. m_pBlock.Free();
  818. }
  819. while(m_pFile->GetPos() < m_pFile->m_segment.pos + m_pFile->m_segment.len 
  820. && m_pCluster->Next(true) && SUCCEEDED(hr) && !CheckRequest(NULL));
  821. m_pCluster.Free();
  822. return(true);
  823. }
  824. // IMediaSeeking
  825. STDMETHODIMP CMatroskaSplitterFilter::GetDuration(LONGLONG* pDuration)
  826. {
  827. CheckPointer(pDuration, E_POINTER);
  828. CheckPointer(m_pFile, VFW_E_NOT_CONNECTED);
  829. Segment& s = m_pFile->m_segment;
  830. *pDuration = s.GetRefTime((INT64)s.SegmentInfo.Duration);
  831. return S_OK;
  832. }
  833. // IKeyFrameInfo
  834. STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrameCount(UINT& nKFs)
  835. {
  836. if(!m_pFile) return E_UNEXPECTED;
  837. HRESULT hr = S_OK;
  838. nKFs = 0;
  839. POSITION pos = m_pFile->m_segment.Cues.GetHeadPosition();
  840. while(pos) nKFs += m_pFile->m_segment.Cues.GetNext(pos)->CuePoints.GetCount();
  841. return hr;
  842. }
  843. STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
  844. {
  845. CheckPointer(pFormat, E_POINTER);
  846. CheckPointer(pKFs, E_POINTER);
  847. if(!m_pFile) return E_UNEXPECTED;
  848. if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
  849. UINT nKFsTmp = 0;
  850. POSITION pos1 = m_pFile->m_segment.Cues.GetHeadPosition();
  851. while(pos1 && nKFsTmp < nKFs)
  852. {
  853. Cue* pCue = m_pFile->m_segment.Cues.GetNext(pos1);
  854. POSITION pos2 = pCue->CuePoints.GetHeadPosition();
  855. while(pos2 && nKFsTmp < nKFs)
  856. pKFs[nKFsTmp++] = m_pFile->m_segment.GetRefTime(pCue->CuePoints.GetNext(pos2)->CueTime);
  857. }
  858. nKFs = nKFsTmp;
  859. return S_OK;
  860. }
  861. //
  862. // CMatroskaSourceFilter
  863. //
  864. CMatroskaSourceFilter::CMatroskaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
  865. : CMatroskaSplitterFilter(pUnk, phr)
  866. {
  867. m_clsid = __uuidof(this);
  868. m_pInput.Free();
  869. }
  870. //
  871. // CMatroskaSplitterOutputPin
  872. //
  873. CMatroskaSplitterOutputPin::CMatroskaSplitterOutputPin(
  874. int nMinCache, REFERENCE_TIME rtDefaultDuration,
  875. CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  876. : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
  877. , m_nMinCache(nMinCache), m_rtDefaultDuration(rtDefaultDuration)
  878. {
  879. m_nMinCache = max(m_nMinCache, 1);
  880. }
  881. CMatroskaSplitterOutputPin::~CMatroskaSplitterOutputPin()
  882. {
  883. }
  884. HRESULT CMatroskaSplitterOutputPin::DeliverEndFlush()
  885. {
  886. {
  887. CAutoLock cAutoLock(&m_csQueue);
  888. m_packets.RemoveAll();
  889. m_rob.RemoveAll();
  890. m_tos.RemoveAll();
  891. }
  892. return __super::DeliverEndFlush();
  893. }
  894. HRESULT CMatroskaSplitterOutputPin::DeliverEndOfStream()
  895. {
  896. CAutoLock cAutoLock(&m_csQueue);
  897. // send out the last remaining packets from the queue
  898. while(m_rob.GetCount())
  899. {
  900. MatroskaPacket* mp = m_rob.RemoveHead();
  901. if(m_rob.GetCount() && !mp->bg->BlockDuration.IsValid()) 
  902. mp->rtStop = m_rob.GetHead()->rtStart;
  903. else if(m_rob.GetCount() == 0 && m_rtDefaultDuration > 0)
  904. mp->rtStop = mp->rtStart + m_rtDefaultDuration;
  905. timeoverride to = {mp->rtStart, mp->rtStop};
  906. m_tos.AddTail(to);
  907. }
  908. while(m_packets.GetCount())
  909. {
  910. HRESULT hr = DeliverBlock(m_packets.RemoveHead());
  911. if(hr != S_OK) return hr;
  912. }
  913. return __super::DeliverEndOfStream();
  914. }
  915. HRESULT CMatroskaSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
  916. {
  917. MatroskaPacket* mp = dynamic_cast<MatroskaPacket*>(p.m_p);
  918. if(!mp) return __super::DeliverPacket(p);
  919. // don't try to understand what's happening here, it's magic
  920. CAutoLock cAutoLock(&m_csQueue);
  921. CAutoPtr<MatroskaPacket> p2;
  922. p.Detach();
  923. p2.Attach(mp);
  924. m_packets.AddTail(p2);
  925. POSITION pos = m_rob.GetTailPosition();
  926. for(int i = m_nMinCache-1; i > 0 && pos && mp->bg->ReferencePriority < m_rob.GetAt(pos)->bg->ReferencePriority; i--)
  927. m_rob.GetPrev(pos);
  928. if(!pos) m_rob.AddHead(mp);
  929. else m_rob.InsertAfter(pos, mp);
  930. mp = NULL;
  931. if(m_rob.GetCount() == m_nMinCache+1)
  932. {
  933. ASSERT(m_nMinCache > 0);
  934. pos = m_rob.GetHeadPosition();
  935. MatroskaPacket* mp1 = m_rob.GetNext(pos);
  936. MatroskaPacket* mp2 = m_rob.GetNext(pos);
  937. if(!mp1->bg->BlockDuration.IsValid())
  938. {
  939. mp1->bg->BlockDuration.Set(1); // just to set it valid
  940. if(mp1->rtStart >= mp2->rtStart)
  941. {
  942. /* CString str;
  943. str.Format(_T("mp1->rtStart (%I64d) >= mp2->rtStart (%I64d)!!!n"), mp1->rtStart, mp2->rtStart);
  944. AfxMessageBox(str);
  945. */
  946. // TRACE(_T("mp1->rtStart (%I64d) >= mp2->rtStart (%I64d)!!!n"), mp1->rtStart, mp2->rtStart);
  947. }
  948. else
  949. {
  950. mp1->rtStop = mp2->rtStart;
  951. }
  952. }
  953. }
  954. while(m_packets.GetCount())
  955. {
  956. mp = m_packets.GetHead();
  957. if(!mp->bg->BlockDuration.IsValid()) break;
  958.         
  959. mp = m_rob.RemoveHead();
  960. timeoverride to = {mp->rtStart, mp->rtStop};
  961. m_tos.AddTail(to);
  962. HRESULT hr = DeliverBlock(m_packets.RemoveHead());
  963. if(hr != S_OK) return hr;
  964. }
  965. return S_OK;
  966. }
  967. HRESULT CMatroskaSplitterOutputPin::DeliverBlock(MatroskaPacket* p)
  968. {
  969. HRESULT hr = S_FALSE;
  970. if(m_tos.GetCount())
  971. {
  972. timeoverride to = m_tos.RemoveHead();
  973. // if(p->TrackNumber == 2)
  974. TRACE(_T("(track=%d) %I64d, %I64d -> %I64d, %I64d (buffcnt=%d)n"), 
  975. p->TrackNumber, p->rtStart, p->rtStop, to.rtStart, to.rtStop,
  976. QueueCount());
  977. /**/
  978. p->rtStart = to.rtStart;
  979. p->rtStop = to.rtStop;
  980. }
  981. REFERENCE_TIME 
  982. rtStart = p->rtStart,
  983. rtDelta = (p->rtStop - p->rtStart) / p->bg->Block.BlockData.GetCount(),
  984. rtStop = p->rtStart + rtDelta;
  985. POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
  986. while(pos)
  987. {
  988. CAutoPtr<Packet> tmp(new Packet());
  989. tmp->TrackNumber = p->TrackNumber;
  990. tmp->bDiscontinuity = p->bDiscontinuity;
  991. tmp->bSyncPoint = p->bSyncPoint;
  992. tmp->rtStart = rtStart;
  993. tmp->rtStop = rtStop;
  994. tmp->pData.Copy(*p->bg->Block.BlockData.GetNext(pos));
  995. if(S_OK != (hr = DeliverPacket(tmp))) break;
  996. rtStart += rtDelta;
  997. rtStop += rtDelta;
  998. p->bSyncPoint = false;
  999. p->bDiscontinuity = false;
  1000. }
  1001. return hr;
  1002. }
  1003. // ITrackInfo
  1004. TrackEntry* CMatroskaSplitterFilter::GetTrackEntryAt(UINT aTrackIdx)
  1005. {
  1006. if(aTrackIdx < 0 || aTrackIdx >= m_pOrderedTrackArray.GetCount())
  1007. return NULL;
  1008. return m_pOrderedTrackArray[aTrackIdx];
  1009. }
  1010. STDMETHODIMP_(UINT) CMatroskaSplitterFilter::GetTrackCount()
  1011. {
  1012. return m_pTrackEntryMap.GetCount();
  1013. }
  1014. STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackInfo(UINT aTrackIdx, struct TrackElement* pStructureToFill)
  1015. {
  1016. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1017. if(pTE == NULL)
  1018. return FALSE;
  1019. pStructureToFill->FlagDefault = !!pTE->FlagDefault;
  1020. pStructureToFill->FlagLacing = !!pTE->FlagLacing;
  1021. strncpy(pStructureToFill->Language, pTE->Language, 3);
  1022. if(pStructureToFill->Language[0] == '')
  1023. strncpy(pStructureToFill->Language, "eng", 3);
  1024. pStructureToFill->Language[3] = '';
  1025. pStructureToFill->MaxCache = (UINT)pTE->MaxCache;
  1026. pStructureToFill->MinCache = (UINT)pTE->MinCache;
  1027. pStructureToFill->Type = (BYTE)pTE->TrackType;
  1028. return TRUE;
  1029. }
  1030. STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackExtendedInfo(UINT aTrackIdx, void* pStructureToFill)
  1031. {
  1032. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1033. if(pTE == NULL)
  1034. return FALSE;
  1035. if(pTE->TrackType == TrackEntry::TypeVideo)
  1036. {
  1037. TrackExtendedInfoVideo* pTEIV = (TrackExtendedInfoVideo*)pStructureToFill;
  1038. pTEIV->AspectRatioType = (BYTE)pTE->v.AspectRatioType;
  1039. pTEIV->DisplayUnit = (BYTE)pTE->v.DisplayUnit;
  1040. pTEIV->DisplayWidth = (UINT)pTE->v.DisplayWidth;
  1041. pTEIV->DisplayHeight = (UINT)pTE->v.DisplayHeight;
  1042. pTEIV->Interlaced = !!pTE->v.FlagInterlaced;
  1043. pTEIV->PixelWidth = (UINT)pTE->v.PixelWidth;
  1044. pTEIV->PixelHeight = (UINT)pTE->v.PixelHeight;
  1045. } else if(pTE->TrackType == TrackEntry::TypeAudio) {
  1046. TrackExtendedInfoAudio* pTEIA = (TrackExtendedInfoAudio*)pStructureToFill;
  1047. pTEIA->BitDepth = (UINT)pTE->a.BitDepth;
  1048. pTEIA->Channels = (UINT)pTE->a.Channels;
  1049. pTEIA->OutputSamplingFrequency = pTE->a.OutputSamplingFrequency;
  1050. pTEIA->SamplingFreq = pTE->a.SamplingFrequency;
  1051. } else {
  1052. return FALSE;
  1053. }
  1054. return TRUE;
  1055. }
  1056. STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackName(UINT aTrackIdx)
  1057. {
  1058. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1059. if(pTE == NULL)
  1060. return NULL;
  1061. return pTE->Name.AllocSysString();
  1062. }
  1063. STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecID(UINT aTrackIdx)
  1064. {
  1065. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1066. if(pTE == NULL)
  1067. return NULL;
  1068. return pTE->CodecID.ToString().AllocSysString();
  1069. }
  1070. STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecName(UINT aTrackIdx)
  1071. {
  1072. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1073. if(pTE == NULL)
  1074. return NULL;
  1075. return pTE->CodecName.AllocSysString();
  1076. }
  1077. STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecInfoURL(UINT aTrackIdx)
  1078. {
  1079. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1080. if(pTE == NULL)
  1081. return NULL;
  1082. return pTE->CodecInfoURL.AllocSysString();
  1083. }
  1084. STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecDownloadURL(UINT aTrackIdx)
  1085. {
  1086. TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
  1087. if(pTE == NULL)
  1088. return NULL;
  1089. return pTE->CodecDownloadURL.AllocSysString();
  1090. }