Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit f46f524

Browse files
[BigSur] Appending a new WebM init segment between Cluster elements throws an error
https://bugs.webkit.org/show_bug.cgi?id=218149 <rdar://problem/70416537> Reviewed by Eric Carlson. Source/ThirdParty/libwebrtc: Add an "OnElementEnd()" callback to libwebm. * Source/third_party/libwebm/webm_parser/include/webm/callback.h: * Source/third_party/libwebm/webm_parser/src/callback.cc: * Source/third_party/libwebm/webm_parser/src/master_parser.cc: * Source/third_party/libwebm/webm_parser/src/webm_parser.cc: Source/WebCore: Test: media/media-source/media-source-webm-init-inside-segment.html The WebM Byte Stream Format specification states that an "initialization segment" consists of both a leading Ebml element and Segment element, and a "media segment" consists of a single Cluster element. However, while both Ebml and Segment elements are top-level, Cluster elements are contained within a Segment. This means if a client pushes a new "initialization segment" after parsing some-but-not-all Clusters within a Segment, the new Ebml and Segment elements will be parsed as children of the preceeding Segment, and the subsquent Segment will overflow its "parent's" size. In order to support appending a new "initialization segment" while still in the middle of parsing the previous Segment element, first improve our state tracking in order to determine what the current parent element is. Then, when we detect that an Ebml element is parsed while still inside a Segment, abort with a simulated error, which when caught, will indicate that the parser needs to be reset, and the reader "rewound" to the Ebml's position. To allow the reader to rewind, we must not throw away appended data as we iterate over them. Instead, we will only discard read samples once each parsing pass is fully complete. This allows us to "rewind" across appended segment boundaries, if necessary. Because all WTF::Deque iterators are invalidated whenever any element is removed, and because we do not need random-access to the elements in the deque, replace the Deque with a StdList to store the incoming data. * platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h: * platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm: (WebCore::SourceBufferParserAVFObjC::setLogger): * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: (WebCore::SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC): * platform/graphics/cocoa/SourceBufferParser.h: * platform/graphics/cocoa/SourceBufferParserWebM.cpp: (WTF::LogArgument<webm::Id>::toString): (WTF::LogArgument<WebCore::SourceBufferParserWebM::State>::toString): (WebCore::logChannel): (WebCore::logClassName): (WebCore::SourceBufferParserWebM::appendData): (WebCore::SourceBufferParserWebM::resetParserState): (WebCore::SourceBufferParserWebM::invalidate): (WebCore::SourceBufferParserWebM::setLogger): (WebCore::SourceBufferParserWebM::OnElementBegin): (WebCore::SourceBufferParserWebM::OnElementEnd): (WebCore::SourceBufferParserWebM::OnEbml): (WebCore::SourceBufferParserWebM::OnSegmentBegin): (WebCore::SourceBufferParserWebM::OnInfo): (WebCore::SourceBufferParserWebM::OnTrackEntry): * platform/graphics/cocoa/SourceBufferParserWebM.h: LayoutTests: * media/media-source/content/test-vp9-long-manifest.json: Added. * media/media-source/content/test-vp9-long.webm: Added. * media/media-source/media-source-webm-init-inside-segment-expected.txt: Added. * media/media-source/media-source-webm-init-inside-segment.html: Added. * platform/mac/TestExpectations: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@268952 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 3da1695 commit f46f524

File tree

18 files changed

+571
-41
lines changed

18 files changed

+571
-41
lines changed

LayoutTests/ChangeLog

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
2020-10-24 Jer Noble <[email protected]>
2+
3+
[BigSur] Appending a new WebM init segment between Cluster elements throws an error
4+
https://bugs.webkit.org/show_bug.cgi?id=218149
5+
<rdar://problem/70416537>
6+
7+
Reviewed by Eric Carlson.
8+
9+
* media/media-source/content/test-vp9-long-manifest.json: Added.
10+
* media/media-source/content/test-vp9-long.webm: Added.
11+
* media/media-source/media-source-webm-init-inside-segment-expected.txt: Added.
12+
* media/media-source/media-source-webm-init-inside-segment.html: Added.
13+
* platform/mac/TestExpectations:
14+
115
2020-10-24 Antti Koivisto <[email protected]>
216

317
[LFC][Integration] Replaced elements in newly created line layout should always be updated
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"url": "content/test-vp9-long.webm",
3+
"type": "video/webm; codecs=\"vp09.00.10.08\"",
4+
"init": { "offset": 0, "size": 524 },
5+
"duration": 10.006,
6+
"media": [
7+
{ "offset": 524, "size": 268592, "timestamp": 0, "duration": 5.006},
8+
{ "offset": 269116, "size": 277107, "timestamp": 5.007, "duration": 10.006}
9+
]
10+
}
Binary file not shown.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
This tests the ability of the SourceBuffer to accept a new WebM Initialization Segment while still in the middle of parsing the Segment Element of the last Media Segment.
2+
3+
RUN(video.src = URL.createObjectURL(source))
4+
EVENT(sourceopen)
5+
RUN(source.duration = loader.duration())
6+
RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
7+
RUN(sourceBuffer.appendBuffer(loader.initSegment()))
8+
EVENT(update)
9+
Append a media segment.
10+
RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0)))
11+
EVENT(update)
12+
Append a new Initialization Segment.
13+
RUN(sourceBuffer.appendBuffer(loader.initSegment()))
14+
EVENT(update)
15+
Append a media segment.
16+
RUN(sourceBuffer.appendBuffer(loader.mediaSegment(1)))
17+
EVENT(update)
18+
END OF TEST
19+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>media-source-webm</title>
5+
<script src="media-source-loader.js"></script>
6+
<script src="../video-test.js"></script>
7+
<script>
8+
var loader;
9+
var source;
10+
var sourceBuffer;
11+
12+
function loaderPromise(loader) {
13+
return new Promise((resolve, reject) => {
14+
loader.onload = resolve;
15+
loader.onerror = reject;
16+
});
17+
}
18+
19+
window.addEventListener('load', async event => {
20+
try {
21+
findMediaElement();
22+
loader = new MediaSourceLoader('content/test-vp9-long-manifest.json');
23+
await loaderPromise(loader);
24+
25+
source = new MediaSource();
26+
run('video.src = URL.createObjectURL(source)');
27+
await waitFor(source, 'sourceopen');
28+
waitFor(source, 'error').then(endTest);
29+
waitForEventAndFail('error');
30+
31+
run('source.duration = loader.duration()');
32+
run('sourceBuffer = source.addSourceBuffer(loader.type())');
33+
run('sourceBuffer.appendBuffer(loader.initSegment())');
34+
35+
await waitFor(sourceBuffer, 'update');
36+
37+
consoleWrite('Append a media segment.')
38+
run('sourceBuffer.appendBuffer(loader.mediaSegment(0))');
39+
40+
await waitFor(sourceBuffer, 'update');
41+
42+
consoleWrite('Append a new Initialization Segment.')
43+
run('sourceBuffer.appendBuffer(loader.initSegment())');
44+
45+
await waitFor(sourceBuffer, 'update');
46+
47+
consoleWrite('Append a media segment.')
48+
run('sourceBuffer.appendBuffer(loader.mediaSegment(1))');
49+
50+
await waitFor(sourceBuffer, 'update');
51+
52+
endTest();
53+
} catch (e) {
54+
failTest(`Caught exception: "${e}"`);
55+
}
56+
});
57+
</script>
58+
</head>
59+
<body>
60+
<div>
61+
This tests the ability of the SourceBuffer to accept a new WebM Initialization Segment while still in the middle of parsing the Segment Element of the last Media Segment.
62+
</div>
63+
<video controls></video>
64+
</body>
65+
</html>

LayoutTests/platform/mac/TestExpectations

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,7 @@ webkit.org/b/214155 imported/w3c/web-platform-tests/html/cross-origin-embedder-p
18771877

18781878
# These test requires system platform support.
18791879
[ Catalina Mojave ] media/media-source/media-source-webm.html [ Skip ]
1880+
[ Catalina Mojave ] media/media-source/media-source-webm-init-inside-segment.html [ Skip ]
18801881
[ Catalina Mojave ] platform/mac/media/mediacapabilities/vp9-decodingInfo-sw.html [ Skip ]
18811882
[ Catalina Mojave ] platform/mac/media/media-source/is-type-supported-vp9-codec-check.html [ Skip ]
18821883

Source/ThirdParty/libwebrtc/ChangeLog

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2020-10-24 Jer Noble <[email protected]>
2+
3+
[BigSur] Appending a new WebM init segment between Cluster elements throws an error
4+
https://bugs.webkit.org/show_bug.cgi?id=218149
5+
<rdar://problem/70416537>
6+
7+
Reviewed by Eric Carlson.
8+
9+
Add an "OnElementEnd()" callback to libwebm.
10+
11+
* Source/third_party/libwebm/webm_parser/include/webm/callback.h:
12+
* Source/third_party/libwebm/webm_parser/src/callback.cc:
13+
* Source/third_party/libwebm/webm_parser/src/master_parser.cc:
14+
* Source/third_party/libwebm/webm_parser/src/webm_parser.cc:
15+
116
2020-10-21 Youenn Fablet <[email protected]>
217

318
WebRTC VP9 Decoder should be able to use VTB

Source/ThirdParty/libwebrtc/Source/third_party/libwebm/webm_parser/include/webm/callback.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ class Callback {
335335
*/
336336
virtual Status OnSegmentEnd(const ElementMetadata& metadata);
337337

338+
virtual Status OnElementEnd(const ElementMetadata& metadata);
339+
338340
protected:
339341
/**
340342
Calls (and returns the result of) `Reader::Skip()`, skipping (up to) the

Source/ThirdParty/libwebrtc/Source/third_party/libwebm/webm_parser/src/callback.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ Status Callback::OnSegmentEnd(const ElementMetadata& /* metadata */) {
135135
return Status(Status::kOkCompleted);
136136
}
137137

138+
Status Callback::OnElementEnd(const ElementMetadata& /* metadata */) {
139+
return Status(Status::kOkCompleted);
140+
}
141+
138142
Status Callback::Skip(Reader* reader, std::uint64_t* bytes_remaining) {
139143
assert(reader != nullptr);
140144
assert(bytes_remaining != nullptr);

Source/ThirdParty/libwebrtc/Source/third_party/libwebm/webm_parser/src/master_parser.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ Status MasterParser::Feed(Callback* callback, Reader* reader,
247247
return Status(Status::kElementOverflow);
248248
} else if (total_bytes_read_ == byte_cap) {
249249
state_ = State::kEndReached;
250+
callback = original_callback;
251+
callback->OnElementEnd(child_metadata_);
250252
continue;
251253
}
252254

@@ -257,6 +259,7 @@ Status MasterParser::Feed(Callback* callback, Reader* reader,
257259
}
258260
PrepareForNextChild();
259261
callback = original_callback;
262+
callback->OnElementEnd(child_metadata_);
260263
continue;
261264
}
262265

0 commit comments

Comments
 (0)