Skip to content

Commit 4f4483c

Browse files
Dan Sanderschromium-wpt-export-bot
Dan Sanders
authored andcommitted
[webcodecs] Implement Audio/VideoDecoder error callback.
This is implemented in terms of an |is_closed_| state, which prevents reentrancy during shutdown. Bug: 1045247 Change-Id: I69e8bd095979f6571fbe95b298f91166b61dc9f3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2363998 Commit-Queue: Dan Sanders <[email protected]> Reviewed-by: Chrome Cunningham <[email protected]> Cr-Commit-Position: refs/heads/master@{#800282}
1 parent 9017ebd commit 4f4483c

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

webcodecs/h264.mp4

7.46 KB
Binary file not shown.

webcodecs/video-decoder.html

+168
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,46 @@
44
<script src="/resources/testharness.js"></script>
55
<script src="/resources/testharnessreport.js"></script>
66
<script>
7+
'use strict';
8+
9+
// TODO(sandersd): Move metadata into a helper library.
10+
// TODO(sandersd): Add H.264 idecode test once there is an API to query for
11+
// supported codecs.
12+
let h264 = {
13+
buffer: fetch('h264.mp4').then(r => r.arrayBuffer()),
14+
codec: "avc1.64000c",
15+
description: {offset: 7229, size: 46},
16+
frames: [{offset: 48, size: 4007},
17+
{offset: 4055, size: 926},
18+
{offset: 4981, size: 241},
19+
{offset: 5222, size: 97},
20+
{offset: 5319, size: 98},
21+
{offset: 5417, size: 624},
22+
{offset: 6041, size: 185},
23+
{offset: 6226, size: 94},
24+
{offset: 6320, size: 109},
25+
{offset: 6429, size: 281}]
26+
};
27+
28+
let vp9 = {
29+
buffer: fetch('vp9.mp4').then(r => r.arrayBuffer()),
30+
// TODO(sandersd): Verify that the file is actually level 1.
31+
codec: "vp09.00.10.08",
32+
frames: [{offset: 44, size: 3315},
33+
{offset: 3359, size: 203},
34+
{offset: 3562, size: 245},
35+
{offset: 3807, size: 172},
36+
{offset: 3979, size: 312},
37+
{offset: 4291, size: 170},
38+
{offset: 4461, size: 195},
39+
{offset: 4656, size: 181},
40+
{offset: 4837, size: 356},
41+
{offset: 5193, size: 159}]
42+
};
43+
44+
function view(buffer, {offset, size}) {
45+
return new Uint8Array(buffer, offset, size);
46+
}
747

848
// Calls done after giving async output/error callbacks a final chance to run.
949
async function asyncDone(test) {
@@ -54,5 +94,133 @@
5494

5595
asyncDone(t);
5696
}, 'Test VideoDecoder.configure() codec validity');
97+
98+
promise_test(t => vp9.buffer.then(buffer => {
99+
let numOutputs = 0;
100+
let decoder = new VideoDecoder({
101+
output(frame) {
102+
t.step(() => {
103+
assert_equals(++numOutputs, 1, "outputs");
104+
assert_equals(frame.cropWidth, 320, "cropWidth");
105+
assert_equals(frame.cropHeight, 240, "cropHeight");
106+
assert_equals(frame.timestamp, 0, "timestamp");
107+
frame.destroy();
108+
});
109+
},
110+
error(e) {
111+
t.step(() => {
112+
// TODO(sandersd): Change to 'throw e' once e is defined.
113+
throw "decode error";
114+
});
115+
}
116+
});
117+
118+
decoder.configure({codec: vp9.codec});
119+
120+
decoder.decode(new EncodedVideoChunk('key', 0, view(buffer, vp9.frames[0])));
121+
122+
return decoder.flush().then(() => {
123+
assert_equals(numOutputs, 1, "outputs");
124+
});
125+
}), 'Decode VP9');
126+
127+
promise_test(t => {
128+
let decoder = new VideoDecoder({
129+
output(frame) {
130+
t.step(() => {
131+
throw "unexpected output";
132+
});
133+
},
134+
error(e) {
135+
t.step(() => {
136+
throw "unexpected error";
137+
});
138+
}
139+
});
140+
141+
decoder.close();
142+
143+
let fakeChunk = new EncodedVideoChunk('key', 0, Uint8Array.of(0));
144+
assert_throws_dom("InvalidStateError",
145+
() => decoder.configure({codec: vp9.codec}),
146+
"configure");
147+
assert_throws_dom("InvalidStateError",
148+
() => decoder.decode(fakeChunk),
149+
"reset");
150+
assert_throws_dom("InvalidStateError",
151+
() => decoder.reset(),
152+
"reset");
153+
assert_throws_dom("InvalidStateError",
154+
() => decoder.close(),
155+
"close");
156+
return promise_rejects_dom(t, 'InvalidStateError', decoder.flush(), 'flush');
157+
}, 'Closed decoder');
158+
159+
promise_test(t => {
160+
let numErrors = 0;
161+
let decoder = new VideoDecoder({
162+
output(frame) {
163+
t.step(() => {
164+
throw "unexpected output";
165+
});
166+
},
167+
error(e) {
168+
numErrors++;
169+
}
170+
});
171+
172+
let fakeChunk = new EncodedVideoChunk('key', 0, Uint8Array.of(0));
173+
decoder.decode(fakeChunk);
174+
175+
return decoder.flush().then(
176+
() => { throw "flush succeeded unexpectedly"; },
177+
() => { assert_equals(numErrors, 1, "errors"); });
178+
}, 'Decode without configure');
179+
180+
promise_test(t => {
181+
let numErrors = 0;
182+
let decoder = new VideoDecoder({
183+
output(frame) {
184+
t.step(() => {
185+
throw "unexpected output";
186+
});
187+
},
188+
error(e) {
189+
numErrors++;
190+
}
191+
});
192+
193+
decoder.configure({codec: vp9.codec});
194+
195+
let fakeChunk = new EncodedVideoChunk('key', 0, Uint8Array.of(0));
196+
decoder.decode(fakeChunk);
197+
198+
return decoder.flush().then(
199+
() => { throw "flush succeeded unexpectedly"; },
200+
() => { assert_equals(numErrors, 1, "errors"); });
201+
}, 'Decode corrupt VP9 frame');
202+
203+
promise_test(t => {
204+
let numErrors = 0;
205+
let decoder = new VideoDecoder({
206+
output(frame) {
207+
t.step(() => {
208+
throw "unexpected output";
209+
});
210+
},
211+
error(e) {
212+
numErrors++;
213+
}
214+
});
215+
216+
decoder.configure({codec: vp9.codec});
217+
218+
let fakeChunk = new EncodedVideoChunk('key', 0, Uint8Array.of());
219+
decoder.decode(fakeChunk);
220+
221+
return decoder.flush().then(
222+
() => { throw "flush succeeded unexpectedly"; },
223+
() => { assert_equals(numErrors, 1, "errors"); });
224+
}, 'Decode empty VP9 frame');
57225
</script>
58226
</html>

webcodecs/vp9.mp4

6.01 KB
Binary file not shown.

0 commit comments

Comments
 (0)