| // META: global=window,dedicatedworker |
| // META: script=/webcodecs/utils.js |
| |
| const defaultConfig = { |
| codec: "opus", |
| sampleRate: 48000, |
| numberOfChannels: 2 |
| }; |
| |
| function getFakeChunk() { |
| return new EncodedAudioChunk({ |
| type:'key', |
| timestamp:0, |
| data:Uint8Array.of(0) |
| }); |
| } |
| |
| const invalidConfigs = [ |
| { |
| comment: 'Emtpy codec', |
| config: {codec: ''}, |
| }, |
| { |
| comment: 'Unrecognized codec', |
| config: {codec: 'bogus'}, |
| }, |
| { |
| comment: 'Video codec', |
| config: {codec: 'vp8'}, |
| }, |
| { |
| comment: 'Ambiguous codec', |
| config: {codec: 'vp9'}, |
| }, |
| { |
| comment: 'Codec with MIME type', |
| config: {codec: 'audio/webm; codecs="opus"'}, |
| }, |
| ]; |
| |
| 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); |
| }); |
| |
| promise_test(t => { |
| return AudioDecoder.isConfigSupported({ |
| codec: 'opus', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| // Opus header extradata. |
| description: new Uint8Array([0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, |
| 0x01, 0x02, 0x38, 0x01, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00]) |
| }); |
| }, 'Test AudioDecoder.isConfigSupported() with a valid config'); |
| |
| promise_test(t => { |
| // Define a valid config that includes a hypothetical 'futureConfigFeature', |
| // which is not yet recognized by the User Agent. |
| const validConfig = { |
| codec: 'opus', |
| sampleRate: 48000, |
| numberOfChannels: 2, |
| // Opus header extradata. |
| description: new Uint8Array([0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64, |
| 0x01, 0x02, 0x38, 0x01, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00]), |
| futureConfigFeature: 'foo', |
| }; |
| |
| // The UA will evaluate validConfig as being "valid", ignoring the |
| // `futureConfigFeature` it doesn't recognize. |
| return AudioDecoder.isConfigSupported(validConfig).then((decoderSupport) => { |
| // AudioDecoderSupport must contain the following properites. |
| assert_true(decoderSupport.hasOwnProperty('supported')); |
| assert_true(decoderSupport.hasOwnProperty('config')); |
| |
| // AudioDecoderSupport.config must not contain unrecognized properties. |
| assert_false(decoderSupport.config.hasOwnProperty('futureConfigFeature')); |
| |
| // AudioDecoderSupport.config must contiain the recognized properties. |
| assert_equals(decoderSupport.config.codec, validConfig.codec); |
| assert_equals(decoderSupport.config.sampleRate, validConfig.sampleRate); |
| assert_equals(decoderSupport.config.numberOfChannels, validConfig.numberOfChannels); |
| |
| // The description BufferSource must copy the input config description. |
| assert_not_equals(decoderSupport.config.description, validConfig.description); |
| let parsedDescription = new Uint8Array(decoderSupport.config.description); |
| assert_equals(parsedDescription.length, validConfig.description.length); |
| for (let i = 0; i < parsedDescription.length; ++i) { |
| assert_equals(parsedDescription[i], validConfig.description[i]); |
| } |
| }); |
| }, 'Test that AudioDecoder.isConfigSupported() returns a parsed configuration'); |
| |
| 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)); |
| |
| let badCodecsList = [ |
| '', // Empty codec |
| 'bogus', // Non exsitent codec |
| 'vp8', // Video codec |
| 'audio/webm; codecs="opus"' // Codec with mime type |
| ] |
| |
| testConfigurations(decoder, defaultConfig, badCodecsList); |
| |
| return endAfterEventLoopTurn(); |
| }, 'Test AudioDecoder.configure()'); |
| |
| promise_test(t => { |
| let decoder = new AudioDecoder(getDefaultCodecInit(t)); |
| |
| return testClosedCodec(t, decoder, defaultConfig, getFakeChunk()); |
| }, 'Verify closed AudioDecoder operations'); |
| |
| promise_test(t => { |
| let decoder = new AudioDecoder(getDefaultCodecInit(t)); |
| |
| return testUnconfiguredCodec(t, decoder, getFakeChunk()); |
| }, 'Verify unconfigured AudioDecoder operations'); |