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