Automatic update from web-platform-tests [webcodecs] Deprecate VideoFrame.destroy(). This CL adds VideoFrame.close() as an alias for VideoFrame.destroy(), adds a deprecation message for VideoFrame.destroy(), and changes all callsites to use close(). Bug: 1166930 Change-Id: I39b9c68262553a6814f6bb0b6b81c02012c2d026 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2631405 Commit-Queue: Dan Sanders <sandersd@chromium.org> Reviewed-by: Jeremy Roman <jbroman@chromium.org> Reviewed-by: Eugene Zemtsov <eugene@chromium.org> Reviewed-by: Guido Urdaneta <guidou@chromium.org> Cr-Commit-Position: refs/heads/master@{#844250} -- wpt-commits: 1895256f46deb64c491bff1d5bc2e4372dd35731 wpt-pr: 27194
262 lines
7.5 KiB
JavaScript
262 lines
7.5 KiB
JavaScript
// META: global=window,dedicatedworker
|
|
// META: script=/common/media.js
|
|
// META: script=/webcodecs/utils.js
|
|
|
|
const defaultConfig = {
|
|
codec: 'vp8',
|
|
framerate: 25,
|
|
width: 640,
|
|
height: 480
|
|
};
|
|
|
|
async function generateBitmap(width, height) {
|
|
const src = "pattern.png";
|
|
|
|
var size = {
|
|
resizeWidth: width,
|
|
resizeHeight: height
|
|
};
|
|
|
|
return fetch(src)
|
|
.then(response => response.blob())
|
|
.then(blob => createImageBitmap(blob, size));
|
|
}
|
|
|
|
async function createVideoFrame(width, height, timestamp) {
|
|
let bitmap = await generateBitmap(width, height);
|
|
return new VideoFrame(bitmap, { timestamp: timestamp });
|
|
}
|
|
|
|
promise_test(t => {
|
|
// VideoEncoderInit lacks required fields.
|
|
assert_throws_js(TypeError, () => { new VideoEncoder({}); });
|
|
|
|
// VideoEncoderInit has required fields.
|
|
let encoder = new VideoEncoder(getDefaultCodecInit(t));
|
|
|
|
assert_equals(encoder.state, "unconfigured");
|
|
|
|
encoder.close();
|
|
|
|
return endAfterEventLoopTurn();
|
|
}, 'Test VideoEncoder construction');
|
|
|
|
promise_test(t => {
|
|
let encoder = new VideoEncoder(getDefaultCodecInit(t));
|
|
|
|
let badCodecsList = [
|
|
'', // Empty codec
|
|
'bogus', // Non exsitent codec
|
|
'vorbis', // Audio codec
|
|
'vp9', // Ambiguous codec
|
|
'video/webm; codecs="vp9"' // Codec with mime type
|
|
]
|
|
|
|
testConfigurations(encoder, defaultConfig, badCodecsList);
|
|
|
|
return endAfterEventLoopTurn();
|
|
}, 'Test VideoEncoder.configure()');
|
|
|
|
promise_test(async t => {
|
|
let output_chunks = [];
|
|
let codecInit = getDefaultCodecInit(t);
|
|
codecInit.output = chunk => output_chunks.push(chunk);
|
|
|
|
let encoder = new VideoEncoder(codecInit);
|
|
|
|
// No encodes yet.
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
encoder.configure(defaultConfig);
|
|
|
|
// Still no encodes.
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
let frame1 = await createVideoFrame(640, 480, 0);
|
|
let frame2 = await createVideoFrame(640, 480, 33333);
|
|
|
|
encoder.encode(frame1.clone());
|
|
encoder.encode(frame2.clone());
|
|
|
|
// Could be 0, 1, or 2. We can't guarantee this check runs before the UA has
|
|
// processed the encodes.
|
|
assert_true(encoder.encodeQueueSize >= 0 && encoder.encodeQueueSize <= 2)
|
|
|
|
await encoder.flush();
|
|
|
|
// We can guarantee that all encodes are processed after a flush.
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
assert_equals(output_chunks.length, 2);
|
|
assert_equals(output_chunks[0].timestamp, frame1.timestamp);
|
|
assert_equals(output_chunks[1].timestamp, frame2.timestamp);
|
|
}, 'Test successful configure(), encode(), and flush()');
|
|
|
|
promise_test(async t => {
|
|
let callbacks_before_reset = 0;
|
|
let callbacks_after_reset = 0;
|
|
let codecInit = getDefaultCodecInit(t);
|
|
codecInit.output = chunk => {
|
|
if (chunk.timestamp % 2 == 0) {
|
|
// pre-reset frames have even timestamp
|
|
callbacks_before_reset++;
|
|
} else {
|
|
// after-reset frames have odd timestamp
|
|
callbacks_after_reset++;
|
|
}
|
|
}
|
|
|
|
let encoder = new VideoEncoder(codecInit);
|
|
encoder.configure(defaultConfig);
|
|
await encoder.flush();
|
|
|
|
let frames = [];
|
|
for (let i = 0; i < 200; i++) {
|
|
let frame = await createVideoFrame(640, 480, i * 40_000);
|
|
frames.push(frame);
|
|
}
|
|
|
|
for (frame of frames)
|
|
encoder.encode(frame);
|
|
|
|
// Wait for the first frame to be encoded
|
|
await t.step_wait(() => callbacks_before_reset > 0,
|
|
"Encoded outputs started coming", 10000, 1);
|
|
|
|
let saved_callbacks_before_reset = callbacks_before_reset;
|
|
assert_greater_than(callbacks_before_reset, 0);
|
|
assert_less_than_equal(callbacks_before_reset, frames.length);
|
|
|
|
encoder.reset();
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
let newConfig = { ...defaultConfig };
|
|
newConfig.width = 800;
|
|
newConfig.height = 600;
|
|
encoder.configure(newConfig);
|
|
|
|
for (let i = frames.length; i < frames.length + 5; i++) {
|
|
let frame = await createVideoFrame(800, 600, i * 40_000 + 1);
|
|
encoder.encode(frame);
|
|
}
|
|
await encoder.flush();
|
|
assert_equals(callbacks_after_reset, 5);
|
|
assert_equals(saved_callbacks_before_reset, callbacks_before_reset);
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
}, 'Test successful reset() and re-confiugre()');
|
|
|
|
promise_test(async t => {
|
|
let output_chunks = [];
|
|
let codecInit = getDefaultCodecInit(t);
|
|
codecInit.output = chunk => output_chunks.push(chunk);
|
|
|
|
let encoder = new VideoEncoder(codecInit);
|
|
|
|
// No encodes yet.
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
let config = defaultConfig;
|
|
|
|
encoder.configure(config);
|
|
|
|
let frame1 = await createVideoFrame(640, 480, 0);
|
|
let frame2 = await createVideoFrame(640, 480, 33333);
|
|
|
|
encoder.encode(frame1.clone());
|
|
encoder.configure(config);
|
|
|
|
encoder.encode(frame2.clone());
|
|
|
|
await encoder.flush();
|
|
|
|
// We can guarantee that all encodes are processed after a flush.
|
|
assert_equals(encoder.encodeQueueSize, 0);
|
|
|
|
// The first frame may have been dropped when reconfiguring.
|
|
// This shouldn't happen, and should be fixed/called out in the spec, but
|
|
// this is preptively added to prevent flakiness.
|
|
// TODO: Remove these checks when implementations handle this correctly.
|
|
assert_true(output_chunks.length == 1 || output_chunks.length == 2);
|
|
|
|
if (output_chunks.length == 1) {
|
|
// If we only have one chunk frame, make sure we droped the frame that was
|
|
// in flight when we reconfigured.
|
|
assert_equals(output_chunks[0].timestamp, frame2.timestamp);
|
|
} else {
|
|
assert_equals(output_chunks[0].timestamp, frame1.timestamp);
|
|
assert_equals(output_chunks[1].timestamp, frame2.timestamp);
|
|
}
|
|
|
|
output_chunks = [];
|
|
|
|
let frame3 = await createVideoFrame(640, 480, 66666);
|
|
let frame4 = await createVideoFrame(640, 480, 100000);
|
|
|
|
encoder.encode(frame3.clone());
|
|
|
|
// Verify that a failed call to configure does not change the encoder's state.
|
|
let badConfig = { ...defaultConfig };
|
|
badConfig.codec = 'bogus';
|
|
assert_throws_js(TypeError, () => encoder.configure(badConfig));
|
|
|
|
encoder.encode(frame4.clone());
|
|
|
|
await encoder.flush();
|
|
|
|
assert_equals(output_chunks[0].timestamp, frame3.timestamp);
|
|
assert_equals(output_chunks[1].timestamp, frame4.timestamp);
|
|
}, 'Test successful encode() after re-configure().');
|
|
|
|
promise_test(async t => {
|
|
let output_chunks = [];
|
|
let codecInit = getDefaultCodecInit(t);
|
|
codecInit.output = chunk => output_chunks.push(chunk);
|
|
|
|
let encoder = new VideoEncoder(codecInit);
|
|
|
|
let timestamp = 33333;
|
|
let frame = await createVideoFrame(640, 480, timestamp);
|
|
|
|
encoder.configure(defaultConfig);
|
|
assert_equals(encoder.state, "configured");
|
|
|
|
encoder.encode(frame);
|
|
|
|
// |frame| is not longer valid since it has been closed.
|
|
assert_not_equals(frame.timestamp, timestamp);
|
|
assert_throws_dom("InvalidStateError", () => frame.clone());
|
|
|
|
encoder.close();
|
|
|
|
return endAfterEventLoopTurn();
|
|
}, 'Test encoder consumes (closes) frames.');
|
|
|
|
promise_test(async t => {
|
|
let encoder = new VideoEncoder(getDefaultCodecInit(t));
|
|
|
|
let frame = await createVideoFrame(640, 480, 0);
|
|
|
|
return testClosedCodec(t, encoder, defaultConfig, frame);
|
|
}, 'Verify closed VideoEncoder operations');
|
|
|
|
promise_test(async t => {
|
|
let encoder = new VideoEncoder(getDefaultCodecInit(t));
|
|
|
|
let frame = await createVideoFrame(640, 480, 0);
|
|
|
|
return testUnconfiguredCodec(t, encoder, frame);
|
|
}, 'Verify unconfigured VideoEncoder operations');
|
|
|
|
promise_test(async t => {
|
|
let encoder = new VideoEncoder(getDefaultCodecInit(t));
|
|
|
|
let frame = await createVideoFrame(640, 480, 0);
|
|
frame.close();
|
|
|
|
encoder.configure(defaultConfig);
|
|
|
|
assert_throws_dom("OperationError", () => {
|
|
encoder.encode(frame)
|
|
});
|
|
}, 'Verify encoding closed frames throws.');
|