215 lines
4.6 KiB
C++
215 lines
4.6 KiB
C++
#include "cuepoint.hpp"
|
|
#include "track.hpp"
|
|
#include "segmentinfo.hpp"
|
|
#include "segment.hpp"
|
|
#include "ebmlreadhelpers.hpp"
|
|
#include "mkvprofiler.hpp"
|
|
|
|
#include <stddef.h>
|
|
#include <assert.h>
|
|
|
|
namespace mkvparser
|
|
{
|
|
|
|
CuePoint::CuePoint(long idx, long long pos) :
|
|
m_element_start(0),
|
|
m_element_size(0),
|
|
m_index(idx),
|
|
m_timecode(-1 * pos)
|
|
{
|
|
assert(pos > 0);
|
|
}
|
|
|
|
|
|
CuePoint::~CuePoint()
|
|
{
|
|
}
|
|
|
|
|
|
void CuePoint::Load(IMkvReader* pReader)
|
|
{
|
|
PROFILER_SCOPED_EVENT("webm::CuePoint::Load");
|
|
|
|
//odbgstream os;
|
|
//os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
|
|
|
|
if (m_timecode >= 0) //already loaded
|
|
return;
|
|
|
|
assert(m_track_positions.empty());
|
|
|
|
long long pos_ = -m_timecode;
|
|
const long long element_start = pos_;
|
|
|
|
long long stop;
|
|
|
|
{
|
|
// NOTE:
|
|
// this is already done in Cues, can be removed from here
|
|
// as it is discarded anyway
|
|
|
|
long len;
|
|
|
|
const long long id = ReadUInt(pReader, pos_, len);
|
|
assert(id == 0x3B); //CuePoint ID
|
|
//assert((pos + len) <= stop);
|
|
|
|
pos_ += len; //consume ID
|
|
|
|
const long long size = ReadUInt(pReader, pos_, len);
|
|
assert(size >= 0);
|
|
//assert((pos + len) <= stop);
|
|
|
|
pos_ += len; //consume Size field
|
|
//assert((pos + size) <= stop);
|
|
|
|
//pos_ now points to start of payload
|
|
|
|
stop = pos_ + size;
|
|
}
|
|
|
|
const long long element_size = stop - element_start;
|
|
|
|
long long pos = pos_;
|
|
|
|
while (pos < stop)
|
|
{
|
|
long len;
|
|
|
|
const long long id = ReadUInt(pReader, pos, len);
|
|
assert(id >= 0); //TODO
|
|
assert((pos + len) <= stop);
|
|
|
|
pos += len; //consume ID
|
|
|
|
const long long size = ReadUInt(pReader, pos, len);
|
|
assert(size >= 0);
|
|
assert((pos + len) <= stop);
|
|
|
|
pos += len; //consume Size field
|
|
assert((pos + size) <= stop);
|
|
|
|
if (id == 0x33) //CueTime ID
|
|
{
|
|
m_timecode = UnserializeUInt(pReader, pos, size);
|
|
}
|
|
else if (id == 0x37) //CueTrackPosition(s) ID
|
|
{
|
|
TrackPosition tp;
|
|
tp.Parse(pReader, pos, size);
|
|
|
|
m_track_positions.push_back(tp);
|
|
}
|
|
pos += size; //consume payload
|
|
assert(pos <= stop);
|
|
}
|
|
|
|
assert(m_timecode >= 0);
|
|
assert(m_track_positions.size() > 0);
|
|
|
|
//os << "CuePoint::Load(cont'd): idpos=" << idpos
|
|
// << " timecode=" << m_timecode
|
|
// << endl;
|
|
|
|
m_element_start = element_start;
|
|
m_element_size = element_size;
|
|
}
|
|
|
|
|
|
|
|
void CuePoint::TrackPosition::Parse(
|
|
IMkvReader* pReader,
|
|
long long start_,
|
|
long long size_)
|
|
{
|
|
PROFILER_SCOPED_EVENT("webm::CuePoint::TrackPosition::Parse");
|
|
|
|
const long long stop = start_ + size_;
|
|
long long pos = start_;
|
|
|
|
m_track = -1;
|
|
m_pos = -1;
|
|
m_block = 1; //default
|
|
|
|
while (pos < stop)
|
|
{
|
|
long len;
|
|
|
|
const long long id = ReadUInt(pReader, pos, len);
|
|
assert(id >= 0); //TODO
|
|
assert((pos + len) <= stop);
|
|
|
|
pos += len; //consume ID
|
|
|
|
const long long size = ReadUInt(pReader, pos, len);
|
|
assert(size >= 0);
|
|
assert((pos + len) <= stop);
|
|
|
|
pos += len; //consume Size field
|
|
assert((pos + size) <= stop);
|
|
|
|
if (id == 0x77) //CueTrack ID
|
|
m_track = UnserializeUInt(pReader, pos, size);
|
|
|
|
else if (id == 0x71) //CueClusterPos ID
|
|
m_pos = UnserializeUInt(pReader, pos, size);
|
|
|
|
else if (id == 0x1378) //CueBlockNumber
|
|
m_block = UnserializeUInt(pReader, pos, size);
|
|
|
|
pos += size; //consume payload
|
|
assert(pos <= stop);
|
|
}
|
|
|
|
assert(m_pos >= 0);
|
|
assert(m_track > 0);
|
|
//assert(m_block > 0);
|
|
}
|
|
|
|
|
|
const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const
|
|
{
|
|
PROFILER_SCOPED_EVENT("webm::CuePoint::Find");
|
|
|
|
assert(pTrack);
|
|
|
|
const long long n = pTrack->GetNumber();
|
|
|
|
TrackPosVect_t::const_iterator first = m_track_positions.begin();
|
|
TrackPosVect_t::const_iterator last = m_track_positions.end();
|
|
|
|
for (; first != last; ++first)
|
|
{
|
|
const TrackPosition& p = *first;
|
|
|
|
if (p.m_track == n)
|
|
return &p;
|
|
}
|
|
|
|
return NULL; //no matching track number found
|
|
}
|
|
|
|
|
|
long long CuePoint::GetTimeCode() const
|
|
{
|
|
return m_timecode;
|
|
}
|
|
|
|
long long CuePoint::GetTime(const Segment* pSegment) const
|
|
{
|
|
assert(pSegment);
|
|
assert(m_timecode >= 0);
|
|
|
|
const SegmentInfo* const pInfo = pSegment->GetInfo();
|
|
assert(pInfo);
|
|
|
|
const long long scale = pInfo->GetTimeCodeScale();
|
|
assert(scale >= 1);
|
|
|
|
const long long time = scale * m_timecode;
|
|
|
|
return time;
|
|
}
|
|
|
|
} // namespace mkvparser
|
|
|