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