Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(605)

Unified Diff: source/libvpx/third_party/libwebm/mkvparser.cpp

Issue 1302353004: libvpx: Pull from upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/libvpx.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvparser.hpp ('k') | source/libvpx/third_party/libwebm/webmids.hpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/libvpx/third_party/libwebm/mkvparser.cpp
diff --git a/source/libvpx/third_party/libwebm/mkvparser.cpp b/source/libvpx/third_party/libwebm/mkvparser.cpp
index 441f16596b3d11f87375acb8ad040b5c2ea2afad..fc01be526409dafd5c1b6e4c173f052d5fbf2dab 100644
--- a/source/libvpx/third_party/libwebm/mkvparser.cpp
+++ b/source/libvpx/third_party/libwebm/mkvparser.cpp
@@ -23,7 +23,7 @@ void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) {
major = 1;
minor = 0;
build = 0;
- revision = 28;
+ revision = 30;
}
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) {
@@ -130,6 +130,8 @@ long long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos,
return 0; // success
}
+// TODO(vigneshv): This function assumes that unsigned values never have their
+// high bit set.
long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos,
long long size) {
assert(pReader);
@@ -217,8 +219,8 @@ long mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos,
return 0;
}
-long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size,
- long long& result) {
+long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos,
+ long long size, long long& result) {
assert(pReader);
assert(pos >= 0);
assert(size > 0);
@@ -605,6 +607,7 @@ Segment::Segment(IMkvReader* pReader, long long elem_start,
m_pTracks(NULL),
m_pCues(NULL),
m_pChapters(NULL),
+ m_pTags(NULL),
m_clusters(NULL),
m_clusterCount(0),
m_clusterPreloadCount(0),
@@ -629,6 +632,7 @@ Segment::~Segment() {
delete m_pInfo;
delete m_pCues;
delete m_pChapters;
+ delete m_pTags;
delete m_pSeekHead;
}
@@ -907,6 +911,19 @@ long long Segment::ParseHeaders() {
if (status)
return status;
}
+ } else if (id == 0x0254C367) { // Tags ID
+ if (m_pTags == NULL) {
+ m_pTags = new (std::nothrow)
+ Tags(this, pos, size, element_start, element_size);
+
+ if (m_pTags == NULL)
+ return -1;
+
+ const long status = m_pTags->Parse();
+
+ if (status)
+ return status;
+ }
}
m_pos = pos + size; // consume payload
@@ -1025,23 +1042,11 @@ long Segment::DoLoadCluster(long long& pos, long& len) {
const long long unknown_size = (1LL << (7 * len)) - 1;
-#if 0 // we must handle this to support live webm
- if (size == unknown_size)
- return E_FILE_FORMAT_INVALID; //TODO: allow this
-#endif
-
if ((segment_stop >= 0) && (size != unknown_size) &&
((pos + size) > segment_stop)) {
return E_FILE_FORMAT_INVALID;
}
-#if 0 // commented-out, to support incremental cluster parsing
- len = static_cast<long>(size);
-
- if ((pos + size) > avail)
- return E_BUFFER_NOT_FULL;
-#endif
-
if (id == 0x0C53BB6B) { // Cues ID
if (size == unknown_size)
return E_FILE_FORMAT_INVALID; // TODO: liberalize
@@ -1157,10 +1162,8 @@ long Segment::DoLoadCluster(long long& pos, long& len) {
}
if (status == 0) { // no entries found
- if (cluster_size < 0)
- return E_FILE_FORMAT_INVALID; // TODO: handle this
-
- pos += cluster_size;
+ if (cluster_size >= 0)
+ pos += cluster_size;
if ((total >= 0) && (pos >= total)) {
m_pos = total;
@@ -1201,306 +1204,15 @@ long Segment::DoLoadCluster(long long& pos, long& len) {
return 0; // partial success, since we have a new cluster
-// status == 0 means "no block entries found"
-
-// pos designates start of payload
-// m_pos has NOT been adjusted yet (in case we need to come back here)
-
-#if 0
-
- if (cluster_size < 0) { //unknown size
- const long long payload_pos = pos; //absolute pos of cluster payload
-
- for (;;) { //determine cluster size
- if ((total >= 0) && (pos >= total))
- break;
-
- if ((segment_stop >= 0) && (pos >= segment_stop))
- break; //no more clusters
-
- //Read ID
-
- if ((pos + 1) > avail)
- {
- len = 1;
- return E_BUFFER_NOT_FULL;
- }
-
- long long result = GetUIntLength(m_pReader, pos, len);
-
- if (result < 0) //error
- return static_cast<long>(result);
-
- if (result > 0) //weird
- return E_BUFFER_NOT_FULL;
-
- if ((segment_stop >= 0) && ((pos + len) > segment_stop))
- return E_FILE_FORMAT_INVALID;
-
- if ((pos + len) > avail)
- return E_BUFFER_NOT_FULL;
-
- const long long idpos = pos;
- const long long id = ReadUInt(m_pReader, idpos, len);
-
- if (id < 0) //error (or underflow)
- return static_cast<long>(id);
-
- //This is the distinguished set of ID's we use to determine
- //that we have exhausted the sub-element's inside the cluster
- //whose ID we parsed earlier.
-
- if (id == 0x0F43B675) //Cluster ID
- break;
-
- if (id == 0x0C53BB6B) //Cues ID
- break;
-
- switch (id)
- {
- case 0x20: //BlockGroup
- case 0x23: //Simple Block
- case 0x67: //TimeCode
- case 0x2B: //PrevSize
- break;
-
- default:
- assert(false);
- break;
- }
-
- pos += len; //consume ID (of sub-element)
-
- //Read Size
-
- if ((pos + 1) > avail)
- {
- len = 1;
- return E_BUFFER_NOT_FULL;
- }
-
- result = GetUIntLength(m_pReader, pos, len);
-
- if (result < 0) //error
- return static_cast<long>(result);
-
- if (result > 0) //weird
- return E_BUFFER_NOT_FULL;
-
- if ((segment_stop >= 0) && ((pos + len) > segment_stop))
- return E_FILE_FORMAT_INVALID;
-
- if ((pos + len) > avail)
- return E_BUFFER_NOT_FULL;
-
- const long long size = ReadUInt(m_pReader, pos, len);
-
- if (size < 0) //error
- return static_cast<long>(size);
-
- pos += len; //consume size field of element
-
- //pos now points to start of sub-element's payload
-
- if (size == 0) //weird
- continue;
-
- const long long unknown_size = (1LL << (7 * len)) - 1;
-
- if (size == unknown_size)
- return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
-
- if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
- return E_FILE_FORMAT_INVALID;
-
- pos += size; //consume payload of sub-element
- assert((segment_stop < 0) || (pos <= segment_stop));
- } //determine cluster size
-
- cluster_size = pos - payload_pos;
- assert(cluster_size >= 0);
-
- pos = payload_pos; //reset and re-parse original cluster
- }
-
- if (m_clusterPreloadCount > 0)
- {
- assert(idx < m_clusterSize);
-
- Cluster* const pCluster = m_clusters[idx];
- assert(pCluster);
- assert(pCluster->m_index < 0);
-
- const long long off = pCluster->GetPosition();
- assert(off >= 0);
-
- if (off == cluster_off) //preloaded already
- return E_FILE_FORMAT_INVALID; //subtle
- }
-
- m_pos = pos + cluster_size; //consume payload
- assert((segment_stop < 0) || (m_pos <= segment_stop));
-
- return 2; //try to find another cluster
-
-#endif
+ // status == 0 means "no block entries found"
+ // pos designates start of payload
+ // m_pos has NOT been adjusted yet (in case we need to come back here)
}
long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
assert(m_pos < 0);
assert(m_pUnknownSize);
-#if 0
- assert(m_pUnknownSize->GetElementSize() < 0); //TODO: verify this
-
- const long long element_start = m_pUnknownSize->m_element_start;
-
- pos = -m_pos;
- assert(pos > element_start);
-
- //We have already consumed the (cluster) ID and size fields.
- //We just need to consume the blocks and other sub-elements
- //of this cluster, until we discover the boundary.
-
- long long total, avail;
-
- long status = m_pReader->Length(&total, &avail);
-
- if (status < 0) //error
- return status;
-
- assert((total < 0) || (avail <= total));
-
- const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
-
- long long element_size = -1;
-
- for (;;) { //determine cluster size
- if ((total >= 0) && (pos >= total))
- {
- element_size = total - element_start;
- assert(element_size > 0);
-
- break;
- }
-
- if ((segment_stop >= 0) && (pos >= segment_stop))
- {
- element_size = segment_stop - element_start;
- assert(element_size > 0);
-
- break;
- }
-
- //Read ID
-
- if ((pos + 1) > avail)
- {
- len = 1;
- return E_BUFFER_NOT_FULL;
- }
-
- long long result = GetUIntLength(m_pReader, pos, len);
-
- if (result < 0) //error
- return static_cast<long>(result);
-
- if (result > 0) //weird
- return E_BUFFER_NOT_FULL;
-
- if ((segment_stop >= 0) && ((pos + len) > segment_stop))
- return E_FILE_FORMAT_INVALID;
-
- if ((pos + len) > avail)
- return E_BUFFER_NOT_FULL;
-
- const long long idpos = pos;
- const long long id = ReadUInt(m_pReader, idpos, len);
-
- if (id < 0) //error (or underflow)
- return static_cast<long>(id);
-
- //This is the distinguished set of ID's we use to determine
- //that we have exhausted the sub-element's inside the cluster
- //whose ID we parsed earlier.
-
- if ((id == 0x0F43B675) || (id == 0x0C53BB6B)) { //Cluster ID or Cues ID
- element_size = pos - element_start;
- assert(element_size > 0);
-
- break;
- }
-
-#ifdef _DEBUG
- switch (id)
- {
- case 0x20: //BlockGroup
- case 0x23: //Simple Block
- case 0x67: //TimeCode
- case 0x2B: //PrevSize
- break;
-
- default:
- assert(false);
- break;
- }
-#endif
-
- pos += len; //consume ID (of sub-element)
-
- //Read Size
-
- if ((pos + 1) > avail)
- {
- len = 1;
- return E_BUFFER_NOT_FULL;
- }
-
- result = GetUIntLength(m_pReader, pos, len);
-
- if (result < 0) //error
- return static_cast<long>(result);
-
- if (result > 0) //weird
- return E_BUFFER_NOT_FULL;
-
- if ((segment_stop >= 0) && ((pos + len) > segment_stop))
- return E_FILE_FORMAT_INVALID;
-
- if ((pos + len) > avail)
- return E_BUFFER_NOT_FULL;
-
- const long long size = ReadUInt(m_pReader, pos, len);
-
- if (size < 0) //error
- return static_cast<long>(size);
-
- pos += len; //consume size field of element
-
- //pos now points to start of sub-element's payload
-
- if (size == 0) //weird
- continue;
-
- const long long unknown_size = (1LL << (7 * len)) - 1;
-
- if (size == unknown_size)
- return E_FILE_FORMAT_INVALID; //not allowed for sub-elements
-
- if ((segment_stop >= 0) && ((pos + size) > segment_stop)) //weird
- return E_FILE_FORMAT_INVALID;
-
- pos += size; //consume payload of sub-element
- assert((segment_stop < 0) || (pos <= segment_stop));
- } //determine cluster size
-
- assert(element_size >= 0);
-
- m_pos = element_start + element_size;
- m_pUnknownSize = 0;
-
- return 2; //continue parsing
-#else
const long status = m_pUnknownSize->Parse(pos, len);
if (status < 0) // error or underflow
@@ -1522,7 +1234,6 @@ long Segment::DoLoadClusterUnknownSize(long long& pos, long& len) {
m_pUnknownSize = 0;
return 2; // continue parsing
-#endif
}
void Segment::AppendCluster(Cluster* pCluster) {
@@ -1540,7 +1251,7 @@ void Segment::AppendCluster(Cluster* pCluster) {
if (count >= size) {
const long n = (size <= 0) ? 2048 : 2 * size;
- Cluster** const qq = new Cluster* [n];
+ Cluster** const qq = new Cluster*[n];
Cluster** q = qq;
Cluster** p = m_clusters;
@@ -1594,7 +1305,7 @@ void Segment::PreloadCluster(Cluster* pCluster, ptrdiff_t idx) {
if (count >= size) {
const long n = (size <= 0) ? 2048 : 2 * size;
- Cluster** const qq = new Cluster* [n];
+ Cluster** const qq = new Cluster*[n];
Cluster** q = qq;
Cluster** p = m_clusters;
@@ -1794,55 +1505,6 @@ const SeekHead::VoidElement* SeekHead::GetVoidElement(int idx) const {
return m_void_elements + idx;
}
-#if 0
-void Segment::ParseCues(long long off)
-{
- if (m_pCues)
- return;
-
- //odbgstream os;
- //os << "Segment::ParseCues (begin)" << endl;
-
- long long pos = m_start + off;
- const long long element_start = pos;
- const long long stop = m_start + m_size;
-
- long len;
-
- long long result = GetUIntLength(m_pReader, pos, len);
- assert(result == 0);
- assert((pos + len) <= stop);
-
- const long long idpos = pos;
-
- const long long id = ReadUInt(m_pReader, idpos, len);
- assert(id == 0x0C53BB6B); //Cues ID
-
- pos += len; //consume ID
- assert(pos < stop);
-
- //Read Size
-
- result = GetUIntLength(m_pReader, pos, len);
- assert(result == 0);
- assert((pos + len) <= stop);
-
- const long long size = ReadUInt(m_pReader, pos, len);
- assert(size >= 0);
-
- pos += len; //consume length of size of element
- assert((pos + size) <= stop);
-
- const long long element_size = size + pos - element_start;
-
- //Pos now points to start of payload
-
- m_pCues = new Cues(this, pos, size, element_start, element_size);
- assert(m_pCues); //TODO
-
- //os << "Segment::ParseCues (end)" << endl;
-}
-#else
long Segment::ParseCues(long long off, long long& pos, long& len) {
if (m_pCues)
return 0; // success
@@ -1957,67 +1619,7 @@ long Segment::ParseCues(long long off, long long& pos, long& len) {
return 0; // success
}
-#endif
-
-#if 0
-void Segment::ParseSeekEntry(
- long long start,
- long long size_)
-{
- long long pos = start;
-
- const long long stop = start + size_;
-
- long len;
-
- const long long seekIdId = ReadUInt(m_pReader, pos, len);
- //seekIdId;
- assert(seekIdId == 0x13AB); //SeekID ID
- assert((pos + len) <= stop);
- pos += len; //consume id
-
- const long long seekIdSize = ReadUInt(m_pReader, pos, len);
- assert(seekIdSize >= 0);
- assert((pos + len) <= stop);
-
- pos += len; //consume size
-
- const long long seekId = ReadUInt(m_pReader, pos, len); //payload
- assert(seekId >= 0);
- assert(len == seekIdSize);
- assert((pos + len) <= stop);
-
- pos += seekIdSize; //consume payload
-
- const long long seekPosId = ReadUInt(m_pReader, pos, len);
- //seekPosId;
- assert(seekPosId == 0x13AC); //SeekPos ID
- assert((pos + len) <= stop);
-
- pos += len; //consume id
-
- const long long seekPosSize = ReadUInt(m_pReader, pos, len);
- assert(seekPosSize >= 0);
- assert((pos + len) <= stop);
-
- pos += len; //consume size
- assert((pos + seekPosSize) <= stop);
-
- const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
- assert(seekOff >= 0);
- assert(seekOff < m_size);
-
- pos += seekPosSize; //consume payload
- assert(pos == stop);
-
- const long long seekPos = m_start + seekOff;
- assert(seekPos < (m_start + m_size));
-
- if (seekId == 0x0C53BB6B) //Cues ID
- ParseCues(seekOff);
-}
-#else
bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
Entry* pEntry) {
if (size_ <= 0)
@@ -2110,7 +1712,6 @@ bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
return true;
}
-#endif
Cues::Cues(Segment* pSegment, long long start_, long long size_,
long long element_start, long long element_size)
@@ -2152,9 +1753,9 @@ bool Cues::DoneParsing() const {
return (m_pos >= stop);
}
-void Cues::Init() const {
+bool Cues::Init() const {
if (m_cue_points)
- return;
+ return true;
assert(m_count == 0);
assert(m_preload_count == 0);
@@ -2172,24 +1773,28 @@ void Cues::Init() const {
long len;
const long long id = ReadUInt(pReader, pos, len);
- assert(id >= 0); // TODO
- assert((pos + len) <= stop);
+ if (id < 0 || (pos + len) > stop) {
+ return false;
+ }
pos += len; // consume ID
const long long size = ReadUInt(pReader, pos, len);
- assert(size >= 0);
- assert((pos + len) <= stop);
+ if (size < 0 || (pos + len > stop)) {
+ return false;
+ }
pos += len; // consume Size field
- assert((pos + size) <= stop);
+ if (pos + size > stop) {
+ return false;
+ }
if (id == 0x3B) // CuePoint ID
PreloadCuePoint(cue_points_size, idpos);
- pos += size; // consume payload
- assert(pos <= stop);
+ pos += size; // skip payload
}
+ return true;
}
void Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
@@ -2198,7 +1803,7 @@ void Cues::PreloadCuePoint(long& cue_points_size, long long pos) const {
if (m_preload_count >= cue_points_size) {
const long n = (cue_points_size <= 0) ? 2048 : 2 * cue_points_size;
- CuePoint** const qq = new CuePoint* [n];
+ CuePoint** const qq = new CuePoint*[n];
CuePoint** q = qq; // beginning of target
CuePoint** p = m_cue_points; // beginning of source
@@ -2226,7 +1831,10 @@ bool Cues::LoadCuePoint() const {
if (m_pos >= stop)
return false; // nothing else to do
- Init();
+ if (!Init()) {
+ m_pos = stop;
+ return false;
+ }
IMkvReader* const pReader = m_pSegment->m_pReader;
@@ -2263,7 +1871,10 @@ bool Cues::LoadCuePoint() const {
if (pCP->GetTimeCode() < 0 && (-pCP->GetTimeCode() != idpos))
return false;
- pCP->Load(pReader);
+ if (!pCP->Load(pReader)) {
+ m_pos = stop;
+ return false;
+ }
++m_count;
--m_preload_count;
@@ -2282,62 +1893,6 @@ bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
assert(time_ns >= 0);
assert(pTrack);
-#if 0
- LoadCuePoint(); //establish invariant
-
- assert(m_cue_points);
- assert(m_count > 0);
-
- CuePoint** const ii = m_cue_points;
- CuePoint** i = ii;
-
- CuePoint** const jj = ii + m_count + m_preload_count;
- CuePoint** j = jj;
-
- pCP = *i;
- assert(pCP);
-
- if (time_ns <= pCP->GetTime(m_pSegment))
- {
- pTP = pCP->Find(pTrack);
- return (pTP != NULL);
- }
-
- IMkvReader* const pReader = m_pSegment->m_pReader;
-
- while (i < j)
- {
- //INVARIANT:
- //[ii, i) <= time_ns
- //[i, j) ?
- //[j, jj) > time_ns
-
- CuePoint** const k = i + (j - i) / 2;
- assert(k < jj);
-
- CuePoint* const pCP = *k;
- assert(pCP);
-
- pCP->Load(pReader);
-
- const long long t = pCP->GetTime(m_pSegment);
-
- if (t <= time_ns)
- i = k + 1;
- else
- j = k;
-
- assert(i <= j);
- }
-
- assert(i == j);
- assert(i <= jj);
- assert(i > ii);
-
- pCP = *--i;
- assert(pCP);
- assert(pCP->GetTime(m_pSegment) <= time_ns);
-#else
if (m_cue_points == NULL)
return false;
@@ -2387,7 +1942,6 @@ bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
pCP = *--i;
assert(pCP);
assert(pCP->GetTime(m_pSegment) <= time_ns);
-#endif
// TODO: here and elsewhere, it's probably not correct to search
// for the cue point with this time, and then search for a matching
@@ -2401,65 +1955,6 @@ bool Cues::Find(long long time_ns, const Track* pTrack, const CuePoint*& pCP,
return (pTP != NULL);
}
-#if 0
-bool Cues::FindNext(
- long long time_ns,
- const Track* pTrack,
- const CuePoint*& pCP,
- const CuePoint::TrackPosition*& pTP) const
-{
- pCP = 0;
- pTP = 0;
-
- if (m_count == 0)
- return false;
-
- assert(m_cue_points);
-
- const CuePoint* const* const ii = m_cue_points;
- const CuePoint* const* i = ii;
-
- const CuePoint* const* const jj = ii + m_count;
- const CuePoint* const* j = jj;
-
- while (i < j)
- {
- //INVARIANT:
- //[ii, i) <= time_ns
- //[i, j) ?
- //[j, jj) > time_ns
-
- const CuePoint* const* const k = i + (j - i) / 2;
- assert(k < jj);
-
- pCP = *k;
- assert(pCP);
-
- const long long t = pCP->GetTime(m_pSegment);
-
- if (t <= time_ns)
- i = k + 1;
- else
- j = k;
-
- assert(i <= j);
- }
-
- assert(i == j);
- assert(i <= jj);
-
- if (i >= jj) //time_ns is greater than max cue point
- return false;
-
- pCP = *i;
- assert(pCP);
- assert(pCP->GetTime(m_pSegment) > time_ns);
-
- pTP = pCP->Find(pTrack);
- return (pTP != NULL);
-}
-#endif
-
const CuePoint* Cues::GetFirst() const {
if (m_cue_points == NULL)
return NULL;
@@ -2467,15 +1962,6 @@ const CuePoint* Cues::GetFirst() const {
if (m_count == 0)
return NULL;
-#if 0
- LoadCuePoint(); //init cues
-
- const size_t count = m_count + m_preload_count;
-
- if (count == 0) //weird
- return NULL;
-#endif
-
CuePoint* const* const pp = m_cue_points;
assert(pp);
@@ -2493,34 +1979,14 @@ const CuePoint* Cues::GetLast() const {
if (m_count <= 0)
return NULL;
-#if 0
- LoadCuePoint(); //init cues
-
- const size_t count = m_count + m_preload_count;
+ const long index = m_count - 1;
- if (count == 0) //weird
- return NULL;
-
- const size_t index = count - 1;
-
- CuePoint* const* const pp = m_cue_points;
- assert(pp);
-
- CuePoint* const pCP = pp[index];
- assert(pCP);
-
- pCP->Load(m_pSegment->m_pReader);
- assert(pCP->GetTimeCode() >= 0);
-#else
- const long index = m_count - 1;
-
- CuePoint* const* const pp = m_cue_points;
- assert(pp);
+ CuePoint* const* const pp = m_cue_points;
+ assert(pp);
CuePoint* const pCP = pp[index];
assert(pCP);
assert(pCP->GetTimeCode() >= 0);
-#endif
return pCP;
}
@@ -2533,26 +1999,6 @@ const CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
assert(m_cue_points);
assert(m_count >= 1);
-#if 0
- const size_t count = m_count + m_preload_count;
-
- size_t index = pCurr->m_index;
- assert(index < count);
-
- CuePoint* const* const pp = m_cue_points;
- assert(pp);
- assert(pp[index] == pCurr);
-
- ++index;
-
- if (index >= count)
- return NULL;
-
- CuePoint* const pNext = pp[index];
- assert(pNext);
-
- pNext->Load(m_pSegment->m_pReader);
-#else
long index = pCurr->m_index;
assert(index < m_count);
@@ -2568,7 +2014,6 @@ const CuePoint* Cues::GetNext(const CuePoint* pCurr) const {
CuePoint* const pNext = pp[index];
assert(pNext);
assert(pNext->GetTimeCode() >= 0);
-#endif
return pNext;
}
@@ -2705,12 +2150,12 @@ CuePoint::CuePoint(long idx, long long pos)
CuePoint::~CuePoint() { delete[] m_track_positions; }
-void CuePoint::Load(IMkvReader* pReader) {
+bool CuePoint::Load(IMkvReader* pReader) {
// odbgstream os;
// os << "CuePoint::Load(begin): timecode=" << m_timecode << endl;
if (m_timecode >= 0) // already loaded
- return;
+ return true;
assert(m_track_positions == NULL);
assert(m_track_positions_count == 0);
@@ -2726,7 +2171,7 @@ void CuePoint::Load(IMkvReader* pReader) {
const long long id = ReadUInt(pReader, pos_, len);
assert(id == 0x3B); // CuePoint ID
if (id != 0x3B)
- return;
+ return false;
pos_ += len; // consume ID
@@ -2749,17 +2194,21 @@ void CuePoint::Load(IMkvReader* pReader) {
long len;
const long long id = ReadUInt(pReader, pos, len);
- assert(id >= 0); // TODO
- assert((pos + len) <= stop);
+ if ((id < 0) || (pos + len > stop)) {
+ return false;
+ }
pos += len; // consume ID
const long long size = ReadUInt(pReader, pos, len);
- assert(size >= 0);
- assert((pos + len) <= stop);
+ if ((size < 0) || (pos + len > stop)) {
+ return false;
+ }
pos += len; // consume Size field
- assert((pos + size) <= stop);
+ if ((pos + size) > stop) {
+ return false;
+ }
if (id == 0x33) // CueTime ID
m_timecode = UnserializeUInt(pReader, pos, size);
@@ -2768,11 +2217,11 @@ void CuePoint::Load(IMkvReader* pReader) {
++m_track_positions_count;
pos += size; // consume payload
- assert(pos <= stop);
}
- assert(m_timecode >= 0);
- assert(m_track_positions_count > 0);
+ if (m_timecode < 0 || m_track_positions_count <= 0) {
+ return false;
+ }
// os << "CuePoint::Load(cont'd): idpos=" << idpos
// << " timecode=" << m_timecode
@@ -2789,7 +2238,7 @@ void CuePoint::Load(IMkvReader* pReader) {
long len;
const long long id = ReadUInt(pReader, pos, len);
- assert(id >= 0); // TODO
+ assert(id >= 0);
assert((pos + len) <= stop);
pos += len; // consume ID
@@ -2803,7 +2252,9 @@ void CuePoint::Load(IMkvReader* pReader) {
if (id == 0x37) { // CueTrackPosition(s) ID
TrackPosition& tp = *p++;
- tp.Parse(pReader, pos, size);
+ if (!tp.Parse(pReader, pos, size)) {
+ return false;
+ }
}
pos += size; // consume payload
@@ -2814,9 +2265,11 @@ void CuePoint::Load(IMkvReader* pReader) {
m_element_start = element_start;
m_element_size = element_size;
+
+ return true;
}
-void CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
+bool CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
long long size_) {
const long long stop = start_ + size_;
long long pos = start_;
@@ -2829,17 +2282,21 @@ void CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
long len;
const long long id = ReadUInt(pReader, pos, len);
- assert(id >= 0); // TODO
- assert((pos + len) <= stop);
+ if ((id < 0) || ((pos + len) > stop)) {
+ return false;
+ }
pos += len; // consume ID
const long long size = ReadUInt(pReader, pos, len);
- assert(size >= 0);
- assert((pos + len) <= stop);
+ if ((size < 0) || ((pos + len) > stop)) {
+ return false;
+ }
pos += len; // consume Size field
- assert((pos + size) <= stop);
+ if ((pos + size) > stop) {
+ return false;
+ }
if (id == 0x77) // CueTrack ID
m_track = UnserializeUInt(pReader, pos, size);
@@ -2851,12 +2308,13 @@ void CuePoint::TrackPosition::Parse(IMkvReader* pReader, long long start_,
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);
+ if ((m_pos < 0) || (m_track <= 0)) {
+ return false;
+ }
+
+ return true;
}
const CuePoint::TrackPosition* CuePoint::Find(const Track* pTrack) const {
@@ -2894,20 +2352,6 @@ long long CuePoint::GetTime(const Segment* pSegment) const {
return time;
}
-#if 0
-long long Segment::Unparsed() const
-{
- if (m_size < 0)
- return LLONG_MAX;
-
- const long long stop = m_start + m_size;
-
- const long long result = stop - m_pos;
- assert(result >= 0);
-
- return result;
-}
-#else
bool Segment::DoneParsing() const {
if (m_size < 0) {
long long total, avail;
@@ -2927,7 +2371,6 @@ bool Segment::DoneParsing() const {
return (m_pos >= stop);
}
-#endif
const Cluster* Segment::GetFirst() const {
if ((m_clusters == NULL) || (m_clusterCount <= 0))
@@ -3395,15 +2838,7 @@ long Segment::DoParseNext(const Cluster*& pResult, long long& pos, long& len) {
continue;
}
-#if 0 // this is commented-out to support incremental cluster parsing
- len = static_cast<long>(size);
-
- if (element_stop > avail)
- return E_BUFFER_NOT_FULL;
-#endif
-
// We have a cluster.
-
off_next = idoff;
if (size != unknown_size)
@@ -3647,188 +3082,11 @@ const Cluster* Segment::FindCluster(long long time_ns) const {
return pCluster;
}
-#if 0
-const BlockEntry* Segment::Seek(
- long long time_ns,
- const Track* pTrack) const
-{
- assert(pTrack);
-
- if ((m_clusters == NULL) || (m_clusterCount <= 0))
- return pTrack->GetEOS();
-
- Cluster** const i = m_clusters;
- assert(i);
-
- {
- Cluster* const pCluster = *i;
- assert(pCluster);
- assert(pCluster->m_index == 0); //m_clusterCount > 0
- assert(pCluster->m_pSegment == this);
-
- if (time_ns <= pCluster->GetTime())
- return pCluster->GetEntry(pTrack);
- }
-
- Cluster** const j = i + m_clusterCount;
-
- if (pTrack->GetType() == 2) { //audio
- //TODO: we could decide to use cues for this, as we do for video.
- //But we only use it for video because looking around for a keyframe
- //can get expensive. Audio doesn't require anything special so a
- //straight cluster search is good enough (we assume).
-
- Cluster** lo = i;
- Cluster** hi = j;
-
- while (lo < hi)
- {
- //INVARIANT:
- //[i, lo) <= time_ns
- //[lo, hi) ?
- //[hi, j) > time_ns
-
- Cluster** const mid = lo + (hi - lo) / 2;
- assert(mid < hi);
-
- Cluster* const pCluster = *mid;
- assert(pCluster);
- assert(pCluster->m_index == long(mid - m_clusters));
- assert(pCluster->m_pSegment == this);
-
- const long long t = pCluster->GetTime();
-
- if (t <= time_ns)
- lo = mid + 1;
- else
- hi = mid;
-
- assert(lo <= hi);
- }
-
- assert(lo == hi);
- assert(lo > i);
- assert(lo <= j);
-
- while (lo > i)
- {
- Cluster* const pCluster = *--lo;
- assert(pCluster);
- assert(pCluster->GetTime() <= time_ns);
-
- const BlockEntry* const pBE = pCluster->GetEntry(pTrack);
-
- if ((pBE != 0) && !pBE->EOS())
- return pBE;
-
- //landed on empty cluster (no entries)
- }
-
- return pTrack->GetEOS(); //weird
- }
-
- assert(pTrack->GetType() == 1); //video
-
- Cluster** lo = i;
- Cluster** hi = j;
-
- while (lo < hi)
- {
- //INVARIANT:
- //[i, lo) <= time_ns
- //[lo, hi) ?
- //[hi, j) > time_ns
-
- Cluster** const mid = lo + (hi - lo) / 2;
- assert(mid < hi);
-
- Cluster* const pCluster = *mid;
- assert(pCluster);
-
- const long long t = pCluster->GetTime();
-
- if (t <= time_ns)
- lo = mid + 1;
- else
- hi = mid;
-
- assert(lo <= hi);
- }
-
- assert(lo == hi);
- assert(lo > i);
- assert(lo <= j);
-
- Cluster* pCluster = *--lo;
- assert(pCluster);
- assert(pCluster->GetTime() <= time_ns);
-
- {
- const BlockEntry* const pBE = pCluster->GetEntry(pTrack, time_ns);
-
- if ((pBE != 0) && !pBE->EOS()) //found a keyframe
- return pBE;
- }
-
- const VideoTrack* const pVideo = static_cast<const VideoTrack*>(pTrack);
-
- while (lo != i)
- {
- pCluster = *--lo;
- assert(pCluster);
- assert(pCluster->GetTime() <= time_ns);
-
- const BlockEntry* const pBlockEntry = pCluster->GetMaxKey(pVideo);
-
- if ((pBlockEntry != 0) && !pBlockEntry->EOS())
- return pBlockEntry;
- }
-
- //weird: we're on the first cluster, but no keyframe found
- //should never happen but we must return something anyway
-
- return pTrack->GetEOS();
-}
-#endif
-
-#if 0
-bool Segment::SearchCues(
- long long time_ns,
- Track* pTrack,
- Cluster*& pCluster,
- const BlockEntry*& pBlockEntry,
- const CuePoint*& pCP,
- const CuePoint::TrackPosition*& pTP)
-{
- if (pTrack->GetType() != 1) //not video
- return false; //TODO: for now, just handle video stream
-
- if (m_pCues == NULL)
- return false;
-
- if (!m_pCues->Find(time_ns, pTrack, pCP, pTP))
- return false; //weird
-
- assert(pCP);
- assert(pTP);
- assert(pTP->m_track == pTrack->GetNumber());
-
- //We have the cue point and track position we want,
- //so we now need to search for the cluster having
- //the indicated position.
-
- return GetCluster(pCP, pTP, pCluster, pBlockEntry);
-}
-#endif
-
const Tracks* Segment::GetTracks() const { return m_pTracks; }
-
const SegmentInfo* Segment::GetInfo() const { return m_pInfo; }
-
const Cues* Segment::GetCues() const { return m_pCues; }
-
const Chapters* Segment::GetChapters() const { return m_pChapters; }
-
+const Tags* Segment::GetTags() const { return m_pTags; }
const SeekHead* Segment::GetSeekHead() const { return m_pSeekHead; }
long long Segment::GetDuration() const {
@@ -3853,6 +3111,7 @@ Chapters::~Chapters() {
Edition& e = m_editions[--m_editions_count];
e.Clear();
}
+ delete[] m_editions;
}
long Chapters::Parse() {
@@ -4128,12 +3387,13 @@ long Chapters::Atom::Parse(IMkvReader* pReader, long long pos, long long size) {
if (status < 0) // error
return status;
} else if (id == 0x33C4) { // UID ID
- const long long val = UnserializeUInt(pReader, pos, size);
+ long long val;
+ status = UnserializeInt(pReader, pos, size, val);
- if (val < 0) // error
- return static_cast<long>(val);
+ if (status < 0) // error
+ return status;
- m_uid = val;
+ m_uid = static_cast<unsigned long long>(val);
} else if (id == 0x11) { // TimeStart ID
const long long val = UnserializeUInt(pReader, pos, size);
@@ -4181,79 +3441,351 @@ long long Chapters::Atom::GetTime(const Chapters* pChapters,
if (timecode < 0)
return -1;
- const long long result = timecode_scale * timecode;
+ const long long result = timecode_scale * timecode;
+
+ return result;
+}
+
+long Chapters::Atom::ParseDisplay(IMkvReader* pReader, long long pos,
+ long long size) {
+ if (!ExpandDisplaysArray())
+ return -1;
+
+ Display& d = m_displays[m_displays_count++];
+ d.Init();
+
+ return d.Parse(pReader, pos, size);
+}
+
+bool Chapters::Atom::ExpandDisplaysArray() {
+ if (m_displays_size > m_displays_count)
+ return true; // nothing else to do
+
+ const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size;
+
+ Display* const displays = new (std::nothrow) Display[size];
+
+ if (displays == NULL)
+ return false;
+
+ for (int idx = 0; idx < m_displays_count; ++idx) {
+ m_displays[idx].ShallowCopy(displays[idx]);
+ }
+
+ delete[] m_displays;
+ m_displays = displays;
+
+ m_displays_size = size;
+ return true;
+}
+
+Chapters::Display::Display() {}
+
+Chapters::Display::~Display() {}
+
+const char* Chapters::Display::GetString() const { return m_string; }
+
+const char* Chapters::Display::GetLanguage() const { return m_language; }
+
+const char* Chapters::Display::GetCountry() const { return m_country; }
+
+void Chapters::Display::Init() {
+ m_string = NULL;
+ m_language = NULL;
+ m_country = NULL;
+}
+
+void Chapters::Display::ShallowCopy(Display& rhs) const {
+ rhs.m_string = m_string;
+ rhs.m_language = m_language;
+ rhs.m_country = m_country;
+}
+
+void Chapters::Display::Clear() {
+ delete[] m_string;
+ m_string = NULL;
+
+ delete[] m_language;
+ m_language = NULL;
+
+ delete[] m_country;
+ m_country = NULL;
+}
+
+long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
+ long long size) {
+ const long long stop = pos + size;
+
+ while (pos < stop) {
+ long long id, size;
+
+ long status = ParseElementHeader(pReader, pos, stop, id, size);
+
+ if (status < 0) // error
+ return status;
+
+ if (size == 0) // weird
+ continue;
+
+ if (id == 0x05) { // ChapterString ID
+ status = UnserializeString(pReader, pos, size, m_string);
+
+ if (status)
+ return status;
+ } else if (id == 0x037C) { // ChapterLanguage ID
+ status = UnserializeString(pReader, pos, size, m_language);
+
+ if (status)
+ return status;
+ } else if (id == 0x037E) { // ChapterCountry ID
+ status = UnserializeString(pReader, pos, size, m_country);
+
+ if (status)
+ return status;
+ }
+
+ pos += size;
+ assert(pos <= stop);
+ }
+
+ assert(pos == stop);
+ return 0;
+}
+
+Tags::Tags(Segment* pSegment, long long payload_start, long long payload_size,
+ long long element_start, long long element_size)
+ : m_pSegment(pSegment),
+ m_start(payload_start),
+ m_size(payload_size),
+ m_element_start(element_start),
+ m_element_size(element_size),
+ m_tags(NULL),
+ m_tags_size(0),
+ m_tags_count(0) {}
+
+Tags::~Tags() {
+ while (m_tags_count > 0) {
+ Tag& t = m_tags[--m_tags_count];
+ t.Clear();
+ }
+ delete[] m_tags;
+}
+
+long Tags::Parse() {
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ long long pos = m_start; // payload start
+ const long long stop = pos + m_size; // payload stop
+
+ while (pos < stop) {
+ long long id, size;
+
+ long status = ParseElementHeader(pReader, pos, stop, id, size);
+
+ if (status < 0)
+ return status;
+
+ if (size == 0) // 0 length tag, read another
+ continue;
+
+ if (id == 0x3373) { // Tag ID
+ status = ParseTag(pos, size);
+
+ if (status < 0)
+ return status;
+ }
+
+ pos += size;
+ assert(pos <= stop);
+ if (pos > stop)
+ return -1;
+ }
+
+ assert(pos == stop);
+ if (pos != stop)
+ return -1;
+
+ return 0;
+}
+
+int Tags::GetTagCount() const { return m_tags_count; }
+
+const Tags::Tag* Tags::GetTag(int idx) const {
+ if (idx < 0)
+ return NULL;
+
+ if (idx >= m_tags_count)
+ return NULL;
+
+ return m_tags + idx;
+}
+
+bool Tags::ExpandTagsArray() {
+ if (m_tags_size > m_tags_count)
+ return true; // nothing else to do
+
+ const int size = (m_tags_size == 0) ? 1 : 2 * m_tags_size;
+
+ Tag* const tags = new (std::nothrow) Tag[size];
+
+ if (tags == NULL)
+ return false;
+
+ for (int idx = 0; idx < m_tags_count; ++idx) {
+ m_tags[idx].ShallowCopy(tags[idx]);
+ }
+
+ delete[] m_tags;
+ m_tags = tags;
+
+ m_tags_size = size;
+ return true;
+}
+
+long Tags::ParseTag(long long pos, long long size) {
+ if (!ExpandTagsArray())
+ return -1;
+
+ Tag& t = m_tags[m_tags_count++];
+ t.Init();
+
+ return t.Parse(m_pSegment->m_pReader, pos, size);
+}
+
+Tags::Tag::Tag() {}
+
+Tags::Tag::~Tag() {}
+
+int Tags::Tag::GetSimpleTagCount() const { return m_simple_tags_count; }
+
+const Tags::SimpleTag* Tags::Tag::GetSimpleTag(int index) const {
+ if (index < 0)
+ return NULL;
+
+ if (index >= m_simple_tags_count)
+ return NULL;
+
+ return m_simple_tags + index;
+}
+
+void Tags::Tag::Init() {
+ m_simple_tags = NULL;
+ m_simple_tags_size = 0;
+ m_simple_tags_count = 0;
+}
+
+void Tags::Tag::ShallowCopy(Tag& rhs) const {
+ rhs.m_simple_tags = m_simple_tags;
+ rhs.m_simple_tags_size = m_simple_tags_size;
+ rhs.m_simple_tags_count = m_simple_tags_count;
+}
+
+void Tags::Tag::Clear() {
+ while (m_simple_tags_count > 0) {
+ SimpleTag& d = m_simple_tags[--m_simple_tags_count];
+ d.Clear();
+ }
+
+ delete[] m_simple_tags;
+ m_simple_tags = NULL;
+
+ m_simple_tags_size = 0;
+}
+
+long Tags::Tag::Parse(IMkvReader* pReader, long long pos, long long size) {
+ const long long stop = pos + size;
+
+ while (pos < stop) {
+ long long id, size;
+
+ long status = ParseElementHeader(pReader, pos, stop, id, size);
+
+ if (status < 0)
+ return status;
+
+ if (size == 0) // 0 length tag, read another
+ continue;
+
+ if (id == 0x27C8) { // SimpleTag ID
+ status = ParseSimpleTag(pReader, pos, size);
+
+ if (status < 0)
+ return status;
+ }
+
+ pos += size;
+ assert(pos <= stop);
+ if (pos > stop)
+ return -1;
+ }
- return result;
+ assert(pos == stop);
+ if (pos != stop)
+ return -1;
+ return 0;
}
-long Chapters::Atom::ParseDisplay(IMkvReader* pReader, long long pos,
- long long size) {
- if (!ExpandDisplaysArray())
+long Tags::Tag::ParseSimpleTag(IMkvReader* pReader, long long pos,
+ long long size) {
+ if (!ExpandSimpleTagsArray())
return -1;
- Display& d = m_displays[m_displays_count++];
- d.Init();
+ SimpleTag& st = m_simple_tags[m_simple_tags_count++];
+ st.Init();
- return d.Parse(pReader, pos, size);
+ return st.Parse(pReader, pos, size);
}
-bool Chapters::Atom::ExpandDisplaysArray() {
- if (m_displays_size > m_displays_count)
+bool Tags::Tag::ExpandSimpleTagsArray() {
+ if (m_simple_tags_size > m_simple_tags_count)
return true; // nothing else to do
- const int size = (m_displays_size == 0) ? 1 : 2 * m_displays_size;
+ const int size = (m_simple_tags_size == 0) ? 1 : 2 * m_simple_tags_size;
- Display* const displays = new (std::nothrow) Display[size];
+ SimpleTag* const displays = new (std::nothrow) SimpleTag[size];
if (displays == NULL)
return false;
- for (int idx = 0; idx < m_displays_count; ++idx) {
- m_displays[idx].ShallowCopy(displays[idx]);
+ for (int idx = 0; idx < m_simple_tags_count; ++idx) {
+ m_simple_tags[idx].ShallowCopy(displays[idx]);
}
- delete[] m_displays;
- m_displays = displays;
+ delete[] m_simple_tags;
+ m_simple_tags = displays;
- m_displays_size = size;
+ m_simple_tags_size = size;
return true;
}
-Chapters::Display::Display() {}
-
-Chapters::Display::~Display() {}
+Tags::SimpleTag::SimpleTag() {}
-const char* Chapters::Display::GetString() const { return m_string; }
+Tags::SimpleTag::~SimpleTag() {}
-const char* Chapters::Display::GetLanguage() const { return m_language; }
+const char* Tags::SimpleTag::GetTagName() const { return m_tag_name; }
-const char* Chapters::Display::GetCountry() const { return m_country; }
+const char* Tags::SimpleTag::GetTagString() const { return m_tag_string; }
-void Chapters::Display::Init() {
- m_string = NULL;
- m_language = NULL;
- m_country = NULL;
+void Tags::SimpleTag::Init() {
+ m_tag_name = NULL;
+ m_tag_string = NULL;
}
-void Chapters::Display::ShallowCopy(Display& rhs) const {
- rhs.m_string = m_string;
- rhs.m_language = m_language;
- rhs.m_country = m_country;
+void Tags::SimpleTag::ShallowCopy(SimpleTag& rhs) const {
+ rhs.m_tag_name = m_tag_name;
+ rhs.m_tag_string = m_tag_string;
}
-void Chapters::Display::Clear() {
- delete[] m_string;
- m_string = NULL;
-
- delete[] m_language;
- m_language = NULL;
+void Tags::SimpleTag::Clear() {
+ delete[] m_tag_name;
+ m_tag_name = NULL;
- delete[] m_country;
- m_country = NULL;
+ delete[] m_tag_string;
+ m_tag_string = NULL;
}
-long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
- long long size) {
+long Tags::SimpleTag::Parse(IMkvReader* pReader, long long pos,
+ long long size) {
const long long stop = pos + size;
while (pos < stop) {
@@ -4267,18 +3799,13 @@ long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
if (size == 0) // weird
continue;
- if (id == 0x05) { // ChapterString ID
- status = UnserializeString(pReader, pos, size, m_string);
-
- if (status)
- return status;
- } else if (id == 0x037C) { // ChapterLanguage ID
- status = UnserializeString(pReader, pos, size, m_language);
+ if (id == 0x5A3) { // TagName ID
+ status = UnserializeString(pReader, pos, size, m_tag_name);
if (status)
return status;
- } else if (id == 0x037E) { // ChapterCountry ID
- status = UnserializeString(pReader, pos, size, m_country);
+ } else if (id == 0x487) { // TagString ID
+ status = UnserializeString(pReader, pos, size, m_tag_string);
if (status)
return status;
@@ -4286,9 +3813,13 @@ long Chapters::Display::Parse(IMkvReader* pReader, long long pos,
pos += size;
assert(pos <= stop);
+ if (pos > stop)
+ return -1;
}
assert(pos == stop);
+ if (pos != stop)
+ return -1;
return 0;
}
@@ -4458,7 +3989,7 @@ ContentEncoding::~ContentEncoding() {
}
const ContentEncoding::ContentCompression*
-ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
+ ContentEncoding::GetCompressionByIndex(unsigned long idx) const {
const ptrdiff_t count = compression_entries_end_ - compression_entries_;
assert(count >= 0);
@@ -4554,7 +4085,7 @@ long ContentEncoding::ParseContentEncodingEntry(long long start, long long size,
if (compression_count > 0) {
compression_entries_ =
- new (std::nothrow) ContentCompression* [compression_count];
+ new (std::nothrow) ContentCompression*[compression_count];
if (!compression_entries_)
return -1;
compression_entries_end_ = compression_entries_;
@@ -4562,7 +4093,7 @@ long ContentEncoding::ParseContentEncodingEntry(long long start, long long size,
if (encryption_count > 0) {
encryption_entries_ =
- new (std::nothrow) ContentEncryption* [encryption_count];
+ new (std::nothrow) ContentEncryption*[encryption_count];
if (!encryption_entries_) {
delete[] compression_entries_;
return -1;
@@ -4703,7 +4234,7 @@ long ContentEncoding::ParseEncryptionEntry(long long start, long long size,
return E_FILE_FORMAT_INVALID;
} else if (id == 0x7E2) {
// ContentEncKeyID
- delete[] encryption -> key_id;
+ delete[] encryption->key_id;
encryption->key_id = NULL;
encryption->key_id_len = 0;
@@ -4727,7 +4258,7 @@ long ContentEncoding::ParseEncryptionEntry(long long start, long long size,
encryption->key_id_len = buflen;
} else if (id == 0x7E3) {
// ContentSignature
- delete[] encryption -> signature;
+ delete[] encryption->signature;
encryption->signature = NULL;
encryption->signature_len = 0;
@@ -4751,7 +4282,7 @@ long ContentEncoding::ParseEncryptionEntry(long long start, long long size,
encryption->signature_len = buflen;
} else if (id == 0x7E4) {
// ContentSigKeyID
- delete[] encryption -> sig_key_id;
+ delete[] encryption->sig_key_id;
encryption->sig_key_id = NULL;
encryption->sig_key_id_len = 0;
@@ -4991,17 +4522,10 @@ long Track::GetFirst(const BlockEntry*& pBlockEntry) const {
}
if (pCluster->EOS()) {
-#if 0
- if (m_pSegment->Unparsed() <= 0) { //all clusters have been loaded
- pBlockEntry = GetEOS();
- return 1;
- }
-#else
if (m_pSegment->DoneParsing()) {
pBlockEntry = GetEOS();
return 1;
}
-#endif
pBlockEntry = 0;
return E_BUFFER_NOT_FULL;
@@ -5098,18 +4622,10 @@ long Track::GetNext(const BlockEntry* pCurrEntry,
}
if (pCluster->EOS()) {
-#if 0
- if (m_pSegment->Unparsed() <= 0) //all clusters have been loaded
- {
- pNextEntry = GetEOS();
- return 1;
- }
-#else
if (m_pSegment->DoneParsing()) {
pNextEntry = GetEOS();
return 1;
}
-#endif
// TODO: there is a potential O(n^2) problem here: we tell the
// caller to (pre)load another cluster, which he does, but then he
@@ -5291,7 +4807,7 @@ long Track::ParseContentEncodingsEntry(long long start, long long size) {
if (count <= 0)
return -1;
- content_encoding_entries_ = new (std::nothrow) ContentEncoding* [count];
+ content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
if (!content_encoding_entries_)
return -1;
@@ -5350,6 +4866,11 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
long long width = 0;
long long height = 0;
+ long long display_width = 0;
+ long long display_height = 0;
+ long long display_unit = 0;
+ long long stereo_mode = 0;
+
double rate = 0.0;
IMkvReader* const pReader = pSegment->m_pReader;
@@ -5381,6 +4902,26 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
if (height <= 0)
return E_FILE_FORMAT_INVALID;
+ } else if (id == 0x14B0) { // display width
+ display_width = UnserializeUInt(pReader, pos, size);
+
+ if (display_width <= 0)
+ return E_FILE_FORMAT_INVALID;
+ } else if (id == 0x14BA) { // display height
+ display_height = UnserializeUInt(pReader, pos, size);
+
+ if (display_height <= 0)
+ return E_FILE_FORMAT_INVALID;
+ } else if (id == 0x14B2) { // display unit
+ display_unit = UnserializeUInt(pReader, pos, size);
+
+ if (display_unit < 0)
+ return E_FILE_FORMAT_INVALID;
+ } else if (id == 0x13B8) { // stereo mode
+ stereo_mode = UnserializeUInt(pReader, pos, size);
+
+ if (stereo_mode < 0)
+ return E_FILE_FORMAT_INVALID;
} else if (id == 0x0383E3) { // frame rate
const long status = UnserializeFloat(pReader, pos, size, rate);
@@ -5412,6 +4953,10 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
pTrack->m_width = width;
pTrack->m_height = height;
+ pTrack->m_display_width = display_width;
+ pTrack->m_display_height = display_height;
+ pTrack->m_display_unit = display_unit;
+ pTrack->m_stereo_mode = stereo_mode;
pTrack->m_rate = rate;
pResult = pTrack;
@@ -5498,16 +5043,7 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
assert(pCluster);
assert(pCluster->GetTime() <= time_ns);
-#if 0
- //TODO:
- //We need to handle the case when a cluster
- //contains multiple keyframes. Simply returning
- //the largest keyframe on the cluster isn't
- //good enough.
- pResult = pCluster->GetMaxKey(this);
-#else
pResult = pCluster->GetEntry(this, time_ns);
-#endif
if ((pResult != 0) && !pResult->EOS())
return 0;
@@ -5524,6 +5060,18 @@ long long VideoTrack::GetWidth() const { return m_width; }
long long VideoTrack::GetHeight() const { return m_height; }
+long long VideoTrack::GetDisplayWidth() const {
+ return m_display_width > 0 ? m_display_width : GetWidth();
+}
+
+long long VideoTrack::GetDisplayHeight() const {
+ return m_display_height > 0 ? m_display_height : GetHeight();
+}
+
+long long VideoTrack::GetDisplayUnit() const { return m_display_unit; }
+
+long long VideoTrack::GetStereoMode() const { return m_stereo_mode; }
+
double VideoTrack::GetFrameRate() const { return m_rate; }
AudioTrack::AudioTrack(Segment* pSegment, long long element_start,
@@ -5658,7 +5206,7 @@ long Tracks::Parse() {
if (count <= 0)
return 0; // success
- m_trackEntries = new (std::nothrow) Track* [count];
+ m_trackEntries = new (std::nothrow) Track*[count];
if (m_trackEntries == NULL)
return -1;
@@ -5941,7 +5489,7 @@ long Tracks::ParseTrackEntry(long long track_start, long long track_size,
if (v.start >= 0)
return E_FILE_FORMAT_INVALID;
- if (e.start >= 0)
+ if (info.type == Track::kMetadata && e.start >= 0)
return E_FILE_FORMAT_INVALID;
info.settings.start = -1;
@@ -6003,25 +5551,6 @@ const Track* Tracks::GetTrackByIndex(unsigned long idx) const {
return m_trackEntries[idx];
}
-#if 0
-long long Cluster::Unparsed() const
-{
- if (m_timecode < 0) //not even partially loaded
- return LLONG_MAX;
-
- assert(m_pos >= m_element_start);
- //assert(m_element_size > m_size);
-
- const long long element_stop = m_element_start + m_element_size;
- assert(m_pos <= element_stop);
-
- const long long result = element_stop - m_pos;
- assert(result >= 0);
-
- return result;
-}
-#endif
-
long Cluster::Load(long long& pos, long& len) const {
assert(m_pSegment);
assert(m_pos >= m_element_start);
@@ -6115,15 +5644,7 @@ long Cluster::Load(long long& pos, long& len) const {
cluster_size = size;
}
-// pos points to start of payload
-
-#if 0
- len = static_cast<long>(size_);
-
- if (cluster_stop > avail)
- return E_BUFFER_NOT_FULL;
-#endif
-
+ // pos points to start of payload
long long timecode = -1;
long long new_pos = -1;
bool bBlock = false;
@@ -6495,36 +6016,6 @@ long Cluster::ParseSimpleBlock(long long block_size, long long& pos,
if (track == 0)
return E_FILE_FORMAT_INVALID;
-#if 0
- //TODO(matthewjheaney)
- //This turned out to be too conservative. The problem is that
- //if we see a track header in the tracks element with an unsupported
- //track type, we throw that track header away, so it is not present
- //in the track map. But even though we don't understand the track
- //header, there are still blocks in the cluster with that track
- //number. It was our decision to ignore that track header, so it's
- //up to us to deal with blocks associated with that track -- we
- //cannot simply report an error since technically there's nothing
- //wrong with the file.
- //
- //For now we go ahead and finish the parse, creating a block entry
- //for this block. This is somewhat wasteful, because without a
- //track header there's nothing you can do with the block. What
- //we really need here is a special return value that indicates to
- //the caller that he should ignore this particular block, and
- //continue parsing.
-
- const Tracks* const pTracks = m_pSegment->GetTracks();
- assert(pTracks);
-
- const long tn = static_cast<long>(track);
-
- const Track* const pTrack = pTracks->GetTrackByNumber(tn);
-
- if (pTrack == NULL)
- return E_FILE_FORMAT_INVALID;
-#endif
-
pos += len; // consume track number
if ((pos + 2) > block_stop)
@@ -6679,12 +6170,7 @@ long Cluster::ParseBlockGroup(long long payload_size, long long& pos,
return E_FILE_FORMAT_INVALID;
if (id == 0x35A2) { // DiscardPadding
- result = GetUIntLength(pReader, pos, len);
-
- if (result < 0) // error
- return static_cast<long>(result);
-
- status = UnserializeInt(pReader, pos, len, discard_padding);
+ status = UnserializeInt(pReader, pos, size, discard_padding);
if (status < 0) // error
return status;
@@ -6733,36 +6219,6 @@ long Cluster::ParseBlockGroup(long long payload_size, long long& pos,
if (track == 0)
return E_FILE_FORMAT_INVALID;
-#if 0
- //TODO(matthewjheaney)
- //This turned out to be too conservative. The problem is that
- //if we see a track header in the tracks element with an unsupported
- //track type, we throw that track header away, so it is not present
- //in the track map. But even though we don't understand the track
- //header, there are still blocks in the cluster with that track
- //number. It was our decision to ignore that track header, so it's
- //up to us to deal with blocks associated with that track -- we
- //cannot simply report an error since technically there's nothing
- //wrong with the file.
- //
- //For now we go ahead and finish the parse, creating a block entry
- //for this block. This is somewhat wasteful, because without a
- //track header there's nothing you can do with the block. What
- //we really need here is a special return value that indicates to
- //the caller that he should ignore this particular block, and
- //continue parsing.
-
- const Tracks* const pTracks = m_pSegment->GetTracks();
- assert(pTracks);
-
- const long tn = static_cast<long>(track);
-
- const Track* const pTrack = pTracks->GetTrackByNumber(tn);
-
- if (pTrack == NULL)
- return E_FILE_FORMAT_INVALID;
-#endif
-
pos += len; // consume track number
if ((pos + 2) > block_stop)
@@ -6924,68 +6380,6 @@ long long Cluster::GetPosition() const {
long long Cluster::GetElementSize() const { return m_element_size; }
-#if 0
-bool Cluster::HasBlockEntries(
- const Segment* pSegment,
- long long off) {
- assert(pSegment);
- assert(off >= 0); //relative to start of segment payload
-
- IMkvReader* const pReader = pSegment->m_pReader;
-
- long long pos = pSegment->m_start + off; //absolute
- long long size;
-
- {
- long len;
-
- const long long id = ReadUInt(pReader, pos, len);
- (void)id;
- assert(id >= 0);
- assert(id == 0x0F43B675); //Cluster ID
-
- pos += len; //consume id
-
- size = ReadUInt(pReader, pos, len);
- assert(size > 0);
-
- pos += len; //consume size
-
- //pos now points to start of payload
- }
-
- const long long stop = pos + size;
-
- 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); //TODO
- assert((pos + len) <= stop);
-
- pos += len; //consume size
-
- if (id == 0x20) //BlockGroup ID
- return true;
-
- if (id == 0x23) //SimpleBlock ID
- return true;
-
- pos += size; //consume payload
- assert(pos <= stop);
- }
-
- return false;
-}
-#endif
-
long Cluster::HasBlockEntries(
const Segment* pSegment,
long long off, // relative to start of segment payload
@@ -7269,7 +6663,7 @@ long Cluster::CreateBlock(long long id,
assert(m_entries_size == 0);
m_entries_size = 1024;
- m_entries = new BlockEntry* [m_entries_size];
+ m_entries = new BlockEntry*[m_entries_size];
m_entries_count = 0;
} else {
@@ -7280,7 +6674,7 @@ long Cluster::CreateBlock(long long id,
if (m_entries_count >= m_entries_size) {
const long entries_size = 2 * m_entries_size;
- BlockEntry** const entries = new BlockEntry* [entries_size];
+ BlockEntry** const entries = new BlockEntry*[entries_size];
assert(entries);
BlockEntry** src = m_entries;
@@ -7349,12 +6743,16 @@ long Cluster::CreateBlockGroup(long long start_offset, long long size,
bsize = size;
}
} else if (id == 0x1B) { // Duration ID
- assert(size <= 8);
+ if (size > 8)
+ return E_FILE_FORMAT_INVALID;
duration = UnserializeUInt(pReader, pos, size);
- assert(duration >= 0); // TODO
+
+ if (duration < 0)
+ return E_FILE_FORMAT_INVALID;
} else if (id == 0x7B) { // ReferenceBlock
- assert(size <= 8);
+ if (size > 8 || size <= 0)
+ return E_FILE_FORMAT_INVALID;
const long size_ = static_cast<long>(size);
long long time;
@@ -7373,9 +6771,10 @@ long Cluster::CreateBlockGroup(long long start_offset, long long size,
pos += size; // consume payload
assert(pos <= stop);
}
+ if (bpos < 0)
+ return E_FILE_FORMAT_INVALID;
assert(pos == stop);
- assert(bpos >= 0);
assert(bsize >= 0);
const long idx = m_entries_count;
@@ -7539,57 +6938,6 @@ const BlockEntry* Cluster::GetEntry(const Track* pTrack,
if (m_pSegment == NULL) // this is the special EOS cluster
return pTrack->GetEOS();
-#if 0
-
- LoadBlockEntries();
-
- if ((m_entries == NULL) || (m_entries_count <= 0))
- return NULL; //return EOS here?
-
- const BlockEntry* pResult = pTrack->GetEOS();
-
- BlockEntry** i = m_entries;
- assert(i);
-
- BlockEntry** const j = i + m_entries_count;
-
- while (i != j)
- {
- const BlockEntry* const pEntry = *i++;
- assert(pEntry);
- assert(!pEntry->EOS());
-
- const Block* const pBlock = pEntry->GetBlock();
- assert(pBlock);
-
- if (pBlock->GetTrackNumber() != pTrack->GetNumber())
- continue;
-
- if (pTrack->VetEntry(pEntry))
- {
- if (time_ns < 0) //just want first candidate block
- return pEntry;
-
- const long long ns = pBlock->GetTime(this);
-
- if (ns > time_ns)
- break;
-
- pResult = pEntry;
- }
- else if (time_ns >= 0)
- {
- const long long ns = pBlock->GetTime(this);
-
- if (ns > time_ns)
- break;
- }
- }
-
- return pResult;
-
-#else
-
const BlockEntry* pResult = pTrack->GetEOS();
long index = 0;
@@ -7643,103 +6991,11 @@ const BlockEntry* Cluster::GetEntry(const Track* pTrack,
++index;
}
-
-#endif
}
const BlockEntry* Cluster::GetEntry(const CuePoint& cp,
const CuePoint::TrackPosition& tp) const {
assert(m_pSegment);
-
-#if 0
-
- LoadBlockEntries();
-
- if (m_entries == NULL)
- return NULL;
-
- const long long count = m_entries_count;
-
- if (count <= 0)
- return NULL;
-
- const long long tc = cp.GetTimeCode();
-
- if ((tp.m_block > 0) && (tp.m_block <= count))
- {
- const size_t block = static_cast<size_t>(tp.m_block);
- const size_t index = block - 1;
-
- const BlockEntry* const pEntry = m_entries[index];
- assert(pEntry);
- assert(!pEntry->EOS());
-
- const Block* const pBlock = pEntry->GetBlock();
- assert(pBlock);
-
- if ((pBlock->GetTrackNumber() == tp.m_track) &&
- (pBlock->GetTimeCode(this) == tc))
- {
- return pEntry;
- }
- }
-
- const BlockEntry* const* i = m_entries;
- const BlockEntry* const* const j = i + count;
-
- while (i != j)
- {
-#ifdef _DEBUG
- const ptrdiff_t idx = i - m_entries;
- idx;
-#endif
-
- const BlockEntry* const pEntry = *i++;
- assert(pEntry);
- assert(!pEntry->EOS());
-
- const Block* const pBlock = pEntry->GetBlock();
- assert(pBlock);
-
- if (pBlock->GetTrackNumber() != tp.m_track)
- continue;
-
- const long long tc_ = pBlock->GetTimeCode(this);
- assert(tc_ >= 0);
-
- if (tc_ < tc)
- continue;
-
- if (tc_ > tc)
- return NULL;
-
- const Tracks* const pTracks = m_pSegment->GetTracks();
- assert(pTracks);
-
- const long tn = static_cast<long>(tp.m_track);
- const Track* const pTrack = pTracks->GetTrackByNumber(tn);
-
- if (pTrack == NULL)
- return NULL;
-
- const long long type = pTrack->GetType();
-
- if (type == 2) //audio
- return pEntry;
-
- if (type != 1) //not video
- return NULL;
-
- if (!pBlock->IsKey())
- return NULL;
-
- return pEntry;
- }
-
- return NULL;
-
-#else
-
const long long tc = cp.GetTimeCode();
if (tp.m_block > 0) {
@@ -7835,54 +7091,12 @@ const BlockEntry* Cluster::GetEntry(const CuePoint& cp,
return pEntry;
}
-
-#endif
-}
-
-#if 0
-const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
-{
- assert(pTrack);
-
- if (m_pSegment == NULL) //EOS
- return pTrack->GetEOS();
-
- LoadBlockEntries();
-
- if ((m_entries == NULL) || (m_entries_count <= 0))
- return pTrack->GetEOS();
-
- BlockEntry** i = m_entries + m_entries_count;
- BlockEntry** const j = m_entries;
-
- while (i != j)
- {
- const BlockEntry* const pEntry = *--i;
- assert(pEntry);
- assert(!pEntry->EOS());
-
- const Block* const pBlock = pEntry->GetBlock();
- assert(pBlock);
-
- if (pBlock->GetTrackNumber() != pTrack->GetNumber())
- continue;
-
- if (pBlock->IsKey())
- return pEntry;
- }
-
- return pTrack->GetEOS(); //no satisfactory block found
}
-#endif
BlockEntry::BlockEntry(Cluster* p, long idx) : m_pCluster(p), m_index(idx) {}
-
BlockEntry::~BlockEntry() {}
-
bool BlockEntry::EOS() const { return (GetKind() == kBlockEOS); }
-
const Cluster* BlockEntry::GetCluster() const { return m_pCluster; }
-
long BlockEntry::GetIndex() const { return m_index; }
SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start,
@@ -7890,9 +7104,7 @@ SimpleBlock::SimpleBlock(Cluster* pCluster, long idx, long long start,
: BlockEntry(pCluster, idx), m_block(start, size, 0) {}
long SimpleBlock::Parse() { return m_block.Parse(m_pCluster); }
-
BlockEntry::Kind SimpleBlock::GetKind() const { return kBlockSimple; }
-
const Block* SimpleBlock::GetBlock() const { return &m_block; }
BlockGroup::BlockGroup(Cluster* pCluster, long idx, long long block_start,
@@ -7915,30 +7127,10 @@ long BlockGroup::Parse() {
return 0;
}
-#if 0
-void BlockGroup::ParseBlock(long long start, long long size)
-{
- IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
-
- Block* const pBlock = new Block(start, size, pReader);
- assert(pBlock); //TODO
-
- //TODO: the Matroska spec says you have multiple blocks within the
- //same block group, with blocks ranked by priority (the flag bits).
-
- assert(m_pBlock == NULL);
- m_pBlock = pBlock;
-}
-#endif
-
BlockEntry::Kind BlockGroup::GetKind() const { return kBlockGroup; }
-
const Block* BlockGroup::GetBlock() const { return &m_block; }
-
long long BlockGroup::GetPrevTimeCode() const { return m_prev; }
-
long long BlockGroup::GetNextTimeCode() const { return m_next; }
-
long long BlockGroup::GetDurationTimeCode() const { return m_duration; }
Block::Block(long long start, long long size_, long long discard_padding)
@@ -8028,7 +7220,7 @@ long Block::Parse(const Cluster* pCluster) {
const long long frame_size = stop - pos;
- if (frame_size > LONG_MAX)
+ if (frame_size > LONG_MAX || frame_size <= 0)
return E_FILE_FORMAT_INVALID;
f.len = static_cast<long>(frame_size);
@@ -8088,6 +7280,9 @@ long Block::Parse(const Cluster* pCluster) {
f.pos = 0; // patch later
+ if (frame_size <= 0)
+ return E_FILE_FORMAT_INVALID;
+
f.len = frame_size;
size += frame_size; // contribution of this frame
@@ -8112,7 +7307,7 @@ long Block::Parse(const Cluster* pCluster) {
const long long frame_size = total_size - size;
- if (frame_size > LONG_MAX)
+ if (frame_size > LONG_MAX || frame_size <= 0)
return E_FILE_FORMAT_INVALID;
f.len = static_cast<long>(frame_size);
@@ -8129,6 +7324,9 @@ long Block::Parse(const Cluster* pCluster) {
assert(pos == stop);
} else if (lacing == 2) { // fixed-size lacing
+ if (pos >= stop)
+ return E_FILE_FORMAT_INVALID;
+
const long long total_size = stop - pos;
if ((total_size % m_frame_count) != 0)
@@ -8136,7 +7334,7 @@ long Block::Parse(const Cluster* pCluster) {
const long long frame_size = total_size / m_frame_count;
- if (frame_size > LONG_MAX)
+ if (frame_size > LONG_MAX || frame_size <= 0)
return E_FILE_FORMAT_INVALID;
Frame* pf = m_frames;
@@ -8165,7 +7363,7 @@ long Block::Parse(const Cluster* pCluster) {
long long frame_size = ReadUInt(pReader, pos, len);
- if (frame_size < 0)
+ if (frame_size <= 0)
return E_FILE_FORMAT_INVALID;
if (frame_size > LONG_MAX)
@@ -8227,7 +7425,7 @@ long Block::Parse(const Cluster* pCluster) {
frame_size += delta_size;
- if (frame_size < 0)
+ if (frame_size <= 0)
return E_FILE_FORMAT_INVALID;
if (frame_size > LONG_MAX)
@@ -8239,7 +7437,8 @@ long Block::Parse(const Cluster* pCluster) {
--frame_count;
}
- {
+ // parse last frame
+ if (frame_count > 0) {
assert(pos <= stop);
assert(pf < pf_end);
@@ -8262,7 +7461,7 @@ long Block::Parse(const Cluster* pCluster) {
frame_size = total_size - size;
- if (frame_size > LONG_MAX)
+ if (frame_size > LONG_MAX || frame_size <= 0)
return E_FILE_FORMAT_INVALID;
curr.len = static_cast<long>(frame_size);
@@ -8277,7 +7476,8 @@ long Block::Parse(const Cluster* pCluster) {
pos += f.len;
}
- assert(pos == stop);
+ if (pos != stop)
+ return E_FILE_FORMAT_INVALID;
}
return 0; // success
« no previous file with comments | « source/libvpx/third_party/libwebm/mkvparser.hpp ('k') | source/libvpx/third_party/libwebm/webmids.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698