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

241 lines
5.5 KiB
C++

#include "track.hpp"
#include "segment.hpp"
#include "imkvreader.hpp"
#include "block.hpp"
#include "ebmlreadhelpers.hpp"
#include "contentencoding.hpp"
#include "mkvprofiler.hpp"
#include <stddef.h>
#include <assert.h>
#include <limits.h>
namespace mkvparser
{
Track::Info::Info()
: type(0)
, number(0)
, uid(0)
, nameAsUTF8(NULL)
, codecId(NULL)
, codecNameAsUTF8(NULL)
, lacing(false)
{
settings.start = 0;
settings.size = 0;
}
Track::Info::~Info()
{
Clear();
}
void Track::Info::Clear()
{
mem::Free(nameAsUTF8);
nameAsUTF8 = NULL;
mem::Free(codecId);
codecId = NULL;
codecPrivate.clear();
mem::Free(codecNameAsUTF8);
codecNameAsUTF8 = NULL;
}
int Track::Info::CopyStr(char* Info::*str, Info& dst_) const
{
if (str == static_cast<char* Info::*>(NULL))
return -1;
char*& dst = dst_.*str;
if (dst) //should be NULL already
return -1;
const char* const src = this->*str;
if (src == NULL)
return 0;
const size_t len = std::strlen(src);
dst = static_cast<char*>(mem::Allocate(len+1));
if (dst == NULL)
return -1;
std::strcpy(dst, src);
return 0;
}
int Track::Info::Copy(Info& dst) const
{
if (&dst == this)
return 0;
dst.type = type;
dst.number = number;
dst.uid = uid;
dst.lacing = lacing;
dst.settings = settings;
//We now copy the string member variables from src to dst.
//This involves memory allocation so in principle the operation
//can fail (indeed, that's why we have Info::Copy), so we must
//report this to the caller. An error return from this function
//therefore implies that the copy was only partially successful.
if (int status = CopyStr(&Info::nameAsUTF8, dst))
return status;
if (int status = CopyStr(&Info::codecId, dst))
return status;
if (int status = CopyStr(&Info::codecNameAsUTF8, dst))
return status;
dst.codecPrivate = codecPrivate;
if (dst.codecPrivate.size() != codecPrivate.size())
return -1;
return 0;
}
Track::Track(Segment* pSegment, long long element_start, long long element_size)
: m_pSegment(pSegment)
, m_element_start(element_start)
, m_element_size(element_size)
{
}
Track::~Track()
{
m_info.Clear();
ContEncodingVect_t::iterator first = content_encoding_entries_.begin();
ContEncodingVect_t::iterator last = content_encoding_entries_.end();
for (; first != last; ++first)
{
delete (*first);
}
}
long Track::Create(Segment* pSegment,
const Info& info,
long long element_start,
long long element_size,
Track*& pResult)
{
if (pResult)
return -1;
Track* const pTrack = new Track(pSegment, element_start, element_size);
if (pTrack == NULL)
return -1; //generic error
const int status = info.Copy(pTrack->m_info);
if (status) // error
{
delete pTrack;
return status;
}
pResult = pTrack;
return 0; //success
}
const unsigned char* Track::GetCodecPrivate(size_t& size) const
{
size = m_info.codecPrivate.size();
if (size > 0)
return &m_info.codecPrivate[0];
return 0;
}
bool Track::VetEntry(const BlockEntry* pBlockEntry) const
{
assert(pBlockEntry);
assert(pBlockEntry->GetBlock());
assert(pBlockEntry->GetBlock()->GetTrackNumber() == m_info.number);
// This function is used during a seek to determine whether the
// frame is a valid seek target. This default function simply
// returns true, which means all frames are valid seek targets.
// It gets overridden by the VideoTrack class, because only video
// keyframes can be used as seek target.
return true;
}
const ContentEncoding* Track::GetContentEncodingByIndex(unsigned long idx) const
{
if (idx >= content_encoding_entries_.size())
return NULL;
return content_encoding_entries_[idx];
}
unsigned long Track::GetContentEncodingCount() const
{
return static_cast<unsigned long>(content_encoding_entries_.size());
}
long Track::ParseContentEncodingsEntry(long long start, long long size)
{
PROFILER_SCOPED_EVENT("webm::Track::ParseContentEncodingsEntry");
IMkvReader* const pReader = m_pSegment->GetReader();
assert(pReader);
long long pos = start;
const long long stop = start + size;
while (pos < stop)
{
long long id, size;
long status = ParseElementHeader(pReader,
pos,
stop,
id,
size);
if (status < 0) //error
return status;
//pos now designates start of element
if (id == 0x2240) // ContentEncoding ID
{
ContentEncoding* const content_encoding = new ContentEncoding();
if (!content_encoding)
return -1;
status = content_encoding->ParseContentEncodingEntry(pos,
size,
pReader);
if (status)
{
delete content_encoding;
return status;
}
content_encoding_entries_.push_back(content_encoding);
}
pos += size; //consume payload
assert(pos <= stop);
}
assert(pos == stop);
return 0;
}
} // namespace mkvparser