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