[MSE] 1362440 Fix WebM segments with Tags elements not properly handled.
parent
75e5edbef3
commit
6d0a42e587
|
@ -127,58 +127,37 @@ public:
|
||||||
MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
|
MediaResult IsInitSegmentPresent(MediaByteBuffer* aData) override
|
||||||
{
|
{
|
||||||
ContainerParser::IsInitSegmentPresent(aData);
|
ContainerParser::IsInitSegmentPresent(aData);
|
||||||
// XXX: This is overly primitive, needs to collect data as it's appended
|
|
||||||
// to the SB and handle, rather than assuming everything is present in a
|
|
||||||
// single aData segment.
|
|
||||||
// 0x1a45dfa3 // EBML
|
|
||||||
// ...
|
|
||||||
// DocType == "webm"
|
|
||||||
// ...
|
|
||||||
// 0x18538067 // Segment (must be "unknown" size or contain a value large
|
|
||||||
// enough to include the Segment Information and Tracks
|
|
||||||
// elements that follow)
|
|
||||||
// 0x1549a966 // -> Segment Info
|
|
||||||
// 0x1654ae6b // -> One or more Tracks
|
|
||||||
|
|
||||||
// 0x1a45dfa3 // EBML
|
|
||||||
if (aData->Length() < 4) {
|
if (aData->Length() < 4) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
if ((*aData)[0] == 0x1a && (*aData)[1] == 0x45 && (*aData)[2] == 0xdf &&
|
WebMBufferedParser parser(0);
|
||||||
(*aData)[3] == 0xa3) {
|
nsTArray<WebMTimeDataOffset> mapping;
|
||||||
return NS_OK;
|
ReentrantMonitor dummy("dummy");
|
||||||
|
bool result = parser.Append(aData->Elements(), aData->Length(), mapping,
|
||||||
|
dummy);
|
||||||
|
if (!result) {
|
||||||
|
return MediaResult(NS_ERROR_FAILURE, RESULT_DETAIL("Invalid webm content"));
|
||||||
}
|
}
|
||||||
return MediaResult(NS_ERROR_FAILURE, RESULT_DETAIL("Invalid webm content"));
|
return parser.mInitEndOffset > 0 ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
|
MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
|
||||||
{
|
{
|
||||||
ContainerParser::IsMediaSegmentPresent(aData);
|
ContainerParser::IsMediaSegmentPresent(aData);
|
||||||
// XXX: This is overly primitive, needs to collect data as it's appended
|
|
||||||
// to the SB and handle, rather than assuming everything is present in a
|
|
||||||
// single aData segment.
|
|
||||||
// 0x1a45dfa3 // EBML
|
|
||||||
// ...
|
|
||||||
// DocType == "webm"
|
|
||||||
// ...
|
|
||||||
// 0x18538067 // Segment (must be "unknown" size)
|
|
||||||
// 0x1549a966 // -> Segment Info
|
|
||||||
// 0x1654ae6b // -> One or more Tracks
|
|
||||||
|
|
||||||
// 0x1f43b675 // Cluster
|
|
||||||
if (aData->Length() < 4) {
|
if (aData->Length() < 4) {
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
if ((*aData)[0] == 0x1f && (*aData)[1] == 0x43 && (*aData)[2] == 0xb6 &&
|
|
||||||
(*aData)[3] == 0x75) {
|
WebMBufferedParser parser(0);
|
||||||
return NS_OK;
|
nsTArray<WebMTimeDataOffset> mapping;
|
||||||
|
ReentrantMonitor dummy("dummy");
|
||||||
|
parser.AppendMediaSegmentOnly();
|
||||||
|
bool result = parser.Append(aData->Elements(), aData->Length(), mapping,
|
||||||
|
dummy);
|
||||||
|
if (!result) {
|
||||||
|
return MediaResult(NS_ERROR_FAILURE, RESULT_DETAIL("Invalid webm content"));
|
||||||
}
|
}
|
||||||
// 0x1c53bb6b // Cues
|
return parser.GetClusterOffset() >= 0 ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
||||||
if ((*aData)[0] == 0x1c && (*aData)[1] == 0x53 && (*aData)[2] == 0xbb &&
|
|
||||||
(*aData)[3] == 0x6b) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
return MediaResult(NS_ERROR_FAILURE, RESULT_DETAIL("Invalid webm content"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaResult ParseStartAndEndTimestamps(MediaByteBuffer* aData,
|
MediaResult ParseStartAndEndTimestamps(MediaByteBuffer* aData,
|
||||||
|
|
|
@ -113,6 +113,7 @@ bool WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
} else {
|
} else {
|
||||||
mClusterEndOffset = -1;
|
mClusterEndOffset = -1;
|
||||||
}
|
}
|
||||||
|
mGotClusterTimecode = false;
|
||||||
mState = READ_ELEMENT_ID;
|
mState = READ_ELEMENT_ID;
|
||||||
break;
|
break;
|
||||||
case BLOCKGROUP_ID:
|
case BLOCKGROUP_ID:
|
||||||
|
@ -121,6 +122,11 @@ bool WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
case SIMPLEBLOCK_ID:
|
case SIMPLEBLOCK_ID:
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case BLOCK_ID:
|
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;
|
mBlockSize = mElement.mSize.mValue;
|
||||||
mBlockTimecode = 0;
|
mBlockTimecode = 0;
|
||||||
mBlockTimecodeLength = BLOCK_TIMECODE_LENGTH;
|
mBlockTimecodeLength = BLOCK_TIMECODE_LENGTH;
|
||||||
|
@ -164,6 +170,7 @@ bool WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
break;
|
break;
|
||||||
case READ_TIMECODESCALE:
|
case READ_TIMECODESCALE:
|
||||||
if (!mGotTimecodeScale) {
|
if (!mGotTimecodeScale) {
|
||||||
|
WEBM_DEBUG("Should get the SegmentInfo first");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mTimecodeScale = mVInt.mValue;
|
mTimecodeScale = mVInt.mValue;
|
||||||
|
@ -171,6 +178,7 @@ bool WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
break;
|
break;
|
||||||
case READ_CLUSTER_TIMECODE:
|
case READ_CLUSTER_TIMECODE:
|
||||||
mClusterTimecode = mVInt.mValue;
|
mClusterTimecode = mVInt.mValue;
|
||||||
|
mGotClusterTimecode = true;
|
||||||
mState = READ_ELEMENT_ID;
|
mState = READ_ELEMENT_ID;
|
||||||
break;
|
break;
|
||||||
case READ_BLOCK_TIMECODE:
|
case READ_BLOCK_TIMECODE:
|
||||||
|
@ -190,6 +198,7 @@ bool WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
// Don't insert invalid negative timecodes.
|
// Don't insert invalid negative timecodes.
|
||||||
if (mBlockTimecode >= 0 || mClusterTimecode >= uint16_t(abs(mBlockTimecode))) {
|
if (mBlockTimecode >= 0 || mClusterTimecode >= uint16_t(abs(mBlockTimecode))) {
|
||||||
if (!mGotTimecodeScale) {
|
if (!mGotTimecodeScale) {
|
||||||
|
WEBM_DEBUG("Should get the TimecodeScale first");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
|
uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
|
||||||
|
@ -266,6 +275,12 @@ WebMBufferedParser::EndSegmentOffset(int64_t aOffset)
|
||||||
return mBlockEndOffset;
|
return mBlockEndOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
WebMBufferedParser::GetClusterOffset() const
|
||||||
|
{
|
||||||
|
return mClusterOffset;
|
||||||
|
}
|
||||||
|
|
||||||
// SyncOffsetComparator and TimeComparator are slightly confusing, in that
|
// SyncOffsetComparator and TimeComparator are slightly confusing, in that
|
||||||
// the nsTArray they're used with (mTimeMapping) is sorted by mEndOffset and
|
// the nsTArray they're used with (mTimeMapping) is sorted by mEndOffset and
|
||||||
// these comparators are used on the other fields of WebMTimeDataOffset.
|
// these comparators are used on the other fields of WebMTimeDataOffset.
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct WebMBufferedParser
|
||||||
, mVIntLeft(0)
|
, mVIntLeft(0)
|
||||||
, mBlockSize(0)
|
, mBlockSize(0)
|
||||||
, mClusterTimecode(0)
|
, mClusterTimecode(0)
|
||||||
, mClusterOffset(0)
|
, mClusterOffset(-1)
|
||||||
, mClusterEndOffset(-1)
|
, mClusterEndOffset(-1)
|
||||||
, mBlockOffset(0)
|
, mBlockOffset(0)
|
||||||
, mBlockTimecode(0)
|
, mBlockTimecode(0)
|
||||||
|
@ -75,6 +75,7 @@ struct WebMBufferedParser
|
||||||
, mSkipBytes(0)
|
, mSkipBytes(0)
|
||||||
, mTimecodeScale(1000000)
|
, mTimecodeScale(1000000)
|
||||||
, mGotTimecodeScale(false)
|
, mGotTimecodeScale(false)
|
||||||
|
, mGotClusterTimecode(false)
|
||||||
{
|
{
|
||||||
if (mStartOffset != 0) {
|
if (mStartOffset != 0) {
|
||||||
mState = FIND_CLUSTER_SYNC;
|
mState = FIND_CLUSTER_SYNC;
|
||||||
|
@ -86,6 +87,12 @@ struct WebMBufferedParser
|
||||||
return mTimecodeScale;
|
return mTimecodeScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use this function when we would only feed media segment for the parser.
|
||||||
|
void AppendMediaSegmentOnly()
|
||||||
|
{
|
||||||
|
mGotTimecodeScale = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If this parser is not expected to parse a segment info, it must be told
|
// If this parser is not expected to parse a segment info, it must be told
|
||||||
// the appropriate timecode scale to use from elsewhere.
|
// the appropriate timecode scale to use from elsewhere.
|
||||||
void SetTimecodeScale(uint32_t aTimecodeScale) {
|
void SetTimecodeScale(uint32_t aTimecodeScale) {
|
||||||
|
@ -114,6 +121,9 @@ struct WebMBufferedParser
|
||||||
// This allows to determine the end of the interval containg aOffset.
|
// This allows to determine the end of the interval containg aOffset.
|
||||||
int64_t EndSegmentOffset(int64_t aOffset);
|
int64_t EndSegmentOffset(int64_t aOffset);
|
||||||
|
|
||||||
|
// Return the Cluster offset, return -1 if we can't find the Cluster.
|
||||||
|
int64_t GetClusterOffset() const;
|
||||||
|
|
||||||
// The offset at which this parser started parsing. Used to merge
|
// The offset at which this parser started parsing. Used to merge
|
||||||
// adjacent parsers, in which case the later parser adopts the earlier
|
// adjacent parsers, in which case the later parser adopts the earlier
|
||||||
// parser's mStartOffset.
|
// parser's mStartOffset.
|
||||||
|
@ -231,7 +241,7 @@ private:
|
||||||
|
|
||||||
// Start offset of the cluster currently being parsed. Used as the sync
|
// Start offset of the cluster currently being parsed. Used as the sync
|
||||||
// point offset for the offset-to-time mapping as each block timecode is
|
// point offset for the offset-to-time mapping as each block timecode is
|
||||||
// been parsed.
|
// been parsed. -1 if unknown.
|
||||||
int64_t mClusterOffset;
|
int64_t mClusterOffset;
|
||||||
|
|
||||||
// End offset of the cluster currently being parsed. -1 if unknown.
|
// End offset of the cluster currently being parsed. -1 if unknown.
|
||||||
|
@ -260,6 +270,9 @@ private:
|
||||||
// True if we read the timecode scale from the segment info or have
|
// True if we read the timecode scale from the segment info or have
|
||||||
// confirmed that the default value is to be used.
|
// confirmed that the default value is to be used.
|
||||||
bool mGotTimecodeScale;
|
bool mGotTimecodeScale;
|
||||||
|
|
||||||
|
// True if we've read the cluster time code.
|
||||||
|
bool mGotClusterTimecode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebMBufferedState final
|
class WebMBufferedState final
|
||||||
|
|
Loading…
Reference in New Issue