Home | History | Annotate | Download | only in mkvparser
      1 // Copyright (c) 2012 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 #ifndef MKVPARSER_MKVPARSER_H_
      9 #define MKVPARSER_MKVPARSER_H_
     10 
     11 #include <cstddef>
     12 
     13 namespace mkvparser {
     14 
     15 const int E_PARSE_FAILED = -1;
     16 const int E_FILE_FORMAT_INVALID = -2;
     17 const int E_BUFFER_NOT_FULL = -3;
     18 
     19 class IMkvReader {
     20  public:
     21   virtual int Read(long long pos, long len, unsigned char* buf) = 0;
     22   virtual int Length(long long* total, long long* available) = 0;
     23 
     24  protected:
     25   virtual ~IMkvReader();
     26 };
     27 
     28 template <typename Type>
     29 Type* SafeArrayAlloc(unsigned long long num_elements,
     30                      unsigned long long element_size);
     31 long long GetUIntLength(IMkvReader*, long long, long&);
     32 long long ReadUInt(IMkvReader*, long long, long&);
     33 long long ReadID(IMkvReader* pReader, long long pos, long& len);
     34 long long UnserializeUInt(IMkvReader*, long long pos, long long size);
     35 
     36 long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
     37 long UnserializeInt(IMkvReader*, long long pos, long long size,
     38                     long long& result);
     39 
     40 long UnserializeString(IMkvReader*, long long pos, long long size, char*& str);
     41 
     42 long ParseElementHeader(IMkvReader* pReader,
     43                         long long& pos,  // consume id and size fields
     44                         long long stop,  // if you know size of element's parent
     45                         long long& id, long long& size);
     46 
     47 bool Match(IMkvReader*, long long&, unsigned long, long long&);
     48 bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
     49 
     50 void GetVersion(int& major, int& minor, int& build, int& revision);
     51 
     52 struct EBMLHeader {
     53   EBMLHeader();
     54   ~EBMLHeader();
     55   long long m_version;
     56   long long m_readVersion;
     57   long long m_maxIdLength;
     58   long long m_maxSizeLength;
     59   char* m_docType;
     60   long long m_docTypeVersion;
     61   long long m_docTypeReadVersion;
     62 
     63   long long Parse(IMkvReader*, long long&);
     64   void Init();
     65 };
     66 
     67 class Segment;
     68 class Track;
     69 class Cluster;
     70 
     71 class Block {
     72   Block(const Block&);
     73   Block& operator=(const Block&);
     74 
     75  public:
     76   const long long m_start;
     77   const long long m_size;
     78 
     79   Block(long long start, long long size, long long discard_padding);
     80   ~Block();
     81 
     82   long Parse(const Cluster*);
     83 
     84   long long GetTrackNumber() const;
     85   long long GetTimeCode(const Cluster*) const;  // absolute, but not scaled
     86   long long GetTime(const Cluster*) const;  // absolute, and scaled (ns)
     87   bool IsKey() const;
     88   void SetKey(bool);
     89   bool IsInvisible() const;
     90 
     91   enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml };
     92   Lacing GetLacing() const;
     93 
     94   int GetFrameCount() const;  // to index frames: [0, count)
     95 
     96   struct Frame {
     97     long long pos;  // absolute offset
     98     long len;
     99 
    100     long Read(IMkvReader*, unsigned char*) const;
    101   };
    102 
    103   const Frame& GetFrame(int frame_index) const;
    104 
    105   long long GetDiscardPadding() const;
    106 
    107  private:
    108   long long m_track;  // Track::Number()
    109   short m_timecode;  // relative to cluster
    110   unsigned char m_flags;
    111 
    112   Frame* m_frames;
    113   int m_frame_count;
    114 
    115  protected:
    116   const long long m_discard_padding;
    117 };
    118 
    119 class BlockEntry {
    120   BlockEntry(const BlockEntry&);
    121   BlockEntry& operator=(const BlockEntry&);
    122 
    123  protected:
    124   BlockEntry(Cluster*, long index);
    125 
    126  public:
    127   virtual ~BlockEntry();
    128 
    129   bool EOS() const { return (GetKind() == kBlockEOS); }
    130   const Cluster* GetCluster() const;
    131   long GetIndex() const;
    132   virtual const Block* GetBlock() const = 0;
    133 
    134   enum Kind { kBlockEOS, kBlockSimple, kBlockGroup };
    135   virtual Kind GetKind() const = 0;
    136 
    137  protected:
    138   Cluster* const m_pCluster;
    139   const long m_index;
    140 };
    141 
    142 class SimpleBlock : public BlockEntry {
    143   SimpleBlock(const SimpleBlock&);
    144   SimpleBlock& operator=(const SimpleBlock&);
    145 
    146  public:
    147   SimpleBlock(Cluster*, long index, long long start, long long size);
    148   long Parse();
    149 
    150   Kind GetKind() const;
    151   const Block* GetBlock() const;
    152 
    153  protected:
    154   Block m_block;
    155 };
    156 
    157 class BlockGroup : public BlockEntry {
    158   BlockGroup(const BlockGroup&);
    159   BlockGroup& operator=(const BlockGroup&);
    160 
    161  public:
    162   BlockGroup(Cluster*, long index,
    163              long long block_start,  // absolute pos of block's payload
    164              long long block_size,  // size of block's payload
    165              long long prev, long long next, long long duration,
    166              long long discard_padding);
    167 
    168   long Parse();
    169 
    170   Kind GetKind() const;
    171   const Block* GetBlock() const;
    172 
    173   long long GetPrevTimeCode() const;  // relative to block's time
    174   long long GetNextTimeCode() const;  // as above
    175   long long GetDurationTimeCode() const;
    176 
    177  private:
    178   Block m_block;
    179   const long long m_prev;
    180   const long long m_next;
    181   const long long m_duration;
    182 };
    183 
    184 ///////////////////////////////////////////////////////////////
    185 // ContentEncoding element
    186 // Elements used to describe if the track data has been encrypted or
    187 // compressed with zlib or header stripping.
    188 class ContentEncoding {
    189  public:
    190   enum { kCTR = 1 };
    191 
    192   ContentEncoding();
    193   ~ContentEncoding();
    194 
    195   // ContentCompression element names
    196   struct ContentCompression {
    197     ContentCompression();
    198     ~ContentCompression();
    199 
    200     unsigned long long algo;
    201     unsigned char* settings;
    202     long long settings_len;
    203   };
    204 
    205   // ContentEncAESSettings element names
    206   struct ContentEncAESSettings {
    207     ContentEncAESSettings() : cipher_mode(kCTR) {}
    208     ~ContentEncAESSettings() {}
    209 
    210     unsigned long long cipher_mode;
    211   };
    212 
    213   // ContentEncryption element names
    214   struct ContentEncryption {
    215     ContentEncryption();
    216     ~ContentEncryption();
    217 
    218     unsigned long long algo;
    219     unsigned char* key_id;
    220     long long key_id_len;
    221     unsigned char* signature;
    222     long long signature_len;
    223     unsigned char* sig_key_id;
    224     long long sig_key_id_len;
    225     unsigned long long sig_algo;
    226     unsigned long long sig_hash_algo;
    227 
    228     ContentEncAESSettings aes_settings;
    229   };
    230 
    231   // Returns ContentCompression represented by |idx|. Returns NULL if |idx|
    232   // is out of bounds.
    233   const ContentCompression* GetCompressionByIndex(unsigned long idx) const;
    234 
    235   // Returns number of ContentCompression elements in this ContentEncoding
    236   // element.
    237   unsigned long GetCompressionCount() const;
    238 
    239   // Parses the ContentCompression element from |pReader|. |start| is the
    240   // starting offset of the ContentCompression payload. |size| is the size in
    241   // bytes of the ContentCompression payload. |compression| is where the parsed
    242   // values will be stored.
    243   long ParseCompressionEntry(long long start, long long size,
    244                              IMkvReader* pReader,
    245                              ContentCompression* compression);
    246 
    247   // Returns ContentEncryption represented by |idx|. Returns NULL if |idx|
    248   // is out of bounds.
    249   const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const;
    250 
    251   // Returns number of ContentEncryption elements in this ContentEncoding
    252   // element.
    253   unsigned long GetEncryptionCount() const;
    254 
    255   // Parses the ContentEncAESSettings element from |pReader|. |start| is the
    256   // starting offset of the ContentEncAESSettings payload. |size| is the
    257   // size in bytes of the ContentEncAESSettings payload. |encryption| is
    258   // where the parsed values will be stored.
    259   long ParseContentEncAESSettingsEntry(long long start, long long size,
    260                                        IMkvReader* pReader,
    261                                        ContentEncAESSettings* aes);
    262 
    263   // Parses the ContentEncoding element from |pReader|. |start| is the
    264   // starting offset of the ContentEncoding payload. |size| is the size in
    265   // bytes of the ContentEncoding payload. Returns true on success.
    266   long ParseContentEncodingEntry(long long start, long long size,
    267                                  IMkvReader* pReader);
    268 
    269   // Parses the ContentEncryption element from |pReader|. |start| is the
    270   // starting offset of the ContentEncryption payload. |size| is the size in
    271   // bytes of the ContentEncryption payload. |encryption| is where the parsed
    272   // values will be stored.
    273   long ParseEncryptionEntry(long long start, long long size,
    274                             IMkvReader* pReader, ContentEncryption* encryption);
    275 
    276   unsigned long long encoding_order() const { return encoding_order_; }
    277   unsigned long long encoding_scope() const { return encoding_scope_; }
    278   unsigned long long encoding_type() const { return encoding_type_; }
    279 
    280  private:
    281   // Member variables for list of ContentCompression elements.
    282   ContentCompression** compression_entries_;
    283   ContentCompression** compression_entries_end_;
    284 
    285   // Member variables for list of ContentEncryption elements.
    286   ContentEncryption** encryption_entries_;
    287   ContentEncryption** encryption_entries_end_;
    288 
    289   // ContentEncoding element names
    290   unsigned long long encoding_order_;
    291   unsigned long long encoding_scope_;
    292   unsigned long long encoding_type_;
    293 
    294   // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
    295   ContentEncoding(const ContentEncoding&);
    296   ContentEncoding& operator=(const ContentEncoding&);
    297 };
    298 
    299 class Track {
    300   Track(const Track&);
    301   Track& operator=(const Track&);
    302 
    303  public:
    304   class Info;
    305   static long Create(Segment*, const Info&, long long element_start,
    306                      long long element_size, Track*&);
    307 
    308   enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 };
    309 
    310   Segment* const m_pSegment;
    311   const long long m_element_start;
    312   const long long m_element_size;
    313   virtual ~Track();
    314 
    315   long GetType() const;
    316   long GetNumber() const;
    317   unsigned long long GetUid() const;
    318   const char* GetNameAsUTF8() const;
    319   const char* GetLanguage() const;
    320   const char* GetCodecNameAsUTF8() const;
    321   const char* GetCodecId() const;
    322   const unsigned char* GetCodecPrivate(size_t&) const;
    323   bool GetLacing() const;
    324   unsigned long long GetDefaultDuration() const;
    325   unsigned long long GetCodecDelay() const;
    326   unsigned long long GetSeekPreRoll() const;
    327 
    328   const BlockEntry* GetEOS() const;
    329 
    330   struct Settings {
    331     long long start;
    332     long long size;
    333   };
    334 
    335   class Info {
    336    public:
    337     Info();
    338     ~Info();
    339     int Copy(Info&) const;
    340     void Clear();
    341     long type;
    342     long number;
    343     unsigned long long uid;
    344     unsigned long long defaultDuration;
    345     unsigned long long codecDelay;
    346     unsigned long long seekPreRoll;
    347     char* nameAsUTF8;
    348     char* language;
    349     char* codecId;
    350     char* codecNameAsUTF8;
    351     unsigned char* codecPrivate;
    352     size_t codecPrivateSize;
    353     bool lacing;
    354     Settings settings;
    355 
    356    private:
    357     Info(const Info&);
    358     Info& operator=(const Info&);
    359     int CopyStr(char* Info::*str, Info&) const;
    360   };
    361 
    362   long GetFirst(const BlockEntry*&) const;
    363   long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
    364   virtual bool VetEntry(const BlockEntry*) const;
    365   virtual long Seek(long long time_ns, const BlockEntry*&) const;
    366 
    367   const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
    368   unsigned long GetContentEncodingCount() const;
    369 
    370   long ParseContentEncodingsEntry(long long start, long long size);
    371 
    372  protected:
    373   Track(Segment*, long long element_start, long long element_size);
    374 
    375   Info m_info;
    376 
    377   class EOSBlock : public BlockEntry {
    378    public:
    379     EOSBlock();
    380 
    381     Kind GetKind() const;
    382     const Block* GetBlock() const;
    383   };
    384 
    385   EOSBlock m_eos;
    386 
    387  private:
    388   ContentEncoding** content_encoding_entries_;
    389   ContentEncoding** content_encoding_entries_end_;
    390 };
    391 
    392 struct PrimaryChromaticity {
    393   PrimaryChromaticity() : x(0), y(0) {}
    394   ~PrimaryChromaticity() {}
    395   static bool Parse(IMkvReader* reader, long long read_pos,
    396                     long long value_size, bool is_x,
    397                     PrimaryChromaticity** chromaticity);
    398   float x;
    399   float y;
    400 };
    401 
    402 struct MasteringMetadata {
    403   static const float kValueNotPresent;
    404 
    405   MasteringMetadata()
    406       : r(NULL),
    407         g(NULL),
    408         b(NULL),
    409         white_point(NULL),
    410         luminance_max(kValueNotPresent),
    411         luminance_min(kValueNotPresent) {}
    412   ~MasteringMetadata() {
    413     delete r;
    414     delete g;
    415     delete b;
    416     delete white_point;
    417   }
    418 
    419   static bool Parse(IMkvReader* reader, long long element_start,
    420                     long long element_size,
    421                     MasteringMetadata** mastering_metadata);
    422 
    423   PrimaryChromaticity* r;
    424   PrimaryChromaticity* g;
    425   PrimaryChromaticity* b;
    426   PrimaryChromaticity* white_point;
    427   float luminance_max;
    428   float luminance_min;
    429 };
    430 
    431 struct Colour {
    432   static const long long kValueNotPresent;
    433 
    434   // Unless otherwise noted all values assigned upon construction are the
    435   // equivalent of unspecified/default.
    436   Colour()
    437       : matrix_coefficients(kValueNotPresent),
    438         bits_per_channel(kValueNotPresent),
    439         chroma_subsampling_horz(kValueNotPresent),
    440         chroma_subsampling_vert(kValueNotPresent),
    441         cb_subsampling_horz(kValueNotPresent),
    442         cb_subsampling_vert(kValueNotPresent),
    443         chroma_siting_horz(kValueNotPresent),
    444         chroma_siting_vert(kValueNotPresent),
    445         range(kValueNotPresent),
    446         transfer_characteristics(kValueNotPresent),
    447         primaries(kValueNotPresent),
    448         max_cll(kValueNotPresent),
    449         max_fall(kValueNotPresent),
    450         mastering_metadata(NULL) {}
    451   ~Colour() {
    452     delete mastering_metadata;
    453     mastering_metadata = NULL;
    454   }
    455 
    456   static bool Parse(IMkvReader* reader, long long element_start,
    457                     long long element_size, Colour** colour);
    458 
    459   long long matrix_coefficients;
    460   long long bits_per_channel;
    461   long long chroma_subsampling_horz;
    462   long long chroma_subsampling_vert;
    463   long long cb_subsampling_horz;
    464   long long cb_subsampling_vert;
    465   long long chroma_siting_horz;
    466   long long chroma_siting_vert;
    467   long long range;
    468   long long transfer_characteristics;
    469   long long primaries;
    470   long long max_cll;
    471   long long max_fall;
    472 
    473   MasteringMetadata* mastering_metadata;
    474 };
    475 
    476 struct Projection {
    477   enum ProjectionType {
    478     kTypeNotPresent = -1,
    479     kRectangular = 0,
    480     kEquirectangular = 1,
    481     kCubeMap = 2,
    482     kMesh = 3,
    483   };
    484   static const float kValueNotPresent;
    485   Projection()
    486       : type(kTypeNotPresent),
    487         private_data(NULL),
    488         private_data_length(0),
    489         pose_yaw(kValueNotPresent),
    490         pose_pitch(kValueNotPresent),
    491         pose_roll(kValueNotPresent) {}
    492   ~Projection() { delete[] private_data; }
    493   static bool Parse(IMkvReader* reader, long long element_start,
    494                     long long element_size, Projection** projection);
    495 
    496   ProjectionType type;
    497   unsigned char* private_data;
    498   size_t private_data_length;
    499   float pose_yaw;
    500   float pose_pitch;
    501   float pose_roll;
    502 };
    503 
    504 class VideoTrack : public Track {
    505   VideoTrack(const VideoTrack&);
    506   VideoTrack& operator=(const VideoTrack&);
    507 
    508   VideoTrack(Segment*, long long element_start, long long element_size);
    509 
    510  public:
    511   virtual ~VideoTrack();
    512   static long Parse(Segment*, const Info&, long long element_start,
    513                     long long element_size, VideoTrack*&);
    514 
    515   long long GetWidth() const;
    516   long long GetHeight() const;
    517   long long GetDisplayWidth() const;
    518   long long GetDisplayHeight() const;
    519   long long GetDisplayUnit() const;
    520   long long GetStereoMode() const;
    521   double GetFrameRate() const;
    522 
    523   bool VetEntry(const BlockEntry*) const;
    524   long Seek(long long time_ns, const BlockEntry*&) const;
    525 
    526   Colour* GetColour() const;
    527 
    528   Projection* GetProjection() const;
    529 
    530  private:
    531   long long m_width;
    532   long long m_height;
    533   long long m_display_width;
    534   long long m_display_height;
    535   long long m_display_unit;
    536   long long m_stereo_mode;
    537 
    538   double m_rate;
    539 
    540   Colour* m_colour;
    541   Projection* m_projection;
    542 };
    543 
    544 class AudioTrack : public Track {
    545   AudioTrack(const AudioTrack&);
    546   AudioTrack& operator=(const AudioTrack&);
    547 
    548   AudioTrack(Segment*, long long element_start, long long element_size);
    549 
    550  public:
    551   static long Parse(Segment*, const Info&, long long element_start,
    552                     long long element_size, AudioTrack*&);
    553 
    554   double GetSamplingRate() const;
    555   long long GetChannels() const;
    556   long long GetBitDepth() const;
    557 
    558  private:
    559   double m_rate;
    560   long long m_channels;
    561   long long m_bitDepth;
    562 };
    563 
    564 class Tracks {
    565   Tracks(const Tracks&);
    566   Tracks& operator=(const Tracks&);
    567 
    568  public:
    569   Segment* const m_pSegment;
    570   const long long m_start;
    571   const long long m_size;
    572   const long long m_element_start;
    573   const long long m_element_size;
    574 
    575   Tracks(Segment*, long long start, long long size, long long element_start,
    576          long long element_size);
    577 
    578   ~Tracks();
    579 
    580   long Parse();
    581 
    582   unsigned long GetTracksCount() const;
    583 
    584   const Track* GetTrackByNumber(long tn) const;
    585   const Track* GetTrackByIndex(unsigned long idx) const;
    586 
    587  private:
    588   Track** m_trackEntries;
    589   Track** m_trackEntriesEnd;
    590 
    591   long ParseTrackEntry(long long payload_start, long long payload_size,
    592                        long long element_start, long long element_size,
    593                        Track*&) const;
    594 };
    595 
    596 class Chapters {
    597   Chapters(const Chapters&);
    598   Chapters& operator=(const Chapters&);
    599 
    600  public:
    601   Segment* const m_pSegment;
    602   const long long m_start;
    603   const long long m_size;
    604   const long long m_element_start;
    605   const long long m_element_size;
    606 
    607   Chapters(Segment*, long long payload_start, long long payload_size,
    608            long long element_start, long long element_size);
    609 
    610   ~Chapters();
    611 
    612   long Parse();
    613 
    614   class Atom;
    615   class Edition;
    616 
    617   class Display {
    618     friend class Atom;
    619     Display();
    620     Display(const Display&);
    621     ~Display();
    622     Display& operator=(const Display&);
    623 
    624    public:
    625     const char* GetString() const;
    626     const char* GetLanguage() const;
    627     const char* GetCountry() const;
    628 
    629    private:
    630     void Init();
    631     void ShallowCopy(Display&) const;
    632     void Clear();
    633     long Parse(IMkvReader*, long long pos, long long size);
    634 
    635     char* m_string;
    636     char* m_language;
    637     char* m_country;
    638   };
    639 
    640   class Atom {
    641     friend class Edition;
    642     Atom();
    643     Atom(const Atom&);
    644     ~Atom();
    645     Atom& operator=(const Atom&);
    646 
    647    public:
    648     unsigned long long GetUID() const;
    649     const char* GetStringUID() const;
    650 
    651     long long GetStartTimecode() const;
    652     long long GetStopTimecode() const;
    653 
    654     long long GetStartTime(const Chapters*) const;
    655     long long GetStopTime(const Chapters*) const;
    656 
    657     int GetDisplayCount() const;
    658     const Display* GetDisplay(int index) const;
    659 
    660    private:
    661     void Init();
    662     void ShallowCopy(Atom&) const;
    663     void Clear();
    664     long Parse(IMkvReader*, long long pos, long long size);
    665     static long long GetTime(const Chapters*, long long timecode);
    666 
    667     long ParseDisplay(IMkvReader*, long long pos, long long size);
    668     bool ExpandDisplaysArray();
    669 
    670     char* m_string_uid;
    671     unsigned long long m_uid;
    672     long long m_start_timecode;
    673     long long m_stop_timecode;
    674 
    675     Display* m_displays;
    676     int m_displays_size;
    677     int m_displays_count;
    678   };
    679 
    680   class Edition {
    681     friend class Chapters;
    682     Edition();
    683     Edition(const Edition&);
    684     ~Edition();
    685     Edition& operator=(const Edition&);
    686 
    687    public:
    688     int GetAtomCount() const;
    689     const Atom* GetAtom(int index) const;
    690 
    691    private:
    692     void Init();
    693     void ShallowCopy(Edition&) const;
    694     void Clear();
    695     long Parse(IMkvReader*, long long pos, long long size);
    696 
    697     long ParseAtom(IMkvReader*, long long pos, long long size);
    698     bool ExpandAtomsArray();
    699 
    700     Atom* m_atoms;
    701     int m_atoms_size;
    702     int m_atoms_count;
    703   };
    704 
    705   int GetEditionCount() const;
    706   const Edition* GetEdition(int index) const;
    707 
    708  private:
    709   long ParseEdition(long long pos, long long size);
    710   bool ExpandEditionsArray();
    711 
    712   Edition* m_editions;
    713   int m_editions_size;
    714   int m_editions_count;
    715 };
    716 
    717 class Tags {
    718   Tags(const Tags&);
    719   Tags& operator=(const Tags&);
    720 
    721  public:
    722   Segment* const m_pSegment;
    723   const long long m_start;
    724   const long long m_size;
    725   const long long m_element_start;
    726   const long long m_element_size;
    727 
    728   Tags(Segment*, long long payload_start, long long payload_size,
    729        long long element_start, long long element_size);
    730 
    731   ~Tags();
    732 
    733   long Parse();
    734 
    735   class Tag;
    736   class SimpleTag;
    737 
    738   class SimpleTag {
    739     friend class Tag;
    740     SimpleTag();
    741     SimpleTag(const SimpleTag&);
    742     ~SimpleTag();
    743     SimpleTag& operator=(const SimpleTag&);
    744 
    745    public:
    746     const char* GetTagName() const;
    747     const char* GetTagString() const;
    748 
    749    private:
    750     void Init();
    751     void ShallowCopy(SimpleTag&) const;
    752     void Clear();
    753     long Parse(IMkvReader*, long long pos, long long size);
    754 
    755     char* m_tag_name;
    756     char* m_tag_string;
    757   };
    758 
    759   class Tag {
    760     friend class Tags;
    761     Tag();
    762     Tag(const Tag&);
    763     ~Tag();
    764     Tag& operator=(const Tag&);
    765 
    766    public:
    767     int GetSimpleTagCount() const;
    768     const SimpleTag* GetSimpleTag(int index) const;
    769 
    770    private:
    771     void Init();
    772     void ShallowCopy(Tag&) const;
    773     void Clear();
    774     long Parse(IMkvReader*, long long pos, long long size);
    775 
    776     long ParseSimpleTag(IMkvReader*, long long pos, long long size);
    777     bool ExpandSimpleTagsArray();
    778 
    779     SimpleTag* m_simple_tags;
    780     int m_simple_tags_size;
    781     int m_simple_tags_count;
    782   };
    783 
    784   int GetTagCount() const;
    785   const Tag* GetTag(int index) const;
    786 
    787  private:
    788   long ParseTag(long long pos, long long size);
    789   bool ExpandTagsArray();
    790 
    791   Tag* m_tags;
    792   int m_tags_size;
    793   int m_tags_count;
    794 };
    795 
    796 class SegmentInfo {
    797   SegmentInfo(const SegmentInfo&);
    798   SegmentInfo& operator=(const SegmentInfo&);
    799 
    800  public:
    801   Segment* const m_pSegment;
    802   const long long m_start;
    803   const long long m_size;
    804   const long long m_element_start;
    805   const long long m_element_size;
    806 
    807   SegmentInfo(Segment*, long long start, long long size,
    808               long long element_start, long long element_size);
    809 
    810   ~SegmentInfo();
    811 
    812   long Parse();
    813 
    814   long long GetTimeCodeScale() const;
    815   long long GetDuration() const;  // scaled
    816   const char* GetMuxingAppAsUTF8() const;
    817   const char* GetWritingAppAsUTF8() const;
    818   const char* GetTitleAsUTF8() const;
    819 
    820  private:
    821   long long m_timecodeScale;
    822   double m_duration;
    823   char* m_pMuxingAppAsUTF8;
    824   char* m_pWritingAppAsUTF8;
    825   char* m_pTitleAsUTF8;
    826 };
    827 
    828 class SeekHead {
    829   SeekHead(const SeekHead&);
    830   SeekHead& operator=(const SeekHead&);
    831 
    832  public:
    833   Segment* const m_pSegment;
    834   const long long m_start;
    835   const long long m_size;
    836   const long long m_element_start;
    837   const long long m_element_size;
    838 
    839   SeekHead(Segment*, long long start, long long size, long long element_start,
    840            long long element_size);
    841 
    842   ~SeekHead();
    843 
    844   long Parse();
    845 
    846   struct Entry {
    847     Entry();
    848 
    849     // the SeekHead entry payload
    850     long long id;
    851     long long pos;
    852 
    853     // absolute pos of SeekEntry ID
    854     long long element_start;
    855 
    856     // SeekEntry ID size + size size + payload
    857     long long element_size;
    858   };
    859 
    860   int GetCount() const;
    861   const Entry* GetEntry(int idx) const;
    862 
    863   struct VoidElement {
    864     // absolute pos of Void ID
    865     long long element_start;
    866 
    867     // ID size + size size + payload size
    868     long long element_size;
    869   };
    870 
    871   int GetVoidElementCount() const;
    872   const VoidElement* GetVoidElement(int idx) const;
    873 
    874  private:
    875   Entry* m_entries;
    876   int m_entry_count;
    877 
    878   VoidElement* m_void_elements;
    879   int m_void_element_count;
    880 
    881   static bool ParseEntry(IMkvReader*,
    882                          long long pos,  // payload
    883                          long long size, Entry*);
    884 };
    885 
    886 class Cues;
    887 class CuePoint {
    888   friend class Cues;
    889 
    890   CuePoint(long, long long);
    891   ~CuePoint();
    892 
    893   CuePoint(const CuePoint&);
    894   CuePoint& operator=(const CuePoint&);
    895 
    896  public:
    897   long long m_element_start;
    898   long long m_element_size;
    899 
    900   bool Load(IMkvReader*);
    901 
    902   long long GetTimeCode() const;  // absolute but unscaled
    903   long long GetTime(const Segment*) const;  // absolute and scaled (ns units)
    904 
    905   struct TrackPosition {
    906     long long m_track;
    907     long long m_pos;  // of cluster
    908     long long m_block;
    909     // codec_state  //defaults to 0
    910     // reference = clusters containing req'd referenced blocks
    911     //  reftime = timecode of the referenced block
    912 
    913     bool Parse(IMkvReader*, long long, long long);
    914   };
    915 
    916   const TrackPosition* Find(const Track*) const;
    917 
    918  private:
    919   const long m_index;
    920   long long m_timecode;
    921   TrackPosition* m_track_positions;
    922   size_t m_track_positions_count;
    923 };
    924 
    925 class Cues {
    926   friend class Segment;
    927 
    928   Cues(Segment*, long long start, long long size, long long element_start,
    929        long long element_size);
    930   ~Cues();
    931 
    932   Cues(const Cues&);
    933   Cues& operator=(const Cues&);
    934 
    935  public:
    936   Segment* const m_pSegment;
    937   const long long m_start;
    938   const long long m_size;
    939   const long long m_element_start;
    940   const long long m_element_size;
    941 
    942   bool Find(  // lower bound of time_ns
    943       long long time_ns, const Track*, const CuePoint*&,
    944       const CuePoint::TrackPosition*&) const;
    945 
    946   const CuePoint* GetFirst() const;
    947   const CuePoint* GetLast() const;
    948   const CuePoint* GetNext(const CuePoint*) const;
    949 
    950   const BlockEntry* GetBlock(const CuePoint*,
    951                              const CuePoint::TrackPosition*) const;
    952 
    953   bool LoadCuePoint() const;
    954   long GetCount() const;  // loaded only
    955   // long GetTotal() const;  //loaded + preloaded
    956   bool DoneParsing() const;
    957 
    958  private:
    959   bool Init() const;
    960   bool PreloadCuePoint(long&, long long) const;
    961 
    962   mutable CuePoint** m_cue_points;
    963   mutable long m_count;
    964   mutable long m_preload_count;
    965   mutable long long m_pos;
    966 };
    967 
    968 class Cluster {
    969   friend class Segment;
    970 
    971   Cluster(const Cluster&);
    972   Cluster& operator=(const Cluster&);
    973 
    974  public:
    975   Segment* const m_pSegment;
    976 
    977  public:
    978   static Cluster* Create(Segment*,
    979                          long index,  // index in segment
    980                          long long off);  // offset relative to segment
    981   // long long element_size);
    982 
    983   Cluster();  // EndOfStream
    984   ~Cluster();
    985 
    986   bool EOS() const;
    987 
    988   long long GetTimeCode() const;  // absolute, but not scaled
    989   long long GetTime() const;  // absolute, and scaled (nanosecond units)
    990   long long GetFirstTime() const;  // time (ns) of first (earliest) block
    991   long long GetLastTime() const;  // time (ns) of last (latest) block
    992 
    993   long GetFirst(const BlockEntry*&) const;
    994   long GetLast(const BlockEntry*&) const;
    995   long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
    996 
    997   const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
    998   const BlockEntry* GetEntry(const CuePoint&,
    999                              const CuePoint::TrackPosition&) const;
   1000   // const BlockEntry* GetMaxKey(const VideoTrack*) const;
   1001 
   1002   //    static bool HasBlockEntries(const Segment*, long long);
   1003 
   1004   static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
   1005                               long& size);
   1006 
   1007   long GetEntryCount() const;
   1008 
   1009   long Load(long long& pos, long& size) const;
   1010 
   1011   long Parse(long long& pos, long& size) const;
   1012   long GetEntry(long index, const mkvparser::BlockEntry*&) const;
   1013 
   1014  protected:
   1015   Cluster(Segment*, long index, long long element_start);
   1016   // long long element_size);
   1017 
   1018  public:
   1019   const long long m_element_start;
   1020   long long GetPosition() const;  // offset relative to segment
   1021 
   1022   long GetIndex() const;
   1023   long long GetElementSize() const;
   1024   // long long GetPayloadSize() const;
   1025 
   1026   // long long Unparsed() const;
   1027 
   1028  private:
   1029   long m_index;
   1030   mutable long long m_pos;
   1031   // mutable long long m_size;
   1032   mutable long long m_element_size;
   1033   mutable long long m_timecode;
   1034   mutable BlockEntry** m_entries;
   1035   mutable long m_entries_size;
   1036   mutable long m_entries_count;
   1037 
   1038   long ParseSimpleBlock(long long, long long&, long&);
   1039   long ParseBlockGroup(long long, long long&, long&);
   1040 
   1041   long CreateBlock(long long id, long long pos, long long size,
   1042                    long long discard_padding);
   1043   long CreateBlockGroup(long long start_offset, long long size,
   1044                         long long discard_padding);
   1045   long CreateSimpleBlock(long long, long long);
   1046 };
   1047 
   1048 class Segment {
   1049   friend class Cues;
   1050   friend class Track;
   1051   friend class VideoTrack;
   1052 
   1053   Segment(const Segment&);
   1054   Segment& operator=(const Segment&);
   1055 
   1056  private:
   1057   Segment(IMkvReader*, long long elem_start,
   1058           // long long elem_size,
   1059           long long pos, long long size);
   1060 
   1061  public:
   1062   IMkvReader* const m_pReader;
   1063   const long long m_element_start;
   1064   // const long long m_element_size;
   1065   const long long m_start;  // posn of segment payload
   1066   const long long m_size;  // size of segment payload
   1067   Cluster m_eos;  // TODO: make private?
   1068 
   1069   static long long CreateInstance(IMkvReader*, long long, Segment*&);
   1070   ~Segment();
   1071 
   1072   long Load();  // loads headers and all clusters
   1073 
   1074   // for incremental loading
   1075   // long long Unparsed() const;
   1076   bool DoneParsing() const;
   1077   long long ParseHeaders();  // stops when first cluster is found
   1078   // long FindNextCluster(long long& pos, long& size) const;
   1079   long LoadCluster(long long& pos, long& size);  // load one cluster
   1080   long LoadCluster();
   1081 
   1082   long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
   1083                  long& size);
   1084 
   1085   const SeekHead* GetSeekHead() const;
   1086   const Tracks* GetTracks() const;
   1087   const SegmentInfo* GetInfo() const;
   1088   const Cues* GetCues() const;
   1089   const Chapters* GetChapters() const;
   1090   const Tags* GetTags() const;
   1091 
   1092   long long GetDuration() const;
   1093 
   1094   unsigned long GetCount() const;
   1095   const Cluster* GetFirst() const;
   1096   const Cluster* GetLast() const;
   1097   const Cluster* GetNext(const Cluster*);
   1098 
   1099   const Cluster* FindCluster(long long time_nanoseconds) const;
   1100   // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
   1101 
   1102   const Cluster* FindOrPreloadCluster(long long pos);
   1103 
   1104   long ParseCues(long long cues_off,  // offset relative to start of segment
   1105                  long long& parse_pos, long& parse_len);
   1106 
   1107  private:
   1108   long long m_pos;  // absolute file posn; what has been consumed so far
   1109   Cluster* m_pUnknownSize;
   1110 
   1111   SeekHead* m_pSeekHead;
   1112   SegmentInfo* m_pInfo;
   1113   Tracks* m_pTracks;
   1114   Cues* m_pCues;
   1115   Chapters* m_pChapters;
   1116   Tags* m_pTags;
   1117   Cluster** m_clusters;
   1118   long m_clusterCount;  // number of entries for which m_index >= 0
   1119   long m_clusterPreloadCount;  // number of entries for which m_index < 0
   1120   long m_clusterSize;  // array size
   1121 
   1122   long DoLoadCluster(long long&, long&);
   1123   long DoLoadClusterUnknownSize(long long&, long&);
   1124   long DoParseNext(const Cluster*&, long long&, long&);
   1125 
   1126   bool AppendCluster(Cluster*);
   1127   bool PreloadCluster(Cluster*, ptrdiff_t);
   1128 
   1129   // void ParseSeekHead(long long pos, long long size);
   1130   // void ParseSeekEntry(long long pos, long long size);
   1131   // void ParseCues(long long);
   1132 
   1133   const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
   1134 };
   1135 
   1136 }  // namespace mkvparser
   1137 
   1138 inline long mkvparser::Segment::LoadCluster() {
   1139   long long pos;
   1140   long size;
   1141 
   1142   return LoadCluster(pos, size);
   1143 }
   1144 
   1145 #endif  // MKVPARSER_MKVPARSER_H_
   1146