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