Bug 1362440 - part2 : parsing entire content to decide whether it's media segment.
The spec [1] defines what's the media segment, and the parser would return error
if the format is not correct.
[1] https://w3c.github.io/media-source/webm-byte-stream-format.html
MozReview-Commit-ID: 4hq59Pywz2t
--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -155,41 +155,30 @@ public:
return NS_OK;
}
return MediaResult(NS_ERROR_FAILURE, RESULT_DETAIL("Invalid webm content"));
}
MediaResult IsMediaSegmentPresent(MediaByteBuffer* aData) override
{
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) {
return NS_ERROR_NOT_AVAILABLE;
}
- if ((*aData)[0] == 0x1f && (*aData)[1] == 0x43 && (*aData)[2] == 0xb6 &&
- (*aData)[3] == 0x75) {
- return NS_OK;
+
+ WebMBufferedParser parser(0);
+ 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
- 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"));
+ return parser.GetClusterOffset() >= 0 ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
MediaResult ParseStartAndEndTimestamps(MediaByteBuffer* aData,
int64_t& aStart,
int64_t& aEnd) override
{
bool initSegment = NS_SUCCEEDED(IsInitSegmentPresent(aData));
--- a/dom/media/webm/WebMBufferedParser.cpp
+++ b/dom/media/webm/WebMBufferedParser.cpp
@@ -270,16 +270,22 @@ WebMBufferedParser::EndSegmentOffset(int
{
if (mLastInitStartOffset > aOffset || mClusterOffset > aOffset) {
return std::min(mLastInitStartOffset >= 0 ? mLastInitStartOffset : INT64_MAX,
mClusterOffset >= 0 ? mClusterOffset : INT64_MAX);
}
return mBlockEndOffset;
}
+int64_t
+WebMBufferedParser::GetClusterOffset() const
+{
+ return mClusterOffset;
+}
+
// SyncOffsetComparator and TimeComparator are slightly confusing, in that
// the nsTArray they're used with (mTimeMapping) is sorted by mEndOffset and
// these comparators are used on the other fields of WebMTimeDataOffset.
// This is only valid because timecodes are required to be monotonically
// increasing within a file (thus establishing an ordering relationship with
// mTimecode), and mEndOffset is derived from mSyncOffset.
struct SyncOffsetComparator {
bool Equals(const WebMTimeDataOffset& a, const int64_t& b) const {
--- a/dom/media/webm/WebMBufferedParser.h
+++ b/dom/media/webm/WebMBufferedParser.h
@@ -62,17 +62,17 @@ struct WebMBufferedParser
, mState(READ_ELEMENT_ID)
, mNextState(READ_ELEMENT_ID)
, mVIntRaw(false)
, mLastInitStartOffset(-1)
, mClusterSyncPos(0)
, mVIntLeft(0)
, mBlockSize(0)
, mClusterTimecode(0)
- , mClusterOffset(0)
+ , mClusterOffset(-1)
, mClusterEndOffset(-1)
, mBlockOffset(0)
, mBlockTimecode(0)
, mBlockTimecodeLength(0)
, mSkipBytes(0)
, mTimecodeScale(1000000)
, mGotTimecodeScale(false)
, mGotClusterTimecode(false)
@@ -82,16 +82,22 @@ struct WebMBufferedParser
}
}
uint32_t GetTimecodeScale() {
MOZ_ASSERT(mGotTimecodeScale);
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
// the appropriate timecode scale to use from elsewhere.
void SetTimecodeScale(uint32_t aTimecodeScale) {
mTimecodeScale = aTimecodeScale;
mGotTimecodeScale = true;
}
// Steps the parser through aLength bytes of data. Always consumes
@@ -110,16 +116,19 @@ struct WebMBufferedParser
return mCurrentOffset < aOffset;
}
// Returns the start offset of the init (EBML) or media segment (Cluster)
// following the aOffset position. If none were found, returns mBlockEndOffset.
// This allows to determine the end of the interval containg 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
// adjacent parsers, in which case the later parser adopts the earlier
// parser's mStartOffset.
int64_t mStartOffset;
// Current offset within the stream. Updated in chunks as Append() consumes
// data.
int64_t mCurrentOffset;
@@ -227,17 +236,17 @@ private:
// block is skipped once the block timecode has been parsed.
uint64_t mBlockSize;
// Cluster-level timecode.
uint64_t mClusterTimecode;
// 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
- // been parsed.
+ // been parsed. -1 if unknown.
int64_t mClusterOffset;
// End offset of the cluster currently being parsed. -1 if unknown.
int64_t mClusterEndOffset;
// Start offset of the block currently being parsed. Used as the byte
// offset for the offset-to-time mapping once the block timecode has been
// parsed.