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 
    608     struct TrackPosition
    609     {
    610         long long m_track;
    611         long long m_pos;  //of cluster
    612         long long m_block;
    613         //codec_state  //defaults to 0
    614         //reference = clusters containing req'd referenced blocks
    615         //  reftime = timecode of the referenced block
    616 
    617         void Parse(IMkvReader*, long long, long long);
    618     };
    619 
    620     const TrackPosition* Find(const Track*) const;
    621 
    622 private:
    623     const long m_index;
    624     long long m_timecode;
    625     TrackPosition* m_track_positions;
    626     size_t m_track_positions_count;
    627 
    628 };
    629 
    630 
    631 class Cues
    632 {
    633     friend class Segment;
    634 
    635     Cues(
    636         Segment*,
    637         long long start,
    638         long long size,
    639         long long element_start,
    640         long long element_size);
    641     ~Cues();
    642 
    643     Cues(const Cues&);
    644     Cues& operator=(const Cues&);
    645 
    646 public:
    647     Segment* const m_pSegment;
    648     const long long m_start;
    649     const long long m_size;
    650     const long long m_element_start;
    651     const long long m_element_size;
    652 
    653     bool Find(  //lower bound of time_ns
    654         long long time_ns,
    655         const Track*,
    656         const CuePoint*&,
    657         const CuePoint::TrackPosition*&) const;
    658 
    659 #if 0
    660     bool FindNext(  //upper_bound of time_ns
    661         long long time_ns,
    662         const Track*,
    663         const CuePoint*&,
    664         const CuePoint::TrackPosition*&) const;
    665 #endif
    666 
    667     const CuePoint* GetFirst() const;
    668     const CuePoint* GetLast() const;
    669     const CuePoint* GetNext(const CuePoint*) const;
    670 
    671     const BlockEntry* GetBlock(
    672                         const CuePoint*,
    673                         const CuePoint::TrackPosition*) const;
    674 
    675     bool LoadCuePoint() const;
    676     long GetCount() const;  //loaded only
    677     //long GetTotal() const;  //loaded + preloaded
    678     bool DoneParsing() const;
    679 
    680 private:
    681     void Init() const;
    682     void PreloadCuePoint(long&, long long) const;
    683 
    684     mutable CuePoint** m_cue_points;
    685     mutable long m_count;
    686     mutable long m_preload_count;
    687     mutable long long m_pos;
    688 
    689 };
    690 
    691 
    692 class Cluster
    693 {
    694     friend class Segment;
    695 
    696     Cluster(const Cluster&);
    697     Cluster& operator=(const Cluster&);
    698 
    699 public:
    700     Segment* const m_pSegment;
    701 
    702 public:
    703     static Cluster* Create(
    704         Segment*,
    705         long index,       //index in segment
    706         long long off);   //offset relative to segment
    707         //long long element_size);
    708 
    709     Cluster();  //EndOfStream
    710     ~Cluster();
    711 
    712     bool EOS() const;
    713 
    714     long long GetTimeCode() const;   //absolute, but not scaled
    715     long long GetTime() const;       //absolute, and scaled (nanosecond units)
    716     long long GetFirstTime() const;  //time (ns) of first (earliest) block
    717     long long GetLastTime() const;   //time (ns) of last (latest) block
    718 
    719     long GetFirst(const BlockEntry*&) const;
    720     long GetLast(const BlockEntry*&) const;
    721     long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
    722 
    723     const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
    724     const BlockEntry* GetEntry(
    725         const CuePoint&,
    726         const CuePoint::TrackPosition&) const;
    727     //const BlockEntry* GetMaxKey(const VideoTrack*) const;
    728 
    729 //    static bool HasBlockEntries(const Segment*, long long);
    730 
    731     static long HasBlockEntries(
    732             const Segment*,
    733             long long idoff,
    734             long long& pos,
    735             long& size);
    736 
    737     long GetEntryCount() const;
    738 
    739     long Load(long long& pos, long& size) const;
    740 
    741     long Parse(long long& pos, long& size) const;
    742     long GetEntry(long index, const mkvparser::BlockEntry*&) const;
    743 
    744 protected:
    745     Cluster(
    746         Segment*,
    747         long index,
    748         long long element_start);
    749         //long long element_size);
    750 
    751 public:
    752     const long long m_element_start;
    753     long long GetPosition() const;  //offset relative to segment
    754 
    755     long GetIndex() const;
    756     long long GetElementSize() const;
    757     //long long GetPayloadSize() const;
    758 
    759     //long long Unparsed() const;
    760 
    761 private:
    762     long m_index;
    763     mutable long long m_pos;
    764     //mutable long long m_size;
    765     mutable long long m_element_size;
    766     mutable long long m_timecode;
    767     mutable BlockEntry** m_entries;
    768     mutable long m_entries_size;
    769     mutable long m_entries_count;
    770 
    771     long ParseSimpleBlock(long long, long long&, long&);
    772     long ParseBlockGroup(long long, long long&, long&);
    773 
    774     long CreateBlock(long long id, long long pos, long long size);
    775     long CreateBlockGroup(long long, long long);
    776     long CreateSimpleBlock(long long, long long);
    777 
    778 };
    779 
    780 
    781 class Segment
    782 {
    783     friend class Cues;
    784     friend class VideoTrack;
    785     friend class AudioTrack;
    786 
    787     Segment(const Segment&);
    788     Segment& operator=(const Segment&);
    789 
    790 private:
    791     Segment(
    792         IMkvReader*,
    793         long long elem_start,
    794         //long long elem_size,
    795         long long pos,
    796         long long size);
    797 
    798 public:
    799     IMkvReader* const m_pReader;
    800     const long long m_element_start;
    801     //const long long m_element_size;
    802     const long long m_start;  //posn of segment payload
    803     const long long m_size;   //size of segment payload
    804     Cluster m_eos;  //TODO: make private?
    805 
    806     static long long CreateInstance(IMkvReader*, long long, Segment*&);
    807     ~Segment();
    808 
    809     long Load();  //loads headers and all clusters
    810 
    811     //for incremental loading
    812     //long long Unparsed() const;
    813     bool DoneParsing() const;
    814     long long ParseHeaders();  //stops when first cluster is found
    815     //long FindNextCluster(long long& pos, long& size) const;
    816     long LoadCluster(long long& pos, long& size);  //load one cluster
    817     long LoadCluster();
    818 
    819     long ParseNext(
    820             const Cluster* pCurr,
    821             const Cluster*& pNext,
    822             long long& pos,
    823             long& size);
    824 
    825 #if 0
    826     //This pair parses one cluster, but only changes the state of the
    827     //segment object when the cluster is actually added to the index.
    828     long ParseCluster(long long& cluster_pos, long long& new_pos) const;
    829     bool AddCluster(long long cluster_pos, long long new_pos);
    830 #endif
    831 
    832     const SeekHead* GetSeekHead() const;
    833     const Tracks* GetTracks() const;
    834     const SegmentInfo* GetInfo() const;
    835     const Cues* GetCues() const;
    836 
    837     long long GetDuration() const;
    838 
    839     unsigned long GetCount() const;
    840     const Cluster* GetFirst() const;
    841     const Cluster* GetLast() const;
    842     const Cluster* GetNext(const Cluster*);
    843 
    844     const Cluster* FindCluster(long long time_nanoseconds) const;
    845     //const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
    846 
    847     const Cluster* FindOrPreloadCluster(long long pos);
    848 
    849     long ParseCues(
    850         long long cues_off,  //offset relative to start of segment
    851         long long& parse_pos,
    852         long& parse_len);
    853 
    854 private:
    855 
    856     long long m_pos;  //absolute file posn; what has been consumed so far
    857     Cluster* m_pUnknownSize;
    858 
    859     SeekHead* m_pSeekHead;
    860     SegmentInfo* m_pInfo;
    861     Tracks* m_pTracks;
    862     Cues* m_pCues;
    863     Cluster** m_clusters;
    864     long m_clusterCount;         //number of entries for which m_index >= 0
    865     long m_clusterPreloadCount;  //number of entries for which m_index < 0
    866     long m_clusterSize;          //array size
    867 
    868     long DoLoadCluster(long long&, long&);
    869     long DoLoadClusterUnknownSize(long long&, long&);
    870     long DoParseNext(const Cluster*&, long long&, long&);
    871 
    872     void AppendCluster(Cluster*);
    873     void PreloadCluster(Cluster*, ptrdiff_t);
    874 
    875     //void ParseSeekHead(long long pos, long long size);
    876     //void ParseSeekEntry(long long pos, long long size);
    877     //void ParseCues(long long);
    878 
    879     const BlockEntry* GetBlock(
    880         const CuePoint&,
    881         const CuePoint::TrackPosition&);
    882 
    883 };
    884 
    885 }  //end namespace mkvparser
    886 
    887 inline long mkvparser::Segment::LoadCluster()
    888 {
    889     long long pos;
    890     long size;
    891 
    892     return LoadCluster(pos, size);
    893 }
    894 
    895 #endif  //MKVPARSER_HPP
    896