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:
~IMkvReader()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 struct Projection {
477   enum ProjectionType {
478     kTypeNotPresent = -1,
479     kRectangular = 0,
480     kEquirectangular = 1,
481     kCubeMap = 2,
482     kMesh = 3,
483   };
484   static const float kValueNotPresent;
ProjectionProjection485   Projection()
486       : type(kTypeNotPresent),
487         private_data(NULL),
488         private_data_length(0),
489         pose_yaw(kValueNotPresent),
490         pose_pitch(kValueNotPresent),
491         pose_roll(kValueNotPresent) {}
~ProjectionProjection492   ~Projection() { delete[] private_data; }
493   static bool Parse(IMkvReader* reader, long long element_start,
494                     long long element_size, Projection** projection);
495 
496   ProjectionType type;
497   unsigned char* private_data;
498   size_t private_data_length;
499   float pose_yaw;
500   float pose_pitch;
501   float pose_roll;
502 };
503 
504 class VideoTrack : public Track {
505   VideoTrack(const VideoTrack&);
506   VideoTrack& operator=(const VideoTrack&);
507 
508   VideoTrack(Segment*, long long element_start, long long element_size);
509 
510  public:
511   virtual ~VideoTrack();
512   static long Parse(Segment*, const Info&, long long element_start,
513                     long long element_size, VideoTrack*&);
514 
515   long long GetWidth() const;
516   long long GetHeight() const;
517   long long GetDisplayWidth() const;
518   long long GetDisplayHeight() const;
519   long long GetDisplayUnit() const;
520   long long GetStereoMode() const;
521   double GetFrameRate() const;
522 
523   bool VetEntry(const BlockEntry*) const;
524   long Seek(long long time_ns, const BlockEntry*&) const;
525 
526   Colour* GetColour() const;
527 
528   Projection* GetProjection() const;
529 
GetColourSpace()530   const char* GetColourSpace() const { return m_colour_space; }
531 
532  private:
533   long long m_width;
534   long long m_height;
535   long long m_display_width;
536   long long m_display_height;
537   long long m_display_unit;
538   long long m_stereo_mode;
539   char* m_colour_space;
540   double m_rate;
541 
542   Colour* m_colour;
543   Projection* m_projection;
544 };
545 
546 class AudioTrack : public Track {
547   AudioTrack(const AudioTrack&);
548   AudioTrack& operator=(const AudioTrack&);
549 
550   AudioTrack(Segment*, long long element_start, long long element_size);
551 
552  public:
553   static long Parse(Segment*, const Info&, long long element_start,
554                     long long element_size, AudioTrack*&);
555 
556   double GetSamplingRate() const;
557   long long GetChannels() const;
558   long long GetBitDepth() const;
559 
560  private:
561   double m_rate;
562   long long m_channels;
563   long long m_bitDepth;
564 };
565 
566 class Tracks {
567   Tracks(const Tracks&);
568   Tracks& operator=(const Tracks&);
569 
570  public:
571   Segment* const m_pSegment;
572   const long long m_start;
573   const long long m_size;
574   const long long m_element_start;
575   const long long m_element_size;
576 
577   Tracks(Segment*, long long start, long long size, long long element_start,
578          long long element_size);
579 
580   ~Tracks();
581 
582   long Parse();
583 
584   unsigned long GetTracksCount() const;
585 
586   const Track* GetTrackByNumber(long tn) const;
587   const Track* GetTrackByIndex(unsigned long idx) const;
588 
589  private:
590   Track** m_trackEntries;
591   Track** m_trackEntriesEnd;
592 
593   long ParseTrackEntry(long long payload_start, long long payload_size,
594                        long long element_start, long long element_size,
595                        Track*&) const;
596 };
597 
598 class Chapters {
599   Chapters(const Chapters&);
600   Chapters& operator=(const Chapters&);
601 
602  public:
603   Segment* const m_pSegment;
604   const long long m_start;
605   const long long m_size;
606   const long long m_element_start;
607   const long long m_element_size;
608 
609   Chapters(Segment*, long long payload_start, long long payload_size,
610            long long element_start, long long element_size);
611 
612   ~Chapters();
613 
614   long Parse();
615 
616   class Atom;
617   class Edition;
618 
619   class Display {
620     friend class Atom;
621     Display();
622     Display(const Display&);
623     ~Display();
624     Display& operator=(const Display&);
625 
626    public:
627     const char* GetString() const;
628     const char* GetLanguage() const;
629     const char* GetCountry() const;
630 
631    private:
632     void Init();
633     void ShallowCopy(Display&) const;
634     void Clear();
635     long Parse(IMkvReader*, long long pos, long long size);
636 
637     char* m_string;
638     char* m_language;
639     char* m_country;
640   };
641 
642   class Atom {
643     friend class Edition;
644     Atom();
645     Atom(const Atom&);
646     ~Atom();
647     Atom& operator=(const Atom&);
648 
649    public:
650     unsigned long long GetUID() const;
651     const char* GetStringUID() const;
652 
653     long long GetStartTimecode() const;
654     long long GetStopTimecode() const;
655 
656     long long GetStartTime(const Chapters*) const;
657     long long GetStopTime(const Chapters*) const;
658 
659     int GetDisplayCount() const;
660     const Display* GetDisplay(int index) const;
661 
662    private:
663     void Init();
664     void ShallowCopy(Atom&) const;
665     void Clear();
666     long Parse(IMkvReader*, long long pos, long long size);
667     static long long GetTime(const Chapters*, long long timecode);
668 
669     long ParseDisplay(IMkvReader*, long long pos, long long size);
670     bool ExpandDisplaysArray();
671 
672     char* m_string_uid;
673     unsigned long long m_uid;
674     long long m_start_timecode;
675     long long m_stop_timecode;
676 
677     Display* m_displays;
678     int m_displays_size;
679     int m_displays_count;
680   };
681 
682   class Edition {
683     friend class Chapters;
684     Edition();
685     Edition(const Edition&);
686     ~Edition();
687     Edition& operator=(const Edition&);
688 
689    public:
690     int GetAtomCount() const;
691     const Atom* GetAtom(int index) const;
692 
693    private:
694     void Init();
695     void ShallowCopy(Edition&) const;
696     void Clear();
697     long Parse(IMkvReader*, long long pos, long long size);
698 
699     long ParseAtom(IMkvReader*, long long pos, long long size);
700     bool ExpandAtomsArray();
701 
702     Atom* m_atoms;
703     int m_atoms_size;
704     int m_atoms_count;
705   };
706 
707   int GetEditionCount() const;
708   const Edition* GetEdition(int index) const;
709 
710  private:
711   long ParseEdition(long long pos, long long size);
712   bool ExpandEditionsArray();
713 
714   Edition* m_editions;
715   int m_editions_size;
716   int m_editions_count;
717 };
718 
719 class Tags {
720   Tags(const Tags&);
721   Tags& operator=(const Tags&);
722 
723  public:
724   Segment* const m_pSegment;
725   const long long m_start;
726   const long long m_size;
727   const long long m_element_start;
728   const long long m_element_size;
729 
730   Tags(Segment*, long long payload_start, long long payload_size,
731        long long element_start, long long element_size);
732 
733   ~Tags();
734 
735   long Parse();
736 
737   class Tag;
738   class SimpleTag;
739 
740   class SimpleTag {
741     friend class Tag;
742     SimpleTag();
743     SimpleTag(const SimpleTag&);
744     ~SimpleTag();
745     SimpleTag& operator=(const SimpleTag&);
746 
747    public:
748     const char* GetTagName() const;
749     const char* GetTagString() const;
750 
751    private:
752     void Init();
753     void ShallowCopy(SimpleTag&) const;
754     void Clear();
755     long Parse(IMkvReader*, long long pos, long long size);
756 
757     char* m_tag_name;
758     char* m_tag_string;
759   };
760 
761   class Tag {
762     friend class Tags;
763     Tag();
764     Tag(const Tag&);
765     ~Tag();
766     Tag& operator=(const Tag&);
767 
768    public:
769     int GetSimpleTagCount() const;
770     const SimpleTag* GetSimpleTag(int index) const;
771 
772    private:
773     void Init();
774     void ShallowCopy(Tag&) const;
775     void Clear();
776     long Parse(IMkvReader*, long long pos, long long size);
777 
778     long ParseSimpleTag(IMkvReader*, long long pos, long long size);
779     bool ExpandSimpleTagsArray();
780 
781     SimpleTag* m_simple_tags;
782     int m_simple_tags_size;
783     int m_simple_tags_count;
784   };
785 
786   int GetTagCount() const;
787   const Tag* GetTag(int index) const;
788 
789  private:
790   long ParseTag(long long pos, long long size);
791   bool ExpandTagsArray();
792 
793   Tag* m_tags;
794   int m_tags_size;
795   int m_tags_count;
796 };
797 
798 class SegmentInfo {
799   SegmentInfo(const SegmentInfo&);
800   SegmentInfo& operator=(const SegmentInfo&);
801 
802  public:
803   Segment* const m_pSegment;
804   const long long m_start;
805   const long long m_size;
806   const long long m_element_start;
807   const long long m_element_size;
808 
809   SegmentInfo(Segment*, long long start, long long size,
810               long long element_start, long long element_size);
811 
812   ~SegmentInfo();
813 
814   long Parse();
815 
816   long long GetTimeCodeScale() const;
817   long long GetDuration() const;  // scaled
818   const char* GetMuxingAppAsUTF8() const;
819   const char* GetWritingAppAsUTF8() const;
820   const char* GetTitleAsUTF8() const;
821 
822  private:
823   long long m_timecodeScale;
824   double m_duration;
825   char* m_pMuxingAppAsUTF8;
826   char* m_pWritingAppAsUTF8;
827   char* m_pTitleAsUTF8;
828 };
829 
830 class SeekHead {
831   SeekHead(const SeekHead&);
832   SeekHead& operator=(const SeekHead&);
833 
834  public:
835   Segment* const m_pSegment;
836   const long long m_start;
837   const long long m_size;
838   const long long m_element_start;
839   const long long m_element_size;
840 
841   SeekHead(Segment*, long long start, long long size, long long element_start,
842            long long element_size);
843 
844   ~SeekHead();
845 
846   long Parse();
847 
848   struct Entry {
849     Entry();
850 
851     // the SeekHead entry payload
852     long long id;
853     long long pos;
854 
855     // absolute pos of SeekEntry ID
856     long long element_start;
857 
858     // SeekEntry ID size + size size + payload
859     long long element_size;
860   };
861 
862   int GetCount() const;
863   const Entry* GetEntry(int idx) const;
864 
865   struct VoidElement {
866     // absolute pos of Void ID
867     long long element_start;
868 
869     // ID size + size size + payload size
870     long long element_size;
871   };
872 
873   int GetVoidElementCount() const;
874   const VoidElement* GetVoidElement(int idx) const;
875 
876  private:
877   Entry* m_entries;
878   int m_entry_count;
879 
880   VoidElement* m_void_elements;
881   int m_void_element_count;
882 
883   static bool ParseEntry(IMkvReader*,
884                          long long pos,  // payload
885                          long long size, Entry*);
886 };
887 
888 class Cues;
889 class CuePoint {
890   friend class Cues;
891 
892   CuePoint(long, long long);
893   ~CuePoint();
894 
895   CuePoint(const CuePoint&);
896   CuePoint& operator=(const CuePoint&);
897 
898  public:
899   long long m_element_start;
900   long long m_element_size;
901 
902   bool Load(IMkvReader*);
903 
904   long long GetTimeCode() const;  // absolute but unscaled
905   long long GetTime(const Segment*) const;  // absolute and scaled (ns units)
906 
907   struct TrackPosition {
908     long long m_track;
909     long long m_pos;  // of cluster
910     long long m_block;
911     // codec_state  //defaults to 0
912     // reference = clusters containing req'd referenced blocks
913     //  reftime = timecode of the referenced block
914 
915     bool Parse(IMkvReader*, long long, long long);
916   };
917 
918   const TrackPosition* Find(const Track*) const;
919 
920  private:
921   const long m_index;
922   long long m_timecode;
923   TrackPosition* m_track_positions;
924   size_t m_track_positions_count;
925 };
926 
927 class Cues {
928   friend class Segment;
929 
930   Cues(Segment*, long long start, long long size, long long element_start,
931        long long element_size);
932   ~Cues();
933 
934   Cues(const Cues&);
935   Cues& operator=(const Cues&);
936 
937  public:
938   Segment* const m_pSegment;
939   const long long m_start;
940   const long long m_size;
941   const long long m_element_start;
942   const long long m_element_size;
943 
944   bool Find(  // lower bound of time_ns
945       long long time_ns, const Track*, const CuePoint*&,
946       const CuePoint::TrackPosition*&) const;
947 
948   const CuePoint* GetFirst() const;
949   const CuePoint* GetLast() const;
950   const CuePoint* GetNext(const CuePoint*) const;
951 
952   const BlockEntry* GetBlock(const CuePoint*,
953                              const CuePoint::TrackPosition*) const;
954 
955   bool LoadCuePoint() const;
956   long GetCount() const;  // loaded only
957   // long GetTotal() const;  //loaded + preloaded
958   bool DoneParsing() const;
959 
960  private:
961   bool Init() const;
962   bool PreloadCuePoint(long&, long long) const;
963 
964   mutable CuePoint** m_cue_points;
965   mutable long m_count;
966   mutable long m_preload_count;
967   mutable long long m_pos;
968 };
969 
970 class Cluster {
971   friend class Segment;
972 
973   Cluster(const Cluster&);
974   Cluster& operator=(const Cluster&);
975 
976  public:
977   Segment* const m_pSegment;
978 
979  public:
980   static Cluster* Create(Segment*,
981                          long index,  // index in segment
982                          long long off);  // offset relative to segment
983   // long long element_size);
984 
985   Cluster();  // EndOfStream
986   ~Cluster();
987 
988   bool EOS() const;
989 
990   long long GetTimeCode() const;  // absolute, but not scaled
991   long long GetTime() const;  // absolute, and scaled (nanosecond units)
992   long long GetFirstTime() const;  // time (ns) of first (earliest) block
993   long long GetLastTime() const;  // time (ns) of last (latest) block
994 
995   long GetFirst(const BlockEntry*&) const;
996   long GetLast(const BlockEntry*&) const;
997   long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
998 
999   const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
1000   const BlockEntry* GetEntry(const CuePoint&,
1001                              const CuePoint::TrackPosition&) const;
1002   // const BlockEntry* GetMaxKey(const VideoTrack*) const;
1003 
1004   //    static bool HasBlockEntries(const Segment*, long long);
1005 
1006   static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
1007                               long& size);
1008 
1009   long GetEntryCount() const;
1010 
1011   long Load(long long& pos, long& size) const;
1012 
1013   long Parse(long long& pos, long& size) const;
1014   long GetEntry(long index, const mkvparser::BlockEntry*&) const;
1015 
1016  protected:
1017   Cluster(Segment*, long index, long long element_start);
1018   // long long element_size);
1019 
1020  public:
1021   const long long m_element_start;
1022   long long GetPosition() const;  // offset relative to segment
1023 
1024   long GetIndex() const;
1025   long long GetElementSize() const;
1026   // long long GetPayloadSize() const;
1027 
1028   // long long Unparsed() const;
1029 
1030  private:
1031   long m_index;
1032   mutable long long m_pos;
1033   // mutable long long m_size;
1034   mutable long long m_element_size;
1035   mutable long long m_timecode;
1036   mutable BlockEntry** m_entries;
1037   mutable long m_entries_size;
1038   mutable long m_entries_count;
1039 
1040   long ParseSimpleBlock(long long, long long&, long&);
1041   long ParseBlockGroup(long long, long long&, long&);
1042 
1043   long CreateBlock(long long id, long long pos, long long size,
1044                    long long discard_padding);
1045   long CreateBlockGroup(long long start_offset, long long size,
1046                         long long discard_padding);
1047   long CreateSimpleBlock(long long, long long);
1048 };
1049 
1050 class Segment {
1051   friend class Cues;
1052   friend class Track;
1053   friend class VideoTrack;
1054 
1055   Segment(const Segment&);
1056   Segment& operator=(const Segment&);
1057 
1058  private:
1059   Segment(IMkvReader*, long long elem_start,
1060           // long long elem_size,
1061           long long pos, long long size);
1062 
1063  public:
1064   IMkvReader* const m_pReader;
1065   const long long m_element_start;
1066   // const long long m_element_size;
1067   const long long m_start;  // posn of segment payload
1068   const long long m_size;  // size of segment payload
1069   Cluster m_eos;  // TODO: make private?
1070 
1071   static long long CreateInstance(IMkvReader*, long long, Segment*&);
1072   ~Segment();
1073 
1074   long Load();  // loads headers and all clusters
1075 
1076   // for incremental loading
1077   // long long Unparsed() const;
1078   bool DoneParsing() const;
1079   long long ParseHeaders();  // stops when first cluster is found
1080   // long FindNextCluster(long long& pos, long& size) const;
1081   long LoadCluster(long long& pos, long& size);  // load one cluster
1082   long LoadCluster();
1083 
1084   long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
1085                  long& size);
1086 
1087   const SeekHead* GetSeekHead() const;
1088   const Tracks* GetTracks() const;
1089   const SegmentInfo* GetInfo() const;
1090   const Cues* GetCues() const;
1091   const Chapters* GetChapters() const;
1092   const Tags* GetTags() const;
1093 
1094   long long GetDuration() const;
1095 
1096   unsigned long GetCount() const;
1097   const Cluster* GetFirst() const;
1098   const Cluster* GetLast() const;
1099   const Cluster* GetNext(const Cluster*);
1100 
1101   const Cluster* FindCluster(long long time_nanoseconds) const;
1102   // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;
1103 
1104   const Cluster* FindOrPreloadCluster(long long pos);
1105 
1106   long ParseCues(long long cues_off,  // offset relative to start of segment
1107                  long long& parse_pos, long& parse_len);
1108 
1109  private:
1110   long long m_pos;  // absolute file posn; what has been consumed so far
1111   Cluster* m_pUnknownSize;
1112 
1113   SeekHead* m_pSeekHead;
1114   SegmentInfo* m_pInfo;
1115   Tracks* m_pTracks;
1116   Cues* m_pCues;
1117   Chapters* m_pChapters;
1118   Tags* m_pTags;
1119   Cluster** m_clusters;
1120   long m_clusterCount;  // number of entries for which m_index >= 0
1121   long m_clusterPreloadCount;  // number of entries for which m_index < 0
1122   long m_clusterSize;  // array size
1123 
1124   long DoLoadCluster(long long&, long&);
1125   long DoLoadClusterUnknownSize(long long&, long&);
1126   long DoParseNext(const Cluster*&, long long&, long&);
1127 
1128   bool AppendCluster(Cluster*);
1129   bool PreloadCluster(Cluster*, ptrdiff_t);
1130 
1131   // void ParseSeekHead(long long pos, long long size);
1132   // void ParseSeekEntry(long long pos, long long size);
1133   // void ParseCues(long long);
1134 
1135   const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
1136 };
1137 
1138 }  // namespace mkvparser
1139 
LoadCluster()1140 inline long mkvparser::Segment::LoadCluster() {
1141   long long pos;
1142   long size;
1143 
1144   return LoadCluster(pos, size);
1145 }
1146 
1147 #endif  // MKVPARSER_MKVPARSER_H_
1148