| // META: global=window,dedicatedworker |
| // META: script=/webcodecs/utils.js |
| |
| |
| const detachedArrayBuffer = new ArrayBuffer(4); |
| var b = detachedArrayBuffer.transferToFixedLength(); |
| |
| const invalidConfigs = [ |
| { |
| comment: 'Missing codec', |
| config: { |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Empty codec', |
| config: { |
| codec: '', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Missing sampleRate', |
| config: { |
| codec: 'opus', |
| sampleRate: 48000, |
| }, |
| }, |
| { |
| comment: 'Missing numberOfChannels', |
| config: { |
| codec: 'opus', |
| sampleRate: 48000, |
| }, |
| }, |
| { |
| comment: 'Zero sampleRate', |
| config: { |
| codec: 'opus', |
| sampleRate: 0, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Zero channels', |
| config: { |
| codec: 'opus', |
| sampleRate: 8000, |
| numberOfChannels: 0, |
| }, |
| }, |
| { |
| comment: 'Valid configuration except detached description', |
| config: { |
| codec: 'opus', |
| sampleRate: 8000, |
| numberOfChannels: 1, |
| description: detachedArrayBuffer |
| }, |
| }, |
| ]; |
| |
| invalidConfigs.forEach(entry => { |
| promise_test( |
| t => { |
| return promise_rejects_js( |
| t, TypeError, AudioDecoder.isConfigSupported(entry.config)); |
| }, |
| 'Test that AudioDecoder.isConfigSupported() rejects invalid config: ' + |
| entry.comment); |
| }); |
| |
| invalidConfigs.forEach(entry => { |
| async_test( |
| t => { |
| let codec = new AudioDecoder(getDefaultCodecInit(t)); |
| assert_throws_js(TypeError, () => { |
| codec.configure(entry.config); |
| }); |
| t.done(); |
| }, |
| 'Test that AudioDecoder.configure() rejects invalid config: ' + |
| entry.comment); |
| }); |
| |
| const validButUnsupportedConfigs = [ |
| { |
| comment: 'Unrecognized codec', |
| config: { |
| codec: 'bogus', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Video codec', |
| config: { |
| codec: 'vp8', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Ambiguous codec', |
| config: { |
| codec: 'vp9', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Codec with MIME type', |
| config: { |
| codec: 'audio/webm; codecs="opus"', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| }, |
| }, |
| { |
| comment: 'Possible future opus codec string', |
| config: { |
| codec: 'opus.123', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| } |
| }, |
| { |
| comment: 'Possible future aac codec string', |
| config: { |
| codec: 'mp4a.FF.9', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| } |
| }, |
| ]; |
| |
| validButUnsupportedConfigs.forEach(entry => { |
| promise_test( |
| t => { |
| return AudioDecoder.isConfigSupported(entry.config).then(support => { |
| assert_false(support.supported); |
| }); |
| }, |
| 'Test that AudioDecoder.isConfigSupported() doesn\'t support config: ' + |
| entry.comment); |
| }); |
| |
| validButUnsupportedConfigs.forEach(entry => { |
| promise_test( |
| t => { |
| let isErrorCallbackCalled = false; |
| let codec = new AudioDecoder({ |
| output: t.unreached_func('unexpected output'), |
| error: t.step_func_done(e => { |
| isErrorCallbackCalled = true; |
| assert_true(e instanceof DOMException); |
| assert_equals(e.name, 'NotSupportedError'); |
| assert_equals(codec.state, 'closed', 'state'); |
| }) |
| }); |
| codec.configure(entry.config); |
| return codec.flush() |
| .then(t.unreached_func('flush succeeded unexpectedly')) |
| .catch(t.step_func(e => { |
| assert_true(isErrorCallbackCalled, "isErrorCallbackCalled"); |
| assert_true(e instanceof DOMException); |
| assert_equals(e.name, 'NotSupportedError'); |
| assert_equals(codec.state, 'closed', 'state'); |
| })); |
| }, |
| 'Test that AudioDecoder.configure() doesn\'t support config: ' + |
| entry.comment); |
| }); |
| |
| function getFakeChunk() { |
| return new EncodedAudioChunk( |
| {type: 'key', timestamp: 0, data: Uint8Array.of(0)}); |
| } |
| |
| promise_test(t => { |
| // AudioDecoderInit lacks required fields. |
| assert_throws_js(TypeError, () => { |
| new AudioDecoder({}); |
| }); |
| |
| // AudioDecoderInit has required fields. |
| let decoder = new AudioDecoder(getDefaultCodecInit(t)); |
| |
| assert_equals(decoder.state, 'unconfigured'); |
| decoder.close(); |
| |
| return endAfterEventLoopTurn(); |
| }, 'Test AudioDecoder construction'); |
| |
| promise_test(t => { |
| let decoder = new AudioDecoder(getDefaultCodecInit(t)); |
| return testUnconfiguredCodec(t, decoder, getFakeChunk()); |
| }, 'Verify unconfigured AudioDecoder operations'); |