• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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