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