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
16namespace mkvparser
17{
18
19const int E_FILE_FORMAT_INVALID = -2;
20const int E_BUFFER_NOT_FULL = -3;
21
22class IMkvReader
23{
24public:
25    virtual int Read(long long pos, long len, unsigned char* buf) = 0;
26    virtual int Length(long long* total, long long* available) = 0;
27protected:
28    virtual ~IMkvReader();
29};
30
31long long GetUIntLength(IMkvReader*, long long, long&);
32long long ReadUInt(IMkvReader*, long long, long&);
33long long UnserializeUInt(IMkvReader*, long long pos, long long size);
34
35long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
36long UnserializeInt(IMkvReader*, long long pos, long len, long long& result);
37
38long UnserializeString(
39        IMkvReader*,
40        long long pos,
41        long long size,
42        char*& str);
43
44long 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
51bool Match(IMkvReader*, long long&, unsigned long, long long&);
52bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);
53
54void GetVersion(int& major, int& minor, int& build, int& revision);
55
56struct 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
73class Segment;
74class Track;
75class Cluster;
76
77class Block
78{
79    Block(const Block&);
80    Block& operator=(const Block&);
81
82public:
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
115private:
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
123protected:
124    const long long m_discard_padding;
125};
126
127
128class BlockEntry
129{
130    BlockEntry(const BlockEntry&);
131    BlockEntry& operator=(const BlockEntry&);
132
133protected:
134    BlockEntry(Cluster*, long index);
135
136public:
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
147protected:
148    Cluster* const m_pCluster;
149    const long m_index;
150
151};
152
153
154class SimpleBlock : public BlockEntry
155{
156    SimpleBlock(const SimpleBlock&);
157    SimpleBlock& operator=(const SimpleBlock&);
158
159public:
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
166protected:
167    Block m_block;
168
169};
170
171
172class BlockGroup : public BlockEntry
173{
174    BlockGroup(const BlockGroup&);
175    BlockGroup& operator=(const BlockGroup&);
176
177public:
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
197private:
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.
208class ContentEncoding {
209public:
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
307private:
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
326class Track
327{
328    Track(const Track&);
329    Track& operator=(const Track&);
330
331public:
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
411protected:
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
430private:
431    ContentEncoding** content_encoding_entries_;
432    ContentEncoding** content_encoding_entries_end_;
433};
434
435
436class 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
446public:
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
461private:
462    long long m_width;
463    long long m_height;
464    double m_rate;
465
466};
467
468
469class 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);
478public:
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
490private:
491    double m_rate;
492    long long m_channels;
493    long long m_bitDepth;
494};
495
496
497class Tracks
498{
499    Tracks(const Tracks&);
500    Tracks& operator=(const Tracks&);
501
502public:
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
525private:
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
539class Chapters
540{
541    Chapters(const Chapters&);
542    Chapters& operator=(const Chapters&);
543
544public:
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
653private:
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
664class SegmentInfo
665{
666    SegmentInfo(const SegmentInfo&);
667    SegmentInfo& operator=(const SegmentInfo&);
668
669public:
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
693private:
694    long long m_timecodeScale;
695    double m_duration;
696    char* m_pMuxingAppAsUTF8;
697    char* m_pWritingAppAsUTF8;
698    char* m_pTitleAsUTF8;
699};
700
701
702class SeekHead
703{
704    SeekHead(const SeekHead&);
705    SeekHead& operator=(const SeekHead&);
706
707public:
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
753private:
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
768class Cues;
769class 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
779public:
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
802private:
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
811class 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
826public:
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
860private:
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
872class Cluster
873{
874    friend class Segment;
875
876    Cluster(const Cluster&);
877    Cluster& operator=(const Cluster&);
878
879public:
880    Segment* const m_pSegment;
881
882public:
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
924protected:
925    Cluster(
926        Segment*,
927        long index,
928        long long element_start);
929        //long long element_size);
930
931public:
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
941private:
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
963class 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
972private:
973    Segment(
974        IMkvReader*,
975        long long elem_start,
976        //long long elem_size,
977        long long pos,
978        long long size);
979
980public:
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
1037private:
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
1071inline 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