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