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