| <!DOCTYPE html> |
| <!-- |
| The most basic GPU smoke test for WebCodecs: Accelerated VideoEncoder encodes |
| several frames and accelerated VideoDecoder needs to successfully decode them. |
| --> |
| <html> |
| |
| <head> |
| <title>Encode, decode, render test</title> |
| <script src="webcodecs_common.js"></script> |
| <script type="text/javascript"> |
| 'use strict'; |
| function showFrameForDebug(frame) { |
| const cnv = document.getElementById('debug_cnv'); |
| var ctx = cnv.getContext('2d'); |
| ctx.drawImage(frame, 0, 0); |
| } |
| |
| async function main(arg) { |
| const width = 640; |
| const height = 480; |
| const frames_to_encode = 32; |
| let frames_encoded = 0; |
| let frames_decoded = 0; |
| let errors = 0; |
| |
| const encoder_config = { |
| codec: arg.codec, |
| hardwareAcceleration: arg.acceleration, |
| width: width, |
| height: height, |
| bitrate: 5000000, |
| framerate: 24 |
| }; |
| if (arg.codec.startsWith('avc1')) { |
| encoder_config.avc = { format: 'annexb' }; |
| } else if (arg.codec.startsWith('hvc1')) { |
| encoder_config.hevc = { format: 'annexb' }; |
| } |
| |
| TEST.log('Starting test with arguments: ' + JSON.stringify(arg)); |
| let supported = false; |
| try { |
| supported = (await VideoEncoder.isConfigSupported(encoder_config)).supported; |
| } catch (e) {} |
| if (!supported) { |
| TEST.skip('Unsupported codec: ' + arg.codec); |
| return; |
| } |
| |
| let decoder = new VideoDecoder({ |
| output(frame) { |
| let dots = frames_decoded; |
| // Check that we have intended number of dots and no more. |
| // Completely black frame shouldn't pass the test. |
| // Only count dots for sources that can actually pain them. |
| if (['offscreen', 'arraybuffer'].includes(arg.source_type)) { |
| if(!validateBlackDots(frame, dots) || |
| validateBlackDots(frame, dots + 1)) { |
| showFrameForDebug(frame); |
| TEST.reportFailure( |
| `Unexpected dot count ts:${frame.timestamp} dots:${dots}`); |
| } |
| } |
| frames_decoded++; |
| frame.close(); |
| }, |
| error(e) { |
| errors++; |
| TEST.log(e); |
| } |
| }); |
| |
| let timestamps = []; |
| |
| const encoder_init = { |
| output(chunk, metadata) { |
| let config = metadata.decoderConfig; |
| if (config) { |
| decoder.configure(config); |
| } |
| decoder.decode(chunk); |
| frames_encoded++; |
| |
| let expected_timestamp = timestamps.shift(); |
| TEST.assert( |
| chunk.timestamp == expected_timestamp, |
| `EncodedVideoChunk timestamp mismatch. Expected: ${ |
| expected_timestamp} got ${chunk.timestamp}`); |
| }, |
| error(e) { |
| errors++; |
| TEST.log(e); |
| } |
| }; |
| |
| let encoder = new VideoEncoder(encoder_init); |
| encoder.configure(encoder_config); |
| |
| let source = await createFrameSource(arg.source_type, width, height); |
| if (!source) { |
| TEST.skip('Unsupported source: ' + arg.source_type); |
| return; |
| } |
| |
| for (let i = 0; i < frames_to_encode; i++) { |
| let frame = await source.getNextFrame(); |
| let keyframe = (i % 10 == 0); |
| timestamps.push(frame.timestamp); |
| encoder.encode(frame, { keyFrame: keyframe }); |
| frame.close(); |
| |
| await waitForNextFrame(); |
| } |
| await encoder.flush(); |
| await decoder.flush(); |
| encoder.close(); |
| decoder.close(); |
| source.close(); |
| |
| TEST.assert( |
| frames_encoded == frames_to_encode, |
| 'frames_encoded mismatch: ' + frames_encoded); |
| TEST.assert( |
| frames_decoded == frames_to_encode, |
| 'frames_decoded mismatch: ' + frames_decoded); |
| TEST.assert( |
| errors == 0, 'Decoding or encoding errors occurred during the test'); |
| TEST.log('Test completed'); |
| } |
| addManualTestButton([{ |
| 'source_type': 'offscreen', |
| 'codec': 'avc1.42001E', |
| 'acceleration':'prefer-software' |
| }, |
| { |
| 'source_type': 'camera', |
| 'codec': 'avc1.42001E', |
| 'acceleration':'prefer-software' |
| }, |
| { |
| 'source_type': 'offscreen', |
| 'codec': 'avc1.42001E', |
| 'acceleration':'prefer-hardware' |
| }, |
| { |
| 'source_type': 'offscreen', |
| 'codec': 'hvc1.1.6.L123.00', |
| 'acceleration':'prefer-software' |
| }, |
| { |
| 'source_type': 'offscreen', |
| 'codec': 'hvc1.1.6.L123.00', |
| 'acceleration':'prefer-hardware' |
| }]); |
| </script> |
| </head> |
| |
| <body> |
| <canvas id="debug_cnv" width="640" height="480"></canvas> |
| </body> |
| |
| </html> |