changed headers for license

Change-Id: Ie09fd98548a9c3300a523b40f83d42c3de13e1c3
This commit is contained in:
Hwasoo Lee
2010-06-15 17:43:20 -04:00
parent 8ccdd10ad8
commit 0a8911b74c
5 changed files with 3940 additions and 3935 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,433 +1,434 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved. // Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// //
// Use of this source code is governed by a BSD-style license and patent // Use of this source code is governed by a BSD-style license
// grant that can be found in the LICENSE file in the root of the source // that can be found in the LICENSE file in the root of the source
// tree. All contributing project authors may be found in the AUTHORS // tree. An additional intellectual property rights grant can be found
// file in the root of the source tree. // in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef MKVPARSER_HPP
#define MKVPARSER_HPP #ifndef MKVPARSER_HPP
#define MKVPARSER_HPP
#include <cstdlib>
#include <cstdio> #include <cstdlib>
#include <cstdio>
namespace mkvparser
{ namespace mkvparser
{
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3; const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;
class IMkvReader
{ class IMkvReader
public: {
virtual int Read(long long position, long length, unsigned char* buffer) = 0; public:
virtual int Length(long long* total, long long* available) = 0; virtual int Read(long long position, long length, unsigned char* buffer) = 0;
protected: virtual int Length(long long* total, long long* available) = 0;
virtual ~IMkvReader(); protected:
}; virtual ~IMkvReader();
};
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&); long long GetUIntLength(IMkvReader*, long long, long&);
long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&); long long ReadUInt(IMkvReader*, long long, long&);
long long UnserializeUInt(IMkvReader*, long long pos, long long size); long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
float Unserialize4Float(IMkvReader*, long long); long long UnserializeUInt(IMkvReader*, long long pos, long long size);
double Unserialize8Double(IMkvReader*, long long); float Unserialize4Float(IMkvReader*, long long);
short Unserialize2SInt(IMkvReader*, long long); double Unserialize8Double(IMkvReader*, long long);
signed char Unserialize1SInt(IMkvReader*, long long); short Unserialize2SInt(IMkvReader*, long long);
bool Match(IMkvReader*, long long&, unsigned long, long long&); signed char Unserialize1SInt(IMkvReader*, long long);
bool Match(IMkvReader*, long long&, unsigned long, char*&); bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&); bool Match(IMkvReader*, long long&, unsigned long, char*&);
bool Match(IMkvReader*, long long&, unsigned long, double&); bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);
bool Match(IMkvReader*, long long&, unsigned long, short&); bool Match(IMkvReader*, long long&, unsigned long, double&);
bool Match(IMkvReader*, long long&, unsigned long, short&);
struct EBMLHeader
{ struct EBMLHeader
EBMLHeader(); {
~EBMLHeader(); EBMLHeader();
long long m_version; ~EBMLHeader();
long long m_readVersion; long long m_version;
long long m_maxIdLength; long long m_readVersion;
long long m_maxSizeLength; long long m_maxIdLength;
char* m_docType; long long m_maxSizeLength;
long long m_docTypeVersion; char* m_docType;
long long m_docTypeReadVersion; long long m_docTypeVersion;
long long m_docTypeReadVersion;
long long Parse(IMkvReader*, long long&);
}; long long Parse(IMkvReader*, long long&);
};
class Segment;
class Track; class Segment;
class Cluster; class Track;
class Cluster;
class Block
{ class Block
Block(const Block&); {
Block& operator=(const Block&); Block(const Block&);
Block& operator=(const Block&);
public:
const long long m_start; public:
const long long m_size; const long long m_start;
const long long m_size;
Block(long long start, long long size, IMkvReader*);
Block(long long start, long long size, IMkvReader*);
unsigned long GetTrackNumber() const;
unsigned long GetTrackNumber() const;
long long GetTimeCode(Cluster*) const; //absolute, but not scaled
long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units) long long GetTimeCode(Cluster*) const; //absolute, but not scaled
bool IsKey() const; long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units)
void SetKey(bool); bool IsKey() const;
void SetKey(bool);
long GetSize() const;
long Read(IMkvReader*, unsigned char*) const; long GetSize() const;
long Read(IMkvReader*, unsigned char*) const;
private:
long long m_track; //Track::Number() private:
short m_timecode; //relative to cluster long long m_track; //Track::Number()
unsigned char m_flags; short m_timecode; //relative to cluster
long long m_frameOff; unsigned char m_flags;
long m_frameSize; long long m_frameOff;
long m_frameSize;
};
};
class BlockEntry
{ class BlockEntry
BlockEntry(const BlockEntry&); {
BlockEntry& operator=(const BlockEntry&); BlockEntry(const BlockEntry&);
BlockEntry& operator=(const BlockEntry&);
public:
virtual ~BlockEntry(); public:
virtual bool EOS() const = 0; virtual ~BlockEntry();
virtual Cluster* GetCluster() const = 0; virtual bool EOS() const = 0;
virtual size_t GetIndex() const = 0; virtual Cluster* GetCluster() const = 0;
virtual const Block* GetBlock() const = 0; virtual size_t GetIndex() const = 0;
virtual bool IsBFrame() const = 0; virtual const Block* GetBlock() const = 0;
virtual bool IsBFrame() const = 0;
protected:
BlockEntry(); protected:
BlockEntry();
};
};
class SimpleBlock : public BlockEntry
{ class SimpleBlock : public BlockEntry
SimpleBlock(const SimpleBlock&); {
SimpleBlock& operator=(const SimpleBlock&); SimpleBlock(const SimpleBlock&);
SimpleBlock& operator=(const SimpleBlock&);
public:
SimpleBlock(Cluster*, size_t, long long start, long long size); public:
SimpleBlock(Cluster*, size_t, long long start, long long size);
bool EOS() const;
Cluster* GetCluster() const; bool EOS() const;
size_t GetIndex() const; Cluster* GetCluster() const;
const Block* GetBlock() const; size_t GetIndex() const;
bool IsBFrame() const; const Block* GetBlock() const;
bool IsBFrame() const;
protected:
Cluster* const m_pCluster; protected:
const size_t m_index; Cluster* const m_pCluster;
Block m_block; const size_t m_index;
Block m_block;
};
};
class BlockGroup : public BlockEntry
{ class BlockGroup : public BlockEntry
BlockGroup(const BlockGroup&); {
BlockGroup& operator=(const BlockGroup&); BlockGroup(const BlockGroup&);
BlockGroup& operator=(const BlockGroup&);
public:
BlockGroup(Cluster*, size_t, long long, long long); public:
~BlockGroup(); BlockGroup(Cluster*, size_t, long long, long long);
~BlockGroup();
bool EOS() const;
Cluster* GetCluster() const; bool EOS() const;
size_t GetIndex() const; Cluster* GetCluster() const;
const Block* GetBlock() const; size_t GetIndex() const;
bool IsBFrame() const; const Block* GetBlock() const;
bool IsBFrame() const;
short GetPrevTimeCode() const; //relative to block's time
short GetNextTimeCode() const; //as above short GetPrevTimeCode() const; //relative to block's time
short GetNextTimeCode() const; //as above
protected:
Cluster* const m_pCluster; protected:
const size_t m_index; Cluster* const m_pCluster;
const size_t m_index;
private:
BlockGroup(Cluster*, size_t, unsigned long); private:
void ParseBlock(long long start, long long size); BlockGroup(Cluster*, size_t, unsigned long);
void ParseBlock(long long start, long long size);
short m_prevTimeCode;
short m_nextTimeCode; short m_prevTimeCode;
short m_nextTimeCode;
//TODO: the Matroska spec says you can have multiple blocks within the
//same block group, with blocks ranked by priority (the flag bits). //TODO: the Matroska spec says you can have multiple blocks within the
//For now we just cache a single block. //same block group, with blocks ranked by priority (the flag bits).
#if 0 //For now we just cache a single block.
typedef std::deque<Block*> blocks_t; #if 0
blocks_t m_blocks; //In practice should contain only a single element. typedef std::deque<Block*> blocks_t;
#else blocks_t m_blocks; //In practice should contain only a single element.
Block* m_pBlock; #else
#endif Block* m_pBlock;
#endif
};
};
class Track
{ class Track
Track(const Track&); {
Track& operator=(const Track&); Track(const Track&);
Track& operator=(const Track&);
public:
Segment* const m_pSegment; public:
virtual ~Track(); Segment* const m_pSegment;
virtual ~Track();
long long GetType() const;
unsigned long GetNumber() const; long long GetType() const;
const char* GetNameAsUTF8() const; unsigned long GetNumber() const;
const char* GetCodecNameAsUTF8() const; const char* GetNameAsUTF8() const;
const char* GetCodecId() const; const char* GetCodecNameAsUTF8() const;
const unsigned char* GetCodecPrivate(size_t&) const; const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const;
const BlockEntry* GetEOS() const;
const BlockEntry* GetEOS() const;
struct Settings
{ struct Settings
long long start; {
long long size; long long start;
}; long long size;
};
struct Info
{ struct Info
long long type; {
long long number; long long type;
long long uid; long long number;
char* nameAsUTF8; long long uid;
char* codecId; char* nameAsUTF8;
unsigned char* codecPrivate; char* codecId;
size_t codecPrivateSize; unsigned char* codecPrivate;
char* codecNameAsUTF8; size_t codecPrivateSize;
Settings settings; char* codecNameAsUTF8;
Info(); Settings settings;
void Clear(); Info();
}; void Clear();
};
long GetFirst(const BlockEntry*&) const;
long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const; long GetFirst(const BlockEntry*&) const;
virtual bool VetEntry(const BlockEntry*) const = 0; long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
virtual bool VetEntry(const BlockEntry*) const = 0;
protected:
Track(Segment*, const Info&); protected:
const Info m_info; Track(Segment*, const Info&);
const Info m_info;
class EOSBlock : public BlockEntry
{ class EOSBlock : public BlockEntry
public: {
EOSBlock(); public:
EOSBlock();
bool EOS() const;
Cluster* GetCluster() const; bool EOS() const;
size_t GetIndex() const; Cluster* GetCluster() const;
const Block* GetBlock() const; size_t GetIndex() const;
bool IsBFrame() const; const Block* GetBlock() const;
}; bool IsBFrame() const;
};
EOSBlock m_eos;
EOSBlock m_eos;
};
};
class VideoTrack : public Track
{ class VideoTrack : public Track
VideoTrack(const VideoTrack&); {
VideoTrack& operator=(const VideoTrack&); VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
public:
VideoTrack(Segment*, const Info&); public:
long long GetWidth() const; VideoTrack(Segment*, const Info&);
long long GetHeight() const; long long GetWidth() const;
double GetFrameRate() const; long long GetHeight() const;
double GetFrameRate() const;
bool VetEntry(const BlockEntry*) const;
bool VetEntry(const BlockEntry*) const;
private:
long long m_width; private:
long long m_height; long long m_width;
double m_rate; long long m_height;
double m_rate;
};
};
class AudioTrack : public Track
{ class AudioTrack : public Track
AudioTrack(const AudioTrack&); {
AudioTrack& operator=(const AudioTrack&); AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&);
public:
AudioTrack(Segment*, const Info&); public:
double GetSamplingRate() const; AudioTrack(Segment*, const Info&);
long long GetChannels() const; double GetSamplingRate() const;
long long GetBitDepth() const; long long GetChannels() const;
bool VetEntry(const BlockEntry*) const; long long GetBitDepth() const;
bool VetEntry(const BlockEntry*) const;
private:
double m_rate; private:
long long m_channels; double m_rate;
long long m_bitDepth; long long m_channels;
}; long long m_bitDepth;
};
class Tracks
{ class Tracks
Tracks(const Tracks&); {
Tracks& operator=(const Tracks&); Tracks(const Tracks&);
Tracks& operator=(const Tracks&);
public:
Segment* const m_pSegment; public:
const long long m_start; Segment* const m_pSegment;
const long long m_size; const long long m_start;
const long long m_size;
Tracks(Segment*, long long start, long long size);
virtual ~Tracks(); Tracks(Segment*, long long start, long long size);
virtual ~Tracks();
Track* GetTrackByNumber(unsigned long tn) const;
Track* GetTrackByIndex(unsigned long idx) const; Track* GetTrackByNumber(unsigned long tn) const;
Track* GetTrackByIndex(unsigned long idx) const;
private:
Track** m_trackEntries; private:
Track** m_trackEntriesEnd; Track** m_trackEntries;
Track** m_trackEntriesEnd;
void ParseTrackEntry(long long, long long, Track*&);
void ParseTrackEntry(long long, long long, Track*&);
public:
unsigned long GetTracksCount() const; public:
}; unsigned long GetTracksCount() const;
};
class SegmentInfo
{ class SegmentInfo
SegmentInfo(const SegmentInfo&); {
SegmentInfo& operator=(const SegmentInfo&); SegmentInfo(const SegmentInfo&);
SegmentInfo& operator=(const SegmentInfo&);
public:
Segment* const m_pSegment; public:
const long long m_start; Segment* const m_pSegment;
const long long m_size; const long long m_start;
const long long m_size;
SegmentInfo(Segment*, long long start, long long size);
~SegmentInfo(); SegmentInfo(Segment*, long long start, long long size);
long long GetTimeCodeScale() const; ~SegmentInfo();
long long GetDuration() const; //scaled long long GetTimeCodeScale() const;
const char* GetMuxingAppAsUTF8() const; long long GetDuration() const; //scaled
const char* GetWritingAppAsUTF8() const; const char* GetMuxingAppAsUTF8() const;
const char* GetTitleAsUTF8() const; const char* GetWritingAppAsUTF8() const;
const char* GetTitleAsUTF8() const;
private:
long long m_timecodeScale; private:
double m_duration; long long m_timecodeScale;
char* m_pMuxingAppAsUTF8; double m_duration;
char* m_pWritingAppAsUTF8; char* m_pMuxingAppAsUTF8;
char* m_pTitleAsUTF8; char* m_pWritingAppAsUTF8;
}; char* m_pTitleAsUTF8;
};
class Cluster
{ class Cluster
Cluster(const Cluster&); {
Cluster& operator=(const Cluster&); Cluster(const Cluster&);
Cluster& operator=(const Cluster&);
public:
Segment* const m_pSegment; public:
const size_t m_index; Segment* const m_pSegment;
const size_t m_index;
public:
static Cluster* Parse(Segment*, size_t, long long off); public:
static Cluster* Parse(Segment*, size_t, long long off);
Cluster(); //EndOfStream
~Cluster(); Cluster(); //EndOfStream
~Cluster();
bool EOS() const;
bool EOS() const;
long long GetTimeCode(); //absolute, but not scaled
long long GetTime(); //absolute, and scaled (nanosecond units) long long GetTimeCode(); //absolute, but not scaled
long long GetTime(); //absolute, and scaled (nanosecond units)
const BlockEntry* GetFirst();
const BlockEntry* GetLast(); const BlockEntry* GetFirst();
const BlockEntry* GetNext(const BlockEntry*) const; const BlockEntry* GetLast();
const BlockEntry* GetEntry(const Track*); const BlockEntry* GetNext(const BlockEntry*) const;
protected: const BlockEntry* GetEntry(const Track*);
Cluster(Segment*, size_t, long long off); protected:
Cluster(Segment*, size_t, long long off);
private:
long long m_start; private:
long long m_size; long long m_start;
long long m_timecode; long long m_size;
BlockEntry** m_pEntries; long long m_timecode;
size_t m_entriesCount; BlockEntry** m_pEntries;
size_t m_entriesCount;
void Load();
void LoadBlockEntries(); void Load();
void ParseBlockGroup(long long, long long, size_t); void LoadBlockEntries();
void ParseSimpleBlock(long long, long long, size_t); void ParseBlockGroup(long long, long long, size_t);
void ParseSimpleBlock(long long, long long, size_t);
};
};
class Segment
{ class Segment
Segment(const Segment&); {
Segment& operator=(const Segment&); Segment(const Segment&);
Segment& operator=(const Segment&);
private:
Segment(IMkvReader*, long long pos, long long size); private:
Segment(IMkvReader*, long long pos, long long size);
public:
IMkvReader* const m_pReader; public:
const long long m_start; //posn of segment payload IMkvReader* const m_pReader;
const long long m_size; //size of segment payload const long long m_start; //posn of segment payload
Cluster m_eos; //TODO: make private? const long long m_size; //size of segment payload
Cluster m_eos; //TODO: make private?
static long long CreateInstance(IMkvReader*, long long, Segment*&);
~Segment(); static long long CreateInstance(IMkvReader*, long long, Segment*&);
~Segment();
//for big-bang loading (source filter)
long Load(); //for big-bang loading (source filter)
long Load();
//for incremental loading (splitter)
long long Unparsed() const; //for incremental loading (splitter)
long long ParseHeaders(); long long Unparsed() const;
long ParseCluster(Cluster*&, long long& newpos) const; long long ParseHeaders();
bool AddCluster(Cluster*, long long); long ParseCluster(Cluster*&, long long& newpos) const;
bool AddCluster(Cluster*, long long);
Tracks* GetTracks() const;
const SegmentInfo* const GetInfo() const; Tracks* GetTracks() const;
long long GetDuration() const; const SegmentInfo* const GetInfo() const;
long long GetDuration() const;
//NOTE: this turned out to be too inefficient.
//long long Load(long long time_nanoseconds); //NOTE: this turned out to be too inefficient.
//long long Load(long long time_nanoseconds);
Cluster* GetFirst();
Cluster* GetLast(); Cluster* GetFirst();
unsigned long GetCount() const; Cluster* GetLast();
unsigned long GetCount() const;
Cluster* GetNext(const Cluster*);
Cluster* GetCluster(long long time_nanoseconds); Cluster* GetNext(const Cluster*);
Cluster* GetCluster(long long time_nanoseconds);
private:
long long m_pos; //absolute file posn; what has been consumed so far private:
SegmentInfo* m_pInfo; long long m_pos; //absolute file posn; what has been consumed so far
Tracks* m_pTracks; SegmentInfo* m_pInfo;
Cluster** m_clusters; Tracks* m_pTracks;
size_t m_clusterCount; Cluster** m_clusters;
size_t m_clusterCount;
void ParseSeekHead(long long pos, long long size, size_t*);
void ParseSeekEntry(long long pos, long long size, size_t*); void ParseSeekHead(long long pos, long long size, size_t*);
void ParseSecondarySeekHead(long long off, size_t*); void ParseSeekEntry(long long pos, long long size, size_t*);
}; void ParseSecondarySeekHead(long long off, size_t*);
};
} //end namespace mkvparser
} //end namespace mkvparser
#endif //MKVPARSER_HPP
#endif //MKVPARSER_HPP

View File

@@ -1,122 +1,123 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved. // Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// //
// Use of this source code is governed by a BSD-style license and patent // Use of this source code is governed by a BSD-style license
// grant that can be found in the LICENSE file in the root of the source // that can be found in the LICENSE file in the root of the source
// tree. All contributing project authors may be found in the AUTHORS // tree. An additional intellectual property rights grant can be found
// file in the root of the source tree. // in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "mkvreader.hpp"
#include "mkvreader.hpp"
#include <cassert>
#include <cassert>
MkvReader::MkvReader() :
m_file(NULL) MkvReader::MkvReader() :
{ m_file(NULL)
} {
}
MkvReader::~MkvReader()
{ MkvReader::~MkvReader()
Close(); {
} Close();
}
int MkvReader::Open(const char* fileName)
{ int MkvReader::Open(const char* fileName)
if (fileName == NULL) {
return -1; if (fileName == NULL)
return -1;
if (m_file)
return -1; if (m_file)
return -1;
#ifdef WIN32
const errno_t e = fopen_s(&m_file, fileName, "rb"); #ifdef WIN32
const errno_t e = fopen_s(&m_file, fileName, "rb");
if (e)
return -1; //error if (e)
#else return -1; //error
m_file = fopen(fileName, "rb"); #else
m_file = fopen(fileName, "rb");
if (m_file == NULL)
return -1; if (m_file == NULL)
#endif return -1;
#endif
#ifdef WIN32
int status = _fseeki64(m_file, 0L, SEEK_END); #ifdef WIN32
int status = _fseeki64(m_file, 0L, SEEK_END);
if (status)
return -1; //error if (status)
return -1; //error
m_length = _ftelli64(m_file);
#else m_length = _ftelli64(m_file);
fseek(m_file, 0L, SEEK_END); #else
m_length = ftell(m_file); fseek(m_file, 0L, SEEK_END);
#endif m_length = ftell(m_file);
assert(m_length >= 0); #endif
assert(m_length >= 0);
#ifdef WIN32
status = _fseeki64(m_file, 0L, SEEK_SET); #ifdef WIN32
status = _fseeki64(m_file, 0L, SEEK_SET);
if (status)
return -1; //error if (status)
#else return -1; //error
fseek(m_file, 0L, SEEK_SET); #else
#endif fseek(m_file, 0L, SEEK_SET);
#endif
return 0;
} return 0;
}
void MkvReader::Close()
{ void MkvReader::Close()
if (m_file != NULL) {
{ if (m_file != NULL)
fclose(m_file); {
m_file = NULL; fclose(m_file);
} m_file = NULL;
} }
}
int MkvReader::Length(long long* total, long long* available)
{ int MkvReader::Length(long long* total, long long* available)
if (m_file == NULL) {
return -1; if (m_file == NULL)
return -1;
if (total)
*total = m_length; if (total)
*total = m_length;
if (available)
*available = m_length; if (available)
*available = m_length;
return 0;
} return 0;
}
int MkvReader::Read(long long offset, long len, unsigned char* buffer)
{ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
if (m_file == NULL) {
return -1; if (m_file == NULL)
return -1;
if (offset < 0)
return -1; if (offset < 0)
return -1;
if (len < 0)
return -1; if (len < 0)
return -1;
if (len == 0)
return 0; if (len == 0)
return 0;
if (offset >= m_length)
return -1; if (offset >= m_length)
return -1;
#ifdef WIN32
const int status = _fseeki64(m_file, offset, SEEK_SET); #ifdef WIN32
const int status = _fseeki64(m_file, offset, SEEK_SET);
if (status)
return -1; //error if (status)
#else return -1; //error
fseek(m_file, offset, SEEK_SET); #else
#endif fseek(m_file, offset, SEEK_SET);
#endif
const size_t size = fread(buffer, 1, len, m_file);
const size_t size = fread(buffer, 1, len, m_file);
if (size < size_t(len))
return -1; //error if (size < size_t(len))
return -1; //error
return 0; //success
} return 0; //success
}

View File

@@ -1,33 +1,34 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved. // Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// //
// Use of this source code is governed by a BSD-style license and patent // Use of this source code is governed by a BSD-style license
// grant that can be found in the LICENSE file in the root of the source // that can be found in the LICENSE file in the root of the source
// tree. All contributing project authors may be found in the AUTHORS // tree. An additional intellectual property rights grant can be found
// file in the root of the source tree. // in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef MKVREADER_HPP
#define MKVREADER_HPP #ifndef MKVREADER_HPP
#define MKVREADER_HPP
#include "mkvparser.hpp"
#include <cstdio> #include "mkvparser.hpp"
#include <cstdio>
class MkvReader : public mkvparser::IMkvReader
{ class MkvReader : public mkvparser::IMkvReader
MkvReader(const MkvReader&); {
MkvReader& operator=(const MkvReader&); MkvReader(const MkvReader&);
public: MkvReader& operator=(const MkvReader&);
MkvReader(); public:
virtual ~MkvReader(); MkvReader();
virtual ~MkvReader();
int Open(const char*);
void Close(); int Open(const char*);
bool IsOpen() const; void Close();
bool IsOpen() const;
virtual int Read(long long position, long length, unsigned char* buffer);
virtual int Length(long long* total, long long* available); virtual int Read(long long position, long length, unsigned char* buffer);
private: virtual int Length(long long* total, long long* available);
long long m_length; private:
FILE* m_file; long long m_length;
}; FILE* m_file;
};
#endif //MKVREADER_HPP
#endif //MKVREADER_HPP

View File

@@ -1,236 +1,237 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved. // Copyright (c) 2010 The WebM project authors. All Rights Reserved.
// //
// Use of this source code is governed by a BSD-style license and patent // Use of this source code is governed by a BSD-style license
// grant that can be found in the LICENSE file in the root of the source // that can be found in the LICENSE file in the root of the source
// tree. All contributing project authors may be found in the AUTHORS // tree. An additional intellectual property rights grant can be found
// file in the root of the source tree. // in the file PATENTS. All contributing project authors may
// // be found in the AUTHORS file in the root of the source tree.
// This sample application is designed to help clients understand how to use //
// mkvparser library. // This sample application is designed to help clients understand how to use
// By using the mkvparser lib clients are able to handle a matroska format file. // mkvparser library.
// By using the mkvparser lib clients are able to handle a matroska format file.
#include "mkvreader.hpp"
#include "mkvparser.hpp" #include "mkvreader.hpp"
#include "mkvparser.hpp"
static const wchar_t* utf8towcs(const char* str)
{ static const wchar_t* utf8towcs(const char* str)
if (str == NULL) {
return NULL; if (str == NULL)
return NULL;
//TODO: this probably requires that the locale be
//configured somehow: //TODO: this probably requires that the locale be
//configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL; if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size+1];
wchar_t* const val = new wchar_t[size+1];
mbstowcs(val, str, size);
val[size] = L'\0'; mbstowcs(val, str, size);
val[size] = L'\0';
return val;
} return val;
}
int main(int argc, char* argv[])
{ int main(int argc, char* argv[])
if (argc == 1) {
{ if (argc == 1)
printf("\t\t\tMkv Parser Sample Application\n"); {
printf("\t\t\tUsage: \n"); printf("\t\t\tMkv Parser Sample Application\n");
printf("\t\t\t ./sample [input file] \n"); printf("\t\t\tUsage: \n");
printf("\t\t\t ./sample sample.mkv \n"); printf("\t\t\t ./sample [input file] \n");
return -1; printf("\t\t\t ./sample sample.mkv \n");
} return -1;
}
using namespace mkvparser;
using namespace mkvparser;
MkvReader reader;
MkvReader reader;
if (reader.Open(argv[1]))
{ if (reader.Open(argv[1]))
printf("\n Filename is invalid or error while opening.\n"); {
return -1; printf("\n Filename is invalid or error while opening.\n");
} return -1;
}
long long pos = 0;
long long pos = 0;
EBMLHeader ebmlHeader;
EBMLHeader ebmlHeader;
ebmlHeader.Parse(&reader, pos);
ebmlHeader.Parse(&reader, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version); printf("\t\t\t EBML Header\n");
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength); printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength); printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType); printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tPos\t\t\t: %lld\n", pos); printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
mkvparser::Segment* pSegment;
mkvparser::Segment* pSegment;
long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
if (ret) long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
{ if (ret)
printf("\n Segment::CreateInstance() failed."); {
return -1; printf("\n Segment::CreateInstance() failed.");
} return -1;
}
ret = pSegment->Load();
if (ret < 0) ret = pSegment->Load();
{ if (ret < 0)
printf("\n Segment::Load() failed."); {
return -1; printf("\n Segment::Load() failed.");
} return -1;
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration(); const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const wchar_t* const pTitle = utf8towcs(pSegmentInfo->GetTitleAsUTF8()); const long long duration_ns = pSegmentInfo->GetDuration();
const wchar_t* const pMuxingApp = utf8towcs(pSegmentInfo->GetMuxingAppAsUTF8()); const wchar_t* const pTitle = utf8towcs(pSegmentInfo->GetTitleAsUTF8());
const wchar_t* const pWritingApp = utf8towcs(pSegmentInfo->GetWritingAppAsUTF8()); const wchar_t* const pMuxingApp = utf8towcs(pSegmentInfo->GetMuxingAppAsUTF8());
const wchar_t* const pWritingApp = utf8towcs(pSegmentInfo->GetWritingAppAsUTF8());
printf("\n");
printf("\t\t\t Segment Info\n"); printf("\n");
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale); printf("\t\t\t Segment Info\n");
printf("\t\tDuration\t\t: %lld\n", duration_ns); printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
printf("\t\tDuration\t\t: %lld\n", duration_ns);
const double duration_sec = double(duration_ns) / 1000000000;
printf("\t\tDuration(secs)\t\t: %7.3f\n", duration_sec); const double duration_sec = double(duration_ns) / 1000000000;
printf("\t\tDuration(secs)\t\t: %7.3f\n", duration_sec);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n"); if (pTitle == NULL)
else printf("\t\tTrack Name\t\t: NULL\n");
printf("\t\tTrack Name\t\t: %ls\n", pTitle); else
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n"); if (pMuxingApp == NULL)
else printf("\t\tMuxing App\t\t: NULL\n");
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp); else
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n"); if (pWritingApp == NULL)
else printf("\t\tWriting App\t\t: NULL\n");
printf("\t\tWriting App\t\t: %ls\n", pWritingApp); else
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start); // position of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size); // size of segment payload printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start); // position of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size); // size of segment payload
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount(); unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount();
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
printf("\n\t\t\t Track Info\n");
printf("\n\t\t\t Track Info\n");
while (i != j)
{ while (i != j)
const Track* const pTrack = pTracks->GetTrackByIndex(i++); {
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
if (pTrack == NULL)
continue; if (pTrack == NULL)
continue;
const long long trackType_ = pTrack->GetType();
unsigned long trackType = static_cast<unsigned long>(trackType_); const long long trackType_ = pTrack->GetType();
unsigned long trackType = static_cast<unsigned long>(trackType_);
unsigned long trackNumber = pTrack->GetNumber();
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8()); unsigned long trackNumber = pTrack->GetNumber();
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
printf("\t\tTrack Type\t\t: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber); printf("\t\tTrack Type\t\t: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
if (pTrackName == NULL)
printf("\t\tTrack Name\t\t: NULL\n"); if (pTrackName == NULL)
else printf("\t\tTrack Name\t\t: NULL\n");
printf("\t\tTrack Name\t\t: %ls \n", pTrackName); else
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
const char* const pCodecId = pTrack->GetCodecId();
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n"); if (pCodecId == NULL)
else printf("\t\tCodec Id\t\t: NULL\n");
printf("\t\tCodec Id\t\t: %s\n", pCodecId); else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const wchar_t* const pCodecName = utf8towcs(pTrack->GetCodecNameAsUTF8());
const wchar_t* const pCodecName = utf8towcs(pTrack->GetCodecNameAsUTF8());
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n"); if (pCodecName == NULL)
else printf("\t\tCodec Name\t\t: NULL\n");
printf("\t\tCodec Name\t\t: %ls\n", pCodecName); else
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
if (trackType == VIDEO_TRACK)
{ if (trackType == VIDEO_TRACK)
const VideoTrack* const pVideoTrack = static_cast<const VideoTrack* const>(pTrack); {
long long width = pVideoTrack->GetWidth(); const VideoTrack* const pVideoTrack = static_cast<const VideoTrack* const>(pTrack);
long long height = pVideoTrack->GetHeight(); long long width = pVideoTrack->GetWidth();
double rate = pVideoTrack->GetFrameRate(); long long height = pVideoTrack->GetHeight();
double rate = pVideoTrack->GetFrameRate();
printf("\t\tVideo Width\t\t: %lld\n", width);
printf("\t\tVideo Height\t\t: %lld\n", height); printf("\t\tVideo Width\t\t: %lld\n", width);
printf("\t\tVideo Rate\t\t: %f\n",rate); printf("\t\tVideo Height\t\t: %lld\n", height);
} printf("\t\tVideo Rate\t\t: %f\n",rate);
}
if (trackType == AUDIO_TRACK)
{ if (trackType == AUDIO_TRACK)
const AudioTrack* const pAudioTrack = static_cast<const AudioTrack* const>(pTrack); {
long long channels = pAudioTrack->GetChannels(); const AudioTrack* const pAudioTrack = static_cast<const AudioTrack* const>(pTrack);
long long bitDepth = pAudioTrack->GetBitDepth(); long long channels = pAudioTrack->GetChannels();
double sampleRate = pAudioTrack->GetSamplingRate(); long long bitDepth = pAudioTrack->GetBitDepth();
double sampleRate = pAudioTrack->GetSamplingRate();
printf("\t\tAudio Channels\t\t: %lld\n", channels);
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth); printf("\t\tAudio Channels\t\t: %lld\n", channels);
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate); printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
} printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
} }
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount(); printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{ if (clusterCount == 0)
printf("\t\tSegment has no clusters.\n"); {
delete pSegment; printf("\t\tSegment has no clusters.\n");
return -1; delete pSegment;
} return -1;
}
mkvparser::Cluster* pCluster = pSegment->GetFirst();
mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{ while ((pCluster != NULL) && !pCluster->EOS())
const long long timeCode = pCluster->GetTimeCode(); {
printf("\t\tCluster Time Code\t: %lld\n", timeCode); const long long timeCode = pCluster->GetTimeCode();
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns); const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
const BlockEntry* pBlockEntry = pCluster->GetFirst();
const BlockEntry* pBlockEntry = pCluster->GetFirst();
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{ while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
const Block* const pBlock = pBlockEntry->GetBlock(); {
const unsigned long trackNum = pBlock->GetTrackNumber(); const Block* const pBlock = pBlockEntry->GetBlock();
const long size = pBlock->GetSize(); const unsigned long trackNum = pBlock->GetTrackNumber();
const long long time_ns = pBlock->GetTime(pCluster); const long size = pBlock->GetSize();
const long long time_ns = pBlock->GetTime(pCluster);
printf("\t\t\tBlock\t\t:%s,%15ld,%s,%15lld\n",
(trackNum == VIDEO_TRACK) ? "V" : "A", printf("\t\t\tBlock\t\t:%s,%15ld,%s,%15lld\n",
size, (trackNum == VIDEO_TRACK) ? "V" : "A",
pBlock->IsKey() ? "I" : "P", size,
time_ns); pBlock->IsKey() ? "I" : "P",
time_ns);
pBlockEntry = pCluster->GetNext(pBlockEntry);
} pBlockEntry = pCluster->GetNext(pBlockEntry);
}
pCluster = pSegment->GetNext(pCluster);
} pCluster = pSegment->GetNext(pCluster);
}
delete pSegment;
return 0; delete pSegment;
return 0;
}
}