1 // Copyright (c) 2010 The WebM project authors. All Rights Reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 9 #ifndef MKVPARSER_HPP 10 #define MKVPARSER_HPP 11 12 #include <cstdlib> 13 #include <cstdio> 14 #include <cstddef> 15 16 namespace mkvparser 17 { 18 19 const int E_FILE_FORMAT_INVALID = -2; 20 const int E_BUFFER_NOT_FULL = -3; 21 22 class IMkvReader 23 { 24 public: 25 virtual int Read(long long pos, long len, unsigned char* buf) = 0; 26 virtual int Length(long long* total, long long* available) = 0; 27 protected: 28 virtual ~IMkvReader(); 29 }; 30 31 long long GetUIntLength(IMkvReader*, long long, long&); 32 long long ReadUInt(IMkvReader*, long long, long&); 33 long long UnserializeUInt(IMkvReader*, long long pos, long long size); 34 35 long UnserializeFloat(IMkvReader*, long long pos, long long size, double&); 36 long UnserializeInt(IMkvReader*, long long pos, long len, long long& result); 37 38 long UnserializeString( 39 IMkvReader*, 40 long long pos, 41 long long size, 42 char*& str); 43 44 long ParseElementHeader( 45 IMkvReader* pReader, 46 long long& pos, //consume id and size fields 47 long long stop, //if you know size of element's parent 48 long long& id, 49 long long& size); 50 51 bool Match(IMkvReader*, long long&, unsigned long, long long&); 52 bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&); 53 54 void GetVersion(int& major, int& minor, int& build, int& revision); 55 56 struct EBMLHeader 57 { 58 EBMLHeader(); 59 ~EBMLHeader(); 60 long long m_version; 61 long long m_readVersion; 62 long long m_maxIdLength; 63 long long m_maxSizeLength; 64 char* m_docType; 65 long long m_docTypeVersion; 66 long long m_docTypeReadVersion; 67 68 long long Parse(IMkvReader*, long long&); 69 void Init(); 70 }; 71 72 73 class Segment; 74 class Track; 75 class Cluster; 76 77 class Block 78 { 79 Block(const Block&); 80 Block& operator=(const Block&); 81 82 public: 83 const long long m_start; 84 const long long m_size; 85 86 Block(long long start, long long size); 87 ~Block(); 88 89 long Parse(IMkvReader*); 90 91 long long GetTrackNumber() const; 92 long long GetTimeCode(const Cluster*) const; //absolute, but not scaled 93 long long GetTime(const Cluster*) const; //absolute, and scaled (ns) 94 bool IsKey() const; 95 void SetKey(bool); 96 bool IsInvisible() const; 97 98 enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml }; 99 Lacing GetLacing() const; 100 101 int GetFrameCount() const; //to index frames: [0, count) 102 103 struct Frame 104 { 105 long long pos; //absolute offset 106 long len; 107 108 long Read(IMkvReader*, unsigned char*) const; 109 }; 110 111 const Frame& GetFrame(int frame_index) const; 112 113 private: 114 long long m_track; //Track::Number() 115 short m_timecode; //relative to cluster 116 unsigned char m_flags; 117 118 Frame* m_frames; 119 int m_frame_count; 120 121 }; 122 123 124 class BlockEntry 125 { 126 BlockEntry(const BlockEntry&); 127 BlockEntry& operator=(const BlockEntry&); 128 129 protected: 130 BlockEntry(Cluster*, long index); 131 132 public: 133 virtual ~BlockEntry(); 134 135 bool EOS() const; 136 const Cluster* GetCluster() const; 137 long GetIndex() const; 138 virtual const Block* GetBlock() const = 0; 139 140 enum Kind { kBlockEOS, kBlockSimple, kBlockGroup }; 141 virtual Kind GetKind() const = 0; 142 143 protected: 144 Cluster* const m_pCluster; 145 const long m_index; 146 147 }; 148 149 150 class SimpleBlock : public BlockEntry 151 { 152 SimpleBlock(const SimpleBlock&); 153 SimpleBlock& operator=(const SimpleBlock&); 154 155 public: 156 SimpleBlock(Cluster*, long index, long long start, long long size); 157 long Parse(); 158 159 Kind GetKind() const; 160 const Block* GetBlock() const; 161 162 protected: 163 Block m_block; 164 165 }; 166 167 168 class BlockGroup : public BlockEntry 169 { 170 BlockGroup(const BlockGroup&); 171 BlockGroup& operator=(const BlockGroup&); 172 173 public: 174 BlockGroup( 175 Cluster*, 176 long index, 177 long long block_start, //absolute pos of block's payload 178 long long block_size, //size of block's payload 179 long long prev, 180 long long next, 181 long long duration); 182 183 long Parse(); 184 185 Kind GetKind() const; 186 const Block* GetBlock() const; 187 188 long long GetPrevTimeCode() const; //relative to block's time 189 long long GetNextTimeCode() const; //as above 190 long long GetDuration() const; 191 192 private: 193 Block m_block; 194 const long long m_prev; 195 const long long m_next; 196 const long long m_duration; 197 198 }; 199 200 /////////////////////////////////////////////////////////////// 201 // ContentEncoding element 202 // Elements used to describe if the track data has been encrypted or 203 // compressed with zlib or header stripping. 204 class ContentEncoding { 205 public: 206 ContentEncoding(); 207 ~ContentEncoding(); 208 209 // ContentCompression element names 210 struct ContentCompression { 211 ContentCompression(); 212 ~ContentCompression(); 213 214 unsigned long long algo; 215 unsigned char* settings; 216 }; 217 218 // ContentEncryption element names 219 struct ContentEncryption { 220 ContentEncryption(); 221 ~ContentEncryption(); 222 223 unsigned long long algo; 224 unsigned char* key_id; 225 long long key_id_len; 226 unsigned char* signature; 227 long long signature_len; 228 unsigned char* sig_key_id; 229 long long sig_key_id_len; 230 unsigned long long sig_algo; 231 unsigned long long sig_hash_algo; 232 }; 233 234 // Returns ContentCompression represented by |idx|. Returns NULL if |idx| 235 // is out of bounds. 236 const ContentCompression* GetCompressionByIndex(unsigned long idx) const; 237 238 // Returns number of ContentCompression elements in this ContentEncoding 239 // element. 240 unsigned long GetCompressionCount() const; 241 242 // Returns ContentEncryption represented by |idx|. Returns NULL if |idx| 243 // is out of bounds. 244 const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const; 245 246 // Returns number of ContentEncryption elements in this ContentEncoding 247 // element. 248 unsigned long GetEncryptionCount() const; 249 250 // Parses the ContentEncoding element from |pReader|. |start| is the 251 // starting offset of the ContentEncoding payload. |size| is the size in 252 // bytes of the ContentEncoding payload. Returns true on success. 253 bool ParseContentEncodingEntry(long long start, 254 long long size, 255 IMkvReader* const pReader); 256 257 // Parses the ContentEncryption element from |pReader|. |start| is the 258 // starting offset of the ContentEncryption payload. |size| is the size in 259 // bytes of the ContentEncryption payload. |encryption| is where the parsed 260 // values will be stored. 261 void ParseEncryptionEntry(long long start, 262 long long size, 263 IMkvReader* const pReader, 264 ContentEncryption* const encryption); 265 266 unsigned long long encoding_order() const { return encoding_order_; } 267 unsigned long long encoding_scope() const { return encoding_scope_; } 268 unsigned long long encoding_type() const { return encoding_type_; } 269 270 private: 271 // Member variables for list of ContentCompression elements. 272 ContentCompression** compression_entries_; 273 ContentCompression** compression_entries_end_; 274 275 // Member variables for list of ContentEncryption elements. 276 ContentEncryption** encryption_entries_; 277 ContentEncryption** encryption_entries_end_; 278 279 // ContentEncoding element names 280 unsigned long long encoding_order_; 281 unsigned long long encoding_scope_; 282 unsigned long long encoding_type_; 283 284 // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); 285 ContentEncoding(const ContentEncoding&); 286 ContentEncoding& operator=(const ContentEncoding&); 287 }; 288 289 class Track 290 { 291 Track(const Track&); 292 Track& operator=(const Track&); 293 294 public: 295 enum Type { kVideo = 1, kAudio = 2 }; 296 297 Segment* const m_pSegment; 298 const long long m_element_start; 299 const long long m_element_size; 300 virtual ~Track(); 301 302 long GetType() const; 303 long GetNumber() const; 304 unsigned long long GetUid() const; 305 const char* GetNameAsUTF8() const; 306 const char* GetCodecNameAsUTF8() const; 307 const char* GetCodecId() const; 308 const unsigned char* GetCodecPrivate(size_t&) const; 309 bool GetLacing() const; 310 311 const BlockEntry* GetEOS() const; 312 313 struct Settings 314 { 315 long long start; 316 long long size; 317 }; 318 319 class Info 320 { 321 public: 322 Info(); 323 ~Info(); 324 int Copy(Info&) const; 325 void Clear(); 326 private: 327 Info(const Info&); 328 Info& operator=(const Info&); 329 public: 330 long type; 331 long number; 332 unsigned long long uid; 333 char* nameAsUTF8; 334 char* codecId; 335 char* codecNameAsUTF8; 336 unsigned char* codecPrivate; 337 size_t codecPrivateSize; 338 bool lacing; 339 Settings settings; 340 private: 341 int CopyStr(char* Info::*str, Info&) const; 342 }; 343 344 long GetFirst(const BlockEntry*&) const; 345 long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; 346 virtual bool VetEntry(const BlockEntry*) const = 0; 347 virtual long Seek(long long time_ns, const BlockEntry*&) const = 0; 348 349 const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const; 350 unsigned long GetContentEncodingCount() const; 351 352 void ParseContentEncodingsEntry(long long start, long long size); 353 354 protected: 355 Track( 356 Segment*, 357 long long element_start, 358 long long element_size); 359 360 Info m_info; 361 362 class EOSBlock : public BlockEntry 363 { 364 public: 365 EOSBlock(); 366 367 Kind GetKind() const; 368 const Block* GetBlock() const; 369 }; 370 371 EOSBlock m_eos; 372 373 private: 374 ContentEncoding** content_encoding_entries_; 375 ContentEncoding** content_encoding_entries_end_; 376 }; 377 378 379 class VideoTrack : public Track 380 { 381 VideoTrack(const VideoTrack&); 382 VideoTrack& operator=(const VideoTrack&); 383 384 VideoTrack( 385 Segment*, 386 long long element_start, 387 long long element_size); 388 389 public: 390 static long Parse( 391 Segment*, 392 const Info&, 393 long long element_start, 394 long long element_size, 395 VideoTrack*&); 396 397 long long GetWidth() const; 398 long long GetHeight() const; 399 double GetFrameRate() const; 400 401 bool VetEntry(const BlockEntry*) const; 402 long Seek(long long time_ns, const BlockEntry*&) const; 403 404 private: 405 long long m_width; 406 long long m_height; 407 double m_rate; 408 409 }; 410 411 412 class AudioTrack : public Track 413 { 414 AudioTrack(const AudioTrack&); 415 AudioTrack& operator=(const AudioTrack&); 416 417 AudioTrack( 418 Segment*, 419 long long element_start, 420 long long element_size); 421 public: 422 static long Parse( 423 Segment*, 424 const Info&, 425 long long element_start, 426 long long element_size, 427 AudioTrack*&); 428 429 double GetSamplingRate() const; 430 long long GetChannels() const; 431 long long GetBitDepth() const; 432 bool VetEntry(const BlockEntry*) const; 433 long Seek(long long time_ns, const BlockEntry*&) const; 434 435 private: 436 double m_rate; 437 long long m_channels; 438 long long m_bitDepth; 439 }; 440 441 442 class Tracks 443 { 444 Tracks(const Tracks&); 445 Tracks& operator=(const Tracks&); 446 447 public: 448 Segment* const m_pSegment; 449 const long long m_start; 450 const long long m_size; 451 const long long m_element_start; 452 const long long m_element_size; 453 454 Tracks( 455 Segment*, 456 long long start, 457 long long size, 458 long long element_start, 459 long long element_size); 460 461 ~Tracks(); 462 463 long Parse(); 464 465 unsigned long GetTracksCount() const; 466 467 const Track* GetTrackByNumber(long tn) const; 468 const Track* GetTrackByIndex(unsigned long idx) const; 469 470 private: 471 Track** m_trackEntries; 472 Track** m_trackEntriesEnd; 473 474 long ParseTrackEntry( 475 long long payload_start, 476 long long payload_size, 477 long long element_start, 478 long long element_size, 479 Track*&) const; 480 481 }; 482 483 484 class SegmentInfo 485 { 486 SegmentInfo(const SegmentInfo&); 487 SegmentInfo& operator=(const SegmentInfo&); 488 489 public: 490 Segment* const m_pSegment; 491 const long long m_start; 492 const long long m_size; 493 const long long m_element_start; 494 const long long m_element_size; 495 496 SegmentInfo( 497 Segment*, 498 long long start, 499 long long size, 500 long long element_start, 501 long long element_size); 502 503 ~SegmentInfo(); 504 505 long Parse(); 506 507 long long GetTimeCodeScale() const; 508 long long GetDuration() const; //scaled 509 const char* GetMuxingAppAsUTF8() const; 510 const char* GetWritingAppAsUTF8() const; 511 const char* GetTitleAsUTF8() const; 512 513 private: 514 long long m_timecodeScale; 515 double m_duration; 516 char* m_pMuxingAppAsUTF8; 517 char* m_pWritingAppAsUTF8; 518 char* m_pTitleAsUTF8; 519 }; 520 521 522 class SeekHead 523 { 524 SeekHead(const SeekHead&); 525 SeekHead& operator=(const SeekHead&); 526 527 public: 528 Segment* const m_pSegment; 529 const long long m_start; 530 const long long m_size; 531 const long long m_element_start; 532 const long long m_element_size; 533 534 SeekHead( 535 Segment*, 536 long long start, 537 long long size, 538 long long element_start, 539 long long element_size); 540 541 ~SeekHead(); 542 543 long Parse(); 544 545 struct Entry 546 { 547 //the SeekHead entry payload 548 long long id; 549 long long pos; 550 551 //absolute pos of SeekEntry ID 552 long long element_start; 553 554 //SeekEntry ID size + size size + payload 555 long long element_size; 556 }; 557 558 int GetCount() const; 559 const Entry* GetEntry(int idx) const; 560 561 struct VoidElement 562 { 563 //absolute pos of Void ID 564 long long element_start; 565 566 //ID size + size size + payload size 567 long long element_size; 568 }; 569 570 int GetVoidElementCount() const; 571 const VoidElement* GetVoidElement(int idx) const; 572 573 private: 574 Entry* m_entries; 575 int m_entry_count; 576 577 VoidElement* m_void_elements; 578 int m_void_element_count; 579 580 static bool ParseEntry( 581 IMkvReader*, 582 long long pos, //payload 583 long long size, 584 Entry*); 585 586 }; 587 588 class Cues; 589 class CuePoint 590 { 591 friend class Cues; 592 593 CuePoint(long, long long); 594 ~CuePoint(); 595 596 CuePoint(const CuePoint&); 597 CuePoint& operator=(const CuePoint&); 598 599 public: 600 long long m_element_start; 601 long long m_element_size; 602 603 void Load(IMkvReader*); 604 605 long long GetTimeCode() const; //absolute but unscaled 606 long long GetTime(const Segment*) const; //absolute and scaled (ns units) 607 608 struct TrackPosition 609 { 610 long long m_track; 611 long long m_pos; //of cluster 612 long long m_block; 613 //codec_state //defaults to 0 614 //reference = clusters containing req'd referenced blocks 615 // reftime = timecode of the referenced block 616 617 void Parse(IMkvReader*, long long, long long); 618 }; 619 620 const TrackPosition* Find(const Track*) const; 621 622 private: 623 const long m_index; 624 long long m_timecode; 625 TrackPosition* m_track_positions; 626 size_t m_track_positions_count; 627 628 }; 629 630 631 class Cues 632 { 633 friend class Segment; 634 635 Cues( 636 Segment*, 637 long long start, 638 long long size, 639 long long element_start, 640 long long element_size); 641 ~Cues(); 642 643 Cues(const Cues&); 644 Cues& operator=(const Cues&); 645 646 public: 647 Segment* const m_pSegment; 648 const long long m_start; 649 const long long m_size; 650 const long long m_element_start; 651 const long long m_element_size; 652 653 bool Find( //lower bound of time_ns 654 long long time_ns, 655 const Track*, 656 const CuePoint*&, 657 const CuePoint::TrackPosition*&) const; 658 659 #if 0 660 bool FindNext( //upper_bound of time_ns 661 long long time_ns, 662 const Track*, 663 const CuePoint*&, 664 const CuePoint::TrackPosition*&) const; 665 #endif 666 667 const CuePoint* GetFirst() const; 668 const CuePoint* GetLast() const; 669 const CuePoint* GetNext(const CuePoint*) const; 670 671 const BlockEntry* GetBlock( 672 const CuePoint*, 673 const CuePoint::TrackPosition*) const; 674 675 bool LoadCuePoint() const; 676 long GetCount() const; //loaded only 677 //long GetTotal() const; //loaded + preloaded 678 bool DoneParsing() const; 679 680 private: 681 void Init() const; 682 void PreloadCuePoint(long&, long long) const; 683 684 mutable CuePoint** m_cue_points; 685 mutable long m_count; 686 mutable long m_preload_count; 687 mutable long long m_pos; 688 689 }; 690 691 692 class Cluster 693 { 694 friend class Segment; 695 696 Cluster(const Cluster&); 697 Cluster& operator=(const Cluster&); 698 699 public: 700 Segment* const m_pSegment; 701 702 public: 703 static Cluster* Create( 704 Segment*, 705 long index, //index in segment 706 long long off); //offset relative to segment 707 //long long element_size); 708 709 Cluster(); //EndOfStream 710 ~Cluster(); 711 712 bool EOS() const; 713 714 long long GetTimeCode() const; //absolute, but not scaled 715 long long GetTime() const; //absolute, and scaled (nanosecond units) 716 long long GetFirstTime() const; //time (ns) of first (earliest) block 717 long long GetLastTime() const; //time (ns) of last (latest) block 718 719 long GetFirst(const BlockEntry*&) const; 720 long GetLast(const BlockEntry*&) const; 721 long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; 722 723 const BlockEntry* GetEntry(const Track*, long long ns = -1) const; 724 const BlockEntry* GetEntry( 725 const CuePoint&, 726 const CuePoint::TrackPosition&) const; 727 //const BlockEntry* GetMaxKey(const VideoTrack*) const; 728 729 // static bool HasBlockEntries(const Segment*, long long); 730 731 static long HasBlockEntries( 732 const Segment*, 733 long long idoff, 734 long long& pos, 735 long& size); 736 737 long GetEntryCount() const; 738 739 long Load(long long& pos, long& size) const; 740 741 long Parse(long long& pos, long& size) const; 742 long GetEntry(long index, const mkvparser::BlockEntry*&) const; 743 744 protected: 745 Cluster( 746 Segment*, 747 long index, 748 long long element_start); 749 //long long element_size); 750 751 public: 752 const long long m_element_start; 753 long long GetPosition() const; //offset relative to segment 754 755 long GetIndex() const; 756 long long GetElementSize() const; 757 //long long GetPayloadSize() const; 758 759 //long long Unparsed() const; 760 761 private: 762 long m_index; 763 mutable long long m_pos; 764 //mutable long long m_size; 765 mutable long long m_element_size; 766 mutable long long m_timecode; 767 mutable BlockEntry** m_entries; 768 mutable long m_entries_size; 769 mutable long m_entries_count; 770 771 long ParseSimpleBlock(long long, long long&, long&); 772 long ParseBlockGroup(long long, long long&, long&); 773 774 long CreateBlock(long long id, long long pos, long long size); 775 long CreateBlockGroup(long long, long long); 776 long CreateSimpleBlock(long long, long long); 777 778 }; 779 780 781 class Segment 782 { 783 friend class Cues; 784 friend class VideoTrack; 785 friend class AudioTrack; 786 787 Segment(const Segment&); 788 Segment& operator=(const Segment&); 789 790 private: 791 Segment( 792 IMkvReader*, 793 long long elem_start, 794 //long long elem_size, 795 long long pos, 796 long long size); 797 798 public: 799 IMkvReader* const m_pReader; 800 const long long m_element_start; 801 //const long long m_element_size; 802 const long long m_start; //posn of segment payload 803 const long long m_size; //size of segment payload 804 Cluster m_eos; //TODO: make private? 805 806 static long long CreateInstance(IMkvReader*, long long, Segment*&); 807 ~Segment(); 808 809 long Load(); //loads headers and all clusters 810 811 //for incremental loading 812 //long long Unparsed() const; 813 bool DoneParsing() const; 814 long long ParseHeaders(); //stops when first cluster is found 815 //long FindNextCluster(long long& pos, long& size) const; 816 long LoadCluster(long long& pos, long& size); //load one cluster 817 long LoadCluster(); 818 819 long ParseNext( 820 const Cluster* pCurr, 821 const Cluster*& pNext, 822 long long& pos, 823 long& size); 824 825 #if 0 826 //This pair parses one cluster, but only changes the state of the 827 //segment object when the cluster is actually added to the index. 828 long ParseCluster(long long& cluster_pos, long long& new_pos) const; 829 bool AddCluster(long long cluster_pos, long long new_pos); 830 #endif 831 832 const SeekHead* GetSeekHead() const; 833 const Tracks* GetTracks() const; 834 const SegmentInfo* GetInfo() const; 835 const Cues* GetCues() const; 836 837 long long GetDuration() const; 838 839 unsigned long GetCount() const; 840 const Cluster* GetFirst() const; 841 const Cluster* GetLast() const; 842 const Cluster* GetNext(const Cluster*); 843 844 const Cluster* FindCluster(long long time_nanoseconds) const; 845 //const BlockEntry* Seek(long long time_nanoseconds, const Track*) const; 846 847 const Cluster* FindOrPreloadCluster(long long pos); 848 849 long ParseCues( 850 long long cues_off, //offset relative to start of segment 851 long long& parse_pos, 852 long& parse_len); 853 854 private: 855 856 long long m_pos; //absolute file posn; what has been consumed so far 857 Cluster* m_pUnknownSize; 858 859 SeekHead* m_pSeekHead; 860 SegmentInfo* m_pInfo; 861 Tracks* m_pTracks; 862 Cues* m_pCues; 863 Cluster** m_clusters; 864 long m_clusterCount; //number of entries for which m_index >= 0 865 long m_clusterPreloadCount; //number of entries for which m_index < 0 866 long m_clusterSize; //array size 867 868 long DoLoadCluster(long long&, long&); 869 long DoLoadClusterUnknownSize(long long&, long&); 870 long DoParseNext(const Cluster*&, long long&, long&); 871 872 void AppendCluster(Cluster*); 873 void PreloadCluster(Cluster*, ptrdiff_t); 874 875 //void ParseSeekHead(long long pos, long long size); 876 //void ParseSeekEntry(long long pos, long long size); 877 //void ParseCues(long long); 878 879 const BlockEntry* GetBlock( 880 const CuePoint&, 881 const CuePoint::TrackPosition&); 882 883 }; 884 885 } //end namespace mkvparser 886 887 inline long mkvparser::Segment::LoadCluster() 888 { 889 long long pos; 890 long size; 891 892 return LoadCluster(pos, size); 893 } 894 895 #endif //MKVPARSER_HPP 896