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