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 class VideoTrack : public Track {
    477   VideoTrack(const VideoTrack&);
    478   VideoTrack& operator=(const VideoTrack&);
    479 
    480   VideoTrack(Segment*, long long element_start, long long element_size);
    481 
    482  public:
    483   virtual ~VideoTrack();
    484   static long Parse(Segment*, const Info&, long long element_start,
    485                     long long element_size, VideoTrack*&);
    486 
    487   long long GetWidth() const;
    488   long long GetHeight() const;
    489   long long GetDisplayWidth() const;
    490   long long GetDisplayHeight() const;
    491   long long GetDisplayUnit() const;
    492   long long GetStereoMode() const;
    493   double GetFrameRate() const;
    494 
    495   bool VetEntry(const BlockEntry*) const;
    496   long Seek(long long time_ns, const BlockEntry*&) const;
    497 
    498   Colour* GetColour() const;
    499 
    500  private:
    501   long long m_width;
    502   long long m_height;
    503   long long m_display_width;
    504   long long m_display_height;
    505   long long m_display_unit;
    506   long long m_stereo_mode;
    507 
    508   double m_rate;
    509 
    510   Colour* m_colour;
    511 };
    512 
    513 class AudioTrack : public Track {
    514   AudioTrack(const AudioTrack&);
    515   AudioTrack& operator=(const AudioTrack&);
    516 
    517   AudioTrack(Segment*, long long element_start, long long element_size);
    518 
    519  public:
    520   static long Parse(Segment*, const Info&, long long element_start,
    521                     long long element_size, AudioTrack*&);
    522 
    523   double GetSamplingRate() const;
    524   long long GetChannels() const;
    525   long long GetBitDepth() const;
    526 
    527  private:
    528   double m_rate;
    529   long long m_channels;
    530   long long m_bitDepth;
    531 };
    532 
    533 class Tracks {
    534   Tracks(const Tracks&);
    535   Tracks& operator=(const Tracks&);
    536 
    537  public:
    538   Segment* const m_pSegment;
    539   const long long m_start;
    540   const long long m_size;
    541   const long long m_element_start;
    542   const long long m_element_size;
    543 
    544   Tracks(Segment*, long long start, long long size, long long element_start,
    545          long long element_size);
    546 
    547   ~Tracks();
    548 
    549   long Parse();
    550 
    551   unsigned long GetTracksCount() const;
    552 
    553   const Track* GetTrackByNumber(long tn) const;
    554   const Track* GetTrackByIndex(unsigned long idx) const;
    555 
    556  private:
    557   Track** m_trackEntries;
    558   Track** m_trackEntriesEnd;
    559 
    560   long ParseTrackEntry(long long payload_start, long long payload_size,
    561                        long long element_start, long long element_size,
    562                        Track*&) const;
    563 };
    564 
    565 class Chapters {
    566   Chapters(const Chapters&);
    567   Chapters& operator=(const Chapters&);
    568 
    569  public:
    570   Segment* const m_pSegment;
    571   const long long m_start;
    572   const long long m_size;
    573   const long long m_element_start;
    574   const long long m_element_size;
    575 
    576   Chapters(Segment*, long long payload_start, long long payload_size,
    577            long long element_start, long long element_size);
    578 
    579   ~Chapters();
    580 
    581   long Parse();
    582 
    583   class Atom;
    584   class Edition;
    585 
    586   class Display {
    587     friend class Atom;
    588     Display();
    589     Display(const Display&);
    590     ~Display();
    591     Display& operator=(const Display&);
    592 
    593    public:
    594     const char* GetString() const;
    595     const char* GetLanguage() const;
    596     const char* GetCountry() const;
    597 
    598    private:
    599     void Init();
    600     void ShallowCopy(Display&) const;
    601     void Clear();
    602     long Parse(IMkvReader*, long long pos, long long size);
    603 
    604     char* m_string;
    605     char* m_language;
    606     char* m_country;
    607   };
    608 
    609   class Atom {
    610     friend class Edition;
    611     Atom();
    612     Atom(const Atom&);
    613     ~Atom();
    614     Atom& operator=(const Atom&);
    615 
    616    public:
    617     unsigned long long GetUID() const;
    618     const char* GetStringUID() const;
    619 
    620     long long GetStartTimecode() const;
    621     long long GetStopTimecode() const;
    622 
    623     long long GetStartTime(const Chapters*) const;
    624     long long GetStopTime(const Chapters*) const;
    625 
    626     int GetDisplayCount() const;
    627     const Display* GetDisplay(int index) const;
    628 
    629    private:
    630     void Init();
    631     void ShallowCopy(Atom&) const;
    632     void Clear();
    633     long Parse(IMkvReader*, long long pos, long long size);
    634     static long long GetTime(const Chapters*, long long timecode);
    635 
    636     long ParseDisplay(IMkvReader*, long long pos, long long size);
    637     bool ExpandDisplaysArray();
    638 
    639     char* m_string_uid;
    640     unsigned long long m_uid;
    641     long long m_start_timecode;
    642     long long m_stop_timecode;
    643 
    644     Display* m_displays;
    645     int m_displays_size;
    646     int m_displays_count;
    647   };
    648 
    649   class Edition {
    650     friend class Chapters;
    651     Edition();
    652     Edition(const Edition&);
    653     ~Edition();
    654     Edition& operator=(const Edition&);
    655 
    656    public:
    657     int GetAtomCount() const;
    658     const Atom* GetAtom(int index) const;
    659 
    660    private:
    661     void Init();
    662     void ShallowCopy(Edition&) const;
    663     void Clear();
    664     long Parse(IMkvReader*, long long pos, long long size);
    665 
    666     long ParseAtom(IMkvReader*, long long pos, long long size);
    667     bool ExpandAtomsArray();
    668 
    669     Atom* m_atoms;
    670     int m_atoms_size;
    671     int m_atoms_count;
    672   };
    673 
    674   int GetEditionCount() const;
    675   const Edition* GetEdition(int index) const;
    676 
    677  private:
    678   long ParseEdition(long long pos, long long size);
    679   bool ExpandEditionsArray();
    680 
    681   Edition* m_editions;
    682   int m_editions_size;
    683   int m_editions_count;
    684 };
    685 
    686 class Tags {
    687   Tags(const Tags&);
    688   Tags& operator=(const Tags&);
    689 
    690  public:
    691   Segment* const m_pSegment;
    692   const long long m_start;
    693   const long long m_size;
    694   const long long m_element_start;
    695   const long long m_element_size;
    696 
    697   Tags(Segment*, long long payload_start, long long payload_size,
    698        long long element_start, long long element_size);
    699 
    700   ~Tags();
    701 
    702   long Parse();
    703 
    704   class Tag;
    705   class SimpleTag;
    706 
    707   class SimpleTag {
    708     friend class Tag;
    709     SimpleTag();
    710     SimpleTag(const SimpleTag&);
    711     ~SimpleTag();
    712     SimpleTag& operator=(const SimpleTag&);
    713 
    714    public:
    715     const char* GetTagName() const;
    716     const char* GetTagString() const;
    717 
    718    private:
    719     void Init();
    720     void ShallowCopy(SimpleTag&) const;
    721     void Clear();
    722     long Parse(IMkvReader*, long long pos, long long size);
    723 
    724     char* m_tag_name;
    725     char* m_tag_string;
    726   };
    727 
    728   class Tag {
    729     friend class Tags;
    730     Tag();
    731     Tag(const Tag&);
    732     ~Tag();
    733     Tag& operator=(const Tag&);
    734 
    735    public:
    736     int GetSimpleTagCount() const;
    737     const SimpleTag* GetSimpleTag(int index) const;
    738 
    739    private:
    740     void Init();
    741     void ShallowCopy(Tag&) const;
    742     void Clear();
    743     long Parse(IMkvReader*, long long pos, long long size);
    744 
    745     long ParseSimpleTag(IMkvReader*, long long pos, long long size);
    746     bool ExpandSimpleTagsArray();
    747 
    748     SimpleTag* m_simple_tags;
    749     int m_simple_tags_size;
    750     int m_simple_tags_count;
    751   };
    752 
    753   int GetTagCount() const;
    754   const Tag* GetTag(int index) const;
    755 
    756  private:
    757   long ParseTag(long long pos, long long size);
    758   bool ExpandTagsArray();
    759 
    760   Tag* m_tags;
    761   int m_tags_size;
    762   int m_tags_count;
    763 };
    764 
    765 class SegmentInfo {
    766   SegmentInfo(const SegmentInfo&);
    767   SegmentInfo& operator=(const SegmentInfo&);
    768 
    769  public:
    770   Segment* const m_pSegment;
    771   const long long m_start;
    772   const long long m_size;
    773   const long long m_element_start;
    774   const long long m_element_size;
    775 
    776   SegmentInfo(Segment*, long long start, long long size,
    777               long long element_start, long long element_size);
    778 
    779   ~SegmentInfo();
    780 
    781   long Parse();
    782 
    783   long long GetTimeCodeScale() const;
    784   long long GetDuration() const;  // scaled
    785   const char* GetMuxingAppAsUTF8() const;
    786   const char* GetWritingAppAsUTF8() const;
    787   const char* GetTitleAsUTF8() const;
    788 
    789  private:
    790   long long m_timecodeScale;
    791   double m_duration;
    792   char* m_pMuxingAppAsUTF8;
    793   char* m_pWritingAppAsUTF8;
    794   char* m_pTitleAsUTF8;
    795 };
    796 
    797 class SeekHead {
    798   SeekHead(const SeekHead&);
    799   SeekHead& operator=(const SeekHead&);
    800 
    801  public:
    802   Segment* const m_pSegment;
    803   const long long m_start;
    804   const long long m_size;
    805   const long long m_element_start;
    806   const long long m_element_size;
    807 
    808   SeekHead(Segment*, long long start, long long size, long long element_start,
    809            long long element_size);
    810 
    811   ~SeekHead();
    812 
    813   long Parse();
    814 
    815   struct Entry {
    816     // the SeekHead entry payload
    817     long long id;
    818     long long pos;
    819 
    820     // absolute pos of SeekEntry ID
    821     long long element_start;
    822 
    823     // SeekEntry ID size + size size + payload
    824     long long element_size;
    825   };
    826 
    827   int GetCount() const;
    828   const Entry* GetEntry(int idx) const;
    829 
    830   struct VoidElement {
    831     // absolute pos of Void ID
    832     long long element_start;
    833 
    834     // ID size + size size + payload size
    835     long long element_size;
    836   };
    837 
    838   int GetVoidElementCount() const;
    839   const VoidElement* GetVoidElement(int idx) const;
    840 
    841  private:
    842   Entry* m_entries;
    843   int m_entry_count;
    844 
    845   VoidElement* m_void_elements;
    846   int m_void_element_count;
    847 
    848   static bool ParseEntry(IMkvReader*,
    849                          long long pos,  // payload
    850                          long long size, Entry*);
    851 };
    852 
    853 class Cues;
    854 class CuePoint {
    855   friend class Cues;
    856 
    857   CuePoint(long, long long);
    858   ~CuePoint();
    859 
    860   CuePoint(const CuePoint&);
    861   CuePoint& operator=(const CuePoint&);
    862 
    863  public:
    864   long long m_element_start;
    865   long long m_element_size;
    866 
    867   bool Load(IMkvReader*);
    868 
    869   long long GetTimeCode() const;  // absolute but unscaled
    870   long long GetTime(const Segment*) const;  // absolute and scaled (ns units)
    871 
    872   struct TrackPosition {
    873     long long m_track;
    874     long long m_pos;  // of cluster
    875     long long m_block;
    876     // codec_state  //defaults to 0
    877     // reference = clusters containing req'd referenced blocks
    878     //  reftime = timecode of the referenced block
    879 
    880     bool Parse(IMkvReader*, long long, long long);
    881   };
    882 
    883   const TrackPosition* Find(const Track*) const;
    884 
    885  private:
    886   const long m_index;
    887   long long m_timecode;
    888   TrackPosition* m_track_positions;
    889   size_t m_track_positions_count;
    890 };
    891 
    892 class Cues {
    893   friend class Segment;
    894 
    895   Cues(Segment*, long long start, long long size, long long element_start,
    896        long long element_size);
    897   ~Cues();
    898 
    899   Cues(const Cues&);
    900   Cues& operator=(const Cues&);
    901 
    902  public:
    903   Segment* const m_pSegment;
    904   const long long m_start;
    905   const long long m_size;
    906   const long long m_element_start;
    907   const long long m_element_size;
    908 
    909   bool Find(  // lower bound of time_ns
    910       long long time_ns, const Track*, const CuePoint*&,
    911       const CuePoint::TrackPosition*&) const;
    912 
    913   const CuePoint* GetFirst() const;
    914   const CuePoint* GetLast() const;
    915   const CuePoint* GetNext(const CuePoint*) const;
    916 
    917   const BlockEntry* GetBlock(const CuePoint*,
    918                              const CuePoint::TrackPosition*) const;
    919 
    920   bool LoadCuePoint() const;
    921   long GetCount() const;  // loaded only
    922   // long GetTotal() const;  //loaded + preloaded
    923   bool DoneParsing() const;
    924 
    925  private:
    926   bool Init() const;
    927   bool PreloadCuePoint(long&, long long) const;
    928 
    929   mutable CuePoint** m_cue_points;
    930   mutable long m_count;
    931   mutable long m_preload_count;
    932   mutable long long m_pos;
    933 };
    934 
    935 class Cluster {
    936   friend class Segment;
    937 
    938   Cluster(const Cluster&);
    939   Cluster& operator=(const Cluster&);
    940 
    941  public:
    942   Segment* const m_pSegment;
    943 
    944  public:
    945   static Cluster* Create(Segment*,
    946                          long index,  // index in segment
    947                          long long off);  // offset relative to segment
    948   // long long element_size);
    949 
    950   Cluster();  // EndOfStream
    951   ~Cluster();
    952 
    953   bool EOS() const;
    954 
    955   long long GetTimeCode() const;  // absolute, but not scaled
    956   long long GetTime() const;  // absolute, and scaled (nanosecond units)
    957   long long GetFirstTime() const;  // time (ns) of first (earliest) block
    958   long long GetLastTime() const;  // time (ns) of last (latest) block
    959 
    960   long GetFirst(const BlockEntry*&) const;
    961   long GetLast(const BlockEntry*&) const;
    962   long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
    963 
    964   const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
    965   const BlockEntry* GetEntry(const CuePoint&,
    966                              const CuePoint::TrackPosition&) const;
    967   // const BlockEntry* GetMaxKey(const VideoTrack*) const;
    968 
    969   //    static bool HasBlockEntries(const Segment*, long long);
    970 
    971   static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
    972                               long& size);
    973 
    974   long GetEntryCount() const;
    975 
    976   long Load(long long& pos, long& size) const;
    977 
    978   long Parse(long long& pos, long& size) const;
    979   long GetEntry(long index, const mkvparser::BlockEntry*&) const;
    980 
    981  protected:
    982   Cluster(Segment*, long index, long long element_start);
    983   // long long element_size);
    984 
    985  public:
    986   const long long m_element_start;
    987   long long GetPosition() const;  // offset relative to segment
    988 
    989   long GetIndex() const;
    990   long long GetElementSize() const;
    991   // long long GetPayloadSize() const;
    992 
    993   // long long Unparsed() const;
    994 
    995  private:
    996   long m_index;
    997   mutable long long m_pos;
    998   // mutable long long m_size;
    999   mutable long long m_element_size;
   1000   mutable long long m_timecode;
   1001   mutable BlockEntry** m_entries;
   1002   mutable long m_entries_size;
   1003   mutable long m_entries_count;
   1004 
   1005   long ParseSimpleBlock(long long, long long&, long&);
   1006   long ParseBlockGroup(long long, long long&, long&);
   1007 
   1008   long CreateBlock(long long id, long long pos, long long size,
   1009                    long long discard_padding);
   1010   long CreateBlockGroup(long long start_offset, long long size,
   1011                         long long discard_padding);
   1012   long CreateSimpleBlock(long long, long long);
   1013 };
   1014 
   1015 class Segment {
   1016   friend class Cues;
   1017   friend class Track;
   1018   friend class VideoTrack;
   1019 
   1020   Segment(const Segment&);
   1021   Segment& operator=(const Segment&);
   1022 
   1023  private:
   1024   Segment(IMkvReader*, long long elem_start,
   1025           // long long elem_size,
   1026           long long pos, long long size);
   1027 
   1028  public:
   1029   IMkvReader* const m_pReader;
   1030   const long long m_element_start;
   1031   // const long long m_element_size;
   1032   const long long m_start;  // posn of segment payload
   1033   const long long m_size;  // size of segment payload
   1034   Cluster m_eos;  // TODO: make private?
   1035 
   1036   static long long CreateInstance(IMkvReader*, long long, Segment*&);
   1037   ~Segment();
   1038 
   1039   long Load();  // loads headers and all clusters
   1040 
   1041   // for incremental loading
   1042   // long long Unparsed() const;
   1043   bool DoneParsing() const;
   1044   long long ParseHeaders();  // stops when first cluster is found
   1045   // long FindNextCluster(long long& pos, long& size) const;
   1046   long LoadCluster(long long& pos, long& size);  // load one cluster
   1047   long LoadCluster();
   1048 
   1049   long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
   1050                  long& size);
   1051 
   1052   const SeekHead* GetSeekHead() const;
   1053   const Tracks* GetTracks() const;
   1054   const SegmentInfo* GetInfo() const;
   1055   const Cues* GetCues() const;
   1056   const Chapters* GetChapters() const;
   1057   const Tags* GetTags() const;
   1058 
   1059   long long GetDuration() const;
   1060 
   1061   unsigned long GetCount() const;
   1062   const Cluster* GetFirst() const;
   1063   const Cluster* GetLast() const;
   1064   const Cluster* GetNext(const Cluster*);
   1065 
   1066   const Cluster* FindCluster(long long time_nanoseconds) const;
   1067   // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
   1068 
   1069   const Cluster* FindOrPreloadCluster(long long pos);
   1070 
   1071   long ParseCues(long long cues_off,  // offset relative to start of segment
   1072                  long long& parse_pos, long& parse_len);
   1073 
   1074  private:
   1075   long long m_pos;  // absolute file posn; what has been consumed so far
   1076   Cluster* m_pUnknownSize;
   1077 
   1078   SeekHead* m_pSeekHead;
   1079   SegmentInfo* m_pInfo;
   1080   Tracks* m_pTracks;
   1081   Cues* m_pCues;
   1082   Chapters* m_pChapters;
   1083   Tags* m_pTags;
   1084   Cluster** m_clusters;
   1085   long m_clusterCount;  // number of entries for which m_index >= 0
   1086   long m_clusterPreloadCount;  // number of entries for which m_index < 0
   1087   long m_clusterSize;  // array size
   1088 
   1089   long DoLoadCluster(long long&, long&);
   1090   long DoLoadClusterUnknownSize(long long&, long&);
   1091   long DoParseNext(const Cluster*&, long long&, long&);
   1092 
   1093   bool AppendCluster(Cluster*);
   1094   bool PreloadCluster(Cluster*, ptrdiff_t);
   1095 
   1096   // void ParseSeekHead(long long pos, long long size);
   1097   // void ParseSeekEntry(long long pos, long long size);
   1098   // void ParseCues(long long);
   1099 
   1100   const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
   1101 };
   1102 
   1103 }  // namespace mkvparser
   1104 
   1105 inline long mkvparser::Segment::LoadCluster() {
   1106   long long pos;
   1107   long size;
   1108 
   1109   return LoadCluster(pos, size);
   1110 }
   1111 
   1112 #endif  // MKVPARSER_MKVPARSER_H_
   1113