Skip to content

Commit a7e8582

Browse files
committed
Bug 1679228 [wpt PR 26642] - [MSE][webcodecs] Plumb AddSourceBufferUsingConfig to ChunkDemuxer AddId, a=testonly
Automatic update from web-platform-tests [MSE][webcodecs] Plumb AddSourceBufferUsingConfig to ChunkDemuxer AddId This change: 1) Exposes as static synchronous helpers the WebCodecs MakeMediaConfig methods' internals so that MediaSource can use them to obtain media::{Audio,Video}DecoderConfigs from WebCodecs {Audio,Video}DecoderConfigs. 2) Implements MediaSource::AddSourceBufferUsingConfig for encoded configs (not decodedMediaType), plumbing the media decoder config through the usual steps in MSE addSourceBuffer, and through new methods in WebMediaSource and WebMediaSourceImpl to let ChunkDemuxer::AddId know it will be expected to handle WebCodecs encoded chunk appends for the associated SourceBuffer. 3) Adds a tentative folder for MSE-for-WebCodecs web_tests and adds a test for the current behavior of addSourceBuffer(webcodecs decoder config) that this CL adds. Later changes will continue plumbing of the configs in ChunkDemuxer and SourceBufferState, and also add implementations and ChunkDemuxer/etc support for appendEncoded{Audio,Video}Chunks. The h264 parser and avcc conditionally created in #1, above, could then be used by SourceBuffer processing of appended EncodedVideoChunks, too. BUG=1144908 Change-Id: I90c1d90c3a28d5cc1e33b1e50e32f4cfea639784 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2548844 Commit-Queue: Matthew Wolenetz <wolenetzchromium.org> Reviewed-by: Daniel Cheng <dchengchromium.org> Reviewed-by: Chrome Cunningham <chcunninghamchromium.org> Reviewed-by: Dan Sanders <sandersdchromium.org> Cr-Commit-Position: refs/heads/master{#835058} -- wpt-commits: 009fb035613e9b4027125e8f30d60f4f1f502f65 wpt-pr: 26642 UltraBlame original commit: ab3d0728e1050d82721db2f31266bd02012636dd
1 parent cd95459 commit a7e8582

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<title>Test MediaSource addSourceBuffer overloads for WebCodecs Audio/VideoDecoderConfigs</title>
4+
<script src="/resources/testharness.js"></script>
5+
<script src="/resources/testharnessreport.js"></script>
6+
<script>
7+
8+
setup(() => {
9+
assert_implements(
10+
SourceBuffer.prototype.hasOwnProperty('appendEncodedChunks'),
11+
'SourceBuffer prototype hasOwnProperty "appendEncodedChunks", used ' +
12+
'here to feature detect MSE-for-WebCodecs implementation.');
13+
});
14+
15+
testInvalidArguments();
16+
testValidArguments();
17+
18+
function getValidAudioConfig() {
19+
// TODO(crbug.com/1144908): Consider confirming with WebCodecs'
20+
// isConfigSupported() once that API is available.
21+
return {
22+
codec: 'opus',
23+
sampleRate: 48000,
24+
numberOfChannels: 2
25+
};
26+
}
27+
28+
function getValidVideoConfig() {
29+
// TODO(crbug.com/1144908): Consider confirming with WebCodecs'
30+
// isConfigSupported() once that API is available.
31+
return { codec: 'vp09.00.10.08' };
32+
}
33+
34+
function testInvalidArguments() {
35+
const INVALID_CASES = [
36+
{ arg: null,
37+
name: 'null' },
38+
{ arg: undefined,
39+
name: 'undefined' },
40+
{ arg: { },
41+
name: '{ empty dictionary }' },
42+
{
43+
arg: {
44+
audioConfig: getValidAudioConfig(),
45+
videoConfig: getValidVideoConfig()
46+
},
47+
name: '{ valid audioConfig and videoConfig }',
48+
},
49+
{
50+
arg: {
51+
audioConfig: {
52+
codec: 'bogus',
53+
sampleRate: 48000,
54+
numberOfChannels: 2
55+
}
56+
},
57+
name: 'bad audio config codec',
58+
},
59+
{ arg: { videoConfig: { codec: 'bogus' } },
60+
name: 'bad video config codec' },
61+
{ arg: { audioConfig: { sampleRate: 48000, numberOfChannels: 2 } },
62+
name: 'audio config missing required member "codec"' },
63+
{ arg: { videoConfig: { } },
64+
name: 'video config missing required member "codec"' },
65+
];
66+
67+
[ 'closed', 'open', 'ended' ].forEach(readyStateScenario => {
68+
INVALID_CASES.forEach(invalidCase => {
69+
runAddSourceBufferTest(invalidCase['arg'] /* argument */,
70+
false /* isValidArgument */,
71+
invalidCase['name'] /* argumentDescription */,
72+
readyStateScenario);
73+
});
74+
});
75+
}
76+
77+
function testValidArguments() {
78+
const VALID_CASES = [
79+
{
80+
arg: {
81+
audioConfig: getValidAudioConfig()
82+
},
83+
name: 'valid audioConfig'
84+
},
85+
{
86+
arg: {
87+
videoConfig: getValidVideoConfig()
88+
},
89+
name: 'valid videoConfig'
90+
},
91+
];
92+
93+
[ 'closed', 'open', 'ended' ].forEach(readyStateScenario => {
94+
VALID_CASES.forEach(validCase => {
95+
runAddSourceBufferTest(
96+
validCase['arg'] /* argument */,
97+
true /* isValidArgument */,
98+
validCase['name'] /* argumentDescription */,
99+
readyStateScenario);
100+
});
101+
});
102+
}
103+
104+
async function getClosedMediaSource(test) {
105+
let mediaSource = new MediaSource();
106+
assert_equals(mediaSource.readyState, 'closed');
107+
return mediaSource;
108+
}
109+
110+
async function getOpenMediaSource(test) {
111+
return new Promise(async resolve => {
112+
const v = document.createElement('video');
113+
const mediaSource = new MediaSource();
114+
const url = URL.createObjectURL(mediaSource);
115+
mediaSource.addEventListener('sourceopen', test.step_func(() => {
116+
URL.revokeObjectURL(url);
117+
assert_equals(mediaSource.readyState, 'open', 'MediaSource is open');
118+
resolve(mediaSource);
119+
}), { once: true });
120+
v.src = url;
121+
});
122+
}
123+
124+
async function getEndedMediaSource(test) {
125+
let mediaSource = await getOpenMediaSource(test);
126+
assert_equals(mediaSource.readyState, 'open', 'MediaSource is open');
127+
mediaSource.endOfStream();
128+
assert_equals(mediaSource.readyState, 'ended', 'MediaSource is ended');
129+
return mediaSource;
130+
}
131+
132+
function runAddSourceBufferTest(argument, isValidArgument, argumentDescription, readyStateScenario) {
133+
const testDescription = 'addSourceBuffer call with ' +
134+
(isValidArgument ? 'valid' : 'invalid') +
135+
' argument ' + argumentDescription + ' while MediaSource readyState is ' +
136+
readyStateScenario;
137+
138+
switch(readyStateScenario) {
139+
case 'closed':
140+
promise_test(async t => {
141+
let mediaSource = await getClosedMediaSource(t);
142+
assert_equals(mediaSource.readyState, 'closed');
143+
let sourceBuffer;
144+
if (isValidArgument) {
145+
assert_throws_dom('InvalidStateError',
146+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
147+
'addSourceBuffer(valid config) throws InvalidStateError if MediaSource is "closed"');
148+
assert_equals(sourceBuffer, undefined,
149+
'addSourceBuffer result for valid config while "closed" should be exception');
150+
} else {
151+
assert_throws_js(TypeError,
152+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
153+
'addSourceBuffer(invalid config) throws TypeError if MediaSource is "closed"');
154+
assert_equals(sourceBuffer, undefined,
155+
'addSourceBuffer result for invalid config while "closed" should be exception');
156+
}
157+
}, testDescription);
158+
break;
159+
case 'open':
160+
promise_test(async t => {
161+
let mediaSource = await getOpenMediaSource(t);
162+
assert_equals(mediaSource.readyState, 'open', 'MediaSource is open');
163+
let sourceBuffer;
164+
if (isValidArgument) {
165+
// TODO(crbug.com/1144908): Update to expect success once the impl is
166+
// more complete.
167+
assert_throws_dom('QuotaExceededError',
168+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
169+
'addSourceBuffer(valid config) throws QuotaExceededError');
170+
assert_equals(sourceBuffer, undefined,
171+
'addSourceBuffer result for valid config while "open" should be exception');
172+
} else {
173+
assert_throws_js(TypeError,
174+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
175+
'addSourceBuffer(invalid config) throws TypeError if MediaSource is "open"');
176+
assert_equals(sourceBuffer, undefined,
177+
'addSourceBufferResult for invalid config while "open" should be exception');
178+
}
179+
}, testDescription);
180+
break;
181+
case 'ended':
182+
promise_test(async t => {
183+
let mediaSource = await getEndedMediaSource(t);
184+
let sourceBuffer;
185+
if (isValidArgument) {
186+
assert_throws_dom('InvalidStateError',
187+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
188+
'addSourceBuffer(valid config) throws InvalidStateError if MediaSource is "ended"');
189+
assert_equals(sourceBuffer, undefined,
190+
'addSourceBuffer result for valid config while "ended" should be exception');
191+
} else {
192+
assert_throws_js(TypeError,
193+
() => { sourceBuffer = mediaSource.addSourceBuffer(argument); },
194+
'addSourceBuffer(invalid config) throws TypeError if MediaSource is "ended"');
195+
assert_equals(sourceBuffer, undefined,
196+
'addSourceBuffer result for invalid config while "ended" should be exception');
197+
}
198+
}, testDescription);
199+
break;
200+
default:
201+
assert_unreached('Invalid readyStateScenario ' + readyStateScenario);
202+
break;
203+
}
204+
}
205+
206+
</script>
207+
</html>

0 commit comments

Comments
 (0)