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