|
|
|
@ -13,17 +13,16 @@
|
|
|
|
|
#include <cstdio> |
|
|
|
|
#include <cstddef> |
|
|
|
|
|
|
|
|
|
namespace mkvparser |
|
|
|
|
{ |
|
|
|
|
namespace mkvparser { |
|
|
|
|
|
|
|
|
|
const int E_FILE_FORMAT_INVALID = -2; |
|
|
|
|
const int E_BUFFER_NOT_FULL = -3; |
|
|
|
|
|
|
|
|
|
class IMkvReader |
|
|
|
|
{ |
|
|
|
|
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(); |
|
|
|
|
}; |
|
|
|
@ -35,26 +34,19 @@ 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 len, long long& result); |
|
|
|
|
|
|
|
|
|
long UnserializeString( |
|
|
|
|
IMkvReader*, |
|
|
|
|
long long pos, |
|
|
|
|
long long size, |
|
|
|
|
char*& str); |
|
|
|
|
long UnserializeString(IMkvReader*, long long pos, long long size, char*& str); |
|
|
|
|
|
|
|
|
|
long ParseElementHeader( |
|
|
|
|
IMkvReader* pReader, |
|
|
|
|
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); |
|
|
|
|
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 |
|
|
|
|
{ |
|
|
|
|
struct EBMLHeader { |
|
|
|
|
EBMLHeader(); |
|
|
|
|
~EBMLHeader(); |
|
|
|
|
long long m_version; |
|
|
|
@ -69,13 +61,11 @@ struct EBMLHeader
|
|
|
|
|
void Init(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Segment; |
|
|
|
|
class Track; |
|
|
|
|
class Cluster; |
|
|
|
|
|
|
|
|
|
class Block |
|
|
|
|
{ |
|
|
|
|
class Block { |
|
|
|
|
Block(const Block&); |
|
|
|
|
Block& operator=(const Block&); |
|
|
|
|
|
|
|
|
@ -83,7 +73,7 @@ public:
|
|
|
|
|
const long long m_start; |
|
|
|
|
const long long m_size; |
|
|
|
|
|
|
|
|
|
Block(long long start, long long size); |
|
|
|
|
Block(long long start, long long size, long long discard_padding); |
|
|
|
|
~Block(); |
|
|
|
|
|
|
|
|
|
long Parse(const Cluster*); |
|
|
|
@ -100,8 +90,7 @@ public:
|
|
|
|
|
|
|
|
|
|
int GetFrameCount() const; // to index frames: [0, count)
|
|
|
|
|
|
|
|
|
|
struct Frame |
|
|
|
|
{ |
|
|
|
|
struct Frame { |
|
|
|
|
long long pos; // absolute offset
|
|
|
|
|
long len; |
|
|
|
|
|
|
|
|
@ -110,6 +99,8 @@ public:
|
|
|
|
|
|
|
|
|
|
const Frame& GetFrame(int frame_index) const; |
|
|
|
|
|
|
|
|
|
long long GetDiscardPadding() const; |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
long long m_track; // Track::Number()
|
|
|
|
|
short m_timecode; // relative to cluster
|
|
|
|
@ -118,11 +109,11 @@ private:
|
|
|
|
|
Frame* m_frames; |
|
|
|
|
int m_frame_count; |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
const long long m_discard_padding; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BlockEntry |
|
|
|
|
{ |
|
|
|
|
class BlockEntry { |
|
|
|
|
BlockEntry(const BlockEntry&); |
|
|
|
|
BlockEntry& operator=(const BlockEntry&); |
|
|
|
|
|
|
|
|
@ -143,12 +134,9 @@ public:
|
|
|
|
|
protected: |
|
|
|
|
Cluster* const m_pCluster; |
|
|
|
|
const long m_index; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SimpleBlock : public BlockEntry |
|
|
|
|
{ |
|
|
|
|
class SimpleBlock : public BlockEntry { |
|
|
|
|
SimpleBlock(const SimpleBlock&); |
|
|
|
|
SimpleBlock& operator=(const SimpleBlock&); |
|
|
|
|
|
|
|
|
@ -161,24 +149,18 @@ public:
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
Block m_block; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BlockGroup : public BlockEntry |
|
|
|
|
{ |
|
|
|
|
class BlockGroup : public BlockEntry { |
|
|
|
|
BlockGroup(const BlockGroup&); |
|
|
|
|
BlockGroup& operator=(const BlockGroup&); |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
BlockGroup( |
|
|
|
|
Cluster*, |
|
|
|
|
long index, |
|
|
|
|
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 prev, long long next, long long duration, |
|
|
|
|
long long discard_padding); |
|
|
|
|
|
|
|
|
|
long Parse(); |
|
|
|
|
|
|
|
|
@ -194,7 +176,6 @@ private:
|
|
|
|
|
const long long m_prev; |
|
|
|
|
const long long m_next; |
|
|
|
|
const long long m_duration; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
@ -203,9 +184,7 @@ private:
|
|
|
|
|
// compressed with zlib or header stripping.
|
|
|
|
|
class ContentEncoding { |
|
|
|
|
public: |
|
|
|
|
enum { |
|
|
|
|
kCTR = 1 |
|
|
|
|
}; |
|
|
|
|
enum { kCTR = 1 }; |
|
|
|
|
|
|
|
|
|
ContentEncoding(); |
|
|
|
|
~ContentEncoding(); |
|
|
|
@ -217,6 +196,7 @@ public:
|
|
|
|
|
|
|
|
|
|
unsigned long long algo; |
|
|
|
|
unsigned char* settings; |
|
|
|
|
long long settings_len; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// ContentEncAESSettings element names
|
|
|
|
@ -253,6 +233,14 @@ public:
|
|
|
|
|
// 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; |
|
|
|
@ -265,26 +253,22 @@ public:
|
|
|
|
|
// 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, |
|
|
|
|
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, |
|
|
|
|
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); |
|
|
|
|
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_; } |
|
|
|
@ -309,21 +293,16 @@ private:
|
|
|
|
|
ContentEncoding& operator=(const ContentEncoding&); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Track |
|
|
|
|
{ |
|
|
|
|
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*&); |
|
|
|
|
static long Create(Segment*, const Info&, long long element_start, |
|
|
|
|
long long element_size, Track*&); |
|
|
|
|
|
|
|
|
|
enum Type { kVideo = 1, kAudio = 2 }; |
|
|
|
|
enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 }; |
|
|
|
|
|
|
|
|
|
Segment* const m_pSegment; |
|
|
|
|
const long long m_element_start; |
|
|
|
@ -334,41 +313,46 @@ public:
|
|
|
|
|
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 |
|
|
|
|
{ |
|
|
|
|
struct Settings { |
|
|
|
|
long long start; |
|
|
|
|
long long size; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Info |
|
|
|
|
{ |
|
|
|
|
class Info { |
|
|
|
|
public: |
|
|
|
|
Info(); |
|
|
|
|
~Info(); |
|
|
|
|
int Copy(Info&) const; |
|
|
|
|
void Clear(); |
|
|
|
|
private: |
|
|
|
|
Info(const Info&); |
|
|
|
|
Info& operator=(const Info&); |
|
|
|
|
public: |
|
|
|
|
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; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -383,15 +367,11 @@ public:
|
|
|
|
|
long ParseContentEncodingsEntry(long long start, long long size); |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
Track( |
|
|
|
|
Segment*, |
|
|
|
|
long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
Track(Segment*, long long element_start, long long element_size); |
|
|
|
|
|
|
|
|
|
Info m_info; |
|
|
|
|
|
|
|
|
|
class EOSBlock : public BlockEntry |
|
|
|
|
{ |
|
|
|
|
class EOSBlock : public BlockEntry { |
|
|
|
|
public: |
|
|
|
|
EOSBlock(); |
|
|
|
|
|
|
|
|
@ -406,24 +386,15 @@ private:
|
|
|
|
|
ContentEncoding** content_encoding_entries_end_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VideoTrack : public Track |
|
|
|
|
{ |
|
|
|
|
class VideoTrack : public Track { |
|
|
|
|
VideoTrack(const VideoTrack&); |
|
|
|
|
VideoTrack& operator=(const VideoTrack&); |
|
|
|
|
|
|
|
|
|
VideoTrack( |
|
|
|
|
Segment*, |
|
|
|
|
long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
VideoTrack(Segment*, long long element_start, long long element_size); |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
static long Parse( |
|
|
|
|
Segment*, |
|
|
|
|
const Info&, |
|
|
|
|
long long element_start, |
|
|
|
|
long long element_size, |
|
|
|
|
VideoTrack*&); |
|
|
|
|
static long Parse(Segment*, const Info&, long long element_start, |
|
|
|
|
long long element_size, VideoTrack*&); |
|
|
|
|
|
|
|
|
|
long long GetWidth() const; |
|
|
|
|
long long GetHeight() const; |
|
|
|
@ -436,31 +407,21 @@ private:
|
|
|
|
|
long long m_width; |
|
|
|
|
long long m_height; |
|
|
|
|
double m_rate; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AudioTrack : public Track |
|
|
|
|
{ |
|
|
|
|
class AudioTrack : public Track { |
|
|
|
|
AudioTrack(const AudioTrack&); |
|
|
|
|
AudioTrack& operator=(const AudioTrack&); |
|
|
|
|
|
|
|
|
|
AudioTrack( |
|
|
|
|
Segment*, |
|
|
|
|
long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
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*&); |
|
|
|
|
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; |
|
|
|
|
long Seek(long long time_ns, const BlockEntry*&) const; |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
double m_rate; |
|
|
|
@ -468,9 +429,7 @@ private:
|
|
|
|
|
long long m_bitDepth; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Tracks |
|
|
|
|
{ |
|
|
|
|
class Tracks { |
|
|
|
|
Tracks(const Tracks&); |
|
|
|
|
Tracks& operator=(const Tracks&); |
|
|
|
|
|
|
|
|
@ -481,11 +440,7 @@ public:
|
|
|
|
|
const long long m_element_start; |
|
|
|
|
const long long m_element_size; |
|
|
|
|
|
|
|
|
|
Tracks( |
|
|
|
|
Segment*, |
|
|
|
|
long long start, |
|
|
|
|
long long size, |
|
|
|
|
long long element_start, |
|
|
|
|
Tracks(Segment*, long long start, long long size, long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
|
|
|
|
|
~Tracks(); |
|
|
|
@ -501,18 +456,12 @@ 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, |
|
|
|
|
long ParseTrackEntry(long long payload_start, long long payload_size, |
|
|
|
|
long long element_start, long long element_size, |
|
|
|
|
Track*&) const; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Chapters |
|
|
|
|
{ |
|
|
|
|
class Chapters { |
|
|
|
|
Chapters(const Chapters&); |
|
|
|
|
Chapters& operator=(const Chapters&); |
|
|
|
|
|
|
|
|
@ -523,12 +472,8 @@ public:
|
|
|
|
|
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(Segment*, long long payload_start, long long payload_size, |
|
|
|
|
long long element_start, long long element_size); |
|
|
|
|
|
|
|
|
|
~Chapters(); |
|
|
|
|
|
|
|
|
@ -537,17 +482,18 @@ public:
|
|
|
|
|
class Atom; |
|
|
|
|
class Edition; |
|
|
|
|
|
|
|
|
|
class Display |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
@ -559,29 +505,38 @@ public:
|
|
|
|
|
char* m_country; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Atom |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
// TODO(matthewjheaney): Cue Identifier (string)
|
|
|
|
|
long long m_start_timecode; |
|
|
|
|
long long m_stop_timecode; |
|
|
|
|
|
|
|
|
@ -590,16 +545,17 @@ public:
|
|
|
|
|
int m_displays_count; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Edition |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
@ -624,12 +580,9 @@ private:
|
|
|
|
|
Edition* m_editions; |
|
|
|
|
int m_editions_size; |
|
|
|
|
int m_editions_count; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SegmentInfo |
|
|
|
|
{ |
|
|
|
|
class SegmentInfo { |
|
|
|
|
SegmentInfo(const SegmentInfo&); |
|
|
|
|
SegmentInfo& operator=(const SegmentInfo&); |
|
|
|
|
|
|
|
|
@ -640,12 +593,8 @@ public:
|
|
|
|
|
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(Segment*, long long start, long long size, |
|
|
|
|
long long element_start, long long element_size); |
|
|
|
|
|
|
|
|
|
~SegmentInfo(); |
|
|
|
|
|
|
|
|
@ -665,9 +614,7 @@ private:
|
|
|
|
|
char* m_pTitleAsUTF8; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SeekHead |
|
|
|
|
{ |
|
|
|
|
class SeekHead { |
|
|
|
|
SeekHead(const SeekHead&); |
|
|
|
|
SeekHead& operator=(const SeekHead&); |
|
|
|
|
|
|
|
|
@ -678,19 +625,14 @@ public:
|
|
|
|
|
const long long m_element_start; |
|
|
|
|
const long long m_element_size; |
|
|
|
|
|
|
|
|
|
SeekHead( |
|
|
|
|
Segment*, |
|
|
|
|
long long start, |
|
|
|
|
long long size, |
|
|
|
|
long long element_start, |
|
|
|
|
SeekHead(Segment*, long long start, long long size, long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
|
|
|
|
|
~SeekHead(); |
|
|
|
|
|
|
|
|
|
long Parse(); |
|
|
|
|
|
|
|
|
|
struct Entry |
|
|
|
|
{ |
|
|
|
|
struct Entry { |
|
|
|
|
// the SeekHead entry payload
|
|
|
|
|
long long id; |
|
|
|
|
long long pos; |
|
|
|
@ -705,8 +647,7 @@ public:
|
|
|
|
|
int GetCount() const; |
|
|
|
|
const Entry* GetEntry(int idx) const; |
|
|
|
|
|
|
|
|
|
struct VoidElement |
|
|
|
|
{ |
|
|
|
|
struct VoidElement { |
|
|
|
|
// absolute pos of Void ID
|
|
|
|
|
long long element_start; |
|
|
|
|
|
|
|
|
@ -724,17 +665,13 @@ private:
|
|
|
|
|
VoidElement* m_void_elements; |
|
|
|
|
int m_void_element_count; |
|
|
|
|
|
|
|
|
|
static bool ParseEntry( |
|
|
|
|
IMkvReader*, |
|
|
|
|
static bool ParseEntry(IMkvReader*, |
|
|
|
|
long long pos, // payload
|
|
|
|
|
long long size, |
|
|
|
|
Entry*); |
|
|
|
|
|
|
|
|
|
long long size, Entry*); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Cues; |
|
|
|
|
class CuePoint |
|
|
|
|
{ |
|
|
|
|
class CuePoint { |
|
|
|
|
friend class Cues; |
|
|
|
|
|
|
|
|
|
CuePoint(long, long long); |
|
|
|
@ -752,8 +689,7 @@ public:
|
|
|
|
|
long long GetTimeCode() const; // absolute but unscaled
|
|
|
|
|
long long GetTime(const Segment*) const; // absolute and scaled (ns units)
|
|
|
|
|
|
|
|
|
|
struct TrackPosition |
|
|
|
|
{ |
|
|
|
|
struct TrackPosition { |
|
|
|
|
long long m_track; |
|
|
|
|
long long m_pos; // of cluster
|
|
|
|
|
long long m_block; |
|
|
|
@ -771,19 +707,12 @@ private:
|
|
|
|
|
long long m_timecode; |
|
|
|
|
TrackPosition* m_track_positions; |
|
|
|
|
size_t m_track_positions_count; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Cues |
|
|
|
|
{ |
|
|
|
|
class Cues { |
|
|
|
|
friend class Segment; |
|
|
|
|
|
|
|
|
|
Cues( |
|
|
|
|
Segment*, |
|
|
|
|
long long start, |
|
|
|
|
long long size, |
|
|
|
|
long long element_start, |
|
|
|
|
Cues(Segment*, long long start, long long size, long long element_start, |
|
|
|
|
long long element_size); |
|
|
|
|
~Cues(); |
|
|
|
|
|
|
|
|
@ -798,9 +727,7 @@ public:
|
|
|
|
|
const long long m_element_size; |
|
|
|
|
|
|
|
|
|
bool Find( // lower bound of time_ns
|
|
|
|
|
long long time_ns, |
|
|
|
|
const Track*, |
|
|
|
|
const CuePoint*&, |
|
|
|
|
long long time_ns, const Track*, const CuePoint*&, |
|
|
|
|
const CuePoint::TrackPosition*&) const; |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
@ -815,8 +742,7 @@ public:
|
|
|
|
|
const CuePoint* GetLast() const; |
|
|
|
|
const CuePoint* GetNext(const CuePoint*) const; |
|
|
|
|
|
|
|
|
|
const BlockEntry* GetBlock( |
|
|
|
|
const CuePoint*, |
|
|
|
|
const BlockEntry* GetBlock(const CuePoint*, |
|
|
|
|
const CuePoint::TrackPosition*) const; |
|
|
|
|
|
|
|
|
|
bool LoadCuePoint() const; |
|
|
|
@ -832,12 +758,9 @@ private:
|
|
|
|
|
mutable long m_count; |
|
|
|
|
mutable long m_preload_count; |
|
|
|
|
mutable long long m_pos; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Cluster |
|
|
|
|
{ |
|
|
|
|
class Cluster { |
|
|
|
|
friend class Segment; |
|
|
|
|
|
|
|
|
|
Cluster(const Cluster&); |
|
|
|
@ -847,8 +770,7 @@ public:
|
|
|
|
|
Segment* const m_pSegment; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
static Cluster* Create( |
|
|
|
|
Segment*, |
|
|
|
|
static Cluster* Create(Segment*, |
|
|
|
|
long index, // index in segment
|
|
|
|
|
long long off); // offset relative to segment
|
|
|
|
|
// long long element_size);
|
|
|
|
@ -868,17 +790,13 @@ public:
|
|
|
|
|
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 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, |
|
|
|
|
static long HasBlockEntries(const Segment*, long long idoff, long long& pos, |
|
|
|
|
long& size); |
|
|
|
|
|
|
|
|
|
long GetEntryCount() const; |
|
|
|
@ -889,10 +807,7 @@ public:
|
|
|
|
|
long GetEntry(long index, const mkvparser::BlockEntry*&) const; |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
Cluster( |
|
|
|
|
Segment*, |
|
|
|
|
long index, |
|
|
|
|
long long element_start); |
|
|
|
|
Cluster(Segment*, long index, long long element_start); |
|
|
|
|
// long long element_size);
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
@ -918,29 +833,25 @@ private:
|
|
|
|
|
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 CreateBlockGroup(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 |
|
|
|
|
{ |
|
|
|
|
class Segment { |
|
|
|
|
friend class Cues; |
|
|
|
|
friend class Track; |
|
|
|
|
friend class VideoTrack; |
|
|
|
|
friend class AudioTrack; |
|
|
|
|
|
|
|
|
|
Segment(const Segment&); |
|
|
|
|
Segment& operator=(const Segment&); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
Segment( |
|
|
|
|
IMkvReader*, |
|
|
|
|
long long elem_start, |
|
|
|
|
Segment(IMkvReader*, long long elem_start, |
|
|
|
|
// long long elem_size,
|
|
|
|
|
long long pos, |
|
|
|
|
long long size); |
|
|
|
|
long long pos, long long size); |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
IMkvReader* const m_pReader; |
|
|
|
@ -963,10 +874,7 @@ public:
|
|
|
|
|
long LoadCluster(long long& pos, long& size); // load one cluster
|
|
|
|
|
long LoadCluster(); |
|
|
|
|
|
|
|
|
|
long ParseNext( |
|
|
|
|
const Cluster* pCurr, |
|
|
|
|
const Cluster*& pNext, |
|
|
|
|
long long& pos, |
|
|
|
|
long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos, |
|
|
|
|
long& size); |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
@ -994,13 +902,10 @@ public:
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
@ -1025,16 +930,12 @@ private:
|
|
|
|
|
// void ParseSeekEntry(long long pos, long long size);
|
|
|
|
|
// void ParseCues(long long);
|
|
|
|
|
|
|
|
|
|
const BlockEntry* GetBlock( |
|
|
|
|
const CuePoint&, |
|
|
|
|
const CuePoint::TrackPosition&); |
|
|
|
|
|
|
|
|
|
const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // end namespace mkvparser
|
|
|
|
|
|
|
|
|
|
inline long mkvparser::Segment::LoadCluster() |
|
|
|
|
{ |
|
|
|
|
inline long mkvparser::Segment::LoadCluster() { |
|
|
|
|
long long pos; |
|
|
|
|
long size; |
|
|
|
|
|
|
|
|
|