mirror of
https://github.com/servo/servo.git
synced 2025-06-25 09:34:32 +01:00
105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
// META: global=window,dedicatedworker
|
|
// META: script=/webcodecs/video-encoder-utils.js
|
|
// META: variant=?av1
|
|
// META: variant=?vp8
|
|
// META: variant=?vp9
|
|
// META: variant=?h264
|
|
|
|
var ENCODER_CONFIG = null;
|
|
promise_setup(async () => {
|
|
const config = {
|
|
'?av1': {codec: 'av01.0.04M.08'},
|
|
'?vp8': {codec: 'vp8'},
|
|
'?vp9': {codec: 'vp09.00.10.08'},
|
|
'?h264': {codec: 'avc1.42001E', avc: {format: 'annexb'}}
|
|
}[location.search];
|
|
config.hardwareAcceleration = 'prefer-software';
|
|
config.width = 320;
|
|
config.height = 200;
|
|
config.bitrate = 1000000;
|
|
config.bitrateMode = "constant";
|
|
config.framerate = 30;
|
|
ENCODER_CONFIG = config;
|
|
});
|
|
|
|
async function svc_test(t, layers, base_layer_decimator) {
|
|
let encoder_config = { ...ENCODER_CONFIG };
|
|
encoder_config.scalabilityMode = "L1T" + layers;
|
|
const w = encoder_config.width;
|
|
const h = encoder_config.height;
|
|
await checkEncoderSupport(t, encoder_config);
|
|
|
|
let frames_to_encode = 24;
|
|
let frames_decoded = 0;
|
|
let frames_encoded = 0;
|
|
let chunks = [];
|
|
let corrupted_frames = [];
|
|
|
|
const encoder_init = {
|
|
output(chunk, metadata) {
|
|
frames_encoded++;
|
|
|
|
// Filter out all frames, but base layer.
|
|
assert_own_property(metadata, "svc");
|
|
assert_own_property(metadata.svc, "temporalLayerId");
|
|
assert_less_than(metadata.svc.temporalLayerId, layers);
|
|
if (metadata.svc.temporalLayerId == 0)
|
|
chunks.push(chunk);
|
|
},
|
|
error(e) {
|
|
assert_unreached(e.message);
|
|
}
|
|
};
|
|
|
|
let encoder = new VideoEncoder(encoder_init);
|
|
encoder.configure(encoder_config);
|
|
|
|
for (let i = 0; i < frames_to_encode; i++) {
|
|
let frame = createDottedFrame(w, h, i);
|
|
encoder.encode(frame, { keyFrame: false });
|
|
frame.close();
|
|
}
|
|
await encoder.flush();
|
|
|
|
let decoder = new VideoDecoder({
|
|
output(frame) {
|
|
frames_decoded++;
|
|
// Check that we have intended number of dots and no more.
|
|
// Completely black frame shouldn't pass the test.
|
|
if(!validateBlackDots(frame, frame.timestamp) ||
|
|
validateBlackDots(frame, frame.timestamp + 1)) {
|
|
corrupted_frames.push(frame.timestamp)
|
|
}
|
|
frame.close();
|
|
},
|
|
error(e) {
|
|
assert_unreached(e.message);
|
|
}
|
|
});
|
|
|
|
let decoder_config = {
|
|
codec: encoder_config.codec,
|
|
hardwareAcceleration: encoder_config.hardwareAcceleration,
|
|
codedWidth: w,
|
|
codedHeight: h,
|
|
};
|
|
decoder.configure(decoder_config);
|
|
|
|
for (let chunk of chunks) {
|
|
decoder.decode(chunk);
|
|
}
|
|
await decoder.flush();
|
|
|
|
encoder.close();
|
|
decoder.close();
|
|
assert_equals(frames_encoded, frames_to_encode);
|
|
|
|
let base_layer_frames = frames_to_encode / base_layer_decimator;
|
|
assert_equals(chunks.length, base_layer_frames);
|
|
assert_equals(frames_decoded, base_layer_frames);
|
|
assert_equals(corrupted_frames.length, 0,
|
|
`corrupted_frames: ${corrupted_frames}`);
|
|
}
|
|
|
|
promise_test(async t => { return svc_test(t, 2, 2) }, "SVC L1T2");
|
|
promise_test(async t => { return svc_test(t, 3, 4) }, "SVC L1T3");
|