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 long GetIndex() const; 608 609 struct TrackPosition 610 { 611 long long m_track; 612 long long m_pos; //of cluster 613 long long m_block; 614 //codec_state //defaults to 0 615 //reference = clusters containing req'd referenced blocks 616 // reftime = timecode of the referenced block 617 618 void Parse(IMkvReader*, long long, long long); 619 }; 620 621 const TrackPosition* Find(const Track*) const; 622 623 private: 624 const long m_index; 625 long long m_timecode; 626 TrackPosition* m_track_positions; 627 size_t m_track_positions_count; 628 629 }; 630 631 632 class Cues 633 { 634 friend class Segment; 635 636 Cues( 637 Segment*, 638 long long start, 639 long long size, 640 long long element_start, 641 long long element_size); 642 ~Cues(); 643 644 Cues(const Cues&); 645 Cues& operator=(const Cues&); 646 647 public: 648 Segment* const m_pSegment; 649 const long long m_start; 650 const long long m_size; 651 const long long m_element_start; 652 const long long m_element_size; 653 654 bool Find( //lower bound of time_ns 655 long long time_ns, 656 const Track*, 657 const CuePoint*&, 658 const CuePoint::TrackPosition*&) const; 659 660 #if 0 661 bool FindNext( //upper_bound of time_ns 662 long long time_ns, 663 const Track*, 664 const CuePoint*&, 665 const CuePoint::TrackPosition*&) const; 666 #endif 667 668 const CuePoint* GetFirst() const; 669 const CuePoint* GetLast() const; 670 const CuePoint* GetNext(const CuePoint*) const; 671 672 const BlockEntry* GetBlock( 673 const CuePoint*, 674 const CuePoint::TrackPosition*) const; 675 676 bool LoadCuePoint() const; 677 long GetCount() const; //loaded only 678 //long GetTotal() const; //loaded + preloaded 679 bool DoneParsing() const; 680 681 private: 682 void Init() const; 683 void PreloadCuePoint(long&, long long) const; 684 685 mutable CuePoint** m_cue_points; 686 mutable long m_count; 687 mutable long m_preload_count; 688 mutable long long m_pos; 689 690 }; 691 692 693 class Cluster 694 { 695 friend class Segment; 696 697 Cluster(const Cluster&); 698 Cluster& operator=(const Cluster&); 699 700 public: 701 Segment* const m_pSegment; 702 703 public: 704 static Cluster* Create( 705 Segment*, 706 long index, //index in segment 707 long long off); //offset relative to segment 708 //long long element_size); 709 710 Cluster(); //EndOfStream 711 ~Cluster(); 712 713 bool EOS() const; 714 715 long long GetTimeCode() const; //absolute, but not scaled 716 long long GetTime() const; //absolute, and scaled (nanosecond units) 717 long long GetFirstTime() const; //time (ns) of first (earliest) block 718 long long GetLastTime() const; //time (ns) of last (latest) block 719 720 long GetFirst(const BlockEntry*&) const; 721 long GetLast(const BlockEntry*&) const; 722 long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; 723 724 const BlockEntry* GetEntry(const Track*, long long ns = -1) const; 725 const BlockEntry* GetEntry( 726 const CuePoint&, 727 const CuePoint::TrackPosition&) const; 728 //const BlockEntry* GetMaxKey(const VideoTrack*) const; 729 730 // static bool HasBlockEntries(const Segment*, long long); 731 732 static long HasBlockEntries( 733 const Segment*, 734 long long idoff, 735 long long& pos, 736 long& size); 737 738 long GetEntryCount() const; 739 740 long Load(long long& pos, long& size) const; 741 742 long Parse(long long& pos, long& size) const; 743 long GetEntry(long index, const mkvparser::BlockEntry*&) const; 744 745 protected: 746 Cluster( 747 Segment*, 748 long index, 749 long long element_start); 750 //long long element_size); 751 752 public: 753 const long long m_element_start; 754 long long GetPosition() const; //offset relative to segment 755 756 long GetIndex() const; 757 long long GetElementSize() const; 758 //long long GetPayloadSize() const; 759 760 //long long Unparsed() const; 761 762 private: 763 long m_index; 764 mutable long long m_pos; 765 //mutable long long m_size; 766 mutable long long m_element_size; 767 mutable long long m_timecode; 768 mutable BlockEntry** m_entries; 769 mutable long m_entries_size; 770 mutable long m_entries_count; 771 772 long ParseSimpleBlock(long long, long long&, long&); 773 long ParseBlockGroup(long long, long long&, long&); 774 775 long CreateBlock(long long id, long long pos, long long size); 776 long CreateBlockGroup(long long, long long); 777 long CreateSimpleBlock(long long, long long); 778 779 }; 780 781 782 class Segment 783 { 784 friend class Cues; 785 friend class VideoTrack; 786 friend class AudioTrack; 787 788 Segment(const Segment&); 789 Segment& operator=(const Segment&); 790 791 private: 792 Segment( 793 IMkvReader*, 794 long long elem_start, 795 //long long elem_size, 796 long long pos, 797 long long size); 798 799 public: 800 IMkvReader* const m_pReader; 801 const long long m_element_start; 802 //const long long m_element_size; 803 const long long m_start; //posn of segment payload 804 const long long m_size; //size of segment payload 805 Cluster m_eos; //TODO: make private? 806 807 static long long CreateInstance(IMkvReader*, long long, Segment*&); 808 ~Segment(); 809 810 long Load(); //loads headers and all clusters 811 812 //for incremental loading 813 //long long Unparsed() const; 814 bool DoneParsing() const; 815 long long ParseHeaders(); //stops when first cluster is found 816 //long FindNextCluster(long long& pos, long& size) const; 817 long LoadCluster(long long& pos, long& size); //load one cluster 818 long LoadCluster(); 819 820 long ParseNext( 821 const Cluster* pCurr, 822 const Cluster*& pNext, 823 long long& pos, 824 long& size); 825 826 #if 0 827 //This pair parses one cluster, but only changes the state of the 828 //segment object when the cluster is actually added to the index. 829 long ParseCluster(long long& cluster_pos, long long& new_pos) const; 830 bool AddCluster(long long cluster_pos, long long new_pos); 831 #endif 832 833 const SeekHead* GetSeekHead() const; 834 const Tracks* GetTracks() const; 835 const SegmentInfo* GetInfo() const; 836 const Cues* GetCues() const; 837 838 long long GetDuration() const; 839 840 unsigned long GetCount() const; 841 const Cluster* GetFirst() const; 842 const Cluster* GetLast() const; 843 const Cluster* GetNext(const Cluster*); 844 845 const Cluster* FindCluster(long long time_nanoseconds) const; 846 //const BlockEntry* Seek(long long time_nanoseconds, const Track*) const; 847 848 const Cluster* FindOrPreloadCluster(long long pos); 849 850 long ParseCues( 851 long long cues_off, //offset relative to start of segment 852 long long& parse_pos, 853 long& parse_len); 854 855 private: 856 857 long long m_pos; //absolute file posn; what has been consumed so far 858 Cluster* m_pUnknownSize; 859 860 SeekHead* m_pSeekHead; 861 SegmentInfo* m_pInfo; 862 Tracks* m_pTracks; 863 Cues* m_pCues; 864 Cluster** m_clusters; 865 long m_clusterCount; //number of entries for which m_index >= 0 866 long m_clusterPreloadCount; //number of entries for which m_index < 0 867 long m_clusterSize; //array size 868 869 long DoLoadCluster(long long&, long&); 870 long DoLoadClusterUnknownSize(long long&, long&); 871 long DoParseNext(const Cluster*&, long long&, long&); 872 873 void AppendCluster(Cluster*); 874 void PreloadCluster(Cluster*, ptrdiff_t); 875 876 //void ParseSeekHead(long long pos, long long size); 877 //void ParseSeekEntry(long long pos, long long size); 878 //void ParseCues(long long); 879 880 const BlockEntry* GetBlock( 881 const CuePoint&, 882 const CuePoint::TrackPosition&); 883 884 }; 885 886 } //end namespace mkvparser 887 888 inline long mkvparser::Segment::LoadCluster() 889 { 890 long long pos; 891 long size; 892 893 return LoadCluster(pos, size); 894 } 895 896 #endif //MKVPARSER_HPP 897