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

多媒体编程

开发平台:

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 "MatroskaFile.h"
  23. #include "......DSUtilDSUtil.h"
  24. #include "......zlibzlib.h"
  25. #define DOCTYPE _T("matroska")
  26. #define DOCTYPEVERSION 2
  27. static void LOG(LPCTSTR fmt, ...)
  28. {
  29. va_list args;
  30. va_start(args, fmt);
  31. if(FILE* f = _tfopen(_T("c:\matroskasplitterlog.txt"), _T("at")))
  32. {
  33. fseek(f, 0, 2);
  34. _vftprintf(f, fmt, args);
  35. fclose(f);
  36. }
  37. va_end(args);
  38. }
  39. using namespace MatroskaReader;
  40. #define BeginChunk
  41. CheckPointer(pMN0, E_POINTER); 
  42. CAutoPtr<CMatroskaNode> pMN = pMN0->Child(); 
  43. if(!pMN) return S_FALSE; 
  44. do 
  45. switch(pMN->m_id) 
  46. #define EndChunk 
  47. while(pMN->Next()); 
  48. return S_OK; 
  49. static void bswap(BYTE* s, int len)
  50. {
  51. for(BYTE* d = s + len-1; s < d; s++, d--)
  52. *s ^= *d, *d ^= *s, *s ^= *d;
  53. }
  54. //
  55. // CMatroskaFile
  56. //
  57. CMatroskaFile::CMatroskaFile(IAsyncReader* pAsyncReader, HRESULT& hr) 
  58. : CBaseSplitterFile(pAsyncReader, hr)
  59. , m_rtOffset(0)
  60. {
  61. if(FAILED(hr)) return;
  62. hr = Init();
  63. }
  64. HRESULT CMatroskaFile::Init()
  65. {
  66. DWORD dw;
  67. if(FAILED(Read(dw)) || dw != 0x1A45DFA3)
  68. return E_FAIL;
  69. CMatroskaNode Root(this);
  70. if(FAILED(Parse(&Root)))
  71. return E_FAIL;
  72. CAutoPtr<CMatroskaNode> pSegment, pCluster;
  73. if((pSegment = Root.Child(0x18538067))
  74. && (pCluster = pSegment->Child(0x1F43B675)))
  75. {
  76. Cluster c0;
  77. c0.ParseTimeCode(pCluster);
  78. m_rtOffset = m_segment.GetRefTime(c0.TimeCode);
  79. }
  80. return S_OK;
  81. }
  82. template <class T>
  83. HRESULT CMatroskaFile::Read(T& var)
  84. {
  85. HRESULT hr = Read((BYTE*)&var, sizeof(var));
  86. if(S_OK == hr) bswap((BYTE*)&var, sizeof(var));
  87. return hr;
  88. }
  89. HRESULT CMatroskaFile::Parse(CMatroskaNode* pMN0)
  90. {
  91. BeginChunk
  92. case 0x1A45DFA3: 
  93. m_ebml.Parse(pMN);
  94. if(m_ebml.DocType != DOCTYPE || m_ebml.DocTypeReadVersion > DOCTYPEVERSION)
  95. return E_FAIL;
  96. break;
  97. case 0x18538067: if(m_segment.SegmentInfo.SegmentUID.IsEmpty()) m_segment.ParseMinimal(pMN); break;
  98. EndChunk
  99. }
  100. //
  101. HRESULT EBML::Parse(CMatroskaNode* pMN0)
  102. {
  103. BeginChunk
  104. case 0x4286: EBMLVersion.Parse(pMN); break;
  105. case 0x42F7: EBMLReadVersion.Parse(pMN); break;
  106. case 0x42F2: EBMLMaxIDLength.Parse(pMN); break;
  107. case 0x42F3: EBMLMaxSizeLength.Parse(pMN); break;
  108. case 0x4282: DocType.Parse(pMN); break;
  109. case 0x4287: DocTypeVersion.Parse(pMN); break;
  110. case 0x4285: DocTypeReadVersion.Parse(pMN); break;
  111. EndChunk
  112. }
  113. HRESULT Segment::Parse(CMatroskaNode* pMN0)
  114. {
  115. pos = pMN0->GetPos();
  116. BeginChunk
  117. case 0x1549A966: SegmentInfo.Parse(pMN); break;
  118. case 0x114D9B74: MetaSeekInfo.Parse(pMN); break;
  119. case 0x1654AE6B: Tracks.Parse(pMN); break;
  120. case 0x1F43B675: Clusters.Parse(pMN); break;
  121. case 0x1C53BB6B: Cues.Parse(pMN); break;
  122. case 0x1941A469: Attachments.Parse(pMN); break;
  123. case 0x1043A770: Chapters.Parse(pMN); break;
  124. // case 0x1254C367: Tags.Parse(pMN); break;
  125. EndChunk
  126. }
  127. HRESULT Segment::ParseMinimal(CMatroskaNode* pMN0)
  128. {
  129. CheckPointer(pMN0, E_POINTER);
  130. pos = pMN0->GetPos();
  131. len = pMN0->m_len;
  132. CAutoPtr<CMatroskaNode> pMN = pMN0->Child();
  133. if(!pMN) return S_FALSE;
  134. int n = 0;
  135. do
  136. {
  137. switch(pMN->m_id)
  138. {
  139. case 0x1549A966: SegmentInfo.Parse(pMN); n++; break;
  140. case 0x114D9B74: MetaSeekInfo.Parse(pMN); n++; break;
  141. case 0x1654AE6B: Tracks.Parse(pMN); n++; break;
  142. case 0x1C53BB6B: Cues.Parse(pMN); break;
  143. }
  144. }
  145. while(n < 3 && pMN->Next());
  146. while(QWORD pos = pMN->FindPos(0x114D9B74, pMN->GetPos()))
  147. {
  148. pMN->SeekTo(pos);
  149. pMN->Parse();
  150. if(pMN->m_id != 0x114D9B74) {ASSERT(0); break;}
  151. MetaSeekInfo.Parse(pMN);
  152. }
  153. if(n == 3)
  154. {
  155. if(Cues.IsEmpty() && (pMN = pMN0->Child(0x1C53BB6B, false)))
  156. {
  157. do {Cues.Parse(pMN);} while(pMN->Next(true));
  158. }
  159. if(Chapters.IsEmpty() && (pMN = pMN0->Child(0x1043A770, false)))
  160. {
  161. do {Chapters.Parse(pMN); /*BIG UGLY HACK:*/ break;} while(pMN->Next(true));
  162. }
  163. if(Attachments.IsEmpty() && (pMN = pMN0->Child(0x1941A469, false)))
  164. {
  165. do {Attachments.Parse(pMN); /*BIG UGLY HACK:*/ break;} while (pMN->Next(true));
  166. }
  167. }
  168. return S_OK;
  169. }
  170. UINT64 Segment::GetMasterTrack()
  171. {
  172. UINT64 TrackNumber = 0, AltTrackNumber = 0;
  173. POSITION pos1 = Tracks.GetHeadPosition();
  174. while(pos1 && TrackNumber == 0)
  175. {
  176. Track* pT = Tracks.GetNext(pos1);
  177. POSITION pos2 = pT->TrackEntries.GetHeadPosition();
  178. while(pos2 && TrackNumber == 0)
  179. {
  180. TrackEntry* pTE = pT->TrackEntries.GetNext(pos2);
  181. if(pTE->TrackType == TrackEntry::TypeVideo)
  182. {
  183. TrackNumber = pTE->TrackNumber;
  184. break;
  185. }
  186. else if(pTE->TrackType == TrackEntry::TypeAudio && AltTrackNumber == 0)
  187. {
  188. AltTrackNumber = pTE->TrackNumber;
  189. }
  190. }
  191. }
  192. if(TrackNumber == 0) TrackNumber = AltTrackNumber;
  193. if(TrackNumber == 0) TrackNumber = 1;
  194. return TrackNumber;
  195. }
  196. ChapterAtom* ChapterAtom::FindChapterAtom(UINT64 id)
  197. {
  198. if(ChapterUID == id)
  199. return(this);
  200. POSITION pos = ChapterAtoms.GetHeadPosition();
  201. while(pos)
  202. {
  203. ChapterAtom* ca = ChapterAtoms.GetNext(pos)->FindChapterAtom(id);
  204. if(ca) return ca;
  205. }
  206. return(NULL);
  207. }
  208. ChapterAtom* Segment::FindChapterAtom(UINT64 id, int nEditionEntry)
  209. {
  210. POSITION pos1 = Chapters.GetHeadPosition();
  211. while(pos1)
  212. {
  213. Chapter* c = Chapters.GetNext(pos1);
  214. POSITION pos2 = c->EditionEntries.GetHeadPosition();
  215. while(pos2)
  216. {
  217. EditionEntry* ee = c->EditionEntries.GetNext(pos2);
  218. if(nEditionEntry-- == 0)
  219. {
  220. return id == 0 ? ee : ee->FindChapterAtom(id);
  221. }
  222. }
  223. }
  224. return(NULL);
  225. }
  226. HRESULT Info::Parse(CMatroskaNode* pMN0)
  227. {
  228. BeginChunk
  229. case 0x73A4: SegmentUID.Parse(pMN); break;
  230. case 0x7384: SegmentFilename.Parse(pMN); break;
  231. case 0x3CB923: PrevUID.Parse(pMN); break;
  232. case 0x3C83AB: PrevFilename.Parse(pMN); break;
  233. case 0x3EB923: NextUID.Parse(pMN); break;
  234. case 0x3E83BB: NextFilename.Parse(pMN); break;
  235. case 0x2AD7B1: TimeCodeScale.Parse(pMN); break;
  236. case 0x4489: Duration.Parse(pMN); break;
  237. case 0x4461: DateUTC.Parse(pMN); break;
  238. case 0x7BA9: Title.Parse(pMN); break;
  239. case 0x4D80: MuxingApp.Parse(pMN); break;
  240. case 0x5741: WritingApp.Parse(pMN); break;
  241. EndChunk
  242. }
  243. HRESULT Seek::Parse(CMatroskaNode* pMN0)
  244. {
  245. BeginChunk
  246. case 0x4DBB: SeekHeads.Parse(pMN); break;
  247. EndChunk
  248. }
  249. HRESULT SeekHead::Parse(CMatroskaNode* pMN0)
  250. {
  251. BeginChunk
  252. case 0x53AB: SeekID.Parse(pMN); break;
  253. case 0x53AC: SeekPosition.Parse(pMN); break;
  254. EndChunk
  255. }
  256. HRESULT Track::Parse(CMatroskaNode* pMN0)
  257. {
  258. BeginChunk
  259. case 0xAE: TrackEntries.Parse(pMN); break;
  260. EndChunk
  261. }
  262. HRESULT TrackEntry::Parse(CMatroskaNode* pMN0)
  263. {
  264. BeginChunk
  265. case 0xD7: TrackNumber.Parse(pMN); break;
  266. case 0x73C5: TrackUID.Parse(pMN); break;
  267. case 0x83: TrackType.Parse(pMN); break;
  268. case 0xB9: FlagEnabled.Parse(pMN); break;
  269. case 0x88: FlagDefault.Parse(pMN); break;
  270. case 0x9C: FlagLacing.Parse(pMN); break;
  271. case 0x6DE7: MinCache.Parse(pMN); break;
  272. case 0x6DF8: MaxCache.Parse(pMN); break;
  273. case 0x536E: Name.Parse(pMN); break;
  274. case 0x22B59C: Language.Parse(pMN); break;
  275. case 0x86: CodecID.Parse(pMN); break;
  276. case 0x63A2: CodecPrivate.Parse(pMN); break;
  277. case 0x258688: CodecName.Parse(pMN); break;
  278. case 0x3A9697: CodecSettings.Parse(pMN); break;
  279. case 0x3B4040: CodecInfoURL.Parse(pMN); break;
  280. case 0x26B240: CodecDownloadURL.Parse(pMN); break;
  281. case 0xAA: CodecDecodeAll.Parse(pMN); break;
  282. case 0x6FAB: TrackOverlay.Parse(pMN); break;
  283. case 0x23E383: case 0x2383E3: DefaultDuration.Parse(pMN); break;
  284. case 0x23314F: TrackTimecodeScale.Parse(pMN); break;
  285. case 0xE0: if(S_OK == v.Parse(pMN)) DescType |= DescVideo; break;
  286. case 0xE1: if(S_OK == a.Parse(pMN)) DescType |= DescAudio; break;
  287. case 0x6D80: ces.Parse(pMN); break;
  288. EndChunk
  289. }
  290. static int cesort(const void* a, const void* b) 
  291. {
  292. UINT64 ce1 = ((ContentEncoding*)a)->ContentEncodingOrder;
  293. UINT64 ce2 = ((ContentEncoding*)b)->ContentEncodingOrder;
  294. return (int)ce1 - (int)ce2; 
  295. }
  296. bool TrackEntry::Expand(CBinary& data, UINT64 Scope)
  297. {
  298. if(ces.ce.GetCount() == 0) return(true);
  299. CArray<ContentEncoding*> cearray;
  300. POSITION pos = ces.ce.GetHeadPosition();
  301. while(pos) cearray.Add(ces.ce.GetNext(pos));
  302. qsort(cearray.GetData(), cearray.GetCount(), sizeof(ContentEncoding*), cesort);
  303. for(int i = cearray.GetCount()-1; i >= 0; i--)
  304. {
  305. ContentEncoding* ce = cearray[i];
  306. if(!(ce->ContentEncodingScope & Scope))
  307. continue;
  308. if(ce->ContentEncodingType == ContentEncoding::Compression)
  309. {
  310. if(!data.Decompress(ce->cc))
  311. return(false);
  312. }
  313. else if(ce->ContentEncodingType == ContentEncoding::Encryption)
  314. {
  315. // TODO
  316. return(false);
  317. }
  318. }
  319. return(true);
  320. }
  321. HRESULT Video::Parse(CMatroskaNode* pMN0)
  322. {
  323. BeginChunk
  324. case 0x9A: FlagInterlaced.Parse(pMN); break;
  325. case 0x53B8: StereoMode.Parse(pMN); break;
  326. case 0xB0: PixelWidth.Parse(pMN); break;
  327. case 0xBA: PixelHeight.Parse(pMN); break;
  328. case 0x54B0: DisplayWidth.Parse(pMN); break;
  329. case 0x54BA: DisplayHeight.Parse(pMN); break;
  330. case 0x54B2: DisplayUnit.Parse(pMN); break;
  331. case 0x54B3: AspectRatioType.Parse(pMN); break;
  332. case 0x2EB524: ColourSpace.Parse(pMN); break;
  333. case 0x2FB523: GammaValue.Parse(pMN); break;
  334. case 0x2383E3: FramePerSec.Parse(pMN); break;
  335. EndChunk
  336. }
  337. HRESULT Audio::Parse(CMatroskaNode* pMN0)
  338. {
  339. BeginChunk
  340. case 0xB5: SamplingFrequency.Parse(pMN); break;
  341. case 0x78B5: OutputSamplingFrequency.Parse(pMN); break;
  342. case 0x9F: Channels.Parse(pMN); break;
  343. case 0x7D7B: ChannelPositions.Parse(pMN); break;
  344. case 0x6264: BitDepth.Parse(pMN); break;
  345. EndChunk
  346. }
  347. HRESULT ContentEncodings::Parse(CMatroskaNode* pMN0)
  348. {
  349. BeginChunk
  350. case 0x6240: ce.Parse(pMN); break;
  351. EndChunk
  352. }
  353. HRESULT ContentEncoding::Parse(CMatroskaNode* pMN0)
  354. {
  355. BeginChunk
  356. case 0x5031: ContentEncodingOrder.Parse(pMN); break;
  357. case 0x5032: ContentEncodingScope.Parse(pMN); break;
  358. case 0x5033: ContentEncodingType.Parse(pMN); break;
  359. case 0x5034: cc.Parse(pMN); break;
  360. case 0x5035: ce.Parse(pMN); break;
  361. EndChunk
  362. }
  363. HRESULT ContentCompression::Parse(CMatroskaNode* pMN0)
  364. {
  365. BeginChunk
  366. case 0x4254: ContentCompAlgo.Parse(pMN); break;
  367. case 0x4255: ContentCompSettings.Parse(pMN); break;
  368. EndChunk
  369. }
  370. HRESULT ContentEncryption::Parse(CMatroskaNode* pMN0)
  371. {
  372. BeginChunk
  373. case 0x47e1: ContentEncAlgo.Parse(pMN); break;
  374. case 0x47e2: ContentEncKeyID.Parse(pMN); break;
  375. case 0x47e3: ContentSignature.Parse(pMN); break;
  376. case 0x47e4: ContentSigKeyID.Parse(pMN); break;
  377. case 0x47e5: ContentSigAlgo.Parse(pMN); break;
  378. case 0x47e6: ContentSigHashAlgo.Parse(pMN); break;
  379. EndChunk
  380. }
  381. HRESULT Cluster::Parse(CMatroskaNode* pMN0)
  382. {
  383. BeginChunk
  384. case 0xE7: TimeCode.Parse(pMN); break;
  385. case 0xA7: Position.Parse(pMN); break;
  386. case 0xAB: PrevSize.Parse(pMN); break;
  387. case 0xA0: BlockGroups.Parse(pMN, true); break;
  388. case 0xA3: SimpleBlocks.Parse(pMN, true); break;
  389. EndChunk
  390. }
  391. HRESULT Cluster::ParseTimeCode(CMatroskaNode* pMN0)
  392. {
  393. BeginChunk
  394. case 0xE7: TimeCode.Parse(pMN); return S_OK;
  395. EndChunk
  396. }
  397. HRESULT BlockGroup::Parse(CMatroskaNode* pMN0, bool fFull)
  398. {
  399. BeginChunk
  400. case 0xA1: Block.Parse(pMN, fFull); break;
  401. case 0xA2: /* TODO: multiple virt blocks? */; break;
  402. case 0x9B: BlockDuration.Parse(pMN); break;
  403. case 0xFA: ReferencePriority.Parse(pMN); break;
  404. case 0xFB: ReferenceBlock.Parse(pMN); break;
  405. case 0xFD: ReferenceVirtual.Parse(pMN); break;
  406. case 0xA4: CodecState.Parse(pMN); break;
  407. case 0xE8: TimeSlices.Parse(pMN); break;
  408. EndChunk
  409. }
  410. HRESULT SimpleBlock::Parse(CMatroskaNode* pMN, bool fFull)
  411. {
  412. pMN->SeekTo(pMN->m_start);
  413. TrackNumber.Parse(pMN); 
  414. CShort s; s.Parse(pMN); TimeCode.Set(s); 
  415. Lacing.Parse(pMN);
  416. if(!fFull) return S_OK;
  417. CList<QWORD> lens;
  418. QWORD tlen = 0;
  419. QWORD FrameSize;
  420. BYTE FramesInLaceLessOne;
  421. switch((Lacing & 0x06) >> 1)
  422. {
  423. case 0:
  424. // No lacing
  425. lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
  426. break;
  427. case 1:
  428. // Xiph lacing
  429. BYTE n;
  430. pMN->Read(n);
  431. while(n-- > 0)
  432. {
  433. BYTE b;
  434. QWORD len = 0;
  435. do {pMN->Read(b); len += b;} while(b == 0xff);
  436. lens.AddTail(len);
  437. tlen += len;
  438. }
  439. lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
  440. break;
  441. case 2:
  442. // Fixed-size lacing
  443. pMN->Read(FramesInLaceLessOne);
  444. FramesInLaceLessOne++;
  445. FrameSize = ((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen)) / FramesInLaceLessOne;
  446. while(FramesInLaceLessOne-- > 0)
  447. lens.AddTail(FrameSize);
  448. break;
  449. case 3:
  450. // EBML lacing
  451. pMN->Read(FramesInLaceLessOne);
  452. CLength FirstFrameSize;
  453. FirstFrameSize.Parse(pMN);
  454. lens.AddTail(FirstFrameSize);
  455. FramesInLaceLessOne--;
  456. tlen = FirstFrameSize;
  457. CSignedLength DiffSize;
  458. FrameSize = FirstFrameSize;
  459. while(FramesInLaceLessOne--)
  460. {
  461. DiffSize.Parse(pMN);
  462. FrameSize += DiffSize;
  463. lens.AddTail(FrameSize);
  464. tlen += FrameSize;
  465. }
  466. lens.AddTail((pMN->m_start+pMN->m_len) - (pMN->GetPos()+tlen));
  467. break;
  468. }
  469. POSITION pos = lens.GetHeadPosition();
  470. while(pos)
  471. {
  472. QWORD len = lens.GetNext(pos);
  473. CAutoPtr<CBinary> p(new CBinary());
  474. p->SetSize((INT_PTR)len);
  475. pMN->Read(p->GetData(), len);
  476. BlockData.AddTail(p);
  477. }
  478. return S_OK;
  479. }
  480. HRESULT TimeSlice::Parse(CMatroskaNode* pMN0)
  481. {
  482. BeginChunk
  483. case 0xCC: LaceNumber.Parse(pMN); break;
  484. case 0xCD: FrameNumber.Parse(pMN); break;
  485. case 0xCE: Delay.Parse(pMN); break;
  486. case 0xCF: Duration.Parse(pMN); break;
  487. EndChunk
  488. }
  489. HRESULT Cue::Parse(CMatroskaNode* pMN0)
  490. {
  491. BeginChunk
  492. case 0xBB: CuePoints.Parse(pMN); break;
  493. EndChunk
  494. }
  495. HRESULT CuePoint::Parse(CMatroskaNode* pMN0)
  496. {
  497. BeginChunk
  498. case 0xB3: CueTime.Parse(pMN); break;
  499. case 0xB7: CueTrackPositions.Parse(pMN); break;
  500. EndChunk
  501. }
  502. HRESULT CueTrackPosition::Parse(CMatroskaNode* pMN0)
  503. {
  504. BeginChunk
  505. case 0xF7: CueTrack.Parse(pMN); break;
  506. case 0xF1: CueClusterPosition.Parse(pMN); break;
  507. case 0x5387: CueBlockNumber.Parse(pMN); break;
  508. case 0xEA: CueCodecState.Parse(pMN); break;
  509. case 0xDB: CueReferences.Parse(pMN); break;
  510. EndChunk
  511. }
  512. HRESULT CueReference::Parse(CMatroskaNode* pMN0)
  513. {
  514. BeginChunk
  515. case 0x96: CueRefTime.Parse(pMN); break;
  516. case 0x97: CueRefCluster.Parse(pMN); break;
  517. case 0x535F: CueRefNumber.Parse(pMN); break;
  518. case 0xEB: CueRefCodecState.Parse(pMN); break;
  519. EndChunk
  520. }
  521. HRESULT Attachment::Parse(CMatroskaNode* pMN0)
  522. {
  523. BeginChunk
  524. case 0x61A7: AttachedFiles.Parse(pMN); break;
  525. EndChunk
  526. }
  527. HRESULT AttachedFile::Parse(CMatroskaNode* pMN0)
  528. {
  529. BeginChunk
  530. case 0x467E: FileDescription.Parse(pMN); break;
  531. case 0x466E: FileName.Parse(pMN); break;
  532. case 0x4660: FileMimeType.Parse(pMN); break;
  533. case 0x465C: // binary
  534. FileDataLen = (INT_PTR)pMN->m_len;
  535. FileDataPos = pMN->m_start;
  536. break;
  537. case 0x46AE: FileUID.Parse(pMN); break;
  538. EndChunk
  539. }
  540. HRESULT Chapter::Parse(CMatroskaNode* pMN0)
  541. {
  542. BeginChunk
  543. case 0x45B9: EditionEntries.Parse(pMN); break;
  544. EndChunk
  545. }
  546. HRESULT EditionEntry::Parse(CMatroskaNode* pMN0)
  547. {
  548. BeginChunk
  549. case 0xB6: ChapterAtoms.Parse(pMN); break;
  550. EndChunk
  551. }
  552. HRESULT ChapterAtom::Parse(CMatroskaNode* pMN0)
  553. {
  554. BeginChunk
  555. case 0x73C4: ChapterUID.Parse(pMN); break;
  556. case 0x91: ChapterTimeStart.Parse(pMN); break;
  557. case 0x92: ChapterTimeEnd.Parse(pMN); break;
  558. // case 0x8F: // TODO 
  559. case 0x80: ChapterDisplays.Parse(pMN); break;
  560. case 0xB6: ChapterAtoms.Parse(pMN); break;
  561. case 0x98: ChapterFlagHidden.Parse(pMN); break;
  562. case 0x4598: ChapterFlagEnabled.Parse(pMN); break;
  563. EndChunk
  564. }
  565. HRESULT ChapterDisplay::Parse(CMatroskaNode* pMN0)
  566. {
  567. BeginChunk
  568. case 0x85: ChapString.Parse(pMN); break;
  569. case 0x437C: ChapLanguage.Parse(pMN); break;
  570. case 0x437E: ChapCountry.Parse(pMN); break;
  571. EndChunk
  572. }
  573. //
  574. HRESULT CBinary::Parse(CMatroskaNode* pMN)
  575. {
  576. ASSERT(pMN->m_len <= INT_MAX);
  577. SetSize((INT_PTR)pMN->m_len);
  578. return pMN->Read(GetData(), pMN->m_len);
  579. }
  580. bool CBinary::Compress(ContentCompression& cc)
  581. {
  582. if(cc.ContentCompAlgo == ContentCompression::ZLIB)
  583. {
  584. int res;
  585. z_stream c_stream;
  586. c_stream.zalloc = (alloc_func)0;
  587. c_stream.zfree = (free_func)0;
  588. c_stream.opaque = (voidpf)0;
  589. if(Z_OK != (res = deflateInit(&c_stream, 9)))
  590. return(false);
  591. c_stream.next_in = GetData();
  592. c_stream.avail_in = GetSize();
  593. BYTE* dst = NULL;
  594. int n = 0;
  595. do
  596. {
  597. dst = (BYTE*)realloc(dst, ++n*10);
  598. c_stream.next_out = &dst[(n-1)*10];
  599. c_stream.avail_out = 10;
  600. if(Z_OK != (res = deflate(&c_stream, Z_FINISH)) && Z_STREAM_END != res)
  601. {
  602. free(dst);
  603. return(false);
  604. }
  605. }
  606. while(0 == c_stream.avail_out && Z_STREAM_END != res);
  607. deflateEnd(&c_stream);
  608. SetSize(c_stream.total_out);
  609. memcpy(GetData(), dst, GetSize());
  610. free(dst);
  611. return(true);
  612. }
  613. return(false);
  614. }
  615. bool CBinary::Decompress(ContentCompression& cc)
  616. {
  617. if(cc.ContentCompAlgo == ContentCompression::ZLIB)
  618. {
  619. int res;
  620. z_stream d_stream;
  621. d_stream.zalloc = (alloc_func)0;
  622. d_stream.zfree = (free_func)0;
  623. d_stream.opaque = (voidpf)0;
  624. if(Z_OK != (res = inflateInit(&d_stream)))
  625. return(false);
  626. d_stream.next_in = GetData();
  627. d_stream.avail_in = GetSize();
  628. BYTE* dst = NULL;
  629. int n = 0;
  630. do
  631. {
  632. dst = (unsigned char *)realloc(dst, ++n*1000);
  633. d_stream.next_out = &dst[(n-1)*1000];
  634. d_stream.avail_out = 1000;
  635. if(Z_OK != (res = inflate(&d_stream, Z_NO_FLUSH)) && Z_STREAM_END != res)
  636. {
  637. free(dst);
  638. return(false);
  639. }
  640. }
  641. while(0 == d_stream.avail_out && 0 != d_stream.avail_in && Z_STREAM_END != res);
  642. inflateEnd(&d_stream);
  643. SetSize(d_stream.total_out);
  644. memcpy(GetData(), dst, GetSize());
  645. free(dst);
  646. return(true);
  647. }
  648. else if(cc.ContentCompAlgo == ContentCompression::HDRSTRIP)
  649. {
  650. InsertAt(0, &cc.ContentCompSettings);
  651. }
  652. return(false);
  653. }
  654. HRESULT CANSI::Parse(CMatroskaNode* pMN)
  655. {
  656. Empty();
  657. QWORD len = pMN->m_len;
  658. CHAR c;
  659. while(len-- > 0 && SUCCEEDED(pMN->Read(c))) 
  660. *this += c;
  661. return(len == -1 ? S_OK : E_FAIL);
  662. }
  663. HRESULT CUTF8::Parse(CMatroskaNode* pMN)
  664. {
  665. Empty();
  666. CAutoVectorPtr<BYTE> buff;
  667. if(!buff.Allocate((UINT)pMN->m_len + 1) || S_OK != pMN->Read(buff, pMN->m_len))
  668. return E_FAIL;
  669. buff[pMN->m_len] = 0;
  670. CStringW::operator = (UTF8To16((LPCSTR)(BYTE*)buff));
  671. return S_OK;
  672. }
  673. HRESULT CUInt::Parse(CMatroskaNode* pMN)
  674. {
  675. m_val = 0;
  676. for(int i = 0; i < (int)pMN->m_len; i++)
  677. {
  678. m_val <<= 8;
  679. HRESULT hr = pMN->Read(*(BYTE*)&m_val);
  680. if(FAILED(hr)) return hr;
  681. }
  682. m_fValid = true;
  683. return S_OK;
  684. }
  685. HRESULT CInt::Parse(CMatroskaNode* pMN)
  686. {
  687. m_val = 0;
  688. for(int i = 0; i < (int)pMN->m_len; i++)
  689. {
  690. HRESULT hr = pMN->Read(*((BYTE*)&m_val+7-i));
  691. if(FAILED(hr)) return hr;
  692. }
  693. m_val >>= (8-pMN->m_len)*8;
  694. m_fValid = true;
  695. return S_OK;
  696. }
  697. HRESULT CFloat::Parse(CMatroskaNode* pMN)
  698. {
  699. HRESULT hr = E_FAIL;
  700. m_val = 0;
  701. if(pMN->m_len == 4)
  702. {
  703. float val = 0;
  704. hr = pMN->Read(val);
  705. m_val = val;
  706. } else if(pMN->m_len == 8) {
  707. hr = pMN->Read(m_val);
  708. }
  709. if(SUCCEEDED(hr))
  710. m_fValid = true;
  711. return hr;
  712. }
  713. template<class T, class BASE>
  714. HRESULT CSimpleVar<T, BASE>::Parse(CMatroskaNode* pMN)
  715. {
  716. m_val = 0;
  717. m_fValid = true;
  718. return pMN->Read(m_val);
  719. }
  720. HRESULT CID::Parse(CMatroskaNode* pMN)
  721. {
  722. m_val = 0;
  723. BYTE b = 0;
  724. HRESULT hr = pMN->Read(b);
  725. if(FAILED(hr)) return hr;
  726. int nMoreBytes = 0;
  727. if((b&0x80) == 0x80) {m_val = b&0xff; nMoreBytes = 0;}
  728. else if((b&0xc0) == 0x40) {m_val = b&0x7f; nMoreBytes = 1;}
  729. else if((b&0xe0) == 0x20) {m_val = b&0x3f; nMoreBytes = 2;}
  730. else if((b&0xf0) == 0x10) {m_val = b&0x1f; nMoreBytes = 3;}
  731. else return E_FAIL;
  732. while(nMoreBytes-- > 0)
  733. {
  734. m_val <<= 8;
  735. hr = pMN->Read(*(BYTE*)&m_val);
  736. if(FAILED(hr)) return hr;
  737. }
  738. m_fValid = true;
  739. return S_OK;
  740. }
  741. HRESULT CLength::Parse(CMatroskaNode* pMN)
  742. {
  743. m_val = 0;
  744. BYTE b = 0;
  745. HRESULT hr = pMN->Read(b);
  746. if(FAILED(hr)) return hr;
  747. int nMoreBytes = 0, nMoreBytesTmp = 0;
  748. if((b&0x80) == 0x80) {m_val = b&0x7f; nMoreBytes = 0;}
  749. else if((b&0xc0) == 0x40) {m_val = b&0x3f; nMoreBytes = 1;}
  750. else if((b&0xe0) == 0x20) {m_val = b&0x1f; nMoreBytes = 2;}
  751. else if((b&0xf0) == 0x10) {m_val = b&0x0f; nMoreBytes = 3;}
  752. else if((b&0xf8) == 0x08) {m_val = b&0x07; nMoreBytes = 4;}
  753. else if((b&0xfc) == 0x04) {m_val = b&0x03; nMoreBytes = 5;}
  754. else if((b&0xfe) == 0x02) {m_val = b&0x01; nMoreBytes = 6;}
  755. else if((b&0xff) == 0x01) {m_val = b&0x00; nMoreBytes = 7;}
  756. else return E_FAIL;
  757. nMoreBytesTmp = nMoreBytes;
  758. QWORD UnknownSize = (1i64<<(7*(nMoreBytes+1)))-1;
  759. while(nMoreBytes-- > 0)
  760. {
  761. m_val <<= 8;
  762. hr = pMN->Read(*(BYTE*)&m_val);
  763. if(FAILED(hr)) return hr;
  764. }
  765. if(m_val == UnknownSize)
  766. {
  767. m_val = pMN->GetLength() - pMN->GetPos();
  768. TRACE(_T("CLength: Unspecified chunk size at %I64d (corrected to %I64d)n"), pMN->GetPos(), m_val);
  769. }
  770. if(m_fSigned)
  771. m_val -= (UnknownSize >> 1);
  772. m_fValid = true;
  773. return S_OK;
  774. }
  775. /*
  776. HRESULT CSignedLength::Parse(CMatroskaNode* pMN)
  777. {
  778. // HRESULT hr = __super::Parse(pMN);
  779. // if(FAILED(hr)) return hr;
  780. m_val = 0;
  781. BYTE b = 0;
  782. HRESULT hr = pMN->Read(b);
  783. if(FAILED(hr)) return hr;
  784. int nMoreBytes = 0, nMoreBytesTmp = 0;
  785. if((b&0x80) == 0x80) {m_val = b&0x7f; nMoreBytes = 0;}
  786. else if((b&0xc0) == 0x40) {m_val = b&0x3f; nMoreBytes = 1;}
  787. else if((b&0xe0) == 0x20) {m_val = b&0x1f; nMoreBytes = 2;}
  788. else if((b&0xf0) == 0x10) {m_val = b&0x0f; nMoreBytes = 3;}
  789. else if((b&0xf8) == 0x08) {m_val = b&0x07; nMoreBytes = 4;}
  790. else if((b&0xfc) == 0x04) {m_val = b&0x03; nMoreBytes = 5;}
  791. else if((b&0xfe) == 0x02) {m_val = b&0x01; nMoreBytes = 6;}
  792. else if((b&0xff) == 0x01) {m_val = b&0x00; nMoreBytes = 7;}
  793. else return E_FAIL;
  794. nMoreBytesTmp = nMoreBytes;
  795. QWORD UnknownSize = (1i64<<(7*(nMoreBytes+1)))-1;
  796. while(nMoreBytes-- > 0)
  797. {
  798. m_val <<= 8;
  799. hr = pMN->Read(*(BYTE*)&m_val);
  800. if(FAILED(hr)) return hr;
  801. }
  802. if(m_val == UnknownSize)
  803. {
  804. m_val = pMN->GetLength() - pMN->GetPos();
  805. TRACE(_T("CLength: Unspecified chunk size at %I64d (corrected to %I64d)n"), pMN->GetPos(), m_val);
  806. }
  807. m_val -= (UnknownSize >> 1);
  808. m_fValid = true;
  809. return S_OK;
  810. }
  811. */
  812. template<class T>
  813. HRESULT CNode<T>::Parse(CMatroskaNode* pMN)
  814. {
  815. CAutoPtr<T> p(new T());
  816. HRESULT hr = E_OUTOFMEMORY;
  817. if(!p || FAILED(hr = p->Parse(pMN))) return hr;
  818. AddTail(p);
  819. return S_OK;
  820. }
  821. HRESULT CBlockGroupNode::Parse(CMatroskaNode* pMN, bool fFull)
  822. {
  823. CAutoPtr<BlockGroup> p(new BlockGroup());
  824. HRESULT hr = E_OUTOFMEMORY;
  825. if(!p || FAILED(hr = p->Parse(pMN, fFull))) return hr;
  826. AddTail(p);
  827. return S_OK;
  828. }
  829. HRESULT CSimpleBlockNode::Parse(CMatroskaNode* pMN, bool fFull)
  830. {
  831. CAutoPtr<SimpleBlock> p(new SimpleBlock());
  832. HRESULT hr = E_OUTOFMEMORY;
  833. if(!p || FAILED(hr = p->Parse(pMN, fFull))) return hr;
  834. AddTail(p);
  835. return S_OK;
  836. }
  837. ///////////////////////////////
  838. CMatroskaNode::CMatroskaNode(CMatroskaFile* pMF)
  839. : m_pMF(pMF)
  840. , m_pParent(NULL)
  841. {
  842. ASSERT(m_pMF);
  843. m_start = m_filepos = 0;
  844. m_len.Set(m_pMF ? m_pMF->GetLength() : 0); 
  845. }
  846. CMatroskaNode::CMatroskaNode(CMatroskaNode* pParent)
  847. : m_pMF(pParent->m_pMF)
  848. , m_pParent(pParent)
  849. {
  850. Parse();
  851. }
  852. HRESULT CMatroskaNode::Parse()
  853. {
  854. m_filepos = GetPos();
  855. if(FAILED(m_id.Parse(this)) || FAILED(m_len.Parse(this)))
  856. return E_FAIL;
  857. m_start = GetPos();
  858. return S_OK;
  859. }
  860. CAutoPtr<CMatroskaNode> CMatroskaNode::Child(DWORD id, bool fSearch)
  861. {
  862. if(m_len == 0) return CAutoPtr<CMatroskaNode>();
  863. SeekTo(m_start);
  864. CAutoPtr<CMatroskaNode> pMN(new CMatroskaNode(this));
  865. if(id && !pMN->Find(id, fSearch)) pMN.Free();
  866. return pMN;
  867. }
  868. bool CMatroskaNode::Next(bool fSame)
  869. {
  870. if(!m_pParent)
  871. return(false);
  872. CID id = m_id;
  873. while(m_start+m_len < m_pParent->m_start+m_pParent->m_len)
  874. {
  875. SeekTo(m_start+m_len);
  876. if(FAILED(Parse()))
  877. {
  878. if(!Resync())
  879. return(false);
  880. }
  881. if(!fSame || m_id == id) 
  882. return(true);
  883. }
  884. return(false);
  885. }
  886. bool CMatroskaNode::Find(DWORD id, bool fSearch)
  887. {
  888. QWORD pos = m_pParent && m_pParent->m_id == 0x18538067 /*segment?*/ 
  889. ? FindPos(id) 
  890. : 0;
  891. if(pos)
  892. {
  893. SeekTo(pos);
  894. Parse();
  895. }
  896. else if(fSearch)
  897. {
  898. while(m_id != id && Next());
  899. }
  900. return(m_id == id);
  901. }
  902. void CMatroskaNode::SeekTo(QWORD pos) {m_pMF->Seek(pos);}
  903. QWORD CMatroskaNode::GetPos() {return m_pMF->GetPos();}
  904. QWORD CMatroskaNode::GetLength() {return m_pMF->GetLength();}
  905. template <class T> 
  906. HRESULT CMatroskaNode::Read(T& var) {return m_pMF->Read(var);}
  907. HRESULT CMatroskaNode::Read(BYTE* pData, QWORD len) {return m_pMF->Read(pData, len);}
  908. QWORD CMatroskaNode::FindPos(DWORD id, QWORD start)
  909. {
  910. Segment& sm = m_pMF->m_segment;
  911. POSITION pos = sm.MetaSeekInfo.GetHeadPosition();
  912. while(pos)
  913. {
  914. Seek* s = sm.MetaSeekInfo.GetNext(pos);
  915. POSITION pos2 = s->SeekHeads.GetHeadPosition();
  916. while(pos2)
  917. {
  918. SeekHead* sh = s->SeekHeads.GetNext(pos2);
  919. if(sh->SeekID == id && sh->SeekPosition+sm.pos >= start)
  920. return sh->SeekPosition+sm.pos;
  921. }
  922. }
  923. return 0;
  924. }
  925. CAutoPtr<CMatroskaNode> CMatroskaNode::Copy()
  926. {
  927. CAutoPtr<CMatroskaNode> pNewNode(new CMatroskaNode(m_pMF));
  928. pNewNode->m_pParent = m_pParent;
  929. pNewNode->m_id.Set(m_id);
  930. pNewNode->m_len.Set(m_len);
  931. pNewNode->m_filepos = m_filepos;
  932. pNewNode->m_start = m_start;
  933. return(pNewNode);
  934. }
  935. CAutoPtr<CMatroskaNode> CMatroskaNode::GetFirstBlock()
  936. {
  937. CAutoPtr<CMatroskaNode> pNode = Child();
  938. do {if(pNode->m_id == 0xA0 || pNode->m_id == 0xA3) return pNode;}
  939. while(pNode->Next());
  940. return CAutoPtr<CMatroskaNode>();
  941. }
  942. bool CMatroskaNode::NextBlock()
  943. {
  944. if(!m_pParent)
  945. return(false);
  946. CID id = m_id;
  947. while(m_start+m_len < m_pParent->m_start+m_pParent->m_len)
  948. {
  949. SeekTo(m_start+m_len);
  950. if(FAILED(Parse()))
  951. {
  952. if(!Resync())
  953. return(false);
  954. }
  955. if(m_id == 0xA0 || m_id == 0xA3) 
  956. return(true);
  957. }
  958. return(false);
  959. }
  960. bool CMatroskaNode::Resync()
  961. {
  962. if(m_pParent->m_id == 0x18538067) /*segment?*/ 
  963. {
  964. SeekTo(m_filepos);
  965. for(BYTE b = 0; S_OK == Read(b); b = 0)
  966. {
  967. if((b&0xf0) != 0x10)
  968. continue;
  969.             DWORD dw = b;
  970. Read((BYTE*)&dw+1, 3);
  971. bswap((BYTE*)&dw, 4);
  972. switch(dw)
  973. {
  974. case 0x1549A966: // SegmentInfo
  975. case 0x114D9B74: // MetaSeekInfo
  976. case 0x1654AE6B: // Tracks
  977. case 0x1F43B675: // Clusters
  978. case 0x1C53BB6B: // Cues
  979. case 0x1941A469: // Attachments
  980. case 0x1043A770: // Chapters
  981. case 0x1254C367: // Tags
  982. SeekTo(GetPos()-4);
  983. return(SUCCEEDED(Parse()));
  984. default:
  985. SeekTo(GetPos()-3);
  986. break;
  987. }
  988. }
  989. }
  990. return(false);
  991. }