Browse Source

Rewrite TrackMgr

Also:
Do not start the video again if it is already playing.
Update files from libwebm
Florian Meißner 10 years ago
parent
commit
2d990ae3e8
  1. 107
      Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp
  2. 2937
      Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvparser.cpp
  3. 339
      Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvparser.hpp
  4. 52
      Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvreader.cpp
  5. 20
      Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvreader.hpp

107
Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp

@ -120,81 +120,48 @@ public:
class TrackMgr class TrackMgr
{ {
const mkvparser::BlockEntry* blk_entry; protected:
bool valid; const mkvparser::Track* fTrack;
const mkvparser::BlockEntry* fCurrentBlock;
bool PeekNextBlockEntry(const std::unique_ptr<mkvparser::Segment>& segment) int32_t fStatus;
{
// Assume that if blk_entry == nullptr, we need to start from the beginning
// Load the current cluster
const mkvparser::Cluster* cluster;
if (blk_entry)
cluster = blk_entry->GetCluster();
else
cluster = segment->GetFirst();
// As long as we have clusters, they contain blocks that we have to process
while (cluster && !cluster->EOS()) {
// If we have no block yet, get the first one, otherwise the next one
if (!blk_entry)
{
SAFE_OP(cluster->GetFirst(blk_entry), "get first block");
}
else
{
SAFE_OP(cluster->GetNext(blk_entry, blk_entry), "get next block");
}
// Are there any blocks left?
while (blk_entry && !blk_entry->EOS()) {
// Is this the next block we want for our track? Awesome, we're done!
if (blk_entry->GetBlock()->GetTrackNumber() == number)
return true;
SAFE_OP(cluster->GetNext(blk_entry, blk_entry), "get next block");
}
// No blocks left, go to next cluster
blk_entry = nullptr;
cluster = segment->GetNext(cluster);
}
// That's it, nothing left...
return false;
}
public: public:
int32_t number; TrackMgr(const mkvparser::Track* track) : fTrack(track), fCurrentBlock(nullptr), fStatus(0) { }
TrackMgr(int32_t num) : blk_entry(nullptr), valid(true), number(num) { } const mkvparser::Track* GetTrack() { return fTrack; }
bool GetFrames(plMoviePlayer* p, int64_t movieTime, std::vector<blkbuf_t>& frames) bool GetFrames(mkvparser::MkvReader* reader, int64_t movieTime, std::vector<blkbuf_t>& frames)
{ {
if (!valid) // If we have no block yet, grab the first one
return false; if (!fCurrentBlock)
fStatus = fTrack->GetFirst(fCurrentBlock);
const mkvparser::BlockEntry* prev = blk_entry; // Continue through the blocks until our current movie time
while (valid = PeekNextBlockEntry(p->fSegment)) while (fCurrentBlock && fStatus == 0)
{ {
const mkvparser::Block* blk = blk_entry->GetBlock(); const mkvparser::Block* block = fCurrentBlock->GetBlock();
if (blk->GetTime(blk_entry->GetCluster()) <= movieTime) int64_t time = block->GetTime(fCurrentBlock->GetCluster()) - fTrack->GetCodecDelay();
if (time <= movieTime * 1000000) // Block time is nano seconds
{ {
frames.reserve(frames.size() + blk->GetFrameCount()); // We want to play this block, add it to the frames buffer
for (int32_t i = 0; i < blk->GetFrameCount(); ++i) frames.reserve(frames.size() + block->GetFrameCount());
for (int32_t i = 0; i < block->GetFrameCount(); i++)
{ {
const mkvparser::Block::Frame data = blk->GetFrame(i); const mkvparser::Block::Frame data = block->GetFrame(i);
uint8_t* buf = new uint8_t[data.len]; uint8_t* buf = new uint8_t[data.len];
data.Read(p->fReader, buf); data.Read(reader, buf);
frames.push_back(std::make_tuple(std::unique_ptr<uint8_t>(buf), static_cast<int32_t>(data.len))); frames.push_back(std::make_tuple(std::unique_ptr<uint8_t>(buf), static_cast<int32_t>(data.len)));
} }
fStatus = fTrack->GetNext(fCurrentBlock, fCurrentBlock);
} }
else else
{ {
blk_entry = prev; // We've got all frames that have to play... come back for more later!
return true; return true;
} }
prev = blk_entry;
} }
return true;
return false; // No more blocks... We're done!
} }
}; };
@ -270,13 +237,13 @@ bool plMoviePlayer::IOpenMovie()
case mkvparser::Track::kAudio: case mkvparser::Track::kAudio:
{ {
if (!fAudioTrack) if (!fAudioTrack)
fAudioTrack.reset(new TrackMgr(track->GetNumber())); fAudioTrack.reset(new TrackMgr(track));
break; break;
} }
case mkvparser::Track::kVideo: case mkvparser::Track::kVideo:
{ {
if (!fVideoTrack) if (!fVideoTrack)
fVideoTrack.reset(new TrackMgr(track->GetNumber())); fVideoTrack.reset(new TrackMgr(track));
break; break;
} }
} }
@ -325,7 +292,7 @@ void plMoviePlayer::IProcessVideoFrame(const std::vector<blkbuf_t>& frames)
void plMoviePlayer::IProcessAudioFrame(const std::vector<blkbuf_t>& frames) void plMoviePlayer::IProcessAudioFrame(const std::vector<blkbuf_t>& frames)
{ {
#ifdef VIDEO_AVAILABLE #ifdef VIDEO_AVAILABLE
const unsigned char* data = nullptr; const uint8_t* data = nullptr;
int32_t size = 0; int32_t size = 0;
for (auto it = frames.begin(); it != frames.end(); ++it) for (auto it = frames.begin(); it != frames.end(); ++it)
{ {
@ -334,7 +301,7 @@ void plMoviePlayer::IProcessAudioFrame(const std::vector<blkbuf_t>& frames)
size = std::get<1>(*it); size = std::get<1>(*it);
static const int frameSize = 5760; //max packet duration at 48kHz static const int frameSize = 5760; //max packet duration at 48kHz
const mkvparser::AudioTrack* audio = static_cast<const mkvparser::AudioTrack*>(fSegment->GetTracks()->GetTrackByNumber(fAudioTrack->number)); const mkvparser::AudioTrack* audio = static_cast<const mkvparser::AudioTrack*>(fAudioTrack->GetTrack());
int16_t* pcm = new int16_t[frameSize * audio->GetChannels() * sizeof(int16_t)]; int16_t* pcm = new int16_t[frameSize * audio->GetChannels() * sizeof(int16_t)];
int samples = opus_decode(fOpusDecoder, data, size, pcm, frameSize, 0); int samples = opus_decode(fOpusDecoder, data, size, pcm, frameSize, 0);
if (samples < 0) if (samples < 0)
@ -346,6 +313,9 @@ void plMoviePlayer::IProcessAudioFrame(const std::vector<blkbuf_t>& frames)
bool plMoviePlayer::Start() bool plMoviePlayer::Start()
{ {
if (fPlaying)
return false;
#ifdef VIDEO_AVAILABLE #ifdef VIDEO_AVAILABLE
if (!IOpenMovie()) if (!IOpenMovie())
return false; return false;
@ -359,7 +329,7 @@ bool plMoviePlayer::Start()
// Need to figure out scaling based on pipe size. // Need to figure out scaling based on pipe size.
plPlateManager& plateMgr = plPlateManager::Instance(); plPlateManager& plateMgr = plPlateManager::Instance();
const mkvparser::VideoTrack* video = static_cast<const mkvparser::VideoTrack*>(fSegment->GetTracks()->GetTrackByNumber(fVideoTrack->number)); const mkvparser::VideoTrack* video = static_cast<const mkvparser::VideoTrack*>(fVideoTrack->GetTrack());
float width = (static_cast<float>(video->GetWidth()) / static_cast<float>(plateMgr.GetPipeWidth())) * fScale.fX; float width = (static_cast<float>(video->GetWidth()) / static_cast<float>(plateMgr.GetPipeWidth())) * fScale.fX;
float height = (static_cast<float>(video->GetHeight()) / static_cast<float>(plateMgr.GetPipeHeight())) * fScale.fY; float height = (static_cast<float>(video->GetHeight()) / static_cast<float>(plateMgr.GetPipeHeight())) * fScale.fY;
@ -368,7 +338,7 @@ bool plMoviePlayer::Start()
fTexture = fPlate->CreateMaterial(static_cast<uint32_t>(video->GetWidth()), static_cast<uint32_t>(video->GetHeight()), nullptr); fTexture = fPlate->CreateMaterial(static_cast<uint32_t>(video->GetWidth()), static_cast<uint32_t>(video->GetHeight()), nullptr);
//initialize opus //initialize opus
const mkvparser::AudioTrack* audio = static_cast<const mkvparser::AudioTrack*>(fSegment->GetTracks()->GetTrackByNumber(fAudioTrack->number)); const mkvparser::AudioTrack* audio = static_cast<const mkvparser::AudioTrack*>(fAudioTrack->GetTrack());
plWAVHeader header; plWAVHeader header;
header.fFormatTag = plWAVHeader::kPCMFormatTag; header.fFormatTag = plWAVHeader::kPCMFormatTag;
header.fNumChannels = audio->GetChannels(); header.fNumChannels = audio->GetChannels();
@ -392,8 +362,9 @@ bool plMoviePlayer::Start()
bool plMoviePlayer::NextFrame() bool plMoviePlayer::NextFrame()
{ {
if (fPlaying) if (!fPlaying)
{ return false;
#ifdef VIDEO_AVAILABLE #ifdef VIDEO_AVAILABLE
// Get our current timecode // Get our current timecode
int64_t movieTime = 0; int64_t movieTime = 0;
@ -407,12 +378,12 @@ bool plMoviePlayer::NextFrame()
uint8_t tracksWithData = 0; uint8_t tracksWithData = 0;
if (fAudioTrack) if (fAudioTrack)
{ {
if (fAudioTrack->GetFrames(this, movieTime, audio)) if (fAudioTrack->GetFrames(fReader, movieTime, audio))
tracksWithData++; tracksWithData++;
} }
if (fVideoTrack) if (fVideoTrack)
{ {
if (fVideoTrack->GetFrames(this, movieTime, video)) if (fVideoTrack->GetFrames(fReader, movieTime, video))
tracksWithData++; tracksWithData++;
} }
if (!tracksWithData) if (!tracksWithData)
@ -430,8 +401,6 @@ bool plMoviePlayer::NextFrame()
return false; return false;
#endif // VIDEO_AVAILABLE #endif // VIDEO_AVAILABLE
} }
return false;
}
bool plMoviePlayer::Stop() bool plMoviePlayer::Stop()
{ {

2937
Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvparser.cpp

File diff suppressed because it is too large Load Diff

339
Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvparser.hpp

@ -13,17 +13,16 @@
#include <cstdio> #include <cstdio>
#include <cstddef> #include <cstddef>
namespace mkvparser namespace mkvparser {
{
const int E_FILE_FORMAT_INVALID = -2; const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3; const int E_BUFFER_NOT_FULL = -3;
class IMkvReader class IMkvReader {
{
public: public:
virtual int Read(long long pos, long len, unsigned char* buf) = 0; virtual int Read(long long pos, long len, unsigned char* buf) = 0;
virtual int Length(long long* total, long long* available) = 0; virtual int Length(long long* total, long long* available) = 0;
protected: protected:
virtual ~IMkvReader(); 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 UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
long UnserializeInt(IMkvReader*, long long pos, long len, long long& result); long UnserializeInt(IMkvReader*, long long pos, long len, long long& result);
long UnserializeString( long UnserializeString(IMkvReader*, long long pos, long long size, char*& str);
IMkvReader*,
long long pos,
long long size,
char*& str);
long ParseElementHeader( long ParseElementHeader(IMkvReader* pReader,
IMkvReader* pReader,
long long& pos, // consume id and size fields long long& pos, // consume id and size fields
long long stop, // if you know size of element's parent long long stop, // if you know size of element's parent
long long& id, long long& id, long long& size);
long long& size);
bool Match(IMkvReader*, long long&, unsigned long, long long&); 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, unsigned char*&, size_t&);
void GetVersion(int& major, int& minor, int& build, int& revision); void GetVersion(int& major, int& minor, int& build, int& revision);
struct EBMLHeader struct EBMLHeader {
{
EBMLHeader(); EBMLHeader();
~EBMLHeader(); ~EBMLHeader();
long long m_version; long long m_version;
@ -69,13 +61,11 @@ struct EBMLHeader
void Init(); void Init();
}; };
class Segment; class Segment;
class Track; class Track;
class Cluster; class Cluster;
class Block class Block {
{
Block(const Block&); Block(const Block&);
Block& operator=(const Block&); Block& operator=(const Block&);
@ -83,7 +73,7 @@ public:
const long long m_start; const long long m_start;
const long long m_size; const long long m_size;
Block(long long start, long long size); Block(long long start, long long size, long long discard_padding);
~Block(); ~Block();
long Parse(const Cluster*); long Parse(const Cluster*);
@ -100,8 +90,7 @@ public:
int GetFrameCount() const; // to index frames: [0, count) int GetFrameCount() const; // to index frames: [0, count)
struct Frame struct Frame {
{
long long pos; // absolute offset long long pos; // absolute offset
long len; long len;
@ -110,6 +99,8 @@ public:
const Frame& GetFrame(int frame_index) const; const Frame& GetFrame(int frame_index) const;
long long GetDiscardPadding() const;
private: private:
long long m_track; // Track::Number() long long m_track; // Track::Number()
short m_timecode; // relative to cluster short m_timecode; // relative to cluster
@ -118,11 +109,11 @@ private:
Frame* m_frames; Frame* m_frames;
int m_frame_count; int m_frame_count;
protected:
const long long m_discard_padding;
}; };
class BlockEntry {
class BlockEntry
{
BlockEntry(const BlockEntry&); BlockEntry(const BlockEntry&);
BlockEntry& operator=(const BlockEntry&); BlockEntry& operator=(const BlockEntry&);
@ -143,12 +134,9 @@ public:
protected: protected:
Cluster* const m_pCluster; Cluster* const m_pCluster;
const long m_index; const long m_index;
}; };
class SimpleBlock : public BlockEntry {
class SimpleBlock : public BlockEntry
{
SimpleBlock(const SimpleBlock&); SimpleBlock(const SimpleBlock&);
SimpleBlock& operator=(const SimpleBlock&); SimpleBlock& operator=(const SimpleBlock&);
@ -161,24 +149,18 @@ public:
protected: protected:
Block m_block; Block m_block;
}; };
class BlockGroup : public BlockEntry {
class BlockGroup : public BlockEntry
{
BlockGroup(const BlockGroup&); BlockGroup(const BlockGroup&);
BlockGroup& operator=(const BlockGroup&); BlockGroup& operator=(const BlockGroup&);
public: public:
BlockGroup( BlockGroup(Cluster*, long index,
Cluster*,
long index,
long long block_start, // absolute pos of block's payload long long block_start, // absolute pos of block's payload
long long block_size, // size of block's payload long long block_size, // size of block's payload
long long prev, long long prev, long long next, long long duration,
long long next, long long discard_padding);
long long duration);
long Parse(); long Parse();
@ -194,7 +176,6 @@ private:
const long long m_prev; const long long m_prev;
const long long m_next; const long long m_next;
const long long m_duration; const long long m_duration;
}; };
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
@ -203,9 +184,7 @@ private:
// compressed with zlib or header stripping. // compressed with zlib or header stripping.
class ContentEncoding { class ContentEncoding {
public: public:
enum { enum { kCTR = 1 };
kCTR = 1
};
ContentEncoding(); ContentEncoding();
~ContentEncoding(); ~ContentEncoding();
@ -217,6 +196,7 @@ public:
unsigned long long algo; unsigned long long algo;
unsigned char* settings; unsigned char* settings;
long long settings_len;
}; };
// ContentEncAESSettings element names // ContentEncAESSettings element names
@ -253,6 +233,14 @@ public:
// element. // element.
unsigned long GetCompressionCount() const; 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| // Returns ContentEncryption represented by |idx|. Returns NULL if |idx|
// is out of bounds. // is out of bounds.
const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const; const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const;
@ -265,26 +253,22 @@ public:
// starting offset of the ContentEncAESSettings payload. |size| is the // starting offset of the ContentEncAESSettings payload. |size| is the
// size in bytes of the ContentEncAESSettings payload. |encryption| is // size in bytes of the ContentEncAESSettings payload. |encryption| is
// where the parsed values will be stored. // where the parsed values will be stored.
long ParseContentEncAESSettingsEntry(long long start, long ParseContentEncAESSettingsEntry(long long start, long long size,
long long size,
IMkvReader* pReader, IMkvReader* pReader,
ContentEncAESSettings* aes); ContentEncAESSettings* aes);
// Parses the ContentEncoding element from |pReader|. |start| is the // Parses the ContentEncoding element from |pReader|. |start| is the
// starting offset of the ContentEncoding payload. |size| is the size in // starting offset of the ContentEncoding payload. |size| is the size in
// bytes of the ContentEncoding payload. Returns true on success. // bytes of the ContentEncoding payload. Returns true on success.
long ParseContentEncodingEntry(long long start, long ParseContentEncodingEntry(long long start, long long size,
long long size,
IMkvReader* pReader); IMkvReader* pReader);
// Parses the ContentEncryption element from |pReader|. |start| is the // Parses the ContentEncryption element from |pReader|. |start| is the
// starting offset of the ContentEncryption payload. |size| is the size in // starting offset of the ContentEncryption payload. |size| is the size in
// bytes of the ContentEncryption payload. |encryption| is where the parsed // bytes of the ContentEncryption payload. |encryption| is where the parsed
// values will be stored. // values will be stored.
long ParseEncryptionEntry(long long start, long ParseEncryptionEntry(long long start, long long size,
long long size, IMkvReader* pReader, ContentEncryption* encryption);
IMkvReader* pReader,
ContentEncryption* encryption);
unsigned long long encoding_order() const { return encoding_order_; } unsigned long long encoding_order() const { return encoding_order_; }
unsigned long long encoding_scope() const { return encoding_scope_; } unsigned long long encoding_scope() const { return encoding_scope_; }
@ -309,21 +293,16 @@ private:
ContentEncoding& operator=(const ContentEncoding&); ContentEncoding& operator=(const ContentEncoding&);
}; };
class Track class Track {
{
Track(const Track&); Track(const Track&);
Track& operator=(const Track&); Track& operator=(const Track&);
public: public:
class Info; class Info;
static long Create( static long Create(Segment*, const Info&, long long element_start,
Segment*, long long element_size, Track*&);
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; Segment* const m_pSegment;
const long long m_element_start; const long long m_element_start;
@ -334,41 +313,46 @@ public:
long GetNumber() const; long GetNumber() const;
unsigned long long GetUid() const; unsigned long long GetUid() const;
const char* GetNameAsUTF8() const; const char* GetNameAsUTF8() const;
const char* GetLanguage() const;
const char* GetCodecNameAsUTF8() const; const char* GetCodecNameAsUTF8() const;
const char* GetCodecId() const; const char* GetCodecId() const;
const unsigned char* GetCodecPrivate(size_t&) const; const unsigned char* GetCodecPrivate(size_t&) const;
bool GetLacing() const; bool GetLacing() const;
unsigned long long GetDefaultDuration() const;
unsigned long long GetCodecDelay() const;
unsigned long long GetSeekPreRoll() const;
const BlockEntry* GetEOS() const; const BlockEntry* GetEOS() const;
struct Settings struct Settings {
{
long long start; long long start;
long long size; long long size;
}; };
class Info class Info {
{
public: public:
Info(); Info();
~Info(); ~Info();
int Copy(Info&) const; int Copy(Info&) const;
void Clear(); void Clear();
private:
Info(const Info&);
Info& operator=(const Info&);
public:
long type; long type;
long number; long number;
unsigned long long uid; unsigned long long uid;
unsigned long long defaultDuration;
unsigned long long codecDelay;
unsigned long long seekPreRoll;
char* nameAsUTF8; char* nameAsUTF8;
char* language;
char* codecId; char* codecId;
char* codecNameAsUTF8; char* codecNameAsUTF8;
unsigned char* codecPrivate; unsigned char* codecPrivate;
size_t codecPrivateSize; size_t codecPrivateSize;
bool lacing; bool lacing;
Settings settings; Settings settings;
private: private:
Info(const Info&);
Info& operator=(const Info&);
int CopyStr(char* Info::*str, Info&) const; int CopyStr(char* Info::*str, Info&) const;
}; };
@ -383,15 +367,11 @@ public:
long ParseContentEncodingsEntry(long long start, long long size); long ParseContentEncodingsEntry(long long start, long long size);
protected: protected:
Track( Track(Segment*, long long element_start, long long element_size);
Segment*,
long long element_start,
long long element_size);
Info m_info; Info m_info;
class EOSBlock : public BlockEntry class EOSBlock : public BlockEntry {
{
public: public:
EOSBlock(); EOSBlock();
@ -406,24 +386,15 @@ private:
ContentEncoding** content_encoding_entries_end_; ContentEncoding** content_encoding_entries_end_;
}; };
class VideoTrack : public Track {
class VideoTrack : public Track
{
VideoTrack(const VideoTrack&); VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&); VideoTrack& operator=(const VideoTrack&);
VideoTrack( VideoTrack(Segment*, long long element_start, long long element_size);
Segment*,
long long element_start,
long long element_size);
public: public:
static long Parse( static long Parse(Segment*, const Info&, long long element_start,
Segment*, long long element_size, VideoTrack*&);
const Info&,
long long element_start,
long long element_size,
VideoTrack*&);
long long GetWidth() const; long long GetWidth() const;
long long GetHeight() const; long long GetHeight() const;
@ -436,31 +407,21 @@ private:
long long m_width; long long m_width;
long long m_height; long long m_height;
double m_rate; double m_rate;
}; };
class AudioTrack : public Track {
class AudioTrack : public Track
{
AudioTrack(const AudioTrack&); AudioTrack(const AudioTrack&);
AudioTrack& operator=(const AudioTrack&); AudioTrack& operator=(const AudioTrack&);
AudioTrack( AudioTrack(Segment*, long long element_start, long long element_size);
Segment*,
long long element_start,
long long element_size);
public: public:
static long Parse( static long Parse(Segment*, const Info&, long long element_start,
Segment*, long long element_size, AudioTrack*&);
const Info&,
long long element_start,
long long element_size,
AudioTrack*&);
double GetSamplingRate() const; double GetSamplingRate() const;
long long GetChannels() const; long long GetChannels() const;
long long GetBitDepth() const; long long GetBitDepth() const;
long Seek(long long time_ns, const BlockEntry*&) const;
private: private:
double m_rate; double m_rate;
@ -468,9 +429,7 @@ private:
long long m_bitDepth; long long m_bitDepth;
}; };
class Tracks {
class Tracks
{
Tracks(const Tracks&); Tracks(const Tracks&);
Tracks& operator=(const Tracks&); Tracks& operator=(const Tracks&);
@ -481,11 +440,7 @@ public:
const long long m_element_start; const long long m_element_start;
const long long m_element_size; const long long m_element_size;
Tracks( Tracks(Segment*, long long start, long long size, long long element_start,
Segment*,
long long start,
long long size,
long long element_start,
long long element_size); long long element_size);
~Tracks(); ~Tracks();
@ -501,18 +456,12 @@ private:
Track** m_trackEntries; Track** m_trackEntries;
Track** m_trackEntriesEnd; Track** m_trackEntriesEnd;
long ParseTrackEntry( long ParseTrackEntry(long long payload_start, long long payload_size,
long long payload_start, long long element_start, long long element_size,
long long payload_size,
long long element_start,
long long element_size,
Track*&) const; Track*&) const;
}; };
class Chapters {
class Chapters
{
Chapters(const Chapters&); Chapters(const Chapters&);
Chapters& operator=(const Chapters&); Chapters& operator=(const Chapters&);
@ -523,12 +472,8 @@ public:
const long long m_element_start; const long long m_element_start;
const long long m_element_size; const long long m_element_size;
Chapters( Chapters(Segment*, long long payload_start, long long payload_size,
Segment*, long long element_start, long long element_size);
long long payload_start,
long long payload_size,
long long element_start,
long long element_size);
~Chapters(); ~Chapters();
@ -537,17 +482,18 @@ public:
class Atom; class Atom;
class Edition; class Edition;
class Display class Display {
{
friend class Atom; friend class Atom;
Display(); Display();
Display(const Display&); Display(const Display&);
~Display(); ~Display();
Display& operator=(const Display&); Display& operator=(const Display&);
public: public:
const char* GetString() const; const char* GetString() const;
const char* GetLanguage() const; const char* GetLanguage() const;
const char* GetCountry() const; const char* GetCountry() const;
private: private:
void Init(); void Init();
void ShallowCopy(Display&) const; void ShallowCopy(Display&) const;
@ -559,29 +505,38 @@ public:
char* m_country; char* m_country;
}; };
class Atom class Atom {
{
friend class Edition; friend class Edition;
Atom(); Atom();
Atom(const Atom&); Atom(const Atom&);
~Atom(); ~Atom();
Atom& operator=(const Atom&); Atom& operator=(const Atom&);
public: public:
unsigned long long GetUID() const;
const char* GetStringUID() const;
long long GetStartTimecode() const; long long GetStartTimecode() const;
long long GetStopTimecode() const; long long GetStopTimecode() const;
long long GetStartTime(const Chapters*) const;
long long GetStopTime(const Chapters*) const;
int GetDisplayCount() const; int GetDisplayCount() const;
const Display* GetDisplay(int index) const; const Display* GetDisplay(int index) const;
private: private:
void Init(); void Init();
void ShallowCopy(Atom&) const; void ShallowCopy(Atom&) const;
void Clear(); void Clear();
long Parse(IMkvReader*, long long pos, long long size); 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); long ParseDisplay(IMkvReader*, long long pos, long long size);
bool ExpandDisplaysArray(); bool ExpandDisplaysArray();
char* m_string_uid;
unsigned long long m_uid; unsigned long long m_uid;
// TODO(matthewjheaney): Cue Identifier (string)
long long m_start_timecode; long long m_start_timecode;
long long m_stop_timecode; long long m_stop_timecode;
@ -590,16 +545,17 @@ public:
int m_displays_count; int m_displays_count;
}; };
class Edition class Edition {
{
friend class Chapters; friend class Chapters;
Edition(); Edition();
Edition(const Edition&); Edition(const Edition&);
~Edition(); ~Edition();
Edition& operator=(const Edition&); Edition& operator=(const Edition&);
public: public:
int GetAtomCount() const; int GetAtomCount() const;
const Atom* GetAtom(int index) const; const Atom* GetAtom(int index) const;
private: private:
void Init(); void Init();
void ShallowCopy(Edition&) const; void ShallowCopy(Edition&) const;
@ -624,12 +580,9 @@ private:
Edition* m_editions; Edition* m_editions;
int m_editions_size; int m_editions_size;
int m_editions_count; int m_editions_count;
}; };
class SegmentInfo {
class SegmentInfo
{
SegmentInfo(const SegmentInfo&); SegmentInfo(const SegmentInfo&);
SegmentInfo& operator=(const SegmentInfo&); SegmentInfo& operator=(const SegmentInfo&);
@ -640,12 +593,8 @@ public:
const long long m_element_start; const long long m_element_start;
const long long m_element_size; const long long m_element_size;
SegmentInfo( SegmentInfo(Segment*, long long start, long long size,
Segment*, long long element_start, long long element_size);
long long start,
long long size,
long long element_start,
long long element_size);
~SegmentInfo(); ~SegmentInfo();
@ -665,9 +614,7 @@ private:
char* m_pTitleAsUTF8; char* m_pTitleAsUTF8;
}; };
class SeekHead {
class SeekHead
{
SeekHead(const SeekHead&); SeekHead(const SeekHead&);
SeekHead& operator=(const SeekHead&); SeekHead& operator=(const SeekHead&);
@ -678,19 +625,14 @@ public:
const long long m_element_start; const long long m_element_start;
const long long m_element_size; const long long m_element_size;
SeekHead( SeekHead(Segment*, long long start, long long size, long long element_start,
Segment*,
long long start,
long long size,
long long element_start,
long long element_size); long long element_size);
~SeekHead(); ~SeekHead();
long Parse(); long Parse();
struct Entry struct Entry {
{
// the SeekHead entry payload // the SeekHead entry payload
long long id; long long id;
long long pos; long long pos;
@ -705,8 +647,7 @@ public:
int GetCount() const; int GetCount() const;
const Entry* GetEntry(int idx) const; const Entry* GetEntry(int idx) const;
struct VoidElement struct VoidElement {
{
// absolute pos of Void ID // absolute pos of Void ID
long long element_start; long long element_start;
@ -724,17 +665,13 @@ private:
VoidElement* m_void_elements; VoidElement* m_void_elements;
int m_void_element_count; int m_void_element_count;
static bool ParseEntry( static bool ParseEntry(IMkvReader*,
IMkvReader*,
long long pos, // payload long long pos, // payload
long long size, long long size, Entry*);
Entry*);
}; };
class Cues; class Cues;
class CuePoint class CuePoint {
{
friend class Cues; friend class Cues;
CuePoint(long, long long); CuePoint(long, long long);
@ -752,8 +689,7 @@ public:
long long GetTimeCode() const; // absolute but unscaled long long GetTimeCode() const; // absolute but unscaled
long long GetTime(const Segment*) const; // absolute and scaled (ns units) long long GetTime(const Segment*) const; // absolute and scaled (ns units)
struct TrackPosition struct TrackPosition {
{
long long m_track; long long m_track;
long long m_pos; // of cluster long long m_pos; // of cluster
long long m_block; long long m_block;
@ -771,19 +707,12 @@ private:
long long m_timecode; long long m_timecode;
TrackPosition* m_track_positions; TrackPosition* m_track_positions;
size_t m_track_positions_count; size_t m_track_positions_count;
}; };
class Cues {
class Cues
{
friend class Segment; friend class Segment;
Cues( Cues(Segment*, long long start, long long size, long long element_start,
Segment*,
long long start,
long long size,
long long element_start,
long long element_size); long long element_size);
~Cues(); ~Cues();
@ -798,9 +727,7 @@ public:
const long long m_element_size; const long long m_element_size;
bool Find( // lower bound of time_ns bool Find( // lower bound of time_ns
long long time_ns, long long time_ns, const Track*, const CuePoint*&,
const Track*,
const CuePoint*&,
const CuePoint::TrackPosition*&) const; const CuePoint::TrackPosition*&) const;
#if 0 #if 0
@ -815,8 +742,7 @@ public:
const CuePoint* GetLast() const; const CuePoint* GetLast() const;
const CuePoint* GetNext(const CuePoint*) const; const CuePoint* GetNext(const CuePoint*) const;
const BlockEntry* GetBlock( const BlockEntry* GetBlock(const CuePoint*,
const CuePoint*,
const CuePoint::TrackPosition*) const; const CuePoint::TrackPosition*) const;
bool LoadCuePoint() const; bool LoadCuePoint() const;
@ -832,12 +758,9 @@ private:
mutable long m_count; mutable long m_count;
mutable long m_preload_count; mutable long m_preload_count;
mutable long long m_pos; mutable long long m_pos;
}; };
class Cluster {
class Cluster
{
friend class Segment; friend class Segment;
Cluster(const Cluster&); Cluster(const Cluster&);
@ -847,8 +770,7 @@ public:
Segment* const m_pSegment; Segment* const m_pSegment;
public: public:
static Cluster* Create( static Cluster* Create(Segment*,
Segment*,
long index, // index in segment long index, // index in segment
long long off); // offset relative to segment long long off); // offset relative to segment
// long long element_size); // long long element_size);
@ -868,17 +790,13 @@ public:
long GetNext(const BlockEntry* curr, const BlockEntry*& next) const; long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;
const BlockEntry* GetEntry(const Track*, long long ns = -1) const; const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
const BlockEntry* GetEntry( const BlockEntry* GetEntry(const CuePoint&,
const CuePoint&,
const CuePoint::TrackPosition&) const; const CuePoint::TrackPosition&) const;
// const BlockEntry* GetMaxKey(const VideoTrack*) const; // const BlockEntry* GetMaxKey(const VideoTrack*) const;
// static bool HasBlockEntries(const Segment*, long long); // static bool HasBlockEntries(const Segment*, long long);
static long HasBlockEntries( static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
const Segment*,
long long idoff,
long long& pos,
long& size); long& size);
long GetEntryCount() const; long GetEntryCount() const;
@ -889,10 +807,7 @@ public:
long GetEntry(long index, const mkvparser::BlockEntry*&) const; long GetEntry(long index, const mkvparser::BlockEntry*&) const;
protected: protected:
Cluster( Cluster(Segment*, long index, long long element_start);
Segment*,
long index,
long long element_start);
// long long element_size); // long long element_size);
public: public:
@ -918,29 +833,25 @@ private:
long ParseSimpleBlock(long long, long long&, long&); long ParseSimpleBlock(long long, long long&, long&);
long ParseBlockGroup(long long, long long&, long&); long ParseBlockGroup(long long, long long&, long&);
long CreateBlock(long long id, long long pos, long long size); long CreateBlock(long long id, long long pos, long long size,
long CreateBlockGroup(long long, long long); long long discard_padding);
long CreateBlockGroup(long long start_offset, long long size,
long long discard_padding);
long CreateSimpleBlock(long long, long long); long CreateSimpleBlock(long long, long long);
}; };
class Segment {
class Segment
{
friend class Cues; friend class Cues;
friend class Track;
friend class VideoTrack; friend class VideoTrack;
friend class AudioTrack;
Segment(const Segment&); Segment(const Segment&);
Segment& operator=(const Segment&); Segment& operator=(const Segment&);
private: private:
Segment( Segment(IMkvReader*, long long elem_start,
IMkvReader*,
long long elem_start,
// long long elem_size, // long long elem_size,
long long pos, long long pos, long long size);
long long size);
public: public:
IMkvReader* const m_pReader; IMkvReader* const m_pReader;
@ -963,10 +874,7 @@ public:
long LoadCluster(long long& pos, long& size); // load one cluster long LoadCluster(long long& pos, long& size); // load one cluster
long LoadCluster(); long LoadCluster();
long ParseNext( long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
const Cluster* pCurr,
const Cluster*& pNext,
long long& pos,
long& size); long& size);
#if 0 #if 0
@ -994,13 +902,10 @@ public:
const Cluster* FindOrPreloadCluster(long long pos); const Cluster* FindOrPreloadCluster(long long pos);
long ParseCues( long ParseCues(long long cues_off, // offset relative to start of segment
long long cues_off, //offset relative to start of segment long long& parse_pos, long& parse_len);
long long& parse_pos,
long& parse_len);
private: private:
long long m_pos; // absolute file posn; what has been consumed so far long long m_pos; // absolute file posn; what has been consumed so far
Cluster* m_pUnknownSize; Cluster* m_pUnknownSize;
@ -1025,16 +930,12 @@ private:
// void ParseSeekEntry(long long pos, long long size); // void ParseSeekEntry(long long pos, long long size);
// void ParseCues(long long); // void ParseCues(long long);
const BlockEntry* GetBlock( const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
const CuePoint&,
const CuePoint::TrackPosition&);
}; };
} // end namespace mkvparser } // end namespace mkvparser
inline long mkvparser::Segment::LoadCluster() inline long mkvparser::Segment::LoadCluster() {
{
long long pos; long long pos;
long size; long size;

52
Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvreader.cpp

@ -10,28 +10,28 @@
#include <cassert> #include <cassert>
namespace mkvparser namespace mkvparser {
{
MkvReader::MkvReader() : MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
m_file(NULL)
{ MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
GetFileSize();
} }
MkvReader::~MkvReader() MkvReader::~MkvReader() {
{ if (reader_owns_file_)
Close(); Close();
m_file = NULL;
} }
int MkvReader::Open(const char* fileName) int MkvReader::Open(const char* fileName) {
{
if (fileName == NULL) if (fileName == NULL)
return -1; return -1;
if (m_file) if (m_file)
return -1; return -1;
#ifdef WIN32 #ifdef _MSC_VER
const errno_t e = fopen_s(&m_file, fileName, "rb"); const errno_t e = fopen_s(&m_file, fileName, "rb");
if (e) if (e)
@ -42,12 +42,17 @@ int MkvReader::Open(const char* fileName)
if (m_file == NULL) if (m_file == NULL)
return -1; return -1;
#endif #endif
return !GetFileSize();
}
#ifdef WIN32 bool MkvReader::GetFileSize() {
if (m_file == NULL)
return false;
#ifdef _MSC_VER
int status = _fseeki64(m_file, 0L, SEEK_END); int status = _fseeki64(m_file, 0L, SEEK_END);
if (status) if (status)
return -1; //error return false; // error
m_length = _ftelli64(m_file); m_length = _ftelli64(m_file);
#else #else
@ -56,29 +61,29 @@ int MkvReader::Open(const char* fileName)
#endif #endif
assert(m_length >= 0); assert(m_length >= 0);
#ifdef WIN32 if (m_length < 0)
return false;
#ifdef _MSC_VER
status = _fseeki64(m_file, 0L, SEEK_SET); status = _fseeki64(m_file, 0L, SEEK_SET);
if (status) if (status)
return -1; //error return false; // error
#else #else
fseek(m_file, 0L, SEEK_SET); fseek(m_file, 0L, SEEK_SET);
#endif #endif
return 0; return true;
} }
void MkvReader::Close() void MkvReader::Close() {
{ if (m_file != NULL) {
if (m_file != NULL)
{
fclose(m_file); fclose(m_file);
m_file = NULL; 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) if (m_file == NULL)
return -1; return -1;
@ -91,8 +96,7 @@ int MkvReader::Length(long long* total, long long* available)
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) if (m_file == NULL)
return -1; return -1;
@ -108,7 +112,7 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer)
if (offset >= m_length) if (offset >= m_length)
return -1; return -1;
#ifdef WIN32 #ifdef _MSC_VER
const int status = _fseeki64(m_file, offset, SEEK_SET); const int status = _fseeki64(m_file, offset, SEEK_SET);
if (status) if (status)

20
Sources/Plasma/FeatureLib/pfMoviePlayer/webm/mkvreader.hpp

@ -12,26 +12,32 @@
#include "mkvparser.hpp" #include "mkvparser.hpp"
#include <cstdio> #include <cstdio>
namespace mkvparser namespace mkvparser {
{
class MkvReader : public IMkvReader class MkvReader : public IMkvReader {
{
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
public: public:
MkvReader(); MkvReader();
explicit MkvReader(FILE* fp);
virtual ~MkvReader(); virtual ~MkvReader();
int Open(const char*); int Open(const char*);
void Close(); void Close();
bool IsOpen() const;
virtual int Read(long long position, long length, unsigned char* buffer); virtual int Read(long long position, long length, unsigned char* buffer);
virtual int Length(long long* total, long long* available); virtual int Length(long long* total, long long* available);
private: private:
MkvReader(const MkvReader&);
MkvReader& operator=(const MkvReader&);
// Determines the size of the file. This is called either by the constructor
// or by the Open function depending on file ownership. Returns true on
// success.
bool GetFileSize();
long long m_length; long long m_length;
FILE* m_file; FILE* m_file;
bool reader_owns_file_;
}; };
} // end namespace mkvparser } // end namespace mkvparser

Loading…
Cancel
Save