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