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.
//
// Use of this source code is governed by a BSD-style license and patent
// grant 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
// file in the root of the source tree.
#ifndef MKVPARSER_HPP
#define MKVPARSER_HPP
#include <cstdlib>
#include <cstdio>
namespace mkvparser
{
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;
class IMkvReader
{
public:
virtual int Read(long long position, long length, unsigned char* buffer) = 0;
virtual int Length(long long* total, long long* available) = 0;
protected:
virtual ~IMkvReader();
};
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
long long UnserializeUInt(IMkvReader*, long long pos, long long size);
float Unserialize4Float(IMkvReader*, long long);
double Unserialize8Double(IMkvReader*, long long);
short Unserialize2SInt(IMkvReader*, long long);
signed char Unserialize1SInt(IMkvReader*, long long);
bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, char*&);
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);
bool Match(IMkvReader*, long long&, unsigned long, double&);
bool Match(IMkvReader*, long long&, unsigned long, short&);
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&);
};
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, IMkvReader*);
unsigned long GetTrackNumber() const;
long long GetTimeCode(Cluster*) const; //absolute, but not scaled
long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units)
bool IsKey() const;
void SetKey(bool);
long GetSize() const;
long Read(IMkvReader*, unsigned char*) const;
private:
long long m_track; //Track::Number()
short m_timecode; //relative to cluster
unsigned char m_flags;
long long m_frameOff;
long m_frameSize;
};
class BlockEntry
{
BlockEntry(const BlockEntry&);
BlockEntry& operator=(const BlockEntry&);
public:
virtual ~BlockEntry();
virtual bool EOS() const = 0;
virtual Cluster* GetCluster() const = 0;
virtual size_t GetIndex() const = 0;
virtual const Block* GetBlock() const = 0;
virtual bool IsBFrame() const = 0;
protected:
BlockEntry();
};
class SimpleBlock : public BlockEntry
{
SimpleBlock(const SimpleBlock&);
SimpleBlock& operator=(const SimpleBlock&);
public:
SimpleBlock(Cluster*, size_t, long long start, long long size);
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
protected:
Cluster* const m_pCluster;
const size_t m_index;
Block m_block;
};
class BlockGroup : public BlockEntry
{
BlockGroup(const BlockGroup&);
BlockGroup& operator=(const BlockGroup&);
public:
BlockGroup(Cluster*, size_t, long long, long long);
~BlockGroup();
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
short GetPrevTimeCode() const; //relative to block's time
short GetNextTimeCode() const; //as above
protected:
Cluster* const m_pCluster;
const size_t m_index;
private:
BlockGroup(Cluster*, size_t, unsigned long);
void ParseBlock(long long start, long long size);
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).
//For now we just cache a single block.
#if 0
typedef std::deque<Block*> blocks_t;
blocks_t m_blocks; //In practice should contain only a single element.
#else
Block* m_pBlock;
#endif
};
class Track
{
Track(const Track&);
Track& operator=(const Track&);
public:
Segment* const m_pSegment;
virtual ~Track();
long long GetType() const;
unsigned long GetNumber() const;
const char* GetNameAsUTF8() const;
const char* GetCodecNameAsUTF8() const;
const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const;
const BlockEntry* GetEOS() const;
struct Settings
{
long long start;
long long size;
};
struct Info
{
long long type;
long long number;
long long uid;
char* nameAsUTF8;
char* codecId;
unsigned char* codecPrivate;
size_t codecPrivateSize;
char* codecNameAsUTF8;
Settings settings;
Info();
void Clear();
};
long GetFirst(const BlockEntry*&) const;
long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
virtual bool VetEntry(const BlockEntry*) const = 0;
protected:
Track(Segment*, const Info&);
const Info m_info;
class EOSBlock : public BlockEntry
{
public:
EOSBlock();
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
};
EOSBlock m_eos;
};
class VideoTrack : public Track
{
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
public:
VideoTrack(Segment*, const Info&);
long long GetWidth() const;
long long GetHeight() const;
double GetFrameRate() const;
bool VetEntry(const BlockEntry*) const;
private:
long long m_width;
long long m_height;
double m_rate;
};
class AudioTrack : public Track
{
AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&);
public:
AudioTrack(Segment*, const Info&);
double GetSamplingRate() const;
long long GetChannels() const;
long long GetBitDepth() const;
bool VetEntry(const BlockEntry*) 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;
Tracks(Segment*, long long start, long long size);
virtual ~Tracks();
Track* GetTrackByNumber(unsigned long tn) const;
Track* GetTrackByIndex(unsigned long idx) const;
private:
Track** m_trackEntries;
Track** m_trackEntriesEnd;
void ParseTrackEntry(long long, long long, Track*&);
public:
unsigned long GetTracksCount() const;
};
class SegmentInfo
{
SegmentInfo(const SegmentInfo&);
SegmentInfo& operator=(const SegmentInfo&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
SegmentInfo(Segment*, long long start, long long size);
~SegmentInfo();
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 Cluster
{
Cluster(const Cluster&);
Cluster& operator=(const Cluster&);
public:
Segment* const m_pSegment;
const size_t m_index;
public:
static Cluster* Parse(Segment*, size_t, long long off);
Cluster(); //EndOfStream
~Cluster();
bool EOS() const;
long long GetTimeCode(); //absolute, but not scaled
long long GetTime(); //absolute, and scaled (nanosecond units)
const BlockEntry* GetFirst();
const BlockEntry* GetLast();
const BlockEntry* GetNext(const BlockEntry*) const;
const BlockEntry* GetEntry(const Track*);
protected:
Cluster(Segment*, size_t, long long off);
private:
long long m_start;
long long m_size;
long long m_timecode;
BlockEntry** m_pEntries;
size_t m_entriesCount;
void Load();
void LoadBlockEntries();
void ParseBlockGroup(long long, long long, size_t);
void ParseSimpleBlock(long long, long long, size_t);
};
class Segment
{
Segment(const Segment&);
Segment& operator=(const Segment&);
private:
Segment(IMkvReader*, long long pos, long long size);
public:
IMkvReader* const m_pReader;
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();
//for big-bang loading (source filter)
long Load();
//for incremental loading (splitter)
long long Unparsed() const;
long long ParseHeaders();
long ParseCluster(Cluster*&, long long& newpos) const;
bool AddCluster(Cluster*, long long);
Tracks* GetTracks() 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);
Cluster* GetFirst();
Cluster* GetLast();
unsigned long GetCount() const;
Cluster* GetNext(const Cluster*);
Cluster* GetCluster(long long time_nanoseconds);
private:
long long m_pos; //absolute file posn; what has been consumed so far
SegmentInfo* m_pInfo;
Tracks* m_pTracks;
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 ParseSecondarySeekHead(long long off, size_t*);
};
} //end namespace mkvparser
#endif //MKVPARSER_HPP
// Copyright (c) 2010 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_HPP
#define MKVPARSER_HPP
#include <cstdlib>
#include <cstdio>
namespace mkvparser
{
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;
class IMkvReader
{
public:
virtual int Read(long long position, long length, unsigned char* buffer) = 0;
virtual int Length(long long* total, long long* available) = 0;
protected:
virtual ~IMkvReader();
};
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
long long UnserializeUInt(IMkvReader*, long long pos, long long size);
float Unserialize4Float(IMkvReader*, long long);
double Unserialize8Double(IMkvReader*, long long);
short Unserialize2SInt(IMkvReader*, long long);
signed char Unserialize1SInt(IMkvReader*, long long);
bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, char*&);
bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&, size_t&);
bool Match(IMkvReader*, long long&, unsigned long, double&);
bool Match(IMkvReader*, long long&, unsigned long, short&);
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&);
};
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, IMkvReader*);
unsigned long GetTrackNumber() const;
long long GetTimeCode(Cluster*) const; //absolute, but not scaled
long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units)
bool IsKey() const;
void SetKey(bool);
long GetSize() const;
long Read(IMkvReader*, unsigned char*) const;
private:
long long m_track; //Track::Number()
short m_timecode; //relative to cluster
unsigned char m_flags;
long long m_frameOff;
long m_frameSize;
};
class BlockEntry
{
BlockEntry(const BlockEntry&);
BlockEntry& operator=(const BlockEntry&);
public:
virtual ~BlockEntry();
virtual bool EOS() const = 0;
virtual Cluster* GetCluster() const = 0;
virtual size_t GetIndex() const = 0;
virtual const Block* GetBlock() const = 0;
virtual bool IsBFrame() const = 0;
protected:
BlockEntry();
};
class SimpleBlock : public BlockEntry
{
SimpleBlock(const SimpleBlock&);
SimpleBlock& operator=(const SimpleBlock&);
public:
SimpleBlock(Cluster*, size_t, long long start, long long size);
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
protected:
Cluster* const m_pCluster;
const size_t m_index;
Block m_block;
};
class BlockGroup : public BlockEntry
{
BlockGroup(const BlockGroup&);
BlockGroup& operator=(const BlockGroup&);
public:
BlockGroup(Cluster*, size_t, long long, long long);
~BlockGroup();
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
short GetPrevTimeCode() const; //relative to block's time
short GetNextTimeCode() const; //as above
protected:
Cluster* const m_pCluster;
const size_t m_index;
private:
BlockGroup(Cluster*, size_t, unsigned long);
void ParseBlock(long long start, long long size);
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).
//For now we just cache a single block.
#if 0
typedef std::deque<Block*> blocks_t;
blocks_t m_blocks; //In practice should contain only a single element.
#else
Block* m_pBlock;
#endif
};
class Track
{
Track(const Track&);
Track& operator=(const Track&);
public:
Segment* const m_pSegment;
virtual ~Track();
long long GetType() const;
unsigned long GetNumber() const;
const char* GetNameAsUTF8() const;
const char* GetCodecNameAsUTF8() const;
const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const;
const BlockEntry* GetEOS() const;
struct Settings
{
long long start;
long long size;
};
struct Info
{
long long type;
long long number;
long long uid;
char* nameAsUTF8;
char* codecId;
unsigned char* codecPrivate;
size_t codecPrivateSize;
char* codecNameAsUTF8;
Settings settings;
Info();
void Clear();
};
long GetFirst(const BlockEntry*&) const;
long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
virtual bool VetEntry(const BlockEntry*) const = 0;
protected:
Track(Segment*, const Info&);
const Info m_info;
class EOSBlock : public BlockEntry
{
public:
EOSBlock();
bool EOS() const;
Cluster* GetCluster() const;
size_t GetIndex() const;
const Block* GetBlock() const;
bool IsBFrame() const;
};
EOSBlock m_eos;
};
class VideoTrack : public Track
{
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
public:
VideoTrack(Segment*, const Info&);
long long GetWidth() const;
long long GetHeight() const;
double GetFrameRate() const;
bool VetEntry(const BlockEntry*) const;
private:
long long m_width;
long long m_height;
double m_rate;
};
class AudioTrack : public Track
{
AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&);
public:
AudioTrack(Segment*, const Info&);
double GetSamplingRate() const;
long long GetChannels() const;
long long GetBitDepth() const;
bool VetEntry(const BlockEntry*) 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;
Tracks(Segment*, long long start, long long size);
virtual ~Tracks();
Track* GetTrackByNumber(unsigned long tn) const;
Track* GetTrackByIndex(unsigned long idx) const;
private:
Track** m_trackEntries;
Track** m_trackEntriesEnd;
void ParseTrackEntry(long long, long long, Track*&);
public:
unsigned long GetTracksCount() const;
};
class SegmentInfo
{
SegmentInfo(const SegmentInfo&);
SegmentInfo& operator=(const SegmentInfo&);
public:
Segment* const m_pSegment;
const long long m_start;
const long long m_size;
SegmentInfo(Segment*, long long start, long long size);
~SegmentInfo();
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 Cluster
{
Cluster(const Cluster&);
Cluster& operator=(const Cluster&);
public:
Segment* const m_pSegment;
const size_t m_index;
public:
static Cluster* Parse(Segment*, size_t, long long off);
Cluster(); //EndOfStream
~Cluster();
bool EOS() const;
long long GetTimeCode(); //absolute, but not scaled
long long GetTime(); //absolute, and scaled (nanosecond units)
const BlockEntry* GetFirst();
const BlockEntry* GetLast();
const BlockEntry* GetNext(const BlockEntry*) const;
const BlockEntry* GetEntry(const Track*);
protected:
Cluster(Segment*, size_t, long long off);
private:
long long m_start;
long long m_size;
long long m_timecode;
BlockEntry** m_pEntries;
size_t m_entriesCount;
void Load();
void LoadBlockEntries();
void ParseBlockGroup(long long, long long, size_t);
void ParseSimpleBlock(long long, long long, size_t);
};
class Segment
{
Segment(const Segment&);
Segment& operator=(const Segment&);
private:
Segment(IMkvReader*, long long pos, long long size);
public:
IMkvReader* const m_pReader;
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();
//for big-bang loading (source filter)
long Load();
//for incremental loading (splitter)
long long Unparsed() const;
long long ParseHeaders();
long ParseCluster(Cluster*&, long long& newpos) const;
bool AddCluster(Cluster*, long long);
Tracks* GetTracks() 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);
Cluster* GetFirst();
Cluster* GetLast();
unsigned long GetCount() const;
Cluster* GetNext(const Cluster*);
Cluster* GetCluster(long long time_nanoseconds);
private:
long long m_pos; //absolute file posn; what has been consumed so far
SegmentInfo* m_pInfo;
Tracks* m_pTracks;
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 ParseSecondarySeekHead(long long off, size_t*);
};
} //end namespace mkvparser
#endif //MKVPARSER_HPP

View File

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

View File

@ -1,33 +1,34 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license and patent
// grant 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
// file in the root of the source tree.
#ifndef MKVREADER_HPP
#define MKVREADER_HPP
#include "mkvparser.hpp"
#include <cstdio>
class MkvReader : public mkvparser::IMkvReader
{
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
public:
MkvReader();
virtual ~MkvReader();
int Open(const char*);
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);
private:
long long m_length;
FILE* m_file;
};
#endif //MKVREADER_HPP
// Copyright (c) 2010 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 MKVREADER_HPP
#define MKVREADER_HPP
#include "mkvparser.hpp"
#include <cstdio>
class MkvReader : public mkvparser::IMkvReader
{
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
public:
MkvReader();
virtual ~MkvReader();
int Open(const char*);
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);
private:
long long m_length;
FILE* m_file;
};
#endif //MKVREADER_HPP

View File

@ -1,236 +1,237 @@
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license and patent
// grant 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
// file in the root of the source tree.
//
// This sample application is designed to help clients understand how to use
// mkvparser library.
// By using the mkvparser lib clients are able to handle a matroska format file.
#include "mkvreader.hpp"
#include "mkvparser.hpp"
static const wchar_t* utf8towcs(const char* str)
{
if (str == NULL)
return NULL;
//TODO: this probably requires that the locale be
//configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size+1];
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
int main(int argc, char* argv[])
{
if (argc == 1)
{
printf("\t\t\tMkv Parser Sample Application\n");
printf("\t\t\tUsage: \n");
printf("\t\t\t ./sample [input file] \n");
printf("\t\t\t ./sample sample.mkv \n");
return -1;
}
using namespace mkvparser;
MkvReader reader;
if (reader.Open(argv[1]))
{
printf("\n Filename is invalid or error while opening.\n");
return -1;
}
long long pos = 0;
EBMLHeader ebmlHeader;
ebmlHeader.Parse(&reader, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
mkvparser::Segment* pSegment;
long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
if (ret)
{
printf("\n Segment::CreateInstance() failed.");
return -1;
}
ret = pSegment->Load();
if (ret < 0)
{
printf("\n Segment::Load() failed.");
return -1;
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const wchar_t* const pTitle = utf8towcs(pSegmentInfo->GetTitleAsUTF8());
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("\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);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
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
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount();
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
printf("\n\t\t\t Track Info\n");
while (i != j)
{
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
if (pTrack == NULL)
continue;
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());
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");
else
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const wchar_t* const pCodecName = utf8towcs(pTrack->GetCodecNameAsUTF8());
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
if (trackType == VIDEO_TRACK)
{
const VideoTrack* const pVideoTrack = static_cast<const VideoTrack* const>(pTrack);
long long width = pVideoTrack->GetWidth();
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 Rate\t\t: %f\n",rate);
}
if (trackType == AUDIO_TRACK)
{
const AudioTrack* const pAudioTrack = static_cast<const AudioTrack* const>(pTrack);
long long channels = pAudioTrack->GetChannels();
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\tAddio Sample Rate\t: %.3f\n", sampleRate);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
delete pSegment;
return -1;
}
mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{
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 BlockEntry* pBlockEntry = pCluster->GetFirst();
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
const Block* const pBlock = pBlockEntry->GetBlock();
const unsigned long trackNum = pBlock->GetTrackNumber();
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",
size,
pBlock->IsKey() ? "I" : "P",
time_ns);
pBlockEntry = pCluster->GetNext(pBlockEntry);
}
pCluster = pSegment->GetNext(pCluster);
}
delete pSegment;
return 0;
}
// Copyright (c) 2010 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.
//
// This sample application is designed to help clients understand how to use
// mkvparser library.
// By using the mkvparser lib clients are able to handle a matroska format file.
#include "mkvreader.hpp"
#include "mkvparser.hpp"
static const wchar_t* utf8towcs(const char* str)
{
if (str == NULL)
return NULL;
//TODO: this probably requires that the locale be
//configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size+1];
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
int main(int argc, char* argv[])
{
if (argc == 1)
{
printf("\t\t\tMkv Parser Sample Application\n");
printf("\t\t\tUsage: \n");
printf("\t\t\t ./sample [input file] \n");
printf("\t\t\t ./sample sample.mkv \n");
return -1;
}
using namespace mkvparser;
MkvReader reader;
if (reader.Open(argv[1]))
{
printf("\n Filename is invalid or error while opening.\n");
return -1;
}
long long pos = 0;
EBMLHeader ebmlHeader;
ebmlHeader.Parse(&reader, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
mkvparser::Segment* pSegment;
long long ret = mkvparser::Segment::CreateInstance(&reader, pos, pSegment);
if (ret)
{
printf("\n Segment::CreateInstance() failed.");
return -1;
}
ret = pSegment->Load();
if (ret < 0)
{
printf("\n Segment::Load() failed.");
return -1;
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const wchar_t* const pTitle = utf8towcs(pSegmentInfo->GetTitleAsUTF8());
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("\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);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
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
mkvparser::Tracks* const pTracks = pSegment->GetTracks();
unsigned long i = 0;
const unsigned long j = pTracks->GetTracksCount();
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
printf("\n\t\t\t Track Info\n");
while (i != j)
{
const Track* const pTrack = pTracks->GetTrackByIndex(i++);
if (pTrack == NULL)
continue;
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());
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");
else
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const wchar_t* const pCodecName = utf8towcs(pTrack->GetCodecNameAsUTF8());
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
if (trackType == VIDEO_TRACK)
{
const VideoTrack* const pVideoTrack = static_cast<const VideoTrack* const>(pTrack);
long long width = pVideoTrack->GetWidth();
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 Rate\t\t: %f\n",rate);
}
if (trackType == AUDIO_TRACK)
{
const AudioTrack* const pAudioTrack = static_cast<const AudioTrack* const>(pTrack);
long long channels = pAudioTrack->GetChannels();
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\tAddio Sample Rate\t: %.3f\n", sampleRate);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
delete pSegment;
return -1;
}
mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{
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 BlockEntry* pBlockEntry = pCluster->GetFirst();
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
const Block* const pBlock = pBlockEntry->GetBlock();
const unsigned long trackNum = pBlock->GetTrackNumber();
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",
size,
pBlock->IsKey() ? "I" : "P",
time_ns);
pBlockEntry = pCluster->GetNext(pBlockEntry);
}
pCluster = pSegment->GetNext(pCluster);
}
delete pSegment;
return 0;
}