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

163 lines
3.8 KiB
C++

#include "seekhead.hpp"
#include "segment.hpp"
#include "ebmlreadhelpers.hpp"
#include "imkvreader.hpp"
#include <assert.h>
namespace mkvparser
{
namespace
{
long long ParseEntry(IMkvReader* pReader, const EBMLElement& entryInfo, SeekHead::Entry* pEntry)
{
assert(pEntry);
if (entryInfo.GetPayloadSize() <= 0)
return E_FILE_FORMAT_INVALID;
pEntry->element_start = entryInfo.GetPos();
pEntry->element_size = entryInfo.GetSize();
long long pos = entryInfo.GetPayloadPos();
const long long stop = entryInfo.GetEndPos();
//parse the container for the level-1 element ID
//seekId
EBMLElement elemInfo;
long long result = elemInfo.Parse(pReader, pos);
if (result != 0)
return result;
if (elemInfo.GetID() != 0x13AB) //SeekID ID
return E_FILE_FORMAT_INVALID;
if (elemInfo.GetEndPos() > stop)
return E_FILE_FORMAT_INVALID;
//Note that the SeekId payload really is serialized
//as a "Matroska integer", not as a plain binary value.
//In fact, Matroska requires that ID values in the
//stream exactly match the binary representation as listed
//in the Matroska specification.
//
//This parser is more liberal, and permits IDs to have
//any width. (This could make the representation in the stream
//different from what's in the spec, but it doesn't matter here,
//since we always normalize "Matroska integer" values.)
long len = 0;
pEntry->id = ReadUInt(pReader, elemInfo.GetPayloadPos(), len); //payload
if (pEntry->id <= 0)
return E_FILE_FORMAT_INVALID;
pos += elemInfo.GetSize(); //consume SeekID payload
//seekPos
result = elemInfo.Parse(pReader, pos);
if (result != 0)
return result;
if (elemInfo.GetID() != 0x13AC) //SeekPos ID
return E_FILE_FORMAT_INVALID;
if (elemInfo.GetEndPos() > stop)
return E_FILE_FORMAT_INVALID;
pEntry->pos = UnserializeUInt(pReader, elemInfo.GetPayloadPos(), elemInfo.GetPayloadSize());
if (pEntry->pos < 0)
return E_FILE_FORMAT_INVALID;
pos += elemInfo.GetSize(); //consume payload
if (pos != stop)
return E_FILE_FORMAT_INVALID;
return 0; // success
}
} // namespace
SeekHead::SeekHead(Segment* pSegment, const EBMLElement& elemInfo)
: m_pSegment(pSegment)
, m_elemInfo(elemInfo)
{
}
SeekHead::~SeekHead()
{
}
long SeekHead::Parse()
{
IMkvReader* const pReader = m_pSegment->GetReader();
long long pos = m_elemInfo.GetPayloadPos();
const long long stop = m_elemInfo.GetEndPos();
while (pos < stop)
{
EBMLElement elemInfo;
long long result = elemInfo.Parse(pReader, pos);
if (result != 0)
return static_cast<long>(result);
if (elemInfo.GetID() == 0x0DBB) //SeekEntry ID
{
Entry e;
if (ParseEntry(pReader, elemInfo, &e) == 0)
{
m_entries.push_back(e);
}
}
else if (elemInfo.GetID() == 0x6C) //Void ID
{
VoidElement e;
e.element_start = elemInfo.GetPos();
e.element_size = elemInfo.GetSize();
m_void_elements.push_back(e);
}
pos += elemInfo.GetSize(); //consume payload
assert(pos <= stop);
}
assert(pos == stop);
return 0;
}
const SeekHead::Entry* SeekHead::GetEntry(int idx) const
{
if (idx < 0)
return 0;
if (idx >= static_cast<int>(m_entries.size()))
return 0;
return &m_entries[idx];
}
const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const
{
if (idx < 0)
return 0;
if (idx >= static_cast<int>(m_void_elements.size()))
return 0;
return &m_void_elements[idx];
}
} // namespace mkvparser