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