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