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