| // Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 
 | // | 
 | // Use of this source code is governed by a BSD-style license | 
 | // that can be found in the LICENSE file in the root of the source | 
 | // tree. An additional intellectual property rights grant can be found | 
 | // in the file PATENTS.  All contributing project authors may | 
 | // be found in the AUTHORS file in the root of the source tree. | 
 | #ifndef MKVPARSER_MKVPARSER_H_ | 
 | #define MKVPARSER_MKVPARSER_H_ | 
 |  | 
 | #include <cstddef> | 
 |  | 
 | namespace mkvparser { | 
 |  | 
 | const int E_PARSE_FAILED = -1; | 
 | const int E_FILE_FORMAT_INVALID = -2; | 
 | const int E_BUFFER_NOT_FULL = -3; | 
 |  | 
 | class IMkvReader { | 
 |  public: | 
 |   virtual int Read(long long pos, long len, unsigned char* buf) = 0; | 
 |   virtual int Length(long long* total, long long* available) = 0; | 
 |  | 
 |  protected: | 
 |   virtual ~IMkvReader() {} | 
 | }; | 
 |  | 
 | template <typename Type> | 
 | Type* SafeArrayAlloc(unsigned long long num_elements, | 
 |                      unsigned long long element_size); | 
 | long long GetUIntLength(IMkvReader*, long long, long&); | 
 | long long ReadUInt(IMkvReader*, long long, long&); | 
 | long long ReadID(IMkvReader* pReader, long long pos, long& len); | 
 | long long UnserializeUInt(IMkvReader*, long long pos, long long size); | 
 |  | 
 | long UnserializeFloat(IMkvReader*, long long pos, long long size, double&); | 
 | long UnserializeInt(IMkvReader*, long long pos, long long size, | 
 |                     long long& result); | 
 |  | 
 | long UnserializeString(IMkvReader*, long long pos, long long size, char*& str); | 
 |  | 
 | long ParseElementHeader(IMkvReader* pReader, | 
 |                         long long& pos,  // consume id and size fields | 
 |                         long long stop,  // if you know size of element's parent | 
 |                         long long& id, long long& size); | 
 |  | 
 | bool Match(IMkvReader*, long long&, unsigned long, long long&); | 
 | bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&); | 
 |  | 
 | void GetVersion(int& major, int& minor, int& build, int& revision); | 
 |  | 
 | struct EBMLHeader { | 
 |   EBMLHeader(); | 
 |   ~EBMLHeader(); | 
 |   long long m_version; | 
 |   long long m_readVersion; | 
 |   long long m_maxIdLength; | 
 |   long long m_maxSizeLength; | 
 |   char* m_docType; | 
 |   long long m_docTypeVersion; | 
 |   long long m_docTypeReadVersion; | 
 |  | 
 |   long long Parse(IMkvReader*, long long&); | 
 |   void Init(); | 
 | }; | 
 |  | 
 | class Segment; | 
 | class Track; | 
 | class Cluster; | 
 |  | 
 | class Block { | 
 |   Block(const Block&); | 
 |   Block& operator=(const Block&); | 
 |  | 
 |  public: | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |  | 
 |   Block(long long start, long long size, long long discard_padding); | 
 |   ~Block(); | 
 |  | 
 |   long Parse(const Cluster*); | 
 |  | 
 |   long long GetTrackNumber() const; | 
 |   long long GetTimeCode(const Cluster*) const;  // absolute, but not scaled | 
 |   long long GetTime(const Cluster*) const;  // absolute, and scaled (ns) | 
 |   bool IsKey() const; | 
 |   void SetKey(bool); | 
 |   bool IsInvisible() const; | 
 |  | 
 |   enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml }; | 
 |   Lacing GetLacing() const; | 
 |  | 
 |   int GetFrameCount() const;  // to index frames: [0, count) | 
 |  | 
 |   struct Frame { | 
 |     long long pos;  // absolute offset | 
 |     long len; | 
 |  | 
 |     long Read(IMkvReader*, unsigned char*) const; | 
 |   }; | 
 |  | 
 |   const Frame& GetFrame(int frame_index) const; | 
 |  | 
 |   long long GetDiscardPadding() const; | 
 |  | 
 |  private: | 
 |   long long m_track;  // Track::Number() | 
 |   short m_timecode;  // relative to cluster | 
 |   unsigned char m_flags; | 
 |  | 
 |   Frame* m_frames; | 
 |   int m_frame_count; | 
 |  | 
 |  protected: | 
 |   const long long m_discard_padding; | 
 | }; | 
 |  | 
 | class BlockEntry { | 
 |   BlockEntry(const BlockEntry&); | 
 |   BlockEntry& operator=(const BlockEntry&); | 
 |  | 
 |  protected: | 
 |   BlockEntry(Cluster*, long index); | 
 |  | 
 |  public: | 
 |   virtual ~BlockEntry(); | 
 |  | 
 |   bool EOS() const { return (GetKind() == kBlockEOS); } | 
 |   const Cluster* GetCluster() const; | 
 |   long GetIndex() const; | 
 |   virtual const Block* GetBlock() const = 0; | 
 |  | 
 |   enum Kind { kBlockEOS, kBlockSimple, kBlockGroup }; | 
 |   virtual Kind GetKind() const = 0; | 
 |  | 
 |  protected: | 
 |   Cluster* const m_pCluster; | 
 |   const long m_index; | 
 | }; | 
 |  | 
 | class SimpleBlock : public BlockEntry { | 
 |   SimpleBlock(const SimpleBlock&); | 
 |   SimpleBlock& operator=(const SimpleBlock&); | 
 |  | 
 |  public: | 
 |   SimpleBlock(Cluster*, long index, long long start, long long size); | 
 |   long Parse(); | 
 |  | 
 |   Kind GetKind() const; | 
 |   const Block* GetBlock() const; | 
 |  | 
 |  protected: | 
 |   Block m_block; | 
 | }; | 
 |  | 
 | class BlockGroup : public BlockEntry { | 
 |   BlockGroup(const BlockGroup&); | 
 |   BlockGroup& operator=(const BlockGroup&); | 
 |  | 
 |  public: | 
 |   BlockGroup(Cluster*, long index, | 
 |              long long block_start,  // absolute pos of block's payload | 
 |              long long block_size,  // size of block's payload | 
 |              long long prev, long long next, long long duration, | 
 |              long long discard_padding); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   Kind GetKind() const; | 
 |   const Block* GetBlock() const; | 
 |  | 
 |   long long GetPrevTimeCode() const;  // relative to block's time | 
 |   long long GetNextTimeCode() const;  // as above | 
 |   long long GetDurationTimeCode() const; | 
 |  | 
 |  private: | 
 |   Block m_block; | 
 |   const long long m_prev; | 
 |   const long long m_next; | 
 |   const long long m_duration; | 
 | }; | 
 |  | 
 | /////////////////////////////////////////////////////////////// | 
 | // ContentEncoding element | 
 | // Elements used to describe if the track data has been encrypted or | 
 | // compressed with zlib or header stripping. | 
 | class ContentEncoding { | 
 |  public: | 
 |   enum { kCTR = 1 }; | 
 |  | 
 |   ContentEncoding(); | 
 |   ~ContentEncoding(); | 
 |  | 
 |   // ContentCompression element names | 
 |   struct ContentCompression { | 
 |     ContentCompression(); | 
 |     ~ContentCompression(); | 
 |  | 
 |     unsigned long long algo; | 
 |     unsigned char* settings; | 
 |     long long settings_len; | 
 |   }; | 
 |  | 
 |   // ContentEncAESSettings element names | 
 |   struct ContentEncAESSettings { | 
 |     ContentEncAESSettings() : cipher_mode(kCTR) {} | 
 |     ~ContentEncAESSettings() {} | 
 |  | 
 |     unsigned long long cipher_mode; | 
 |   }; | 
 |  | 
 |   // ContentEncryption element names | 
 |   struct ContentEncryption { | 
 |     ContentEncryption(); | 
 |     ~ContentEncryption(); | 
 |  | 
 |     unsigned long long algo; | 
 |     unsigned char* key_id; | 
 |     long long key_id_len; | 
 |     unsigned char* signature; | 
 |     long long signature_len; | 
 |     unsigned char* sig_key_id; | 
 |     long long sig_key_id_len; | 
 |     unsigned long long sig_algo; | 
 |     unsigned long long sig_hash_algo; | 
 |  | 
 |     ContentEncAESSettings aes_settings; | 
 |   }; | 
 |  | 
 |   // Returns ContentCompression represented by |idx|. Returns NULL if |idx| | 
 |   // is out of bounds. | 
 |   const ContentCompression* GetCompressionByIndex(unsigned long idx) const; | 
 |  | 
 |   // Returns number of ContentCompression elements in this ContentEncoding | 
 |   // element. | 
 |   unsigned long GetCompressionCount() const; | 
 |  | 
 |   // Parses the ContentCompression element from |pReader|. |start| is the | 
 |   // starting offset of the ContentCompression payload. |size| is the size in | 
 |   // bytes of the ContentCompression payload. |compression| is where the parsed | 
 |   // values will be stored. | 
 |   long ParseCompressionEntry(long long start, long long size, | 
 |                              IMkvReader* pReader, | 
 |                              ContentCompression* compression); | 
 |  | 
 |   // Returns ContentEncryption represented by |idx|. Returns NULL if |idx| | 
 |   // is out of bounds. | 
 |   const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const; | 
 |  | 
 |   // Returns number of ContentEncryption elements in this ContentEncoding | 
 |   // element. | 
 |   unsigned long GetEncryptionCount() const; | 
 |  | 
 |   // Parses the ContentEncAESSettings element from |pReader|. |start| is the | 
 |   // starting offset of the ContentEncAESSettings payload. |size| is the | 
 |   // size in bytes of the ContentEncAESSettings payload. |encryption| is | 
 |   // where the parsed values will be stored. | 
 |   long ParseContentEncAESSettingsEntry(long long start, long long size, | 
 |                                        IMkvReader* pReader, | 
 |                                        ContentEncAESSettings* aes); | 
 |  | 
 |   // Parses the ContentEncoding element from |pReader|. |start| is the | 
 |   // starting offset of the ContentEncoding payload. |size| is the size in | 
 |   // bytes of the ContentEncoding payload. Returns true on success. | 
 |   long ParseContentEncodingEntry(long long start, long long size, | 
 |                                  IMkvReader* pReader); | 
 |  | 
 |   // Parses the ContentEncryption element from |pReader|. |start| is the | 
 |   // starting offset of the ContentEncryption payload. |size| is the size in | 
 |   // bytes of the ContentEncryption payload. |encryption| is where the parsed | 
 |   // values will be stored. | 
 |   long ParseEncryptionEntry(long long start, long long size, | 
 |                             IMkvReader* pReader, ContentEncryption* encryption); | 
 |  | 
 |   unsigned long long encoding_order() const { return encoding_order_; } | 
 |   unsigned long long encoding_scope() const { return encoding_scope_; } | 
 |   unsigned long long encoding_type() const { return encoding_type_; } | 
 |  | 
 |  private: | 
 |   // Member variables for list of ContentCompression elements. | 
 |   ContentCompression** compression_entries_; | 
 |   ContentCompression** compression_entries_end_; | 
 |  | 
 |   // Member variables for list of ContentEncryption elements. | 
 |   ContentEncryption** encryption_entries_; | 
 |   ContentEncryption** encryption_entries_end_; | 
 |  | 
 |   // ContentEncoding element names | 
 |   unsigned long long encoding_order_; | 
 |   unsigned long long encoding_scope_; | 
 |   unsigned long long encoding_type_; | 
 |  | 
 |   // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); | 
 |   ContentEncoding(const ContentEncoding&); | 
 |   ContentEncoding& operator=(const ContentEncoding&); | 
 | }; | 
 |  | 
 | class Track { | 
 |   Track(const Track&); | 
 |   Track& operator=(const Track&); | 
 |  | 
 |  public: | 
 |   class Info; | 
 |   static long Create(Segment*, const Info&, long long element_start, | 
 |                      long long element_size, Track*&); | 
 |  | 
 |   enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 }; | 
 |  | 
 |   Segment* const m_pSegment; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |   virtual ~Track(); | 
 |  | 
 |   long GetType() const; | 
 |   long GetNumber() const; | 
 |   unsigned long long GetUid() const; | 
 |   const char* GetNameAsUTF8() const; | 
 |   const char* GetLanguage() const; | 
 |   const char* GetCodecNameAsUTF8() const; | 
 |   const char* GetCodecId() const; | 
 |   const unsigned char* GetCodecPrivate(size_t&) const; | 
 |   bool GetLacing() const; | 
 |   unsigned long long GetDefaultDuration() const; | 
 |   unsigned long long GetCodecDelay() const; | 
 |   unsigned long long GetSeekPreRoll() const; | 
 |  | 
 |   const BlockEntry* GetEOS() const; | 
 |  | 
 |   struct Settings { | 
 |     long long start; | 
 |     long long size; | 
 |   }; | 
 |  | 
 |   class Info { | 
 |    public: | 
 |     Info(); | 
 |     ~Info(); | 
 |     int Copy(Info&) const; | 
 |     void Clear(); | 
 |     long type; | 
 |     long number; | 
 |     unsigned long long uid; | 
 |     unsigned long long defaultDuration; | 
 |     unsigned long long codecDelay; | 
 |     unsigned long long seekPreRoll; | 
 |     char* nameAsUTF8; | 
 |     char* language; | 
 |     char* codecId; | 
 |     char* codecNameAsUTF8; | 
 |     unsigned char* codecPrivate; | 
 |     size_t codecPrivateSize; | 
 |     bool lacing; | 
 |     Settings settings; | 
 |  | 
 |    private: | 
 |     Info(const Info&); | 
 |     Info& operator=(const Info&); | 
 |     int CopyStr(char* Info::*str, Info&) const; | 
 |   }; | 
 |  | 
 |   long GetFirst(const BlockEntry*&) const; | 
 |   long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; | 
 |   virtual bool VetEntry(const BlockEntry*) const; | 
 |   virtual long Seek(long long time_ns, const BlockEntry*&) const; | 
 |  | 
 |   const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const; | 
 |   unsigned long GetContentEncodingCount() const; | 
 |  | 
 |   long ParseContentEncodingsEntry(long long start, long long size); | 
 |  | 
 |  protected: | 
 |   Track(Segment*, long long element_start, long long element_size); | 
 |  | 
 |   Info m_info; | 
 |  | 
 |   class EOSBlock : public BlockEntry { | 
 |    public: | 
 |     EOSBlock(); | 
 |  | 
 |     Kind GetKind() const; | 
 |     const Block* GetBlock() const; | 
 |   }; | 
 |  | 
 |   EOSBlock m_eos; | 
 |  | 
 |  private: | 
 |   ContentEncoding** content_encoding_entries_; | 
 |   ContentEncoding** content_encoding_entries_end_; | 
 | }; | 
 |  | 
 | struct PrimaryChromaticity { | 
 |   PrimaryChromaticity() : x(0), y(0) {} | 
 |   ~PrimaryChromaticity() {} | 
 |   static bool Parse(IMkvReader* reader, long long read_pos, | 
 |                     long long value_size, bool is_x, | 
 |                     PrimaryChromaticity** chromaticity); | 
 |   float x; | 
 |   float y; | 
 | }; | 
 |  | 
 | struct MasteringMetadata { | 
 |   static const float kValueNotPresent; | 
 |  | 
 |   MasteringMetadata() | 
 |       : r(NULL), | 
 |         g(NULL), | 
 |         b(NULL), | 
 |         white_point(NULL), | 
 |         luminance_max(kValueNotPresent), | 
 |         luminance_min(kValueNotPresent) {} | 
 |   ~MasteringMetadata() { | 
 |     delete r; | 
 |     delete g; | 
 |     delete b; | 
 |     delete white_point; | 
 |   } | 
 |  | 
 |   static bool Parse(IMkvReader* reader, long long element_start, | 
 |                     long long element_size, | 
 |                     MasteringMetadata** mastering_metadata); | 
 |  | 
 |   PrimaryChromaticity* r; | 
 |   PrimaryChromaticity* g; | 
 |   PrimaryChromaticity* b; | 
 |   PrimaryChromaticity* white_point; | 
 |   float luminance_max; | 
 |   float luminance_min; | 
 | }; | 
 |  | 
 | struct Colour { | 
 |   static const long long kValueNotPresent; | 
 |  | 
 |   // Unless otherwise noted all values assigned upon construction are the | 
 |   // equivalent of unspecified/default. | 
 |   Colour() | 
 |       : matrix_coefficients(kValueNotPresent), | 
 |         bits_per_channel(kValueNotPresent), | 
 |         chroma_subsampling_horz(kValueNotPresent), | 
 |         chroma_subsampling_vert(kValueNotPresent), | 
 |         cb_subsampling_horz(kValueNotPresent), | 
 |         cb_subsampling_vert(kValueNotPresent), | 
 |         chroma_siting_horz(kValueNotPresent), | 
 |         chroma_siting_vert(kValueNotPresent), | 
 |         range(kValueNotPresent), | 
 |         transfer_characteristics(kValueNotPresent), | 
 |         primaries(kValueNotPresent), | 
 |         max_cll(kValueNotPresent), | 
 |         max_fall(kValueNotPresent), | 
 |         mastering_metadata(NULL) {} | 
 |   ~Colour() { | 
 |     delete mastering_metadata; | 
 |     mastering_metadata = NULL; | 
 |   } | 
 |  | 
 |   static bool Parse(IMkvReader* reader, long long element_start, | 
 |                     long long element_size, Colour** colour); | 
 |  | 
 |   long long matrix_coefficients; | 
 |   long long bits_per_channel; | 
 |   long long chroma_subsampling_horz; | 
 |   long long chroma_subsampling_vert; | 
 |   long long cb_subsampling_horz; | 
 |   long long cb_subsampling_vert; | 
 |   long long chroma_siting_horz; | 
 |   long long chroma_siting_vert; | 
 |   long long range; | 
 |   long long transfer_characteristics; | 
 |   long long primaries; | 
 |   long long max_cll; | 
 |   long long max_fall; | 
 |  | 
 |   MasteringMetadata* mastering_metadata; | 
 | }; | 
 |  | 
 | struct Projection { | 
 |   enum ProjectionType { | 
 |     kTypeNotPresent = -1, | 
 |     kRectangular = 0, | 
 |     kEquirectangular = 1, | 
 |     kCubeMap = 2, | 
 |     kMesh = 3, | 
 |   }; | 
 |   static const float kValueNotPresent; | 
 |   Projection() | 
 |       : type(kTypeNotPresent), | 
 |         private_data(NULL), | 
 |         private_data_length(0), | 
 |         pose_yaw(kValueNotPresent), | 
 |         pose_pitch(kValueNotPresent), | 
 |         pose_roll(kValueNotPresent) {} | 
 |   ~Projection() { delete[] private_data; } | 
 |   static bool Parse(IMkvReader* reader, long long element_start, | 
 |                     long long element_size, Projection** projection); | 
 |  | 
 |   ProjectionType type; | 
 |   unsigned char* private_data; | 
 |   size_t private_data_length; | 
 |   float pose_yaw; | 
 |   float pose_pitch; | 
 |   float pose_roll; | 
 | }; | 
 |  | 
 | class VideoTrack : public Track { | 
 |   VideoTrack(const VideoTrack&); | 
 |   VideoTrack& operator=(const VideoTrack&); | 
 |  | 
 |   VideoTrack(Segment*, long long element_start, long long element_size); | 
 |  | 
 |  public: | 
 |   virtual ~VideoTrack(); | 
 |   static long Parse(Segment*, const Info&, long long element_start, | 
 |                     long long element_size, VideoTrack*&); | 
 |  | 
 |   long long GetWidth() const; | 
 |   long long GetHeight() const; | 
 |   long long GetDisplayWidth() const; | 
 |   long long GetDisplayHeight() const; | 
 |   long long GetDisplayUnit() const; | 
 |   long long GetStereoMode() const; | 
 |   double GetFrameRate() const; | 
 |  | 
 |   bool VetEntry(const BlockEntry*) const; | 
 |   long Seek(long long time_ns, const BlockEntry*&) const; | 
 |  | 
 |   Colour* GetColour() const; | 
 |  | 
 |   Projection* GetProjection() const; | 
 |  | 
 |   const char* GetColourSpace() const { return m_colour_space; } | 
 |  | 
 |  private: | 
 |   long long m_width; | 
 |   long long m_height; | 
 |   long long m_display_width; | 
 |   long long m_display_height; | 
 |   long long m_display_unit; | 
 |   long long m_stereo_mode; | 
 |   char* m_colour_space; | 
 |   double m_rate; | 
 |  | 
 |   Colour* m_colour; | 
 |   Projection* m_projection; | 
 | }; | 
 |  | 
 | class AudioTrack : public Track { | 
 |   AudioTrack(const AudioTrack&); | 
 |   AudioTrack& operator=(const AudioTrack&); | 
 |  | 
 |   AudioTrack(Segment*, long long element_start, long long element_size); | 
 |  | 
 |  public: | 
 |   static long Parse(Segment*, const Info&, long long element_start, | 
 |                     long long element_size, AudioTrack*&); | 
 |  | 
 |   double GetSamplingRate() const; | 
 |   long long GetChannels() const; | 
 |   long long GetBitDepth() const; | 
 |  | 
 |  private: | 
 |   double m_rate; | 
 |   long long m_channels; | 
 |   long long m_bitDepth; | 
 | }; | 
 |  | 
 | class Tracks { | 
 |   Tracks(const Tracks&); | 
 |   Tracks& operator=(const Tracks&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   Tracks(Segment*, long long start, long long size, long long element_start, | 
 |          long long element_size); | 
 |  | 
 |   ~Tracks(); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   unsigned long GetTracksCount() const; | 
 |  | 
 |   const Track* GetTrackByNumber(long tn) const; | 
 |   const Track* GetTrackByIndex(unsigned long idx) const; | 
 |  | 
 |  private: | 
 |   Track** m_trackEntries; | 
 |   Track** m_trackEntriesEnd; | 
 |  | 
 |   long ParseTrackEntry(long long payload_start, long long payload_size, | 
 |                        long long element_start, long long element_size, | 
 |                        Track*&) const; | 
 | }; | 
 |  | 
 | class Chapters { | 
 |   Chapters(const Chapters&); | 
 |   Chapters& operator=(const Chapters&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   Chapters(Segment*, long long payload_start, long long payload_size, | 
 |            long long element_start, long long element_size); | 
 |  | 
 |   ~Chapters(); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   class Atom; | 
 |   class Edition; | 
 |  | 
 |   class Display { | 
 |     friend class Atom; | 
 |     Display(); | 
 |     Display(const Display&); | 
 |     ~Display(); | 
 |     Display& operator=(const Display&); | 
 |  | 
 |    public: | 
 |     const char* GetString() const; | 
 |     const char* GetLanguage() const; | 
 |     const char* GetCountry() const; | 
 |  | 
 |    private: | 
 |     void Init(); | 
 |     void ShallowCopy(Display&) const; | 
 |     void Clear(); | 
 |     long Parse(IMkvReader*, long long pos, long long size); | 
 |  | 
 |     char* m_string; | 
 |     char* m_language; | 
 |     char* m_country; | 
 |   }; | 
 |  | 
 |   class Atom { | 
 |     friend class Edition; | 
 |     Atom(); | 
 |     Atom(const Atom&); | 
 |     ~Atom(); | 
 |     Atom& operator=(const Atom&); | 
 |  | 
 |    public: | 
 |     unsigned long long GetUID() const; | 
 |     const char* GetStringUID() const; | 
 |  | 
 |     long long GetStartTimecode() const; | 
 |     long long GetStopTimecode() const; | 
 |  | 
 |     long long GetStartTime(const Chapters*) const; | 
 |     long long GetStopTime(const Chapters*) const; | 
 |  | 
 |     int GetDisplayCount() const; | 
 |     const Display* GetDisplay(int index) const; | 
 |  | 
 |    private: | 
 |     void Init(); | 
 |     void ShallowCopy(Atom&) const; | 
 |     void Clear(); | 
 |     long Parse(IMkvReader*, long long pos, long long size); | 
 |     static long long GetTime(const Chapters*, long long timecode); | 
 |  | 
 |     long ParseDisplay(IMkvReader*, long long pos, long long size); | 
 |     bool ExpandDisplaysArray(); | 
 |  | 
 |     char* m_string_uid; | 
 |     unsigned long long m_uid; | 
 |     long long m_start_timecode; | 
 |     long long m_stop_timecode; | 
 |  | 
 |     Display* m_displays; | 
 |     int m_displays_size; | 
 |     int m_displays_count; | 
 |   }; | 
 |  | 
 |   class Edition { | 
 |     friend class Chapters; | 
 |     Edition(); | 
 |     Edition(const Edition&); | 
 |     ~Edition(); | 
 |     Edition& operator=(const Edition&); | 
 |  | 
 |    public: | 
 |     int GetAtomCount() const; | 
 |     const Atom* GetAtom(int index) const; | 
 |  | 
 |    private: | 
 |     void Init(); | 
 |     void ShallowCopy(Edition&) const; | 
 |     void Clear(); | 
 |     long Parse(IMkvReader*, long long pos, long long size); | 
 |  | 
 |     long ParseAtom(IMkvReader*, long long pos, long long size); | 
 |     bool ExpandAtomsArray(); | 
 |  | 
 |     Atom* m_atoms; | 
 |     int m_atoms_size; | 
 |     int m_atoms_count; | 
 |   }; | 
 |  | 
 |   int GetEditionCount() const; | 
 |   const Edition* GetEdition(int index) const; | 
 |  | 
 |  private: | 
 |   long ParseEdition(long long pos, long long size); | 
 |   bool ExpandEditionsArray(); | 
 |  | 
 |   Edition* m_editions; | 
 |   int m_editions_size; | 
 |   int m_editions_count; | 
 | }; | 
 |  | 
 | class Tags { | 
 |   Tags(const Tags&); | 
 |   Tags& operator=(const Tags&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   Tags(Segment*, long long payload_start, long long payload_size, | 
 |        long long element_start, long long element_size); | 
 |  | 
 |   ~Tags(); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   class Tag; | 
 |   class SimpleTag; | 
 |  | 
 |   class SimpleTag { | 
 |     friend class Tag; | 
 |     SimpleTag(); | 
 |     SimpleTag(const SimpleTag&); | 
 |     ~SimpleTag(); | 
 |     SimpleTag& operator=(const SimpleTag&); | 
 |  | 
 |    public: | 
 |     const char* GetTagName() const; | 
 |     const char* GetTagString() const; | 
 |  | 
 |    private: | 
 |     void Init(); | 
 |     void ShallowCopy(SimpleTag&) const; | 
 |     void Clear(); | 
 |     long Parse(IMkvReader*, long long pos, long long size); | 
 |  | 
 |     char* m_tag_name; | 
 |     char* m_tag_string; | 
 |   }; | 
 |  | 
 |   class Tag { | 
 |     friend class Tags; | 
 |     Tag(); | 
 |     Tag(const Tag&); | 
 |     ~Tag(); | 
 |     Tag& operator=(const Tag&); | 
 |  | 
 |    public: | 
 |     int GetSimpleTagCount() const; | 
 |     const SimpleTag* GetSimpleTag(int index) const; | 
 |  | 
 |    private: | 
 |     void Init(); | 
 |     void ShallowCopy(Tag&) const; | 
 |     void Clear(); | 
 |     long Parse(IMkvReader*, long long pos, long long size); | 
 |  | 
 |     long ParseSimpleTag(IMkvReader*, long long pos, long long size); | 
 |     bool ExpandSimpleTagsArray(); | 
 |  | 
 |     SimpleTag* m_simple_tags; | 
 |     int m_simple_tags_size; | 
 |     int m_simple_tags_count; | 
 |   }; | 
 |  | 
 |   int GetTagCount() const; | 
 |   const Tag* GetTag(int index) const; | 
 |  | 
 |  private: | 
 |   long ParseTag(long long pos, long long size); | 
 |   bool ExpandTagsArray(); | 
 |  | 
 |   Tag* m_tags; | 
 |   int m_tags_size; | 
 |   int m_tags_count; | 
 | }; | 
 |  | 
 | class SegmentInfo { | 
 |   SegmentInfo(const SegmentInfo&); | 
 |   SegmentInfo& operator=(const SegmentInfo&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   SegmentInfo(Segment*, long long start, long long size, | 
 |               long long element_start, long long element_size); | 
 |  | 
 |   ~SegmentInfo(); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   long long GetTimeCodeScale() const; | 
 |   long long GetDuration() const;  // scaled | 
 |   const char* GetMuxingAppAsUTF8() const; | 
 |   const char* GetWritingAppAsUTF8() const; | 
 |   const char* GetTitleAsUTF8() const; | 
 |  | 
 |  private: | 
 |   long long m_timecodeScale; | 
 |   double m_duration; | 
 |   char* m_pMuxingAppAsUTF8; | 
 |   char* m_pWritingAppAsUTF8; | 
 |   char* m_pTitleAsUTF8; | 
 | }; | 
 |  | 
 | class SeekHead { | 
 |   SeekHead(const SeekHead&); | 
 |   SeekHead& operator=(const SeekHead&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   SeekHead(Segment*, long long start, long long size, long long element_start, | 
 |            long long element_size); | 
 |  | 
 |   ~SeekHead(); | 
 |  | 
 |   long Parse(); | 
 |  | 
 |   struct Entry { | 
 |     Entry(); | 
 |  | 
 |     // the SeekHead entry payload | 
 |     long long id; | 
 |     long long pos; | 
 |  | 
 |     // absolute pos of SeekEntry ID | 
 |     long long element_start; | 
 |  | 
 |     // SeekEntry ID size + size size + payload | 
 |     long long element_size; | 
 |   }; | 
 |  | 
 |   int GetCount() const; | 
 |   const Entry* GetEntry(int idx) const; | 
 |  | 
 |   struct VoidElement { | 
 |     // absolute pos of Void ID | 
 |     long long element_start; | 
 |  | 
 |     // ID size + size size + payload size | 
 |     long long element_size; | 
 |   }; | 
 |  | 
 |   int GetVoidElementCount() const; | 
 |   const VoidElement* GetVoidElement(int idx) const; | 
 |  | 
 |  private: | 
 |   Entry* m_entries; | 
 |   int m_entry_count; | 
 |  | 
 |   VoidElement* m_void_elements; | 
 |   int m_void_element_count; | 
 |  | 
 |   static bool ParseEntry(IMkvReader*, | 
 |                          long long pos,  // payload | 
 |                          long long size, Entry*); | 
 | }; | 
 |  | 
 | class Cues; | 
 | class CuePoint { | 
 |   friend class Cues; | 
 |  | 
 |   CuePoint(long, long long); | 
 |   ~CuePoint(); | 
 |  | 
 |   CuePoint(const CuePoint&); | 
 |   CuePoint& operator=(const CuePoint&); | 
 |  | 
 |  public: | 
 |   long long m_element_start; | 
 |   long long m_element_size; | 
 |  | 
 |   bool Load(IMkvReader*); | 
 |  | 
 |   long long GetTimeCode() const;  // absolute but unscaled | 
 |   long long GetTime(const Segment*) const;  // absolute and scaled (ns units) | 
 |  | 
 |   struct TrackPosition { | 
 |     long long m_track; | 
 |     long long m_pos;  // of cluster | 
 |     long long m_block; | 
 |     // codec_state  //defaults to 0 | 
 |     // reference = clusters containing req'd referenced blocks | 
 |     //  reftime = timecode of the referenced block | 
 |  | 
 |     bool Parse(IMkvReader*, long long, long long); | 
 |   }; | 
 |  | 
 |   const TrackPosition* Find(const Track*) const; | 
 |  | 
 |  private: | 
 |   const long m_index; | 
 |   long long m_timecode; | 
 |   TrackPosition* m_track_positions; | 
 |   size_t m_track_positions_count; | 
 | }; | 
 |  | 
 | class Cues { | 
 |   friend class Segment; | 
 |  | 
 |   Cues(Segment*, long long start, long long size, long long element_start, | 
 |        long long element_size); | 
 |   ~Cues(); | 
 |  | 
 |   Cues(const Cues&); | 
 |   Cues& operator=(const Cues&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |   const long long m_start; | 
 |   const long long m_size; | 
 |   const long long m_element_start; | 
 |   const long long m_element_size; | 
 |  | 
 |   bool Find(  // lower bound of time_ns | 
 |       long long time_ns, const Track*, const CuePoint*&, | 
 |       const CuePoint::TrackPosition*&) const; | 
 |  | 
 |   const CuePoint* GetFirst() const; | 
 |   const CuePoint* GetLast() const; | 
 |   const CuePoint* GetNext(const CuePoint*) const; | 
 |  | 
 |   const BlockEntry* GetBlock(const CuePoint*, | 
 |                              const CuePoint::TrackPosition*) const; | 
 |  | 
 |   bool LoadCuePoint() const; | 
 |   long GetCount() const;  // loaded only | 
 |   // long GetTotal() const;  //loaded + preloaded | 
 |   bool DoneParsing() const; | 
 |  | 
 |  private: | 
 |   bool Init() const; | 
 |   bool PreloadCuePoint(long&, long long) const; | 
 |  | 
 |   mutable CuePoint** m_cue_points; | 
 |   mutable long m_count; | 
 |   mutable long m_preload_count; | 
 |   mutable long long m_pos; | 
 | }; | 
 |  | 
 | class Cluster { | 
 |   friend class Segment; | 
 |  | 
 |   Cluster(const Cluster&); | 
 |   Cluster& operator=(const Cluster&); | 
 |  | 
 |  public: | 
 |   Segment* const m_pSegment; | 
 |  | 
 |  public: | 
 |   static Cluster* Create(Segment*, | 
 |                          long index,  // index in segment | 
 |                          long long off);  // offset relative to segment | 
 |   // long long element_size); | 
 |  | 
 |   Cluster();  // EndOfStream | 
 |   ~Cluster(); | 
 |  | 
 |   bool EOS() const; | 
 |  | 
 |   long long GetTimeCode() const;  // absolute, but not scaled | 
 |   long long GetTime() const;  // absolute, and scaled (nanosecond units) | 
 |   long long GetFirstTime() const;  // time (ns) of first (earliest) block | 
 |   long long GetLastTime() const;  // time (ns) of last (latest) block | 
 |  | 
 |   long GetFirst(const BlockEntry*&) const; | 
 |   long GetLast(const BlockEntry*&) const; | 
 |   long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; | 
 |  | 
 |   const BlockEntry* GetEntry(const Track*, long long ns = -1) const; | 
 |   const BlockEntry* GetEntry(const CuePoint&, | 
 |                              const CuePoint::TrackPosition&) const; | 
 |   // const BlockEntry* GetMaxKey(const VideoTrack*) const; | 
 |  | 
 |   //    static bool HasBlockEntries(const Segment*, long long); | 
 |  | 
 |   static long HasBlockEntries(const Segment*, long long idoff, long long& pos, | 
 |                               long& size); | 
 |  | 
 |   long GetEntryCount() const; | 
 |  | 
 |   long Load(long long& pos, long& size) const; | 
 |  | 
 |   long Parse(long long& pos, long& size) const; | 
 |   long GetEntry(long index, const mkvparser::BlockEntry*&) const; | 
 |  | 
 |  protected: | 
 |   Cluster(Segment*, long index, long long element_start); | 
 |   // long long element_size); | 
 |  | 
 |  public: | 
 |   const long long m_element_start; | 
 |   long long GetPosition() const;  // offset relative to segment | 
 |  | 
 |   long GetIndex() const; | 
 |   long long GetElementSize() const; | 
 |   // long long GetPayloadSize() const; | 
 |  | 
 |   // long long Unparsed() const; | 
 |  | 
 |  private: | 
 |   long m_index; | 
 |   mutable long long m_pos; | 
 |   // mutable long long m_size; | 
 |   mutable long long m_element_size; | 
 |   mutable long long m_timecode; | 
 |   mutable BlockEntry** m_entries; | 
 |   mutable long m_entries_size; | 
 |   mutable long m_entries_count; | 
 |  | 
 |   long ParseSimpleBlock(long long, long long&, long&); | 
 |   long ParseBlockGroup(long long, long long&, long&); | 
 |  | 
 |   long CreateBlock(long long id, long long pos, long long size, | 
 |                    long long discard_padding); | 
 |   long CreateBlockGroup(long long start_offset, long long size, | 
 |                         long long discard_padding); | 
 |   long CreateSimpleBlock(long long, long long); | 
 | }; | 
 |  | 
 | class Segment { | 
 |   friend class Cues; | 
 |   friend class Track; | 
 |   friend class VideoTrack; | 
 |  | 
 |   Segment(const Segment&); | 
 |   Segment& operator=(const Segment&); | 
 |  | 
 |  private: | 
 |   Segment(IMkvReader*, long long elem_start, | 
 |           // long long elem_size, | 
 |           long long pos, long long size); | 
 |  | 
 |  public: | 
 |   IMkvReader* const m_pReader; | 
 |   const long long m_element_start; | 
 |   // const long long m_element_size; | 
 |   const long long m_start;  // posn of segment payload | 
 |   const long long m_size;  // size of segment payload | 
 |   Cluster m_eos;  // TODO: make private? | 
 |  | 
 |   static long long CreateInstance(IMkvReader*, long long, Segment*&); | 
 |   ~Segment(); | 
 |  | 
 |   long Load();  // loads headers and all clusters | 
 |  | 
 |   // for incremental loading | 
 |   // long long Unparsed() const; | 
 |   bool DoneParsing() const; | 
 |   long long ParseHeaders();  // stops when first cluster is found | 
 |   // long FindNextCluster(long long& pos, long& size) const; | 
 |   long LoadCluster(long long& pos, long& size);  // load one cluster | 
 |   long LoadCluster(); | 
 |  | 
 |   long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos, | 
 |                  long& size); | 
 |  | 
 |   const SeekHead* GetSeekHead() const; | 
 |   const Tracks* GetTracks() const; | 
 |   const SegmentInfo* GetInfo() const; | 
 |   const Cues* GetCues() const; | 
 |   const Chapters* GetChapters() const; | 
 |   const Tags* GetTags() const; | 
 |  | 
 |   long long GetDuration() const; | 
 |  | 
 |   unsigned long GetCount() const; | 
 |   const Cluster* GetFirst() const; | 
 |   const Cluster* GetLast() const; | 
 |   const Cluster* GetNext(const Cluster*); | 
 |  | 
 |   const Cluster* FindCluster(long long time_nanoseconds) const; | 
 |   // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const; | 
 |  | 
 |   const Cluster* FindOrPreloadCluster(long long pos); | 
 |  | 
 |   long ParseCues(long long cues_off,  // offset relative to start of segment | 
 |                  long long& parse_pos, long& parse_len); | 
 |  | 
 |  private: | 
 |   long long m_pos;  // absolute file posn; what has been consumed so far | 
 |   Cluster* m_pUnknownSize; | 
 |  | 
 |   SeekHead* m_pSeekHead; | 
 |   SegmentInfo* m_pInfo; | 
 |   Tracks* m_pTracks; | 
 |   Cues* m_pCues; | 
 |   Chapters* m_pChapters; | 
 |   Tags* m_pTags; | 
 |   Cluster** m_clusters; | 
 |   long m_clusterCount;  // number of entries for which m_index >= 0 | 
 |   long m_clusterPreloadCount;  // number of entries for which m_index < 0 | 
 |   long m_clusterSize;  // array size | 
 |  | 
 |   long DoLoadCluster(long long&, long&); | 
 |   long DoLoadClusterUnknownSize(long long&, long&); | 
 |   long DoParseNext(const Cluster*&, long long&, long&); | 
 |  | 
 |   bool AppendCluster(Cluster*); | 
 |   bool PreloadCluster(Cluster*, ptrdiff_t); | 
 |  | 
 |   // void ParseSeekHead(long long pos, long long size); | 
 |   // void ParseSeekEntry(long long pos, long long size); | 
 |   // void ParseCues(long long); | 
 |  | 
 |   const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&); | 
 | }; | 
 |  | 
 | }  // namespace mkvparser | 
 |  | 
 | inline long mkvparser::Segment::LoadCluster() { | 
 |   long long pos; | 
 |   long size; | 
 |  | 
 |   return LoadCluster(pos, size); | 
 | } | 
 |  | 
 | #endif  // MKVPARSER_MKVPARSER_H_ |