Compare commits

...

11 Commits

Author SHA1 Message Date
matthewjheaney
35ded77a23 libwebm: change version to 1.0.0.21
Change-Id: Ic8ef4e8f02a3dc5b07939f0b09903d31dc4a403f
2011-03-28 13:04:26 -04:00
matthewjheaney
1f33611caa libwebm: bad assert in Cluster::GetEntry
Change-Id: I5bcee1f496260416b438a1c2632dd24e8b26eee4
2011-03-22 14:18:14 -04:00
matthewjheaney
70f9644a8d libwebm: restored Cluster::GetLast
Change-Id: I73564fb508e23004392b5aaab1f1ad7cdedc8bb1
2011-03-19 10:34:12 -04:00
matthewjheaney
f2bd78ef6b libwebm: changed semantics of LoadCuePoint retval
Change-Id: Iabbc82b24bde27c06b44b9f9f45e64215b9164c5
2011-03-19 09:54:41 -04:00
matthewjheaney
2083c72300 libwebm: removed LoadBlockEntries
Change-Id: I1d65c07d91de568573f48e9fddf83b4c5672871d
2011-03-18 21:43:06 -04:00
matthewjheaney
f5ec272e54 libwebm: removed Cluster::Load (non-incremental)
Change-Id: I1f2ad153e0c643d04fa1fe1ec85410bbef1954ef
2011-03-18 11:18:46 -04:00
matthewjheaney
b324e52139 libwebm: handle truncated segment
Change-Id: Iddd15a207bce4a2c26f72e5e35f736c1b3f700d7
2011-03-16 15:08:06 -04:00
matthewjheaney
4137f9c999 libwebm: v1.0.0.20
Change-Id: I8a93517762c0edecd59a38e2f4fc99566c7b2de5
2011-03-15 14:27:53 -04:00
matthewjheaney
ba4096f120 libwebm: fixed bug in LoadBlockEntries
Change-Id: I4a0870030803bcbb5502800ae5627f716d417440
2011-03-10 15:12:16 -05:00
matthewjheaney
365a39b5ec libwebm: set version to v1.0.0.19
Change-Id: I5e88dce1c52bc18bdab2063111830b5fbd0faafe
2011-03-09 11:04:21 -05:00
matthewjheaney
601f7903a3 libwebm: block group must parse ref times too
Change-Id: Iadf7674dfaf311e04f2eea35fc396e2eaab18163
2011-03-08 21:51:13 -05:00
2 changed files with 368 additions and 45 deletions

View File

@@ -21,7 +21,7 @@ void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision)
major = 1;
minor = 0;
build = 0;
revision = 18;
revision = 21;
}
long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
@@ -1007,8 +1007,13 @@ long long Segment::CreateInstance(
else if (total < 0)
size = -1;
#if 0 //this turned out to be too conservative:
else if ((pos + size) > end)
return E_FILE_FORMAT_INVALID;
#else //so do this instead
else if ((pos + size) > total)
size = -1;
#endif
pSegment = new (std::nothrow) Segment(pReader, pos, size);
@@ -1699,9 +1704,19 @@ long Segment::DoLoadCluster(
pos += cluster_size;
m_pos = pos;
assert((segment_stop < 0) || (m_pos <= segment_stop));
if ((total >= 0) && (pos >= total))
{
m_pos = total;
return 1; //no more clusters
}
if ((segment_stop >= 0) && (pos >= segment_stop))
{
m_pos = segment_stop;
return 1; //no more clusters
}
m_pos = pos;
return 2; //try again
}
@@ -1718,31 +1733,6 @@ long Segment::DoLoadCluster(
assert(idx < m_clusterSize);
assert(m_clusters[idx] == pCluster);
//we could handle this as follows.
//if the cluster_size is non-negative, then there's nothing special
//we need to do because we have the end of the cluster, and we're
//"parsing to find the next cluster" in the normal way.
//
//If we don't know have a cluster size, the last cluster object
//is created (or perhaps was already preloaded -- must still reason
//about this), but it doesn't have a known size yet. In this
//case the segment is in a different kind of state, "searching
//for end of last cluster object". We need a way to differentiate
//between these two states.
//
//This has the benefit that we could call cluster::parse on the
//(last) cluster object (with unknown size), and let it fill in
//the value of the cluster size when it is finally discovered.
//At that point the segment transitions out of the "find end of
//last cluster" state and into the "find next cluster" state.
//
//We could mark the segment as being in one state or the other
//using the sign of segment::m_pos: m_pos > 0 means "searching
//for next cluster" and m_pos < 0 means "searching to determine
//end of last cluster with unknown size". Positive m_pos means
//we're outside of a cluster and negative means we're inside
//a cluster.
if (cluster_size >= 0)
{
pos += cluster_size;
@@ -2612,6 +2602,9 @@ long Segment::ParseCues(
pos = m_start + off;
if ((total < 0) || (pos >= total))
return 1; //don't bother parsing cues
const long long element_start = pos;
const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
@@ -2691,6 +2684,9 @@ long Segment::ParseCues(
if ((segment_stop >= 0) && (element_stop > segment_stop))
return E_FILE_FORMAT_INVALID;
if ((total >= 0) && (element_stop > total))
return 1; //don't bother parsing anymore
len = static_cast<long>(size);
if (element_stop > avail)
@@ -3063,10 +3059,11 @@ bool Cues::LoadCuePoint() const
m_pos += size; //consume payload
assert(m_pos <= stop);
break;
return true; //yes, we loaded a cue point
}
return (m_pos < stop);
//return (m_pos < stop);
return false; //no, we did not load a cue point
}
@@ -3741,6 +3738,7 @@ long long CuePoint::GetTime(const Segment* pSegment) const
}
#if 0
long long Segment::Unparsed() const
{
if (m_size < 0)
@@ -3753,6 +3751,29 @@ long long Segment::Unparsed() const
return result;
}
#else
bool Segment::DoneParsing() const
{
if (m_size < 0)
{
long long total, avail;
const int status = m_pReader->Length(&total, &avail);
if (status < 0) //error
return true; //must assume done
if (total < 0)
return false; //assume live stream
return (m_pos >= total);
}
const long long stop = m_start + m_size;
return (m_pos >= stop);
}
#endif
const Cluster* Segment::GetFirst() const
@@ -4976,11 +4997,19 @@ 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;
@@ -5066,11 +5095,19 @@ long Track::GetNext(
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
@@ -5301,12 +5338,16 @@ long VideoTrack::Seek(
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;
@@ -5841,6 +5882,7 @@ long long Cluster::Unparsed() const
#endif
#if 0
void Cluster::Load() const
{
assert(m_pSegment);
@@ -5915,6 +5957,7 @@ void Cluster::Load() const
m_timecode = timecode;
}
#endif
long Cluster::Load(long long& pos, long& len) const
@@ -6494,7 +6537,16 @@ long Cluster::ParseBlockGroup(
assert((total < 0) || (avail <= total));
for (;;)
if ((total >= 0) && (payload_stop > total))
return E_FILE_FORMAT_INVALID;
if (payload_stop > avail)
{
len = static_cast<long>(payload_size);
return E_BUFFER_NOT_FULL;
}
while (pos < payload_stop)
{
//parse sub-block element ID
@@ -6574,7 +6626,7 @@ long Cluster::ParseBlockGroup(
{
pos += size; //consume sub-part of block group
if (pos >= payload_stop)
if (pos > payload_stop)
return E_FILE_FORMAT_INVALID;
continue;
@@ -6582,6 +6634,9 @@ long Cluster::ParseBlockGroup(
const long long block_stop = pos + size;
if (block_stop > payload_stop)
return E_FILE_FORMAT_INVALID;
//parse track number
if ((pos + 1) > avail)
@@ -6668,11 +6723,16 @@ long Cluster::ParseBlockGroup(
return E_BUFFER_NOT_FULL;
}
CreateBlock(0x20, payload_start, payload_size); //BlockGroup ID
m_pos = payload_stop;
return 0; //success
pos = block_stop; //consume block-part of block group
assert(pos <= payload_stop);
}
assert(pos == payload_stop);
CreateBlock(0x20, payload_start, payload_size); //BlockGroup ID
m_pos = payload_stop;
return 0; //success
}
@@ -6680,7 +6740,7 @@ long Cluster::GetEntry(long index, const mkvparser::BlockEntry*& pEntry) const
{
assert(m_pos >= m_element_start);
pEntry = 0;
pEntry = NULL;
if (index < 0)
return -1; //generic error
@@ -6900,6 +6960,9 @@ long Cluster::HasBlockEntries(
pos = pSegment->m_start + off; //absolute
if ((total >= 0) && (pos >= total))
return 0; //we don't even have a complete cluster
const long long segment_stop =
(pSegment->m_size < 0) ? -1 : pSegment->m_start + pSegment->m_size;
@@ -6923,6 +6986,9 @@ long Cluster::HasBlockEntries(
if ((segment_stop >= 0) && ((pos + len) > segment_stop))
return E_FILE_FORMAT_INVALID;
if ((total >= 0) && ((pos + len) > total))
return 0;
if ((pos + len) > avail)
return E_BUFFER_NOT_FULL;
@@ -6955,6 +7021,9 @@ long Cluster::HasBlockEntries(
if ((segment_stop >= 0) && ((pos + len) > segment_stop))
return E_FILE_FORMAT_INVALID;
if ((total >= 0) && ((pos + len) > total))
return 0;
if ((pos + len) > avail)
return E_BUFFER_NOT_FULL;
@@ -6981,7 +7050,8 @@ long Cluster::HasBlockEntries(
return E_FILE_FORMAT_INVALID;
if ((total >= 0) && (cluster_stop > total))
return E_FILE_FORMAT_INVALID;
//return E_FILE_FORMAT_INVALID; //too conservative
return 0; //cluster does not have any entries
}
}
@@ -7086,7 +7156,7 @@ long Cluster::HasBlockEntries(
}
}
#if 0
void Cluster::LoadBlockEntries() const
{
//LoadBlockEntries loads all of the entries on the cluster.
@@ -7138,7 +7208,7 @@ void Cluster::LoadBlockEntries() const
const long long element_size = cluster_stop - m_element_start;
assert((m_element_size <= 0) || (m_element_size == element_size));
if (element_size <= 0)
if (m_element_size <= 0)
m_element_size = element_size;
}
@@ -7277,12 +7347,23 @@ void Cluster::LoadBlockEntries() const
assert(m_pos == cluster_stop);
assert((ppEntry - m_entries) == m_entries_count);
}
#endif
long long Cluster::GetTimeCode() const
{
#if 0
Load();
#else
long long pos;
long len;
const long status = Load(pos, len);
status;
assert(status == 0);
#endif
return m_timecode;
}
@@ -7433,10 +7514,27 @@ void Cluster::CreateSimpleBlock(
const BlockEntry* Cluster::GetFirst() const
{
#if 0
LoadBlockEntries();
if ((m_entries == NULL) || (m_entries_count <= 0))
return NULL;
#else
if (m_entries_count <= 0)
{
long long pos;
long len;
const long status = Parse(pos, len);
assert(status >= 0);
if (m_entries_count <= 0)
return NULL; //empty cluster
assert(m_entries);
assert(m_entries_count > 0);
}
#endif
const BlockEntry* const pFirst = m_entries[0];
assert(pFirst);
@@ -7447,10 +7545,29 @@ const BlockEntry* Cluster::GetFirst() const
const BlockEntry* Cluster::GetLast() const
{
#if 0
LoadBlockEntries();
if ((m_entries == NULL) || (m_entries_count <= 0))
return NULL;
#else
for (;;)
{
long long pos;
long len;
const long status = Parse(pos, len);
assert(status >= 0);
if (status != 0) //no new block
break;
}
if (m_entries_count <= 0)
return NULL;
assert(m_entries);
#endif
const long idx = m_entries_count - 1;
@@ -7473,8 +7590,29 @@ const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
++idx;
#if 0
if (idx >= size_t(m_entries_count))
return NULL;
#else
if (idx >= size_t(m_entries_count))
{
long long pos;
long len;
const long status = Parse(pos, len);
assert(status >= 0);
if (status < 0)
return NULL;
if (status > 0)
return NULL;
assert(m_entries);
assert(m_entries_count > 0);
assert(idx < size_t(m_entries_count));
}
#endif
return m_entries[idx];
}
@@ -7495,6 +7633,8 @@ const BlockEntry* Cluster::GetEntry(
if (m_pSegment == NULL) //this is the special EOS cluster
return pTrack->GetEOS();
#if 0
LoadBlockEntries();
if ((m_entries == NULL) || (m_entries_count <= 0))
@@ -7541,6 +7681,70 @@ const BlockEntry* Cluster::GetEntry(
}
return pResult;
#else
const BlockEntry* pResult = pTrack->GetEOS();
long index = 0;
for (;;)
{
if (index >= m_entries_count)
{
long long pos;
long len;
const long status = Parse(pos, len);
assert(status >= 0);
if (status > 0) //completely parsed, and no more entries
return pResult;
if (status < 0) //should never happen
return 0;
assert(m_entries);
assert(index < m_entries_count);
}
const BlockEntry* const pEntry = m_entries[index];
assert(pEntry);
assert(!pEntry->EOS());
const Block* const pBlock = pEntry->GetBlock();
assert(pBlock);
if (pBlock->GetTrackNumber() != pTrack->GetNumber())
{
++index;
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)
return pResult;
pResult = pEntry; //have a candidate
}
else if (time_ns >= 0)
{
const long long ns = pBlock->GetTime(this);
if (ns > time_ns)
return pResult;
}
++index;
}
#endif
}
@@ -7551,6 +7755,8 @@ Cluster::GetEntry(
{
assert(m_pSegment);
#if 0
LoadBlockEntries();
if (m_entries == NULL)
@@ -7635,9 +7841,125 @@ Cluster::GetEntry(
}
return NULL;
#else
const long long tc = cp.GetTimeCode();
if (tp.m_block > 0)
{
const long block = static_cast<long>(tp.m_block);
const long index = block - 1;
while (index >= m_entries_count)
{
const long old_entries_count = m_entries_count;
old_entries_count;
long long pos;
long len;
const long status = Parse(pos, len);
if (status < 0) //TODO: can this happen?
return NULL;
if (status > 0) //nothing remains to be parsed
return NULL;
assert(m_entries);
assert(m_entries_count > old_entries_count);
}
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;
}
}
long index = 0;
for (;;)
{
if (index >= m_entries_count)
{
long long pos;
long len;
const long status = Parse(pos, len);
if (status < 0) //TODO: can this happen?
return NULL;
if (status > 0) //nothing remains to be parsed
return NULL;
assert(m_entries);
assert(index < m_entries_count);
}
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)
{
++index;
continue;
}
const long long tc_ = pBlock->GetTimeCode(this);
assert(tc_ >= 0);
if (tc_ < tc)
{
++index;
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;
}
#endif
}
#if 0
const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
{
assert(pTrack);
@@ -7671,7 +7993,7 @@ const BlockEntry* Cluster::GetMaxKey(const VideoTrack* pTrack) const
return pTrack->GetEOS(); //no satisfactory block found
}
#endif
BlockEntry::BlockEntry()

View File

@@ -569,7 +569,7 @@ public:
const BlockEntry* GetEntry(
const CuePoint&,
const CuePoint::TrackPosition&) const;
const BlockEntry* GetMaxKey(const VideoTrack*) const;
//const BlockEntry* GetMaxKey(const VideoTrack*) const;
// static bool HasBlockEntries(const Segment*, long long);
@@ -581,10 +581,10 @@ public:
long GetEntryCount() const;
void Load() const;
//void Load() const;
long Load(long long& pos, long& size) const;
void LoadBlockEntries() const;
//void LoadBlockEntries() const;
long Parse(long long& pos, long& size) const;
long GetEntry(long index, const mkvparser::BlockEntry*&) const;
@@ -650,7 +650,8 @@ public:
long Load(); //loads headers and all clusters
//for incremental loading
long long Unparsed() const;
//long long Unparsed() const;
bool DoneParsing() const;
long long ParseHeaders(); //stops when first cluster is found
//long FindNextCluster(long long& pos, long& size) const;
long LoadCluster(long long& pos, long& size); //load one cluster