| // META: timeout=long | |
| // META: global=window,dedicatedworker | |
| // META: script=/webcodecs/video-encoder-utils.js | |
| // META: variant=?av1 | |
| // META: variant=?vp8 | |
| // META: variant=?vp9_p0 | |
| // META: variant=?vp9_p2 | |
| // META: variant=?h264_avc | |
| // META: variant=?h264_annexb | |
| var ENCODER_CONFIG = null; | |
| promise_setup(async () => { | |
| const config = { | |
| '?av1': {codec: 'av01.0.04M.08'}, | |
| '?vp8': {codec: 'vp8'}, | |
| '?vp9_p0': {codec: 'vp09.00.10.08'}, | |
| '?vp9_p2': {codec: 'vp09.02.10.10'}, | |
| '?h264_avc': {codec: 'avc1.42001F', avc: {format: 'avc'}}, | |
| '?h264_annexb': {codec: 'avc1.42001F', avc: {format: 'annexb'}} | |
| }[location.search]; | |
| config.hardwareAcceleration = 'prefer-software'; | |
| config.bitrateMode = "constant"; | |
| config.framerate = 30; | |
| ENCODER_CONFIG = config; | |
| }); | |
| promise_test(async t => { | |
| let original_w = 800; | |
| let original_h = 600; | |
| let original_bitrate = 3_000_000; | |
| let new_w = 640; | |
| let new_h = 480; | |
| let new_bitrate = 2_000_000; | |
| let next_ts = 0 | |
| let reconf_ts = 0; | |
| let frames_to_encode = 16; | |
| let before_reconf_frames = 0; | |
| let after_reconf_frames = 0; | |
| let process_video_chunk = function (chunk, metadata) { | |
| let config = metadata.decoderConfig; | |
| var data = new Uint8Array(chunk.data); | |
| assert_greater_than_equal(data.length, 0); | |
| let after_reconf = (reconf_ts != 0) && (chunk.timestamp >= reconf_ts); | |
| if (after_reconf) { | |
| after_reconf_frames++; | |
| if (config) { | |
| assert_equals(config.codedWidth, new_w); | |
| assert_equals(config.codedHeight, new_h); | |
| } | |
| } else { | |
| before_reconf_frames++; | |
| if (config) { | |
| assert_equals(config.codedWidth, original_w); | |
| assert_equals(config.codedHeight, original_h); | |
| } | |
| } | |
| }; | |
| const init = { | |
| output: (chunk, md) => { | |
| try { | |
| process_video_chunk(chunk, md); | |
| } catch (e) { | |
| assert_unreached(e.message); | |
| } | |
| }, | |
| error: (e) => { | |
| assert_unreached(e.message); | |
| }, | |
| }; | |
| const params = { | |
| ...ENCODER_CONFIG, | |
| width: original_w, | |
| height: original_h, | |
| bitrate: original_bitrate, | |
| }; | |
| await checkEncoderSupport(t, params); | |
| let encoder = new VideoEncoder(init); | |
| encoder.configure(params); | |
| // Remove this flush after crbug.com/1275789 is fixed | |
| await encoder.flush(); | |
| // Encode |frames_to_encode| frames with original settings | |
| for (let i = 0; i < frames_to_encode; i++) { | |
| var frame = createFrame(original_w, original_h, next_ts++); | |
| encoder.encode(frame, {}); | |
| frame.close(); | |
| } | |
| params.width = new_w; | |
| params.height = new_h; | |
| params.bitrate = new_bitrate; | |
| // Reconfigure encoder and run |frames_to_encode| frames with new settings | |
| encoder.configure(params); | |
| reconf_ts = next_ts; | |
| for (let i = 0; i < frames_to_encode; i++) { | |
| var frame = createFrame(new_w, new_h, next_ts++); | |
| encoder.encode(frame, {}); | |
| frame.close(); | |
| } | |
| await encoder.flush(); | |
| // Configure back to original config | |
| params.width = original_w; | |
| params.height = original_h; | |
| params.bitrate = original_bitrate; | |
| encoder.configure(params); | |
| await encoder.flush(); | |
| encoder.close(); | |
| assert_equals(before_reconf_frames, frames_to_encode); | |
| assert_equals(after_reconf_frames, frames_to_encode); | |
| }, "Reconfiguring encoder"); |