JD2022-TU1/main/extern/libwebm/custom/mkvparser/cuepoint.cpp

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