Bug 1362440 - part1 : add timecode checking for parser
The spec [1] defines that
"Timecode (e7) MUST appear before Block (a1) or SimpleBlock (a3)".
[1] https://www.matroska.org/technical/specs/index.html
MozReview-Commit-ID: 7g8lgckuNif
--- a/dom/media/webm/WebMBufferedParser.cpp
+++ b/dom/media/webm/WebMBufferedParser.cpp
@@ -108,24 +108,30 @@ bool WebMBufferedParser::Append(const un
mClusterOffset = mCurrentOffset + (p - aBuffer) -
(mElement.mID.mLength + mElement.mSize.mLength);
// Handle "unknown" length;
if (mElement.mSize.mValue + 1 != uint64_t(1) << (mElement.mSize.mLength * 7)) {
mClusterEndOffset = mClusterOffset + mElement.mID.mLength + mElement.mSize.mLength + mElement.mSize.mValue;
} else {
mClusterEndOffset = -1;
}
+ mGotClusterTimecode = false;
mState = READ_ELEMENT_ID;
break;
case BLOCKGROUP_ID:
mState = READ_ELEMENT_ID;
break;
case SIMPLEBLOCK_ID:
/* FALLTHROUGH */
case BLOCK_ID:
+ if (!mGotClusterTimecode) {
+ WEBM_DEBUG("The Timecode element must appear before any Block or "
+ "SimpleBlock elements in a Cluster");
+ return false;
+ }
mBlockSize = mElement.mSize.mValue;
mBlockTimecode = 0;
mBlockTimecodeLength = BLOCK_TIMECODE_LENGTH;
mBlockOffset = mCurrentOffset + (p - aBuffer) -
(mElement.mID.mLength + mElement.mSize.mLength);
mState = READ_VINT;
mNextState = READ_BLOCK_TIMECODE;
break;
@@ -159,23 +165,25 @@ bool WebMBufferedParser::Append(const un
mVInt.mValue |= *p++;
mVIntLeft -= 1;
} else {
mState = mNextState;
}
break;
case READ_TIMECODESCALE:
if (!mGotTimecodeScale) {
+ WEBM_DEBUG("Should get the SegmentInfo first");
return false;
}
mTimecodeScale = mVInt.mValue;
mState = READ_ELEMENT_ID;
break;
case READ_CLUSTER_TIMECODE:
mClusterTimecode = mVInt.mValue;
+ mGotClusterTimecode = true;
mState = READ_ELEMENT_ID;
break;
case READ_BLOCK_TIMECODE:
if (mBlockTimecodeLength) {
mBlockTimecode <<= 8;
mBlockTimecode |= *p++;
mBlockTimecodeLength -= 1;
} else {
@@ -185,16 +193,17 @@ bool WebMBufferedParser::Append(const un
ReentrantMonitorAutoEnter mon(aReentrantMonitor);
int64_t endOffset = mBlockOffset + mBlockSize +
mElement.mID.mLength + mElement.mSize.mLength;
uint32_t idx = aMapping.IndexOfFirstElementGt(endOffset);
if (idx == 0 || aMapping[idx - 1] != endOffset) {
// Don't insert invalid negative timecodes.
if (mBlockTimecode >= 0 || mClusterTimecode >= uint16_t(abs(mBlockTimecode))) {
if (!mGotTimecodeScale) {
+ WEBM_DEBUG("Should get the TimecodeScale first");
return false;
}
uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
absTimecode *= mTimecodeScale;
// Avoid creating an entry if the timecode is out of order
// (invalid according to the WebM specification) so that
// ordering invariants of aMapping are not violated.
if (idx == 0 ||
--- a/dom/media/webm/WebMBufferedParser.h
+++ b/dom/media/webm/WebMBufferedParser.h
@@ -70,16 +70,17 @@ struct WebMBufferedParser
, mClusterOffset(0)
, mClusterEndOffset(-1)
, mBlockOffset(0)
, mBlockTimecode(0)
, mBlockTimecodeLength(0)
, mSkipBytes(0)
, mTimecodeScale(1000000)
, mGotTimecodeScale(false)
+ , mGotClusterTimecode(false)
{
if (mStartOffset != 0) {
mState = FIND_CLUSTER_SYNC;
}
}
uint32_t GetTimecodeScale() {
MOZ_ASSERT(mGotTimecodeScale);
@@ -255,16 +256,19 @@ private:
// Timecode scale read from the segment info and used to scale absolute
// timecodes.
uint32_t mTimecodeScale;
// True if we read the timecode scale from the segment info or have
// confirmed that the default value is to be used.
bool mGotTimecodeScale;
+
+ // True if we've read the cluster time code.
+ bool mGotClusterTimecode;
};
class WebMBufferedState final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebMBufferedState)
public:
WebMBufferedState()