diff --git a/LayoutTests/TestExpectations b/LayoutTests/TestExpectations index 1f34f059e9d8d..2d5a94c6cc490 100644 --- a/LayoutTests/TestExpectations +++ b/LayoutTests/TestExpectations @@ -5761,6 +5761,12 @@ imported/w3c/web-platform-tests/html/canvas/offscreen/text/canvas.2d.fontStretch imported/w3c/web-platform-tests/html/canvas/offscreen/text/canvas.2d.fontStretch.ultra-expanded.html [ ImageOnlyFailure ] imported/w3c/web-platform-tests/webcodecs/videoFrame-drawImage.any.worker.html [ Failure ] +# Flac and Vorbis decoding requires an extra description which isn't provided. +imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?flac [ Failure ] +imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?vorbis [ Failure ] +imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?flac [ Failure ] +imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?vorbis [ Failure ] + # HEVC support may not be available to all platforms. imported/w3c/web-platform-tests/webcodecs/full-cycle-test.https.any.html?h265_annexb [ Pass Failure ] imported/w3c/web-platform-tests/webcodecs/full-cycle-test.https.any.html?h265_hevc [ Pass Failure ] diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/README.md b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/README.md index 0a1324a1ac46c..dce4ef3650eab 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/README.md +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/README.md @@ -114,16 +114,16 @@ sox -n -r 48000 sfx.wav synth 1 sine 480 ffmpeg -i sfx.wav -frames:a 10 -acodec aac -b:a 96K sfx.adts ``` -### sfx-alaw.wav +### sfx.mp3 ``` sox -n -r 48000 sfx.wav synth 1 sine 480 -ffmpeg -i sfx.wav -frames:a 10 -acodec pcm_alaw sfx-alaw.wav +ffmpeg -i sfx.wav -frames:a 10 -acodec libmp3lame -b:a 96K sfx.mp3 ``` -### sfx.mp3 +### sfx.flac ``` sox -n -r 48000 sfx.wav synth 1 sine 480 -ffmpeg -i sfx.wav -frames:a 10 -acodec libmp3lame -b:a 96K sfx.mp3 +ffmpeg -i sfx.wav -frames:a 10 sfx.flac ``` ### sfx-aac.mp4 @@ -132,16 +132,30 @@ sox -n -r 48000 sfx.wav synth 1 sine 480 ffmpeg -i sfx.wav -frames:a 10 -acodec aac -b:a 96K sfx-aac.mp4 ``` -### sfx-mulaw.wav +### sfx-*.wav ``` sox -n -r 48000 sfx.wav synth 1 sine 480 -ffmpeg -i sfx.wav -frames:a 10 -acodec pcm_mulaw sfx-mulaw.wav +for codec in s16 s24 s32 f32 +do + # Add "le" suffix + ffmpeg -i sfx.wav -frames:a 10 -acodec pcm_"$codec"le sfx-pcm-$codec.wav +done +ffmpeg -i sfx.wav -frames:a 10 -acodec pcm_u8 sfx-pcm-u8.wav +for codec in alaw mulaw +do + ffmpeg -i sfx.wav -frames:a 10 -acodec pcm_$codec sfx-$codec.wav +done ``` ### sfx-opus.ogg ``` sox -n -r 48000 sfx.wav synth 1 sine 480 ffmpeg -i sfx.wav -frames:a 10 -acodec libopus -b:a 96K sfx-opus.ogg + +### sfx-vorbis.ogg +``` +sox -n -r 48000 sfx.wav synth 1 sine 480 +ffmpeg -i sfx.wav -frames:a 10 -acodec libvorbis -b:a 96K sfx-vorbis.ogg ``` ### av1.mp4 diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/WEB_FEATURES.yml b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/WEB_FEATURES.yml new file mode 100644 index 0000000000000..89681db88506d --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/WEB_FEATURES.yml @@ -0,0 +1,3 @@ +features: +- name: webcodecs + files: "**" diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any-expected.txt index bc6d40f96ddb8..a5da49896a2c2 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any-expected.txt @@ -2,9 +2,22 @@ PASS Verify AudioData constructors PASS Verify closing and cloning AudioData PASS Test we can construct AudioData with a negative timestamp. -PASS Test conversion of uint8 data to float32 -PASS Test conversion of int16 data to float32 -PASS Test conversion of int32 data to float32 -PASS Test conversion of float32 data to float32 -PASS Test copying out planar and interleaved data +PASS Test input array is copied on construction +PASS Test that copyTo throws if copying from interleaved with a non-zero planeIndex +PASS Test conversion of u8 to u8 +PASS Test conversion of u8 to s16 +PASS Test conversion of u8 to s32 +PASS Test conversion of u8 to f32 +PASS Test conversion of s16 to u8 +PASS Test conversion of s16 to s16 +PASS Test conversion of s16 to s32 +PASS Test conversion of s16 to f32 +PASS Test conversion of s32 to u8 +PASS Test conversion of s32 to s16 +PASS Test conversion of s32 to s32 +PASS Test conversion of s32 to f32 +PASS Test conversion of f32 to u8 +PASS Test conversion of f32 to s16 +PASS Test conversion of f32 to s32 +PASS Test conversion of f32 to f32 diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.js b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.js index 4c2d96ab80edb..c18606e2b7054 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.js +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.js @@ -2,19 +2,20 @@ // META: script=/common/media.js // META: script=/webcodecs/utils.js -var defaultInit = - { - timestamp: 1234, - channels: 2, - sampleRate: 8000, - frames: 100, - } - -function -createDefaultAudioData() { +var defaultInit = { + timestamp: 1234, + channels: 2, + sampleRate: 8000, + frames: 100, +}; + +function createDefaultAudioData() { return make_audio_data( - defaultInit.timestamp, defaultInit.channels, defaultInit.sampleRate, - defaultInit.frames); + defaultInit.timestamp, + defaultInit.channels, + defaultInit.sampleRate, + defaultInit.frames + ); } test(t => { @@ -128,230 +129,329 @@ test(t => { data.close(); }, 'Test we can construct AudioData with a negative timestamp.'); - -// Each test vector represents two channels of data in the following arbitrary -// layout: . -const testVectorFrames = 5; -const testVectorChannels = 2; -const testVectorInterleavedResult = - [[-1.0, 1.0, 0.5, 0.0, 0.0], [0.0, -1.0, -0.5, 1.0, 0.0]]; -const testVectorPlanarResult = - [[-1.0, 0.0, 1.0, -1.0, 0.5], [-0.5, 0.0, 1.0, 0.0, 0.0]]; - -test(t => { - const INT8_MIN = (-0x7f - 1); - const INT8_MAX = 0x7f; - const UINT8_MAX = 0xff; - - const testVectorUint8 = [ - 0, -INT8_MIN, UINT8_MAX, 0, INT8_MAX / 2 + 128, INT8_MIN / 2 + 128, - -INT8_MIN, UINT8_MAX, -INT8_MIN, -INT8_MIN - ]; - - let data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Uint8Array(testVectorUint8), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'u8' - }); - - const epsilon = 1.0 / (UINT8_MAX - 1); - - let dest = new Float32Array(data.numberOfFrames); - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[0], epsilon, 'interleaved channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[1], epsilon, 'interleaved channel 1'); - - data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Uint8Array(testVectorUint8), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'u8-planar' - }); - - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[0], epsilon, 'planar channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[1], epsilon, 'planar channel 1'); -}, 'Test conversion of uint8 data to float32'); - -test(t => { - const INT16_MIN = (-0x7fff - 1); - const INT16_MAX = 0x7fff; - const testVectorInt16 = [ - INT16_MIN, 0, INT16_MAX, INT16_MIN, INT16_MAX / 2, INT16_MIN / 2, 0, - INT16_MAX, 0, 0 - ]; - - let data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Int16Array(testVectorInt16), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 's16' - }); - - const epsilon = 1.0 / (INT16_MAX + 1); - - let dest = new Float32Array(data.numberOfFrames); - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[0], epsilon, 'interleaved channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[1], epsilon, 'interleaved channel 1'); - - data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Int16Array(testVectorInt16), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 's16-planar' - }); - - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[0], epsilon, 'planar channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[1], epsilon, 'planar channel 1'); -}, 'Test conversion of int16 data to float32'); - test(t => { - const INT32_MIN = (-0x7fffffff - 1); - const INT32_MAX = 0x7fffffff; - const testVectorInt32 = [ - INT32_MIN, 0, INT32_MAX, INT32_MIN, INT32_MAX / 2, INT32_MIN / 2, 0, - INT32_MAX, 0, 0 - ]; - - let data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Int32Array(testVectorInt32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 's32' - }); - - const epsilon = 1.0 / INT32_MAX; - - let dest = new Float32Array(data.numberOfFrames); - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[0], epsilon, 'interleaved channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[1], epsilon, 'interleaved channel 1'); - - data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Int32Array(testVectorInt32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 's32-planar' - }); - - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[0], epsilon, 'planar channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[1], epsilon, 'planar channel 1'); -}, 'Test conversion of int32 data to float32'); + var data = new Float32Array([0]); + let audio_data_init = { + timestamp: 0, + data: data, + numberOfFrames: 1, + numberOfChannels: 1, + sampleRate: 44100, + format: 'f32', + }; + let audioData = new AudioData(audio_data_init); + assert_not_equals(data.length, 0, "Input data is copied when constructing an AudioData"); +}, 'Test input array is copied on construction'); test(t => { - const testVectorFloat32 = - [-1.0, 0.0, 1.0, -1.0, 0.5, -0.5, 0.0, 1.0, 0.0, 0.0]; - - let data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Float32Array(testVectorFloat32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'f32' - }); - - const epsilon = 0; - - let dest = new Float32Array(data.numberOfFrames); - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[0], epsilon, 'interleaved channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorInterleavedResult[1], epsilon, 'interleaved channel 1'); - - data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Float32Array(testVectorFloat32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'f32-planar' - }); + let audio_data_init = { + timestamp: 0, + data: new Float32Array([1,2,3,4,5,6,7,8]), + numberOfFrames: 4, + numberOfChannels: 2, + sampleRate: 44100, + format: 'f32', + }; + let audioData = new AudioData(audio_data_init); + let dest = new Float32Array(8); + assert_throws_js( + RangeError, () => audioData.copyTo(dest, {planeIndex: 1}), + 'copyTo from interleaved data with non-zero planeIndex throws'); + audioData.close(); +}, 'Test that copyTo throws if copying from interleaved with a non-zero planeIndex'); + +// Indices to pick a particular specific value in a specific sample-format +const MIN = 0; // Minimum sample value, max amplitude +const MAX = 1; // Maximum sample value, max amplitude +const HALF = 2; // Half the maximum sample value, positive +const NEGATIVE_HALF = 3; // Half the maximum sample value, negative +const BIAS = 4; // Center of the range, silence +const DISCRETE_STEPS = 5; // Number of different value for a type. + +function pow2(p) { + return 2 ** p; +} +// Rounding operations for conversion, currently always floor (round towards +// zero). +let r = Math.floor.bind(this); + +const TEST_VALUES = { + u8: [0, 255, 191, 64, 128, 256], + s16: [ + -pow2(15), + pow2(15) - 1, + r((pow2(15) - 1) / 2), + r(-pow2(15) / 2), + 0, + pow2(16), + ], + s32: [ + -pow2(31), + pow2(31) - 1, + r((pow2(31) - 1) / 2), + r(-pow2(31) / 2), + 0, + pow2(32), + ], + f32: [-1.0, 1.0, 0.5, -0.5, 0, pow2(24)], +}; + +const TEST_TEMPLATE = { + channels: 2, + frames: 5, + // Each test is run with an element of the cartesian product of a pair of + // elements of the set of type in [u8, s16, s32, f32] + // For each test, this template is copied and the values replaced with the + // appropriate values for this particular type. + // For each test, copy this template and replace the number by the appropriate + // number for this type + testInput: [MIN, BIAS, MAX, MIN, HALF, NEGATIVE_HALF, BIAS, MAX, BIAS, BIAS], + testInterleavedResult: [MIN, NEGATIVE_HALF, BIAS, BIAS, MAX, MAX, MIN, BIAS, HALF, BIAS], + testVectorInterleavedResult: [ + [MIN, MAX, HALF, BIAS, BIAS], + [BIAS, MIN, NEGATIVE_HALF, MAX, BIAS], + ], + testVectorPlanarResult: [ + [MIN, BIAS, MAX, MIN, HALF], + [NEGATIVE_HALF, BIAS, MAX, BIAS, BIAS], + ], +}; + +function isInteger(type) { + switch (type) { + case "u8": + case "s16": + case "s32": + return true; + case "f32": + return false; + default: + throw "invalid type"; + } +} - data.copyTo(dest, {planeIndex: 0, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[0], epsilon, 'planar channel 0'); - data.copyTo(dest, {planeIndex: 1, format: 'f32-planar'}); - assert_array_approx_equals( - dest, testVectorPlanarResult[1], epsilon, 'planar channel 1'); -}, 'Test conversion of float32 data to float32'); +// This is the complex part: carefully select an acceptable error value +// depending on various factors: expected destination value, source type, +// destination type. This is designed to be strict but reachable with simple +// sample format transformation (no dithering or complex transformation). +function epsilon(expectedDestValue, sourceType, destType) { + // Strict comparison if not converting + if (sourceType == destType) { + return 0.0; + } + // There are three cases in which the maximum value cannot be reached, when + // converting from a smaller integer sample type to a wider integer sample + // type: + // - u8 to s16 + // - u8 to s32 + // - s16 to u32 + if (expectedDestValue == TEST_VALUES[destType][MAX]) { + if (sourceType == "u8" && destType == "s16") { + return expectedDestValue - 32511; // INT16_MAX - 2 << 7 + 1 + } else if (sourceType == "u8" && destType == "s32") { + return expectedDestValue - 2130706432; // INT32_MAX - (2 << 23) + 1 + } else if (sourceType == "s16" && destType == "s32") { + return expectedDestValue - 2147418112; // INT32_MAX - UINT16_MAX + } + } + // Min and bias value are correctly mapped for all integer sample-types + if (isInteger(sourceType) && isInteger(destType)) { + if (expectedDestValue == TEST_VALUES[destType][MIN] || + expectedDestValue == TEST_VALUES[destType][BIAS]) { + return 0.0; + } + } + // If converting from float32 to u8 or s16, allow choosing the rounding + // direction. s32 has higher resolution than f32 in [-1.0,1.0] (24 bits of + // mantissa) + if (!isInteger(sourceType) && isInteger(destType) && destType != "s32") { + return 1.0; + } + // In all other cases, expect an accuracy that depends on the source type and + // the destination type. + // The resolution of the source type. + var sourceResolution = TEST_VALUES[sourceType][DISCRETE_STEPS]; + // The resolution of the destination type. + var destResolution = TEST_VALUES[destType][DISCRETE_STEPS]; + // Computations should be exact if going from high resolution to low resolution. + if (sourceResolution > destResolution) { + return 0.0; + } else { + // Something that approaches the precision imbalance + return destResolution / sourceResolution; + } +} -test(t => { - const testVectorFloat32 = - [-1.0, 0.0, 1.0, -1.0, 0.5, -0.5, 0.0, 1.0, 0.0, 0.0]; +// Fill the template above with the values for a particular type +function get_type_values(type) { + let cloned = structuredClone(TEST_TEMPLATE); + cloned.testInput = Array.from( + cloned.testInput, + idx => TEST_VALUES[type][idx] + ); + cloned.testInterleavedResult = Array.from( + cloned.testInterleavedResult, + idx => TEST_VALUES[type][idx] + ); + cloned.testVectorInterleavedResult = Array.from( + cloned.testVectorInterleavedResult, + c => { + return Array.from(c, idx => { + return TEST_VALUES[type][idx]; + }); + } + ); + cloned.testVectorPlanarResult = Array.from( + cloned.testVectorPlanarResult, + c => { + return Array.from(c, idx => { + return TEST_VALUES[type][idx]; + }); + } + ); + return cloned; +} - let data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Float32Array(testVectorFloat32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'f32' - }); +function typeToArrayType(type) { + switch (type) { + case "u8": + return Uint8Array; + case "s16": + return Int16Array; + case "s32": + return Int32Array; + case "f32": + return Float32Array; + default: + throw "Unexpected"; + } +} - const epsilon = 0; +function arrayTypeToType(array) { + switch (array.constructor) { + case Uint8Array: + return "u8"; + case Int16Array: + return "s16"; + case Int32Array: + return "s32"; + case Float32Array: + return "f32"; + default: + throw "Unexpected"; + } +} - // Call copyTo() without specifying a format, for interleaved data. - let dest = new Float32Array(data.numberOfFrames * testVectorChannels); - data.copyTo(dest, {planeIndex: 0}); - assert_array_approx_equals( - dest, testVectorFloat32, epsilon, 'interleaved data'); +function check_array_equality(values, expected, sourceType, message, assert_func) { + if (values.length != expected.length) { + throw "Array not of the same length"; + } + for (var i = 0; i < values.length; i++) { + var eps = epsilon(expected[i], sourceType, arrayTypeToType(values)); + assert_func( + Math.abs(expected[i] - values[i]) <= eps, + `Got ${values[i]} but expected result ${ + expected[i] + } at index ${i} when converting from ${sourceType} to ${arrayTypeToType( + values + )}, epsilon ${eps}` + ); + } + assert_func( + true, + `${values} is equal to ${expected} when converting from ${sourceType} to ${arrayTypeToType( + values + )}` + ); +} - assert_throws_js(RangeError, () => { - data.copyTo(dest, {planeIndex: 1}); - }, 'Interleaved AudioData cannot copy out planeIndex > 0'); +function conversionTest(sourceType, destinationType) { + test(function (t) { + var test = get_type_values(sourceType); + var result = get_type_values(destinationType); + + var sourceArrayCtor = typeToArrayType(sourceType); + var destArrayCtor = typeToArrayType(destinationType); + + let data = new AudioData({ + timestamp: defaultInit.timestamp, + data: new sourceArrayCtor(test.testInput), + numberOfFrames: test.frames, + numberOfChannels: test.channels, + sampleRate: defaultInit.sampleRate, + format: sourceType, + }); + + // All conversions can be supported, but conversion of any type to f32-planar + // MUST be supported. + var assert_func = destinationType == "f32" ? assert_true : assert_implements_optional; + let dest = new destArrayCtor(data.numberOfFrames); + data.copyTo(dest, { planeIndex: 0, format: destinationType + "-planar" }); + check_array_equality( + dest, + result.testVectorInterleavedResult[0], + sourceType, + "interleaved channel 0", + assert_func + ); + data.copyTo(dest, { planeIndex: 1, format: destinationType + "-planar" }); + check_array_equality( + dest, + result.testVectorInterleavedResult[1], + sourceType, + "interleaved channel 0", + assert_func + ); + let destInterleaved = new destArrayCtor(data.numberOfFrames * data.numberOfChannels); + data.copyTo(destInterleaved, { planeIndex: 0, format: destinationType }); + check_array_equality( + destInterleaved, + result.testInput, + sourceType, + "copyTo from interleaved to interleaved (conversion only)", + assert_implements_optional + ); + + data = new AudioData({ + timestamp: defaultInit.timestamp, + data: new sourceArrayCtor(test.testInput), + numberOfFrames: test.frames, + numberOfChannels: test.channels, + sampleRate: defaultInit.sampleRate, + format: sourceType + "-planar", + }); + + data.copyTo(dest, { planeIndex: 0, format: destinationType + "-planar" }); + check_array_equality( + dest, + result.testVectorPlanarResult[0], + sourceType, + "planar channel 0", + assert_func, + ); + data.copyTo(dest, { planeIndex: 1, format: destinationType + "-planar" }); + check_array_equality( + dest, + result.testVectorPlanarResult[1], + sourceType, + "planar channel 1", + assert_func + ); + // Copy to interleaved from planar: all channels are copied + data.copyTo(destInterleaved, {planeIndex: 0, format: destinationType}); + check_array_equality( + destInterleaved, + result.testInterleavedResult, + sourceType, + "planar to interleaved", + assert_func + ); + }, `Test conversion of ${sourceType} to ${destinationType}`); +} - data = new AudioData({ - timestamp: defaultInit.timestamp, - data: new Float32Array(testVectorFloat32), - numberOfFrames: testVectorFrames, - numberOfChannels: testVectorChannels, - sampleRate: defaultInit.sampleRate, - format: 'f32-planar' +const TYPES = ["u8", "s16", "s32", "f32"]; + TYPES.forEach(sourceType => { + TYPES.forEach(destinationType => { + conversionTest(sourceType, destinationType); }); - - // Call copyTo() without specifying a format, for planar data. - dest = new Float32Array(data.numberOfFrames); - data.copyTo(dest, {planeIndex: 0}); - assert_array_approx_equals( - dest, testVectorPlanarResult[0], epsilon, 'planar channel 0'); - data.copyTo(dest, {planeIndex: 1}); - assert_array_approx_equals( - dest, testVectorPlanarResult[1], epsilon, 'planar channel 1'); -}, 'Test copying out planar and interleaved data'); +}); diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.worker-expected.txt index bc6d40f96ddb8..a5da49896a2c2 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.worker-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.worker-expected.txt @@ -2,9 +2,22 @@ PASS Verify AudioData constructors PASS Verify closing and cloning AudioData PASS Test we can construct AudioData with a negative timestamp. -PASS Test conversion of uint8 data to float32 -PASS Test conversion of int16 data to float32 -PASS Test conversion of int32 data to float32 -PASS Test conversion of float32 data to float32 -PASS Test copying out planar and interleaved data +PASS Test input array is copied on construction +PASS Test that copyTo throws if copying from interleaved with a non-zero planeIndex +PASS Test conversion of u8 to u8 +PASS Test conversion of u8 to s16 +PASS Test conversion of u8 to s32 +PASS Test conversion of u8 to f32 +PASS Test conversion of s16 to u8 +PASS Test conversion of s16 to s16 +PASS Test conversion of s16 to s32 +PASS Test conversion of s16 to f32 +PASS Test conversion of s32 to u8 +PASS Test conversion of s32 to s16 +PASS Test conversion of s32 to s32 +PASS Test conversion of s32 to f32 +PASS Test conversion of f32 to u8 +PASS Test conversion of f32 to s16 +PASS Test conversion of f32 to s32 +PASS Test conversion of f32 to f32 diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any-expected.txt index f5776642e9643..8d6995fb25173 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any-expected.txt @@ -1,3 +1,7 @@ +CONSOLE MESSAGE: Unhandled Promise Rejection: TypeError: Config is not valid +CONSOLE MESSAGE: Unhandled Promise Rejection: TypeError: Config is not valid + +Harness Error (FAIL), message = Unhandled rejection: Config is not valid PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing codec PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Empty codec @@ -5,12 +9,16 @@ PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing numberOfChannels PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Zero sampleRate PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Zero channels +PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Opus with >2 channels but no description +PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Valid configuration except detached description PASS Test that AudioDecoder.configure() rejects invalid config: Missing codec PASS Test that AudioDecoder.configure() rejects invalid config: Empty codec PASS Test that AudioDecoder.configure() rejects invalid config: Missing sampleRate PASS Test that AudioDecoder.configure() rejects invalid config: Missing numberOfChannels PASS Test that AudioDecoder.configure() rejects invalid config: Zero sampleRate PASS Test that AudioDecoder.configure() rejects invalid config: Zero channels +PASS Test that AudioDecoder.configure() rejects invalid config: Opus with >2 channels but no description +PASS Test that AudioDecoder.configure() rejects invalid config: Valid configuration except detached description PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Unrecognized codec PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Video codec PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Ambiguous codec @@ -23,6 +31,10 @@ PASS Test that AudioDecoder.configure() doesn't support config: Ambiguous codec PASS Test that AudioDecoder.configure() doesn't support config: Codec with MIME type PASS Test that AudioDecoder.configure() doesn't support config: Possible future opus codec string PASS Test that AudioDecoder.configure() doesn't support config: Possible future aac codec string +FAIL Test that AudioDecoder.configure() doesn't support config: Opus with more than two channels and without description Config is not valid +FAIL Test that AudioDecoder.configure() doesn't support config: Opus with more than two channels and with a description that is too short Config is not valid +PASS Test that AudioDecoder.configure() doesn't support config: vorbis requires a description +PASS Test that AudioDecoder.configure() doesn't support config: flac requires a description PASS Test AudioDecoder construction PASS Verify unconfigured AudioDecoder operations diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.js b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.js index 79ba22157abba..7e041a48f0ab9 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.js +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.js @@ -1,6 +1,10 @@ // META: global=window,dedicatedworker // META: script=/webcodecs/utils.js + +const detachedArrayBuffer = new ArrayBuffer(4); +var b = detachedArrayBuffer.transferToFixedLength(); + const invalidConfigs = [ { comment: 'Missing codec', @@ -47,6 +51,23 @@ const invalidConfigs = [ numberOfChannels: 0, }, }, + { + comment: 'Opus with >2 channels but no description', + config: { + codec: 'opus', + sampleRate: 48000, + numberOfChannels: 6, + } + }, + { + comment: 'Valid configuration except detached description', + config: { + codec: 'opus', + sampleRate: 8000, + numberOfChannels: 1, + description: detachedArrayBuffer, + }, + }, ]; invalidConfigs.forEach(entry => { @@ -123,6 +144,45 @@ const validButUnsupportedConfigs = [ }, ]; +// Those configurations are supported, but attempting to configure an +// AudioDecoder will fail, because `description` is invalid for this particular +// codec +var supportedButErrorOnConfiguration = [ + { + comment: 'Opus with more than two channels and without description', + config: { + codec: 'opus', + sampleRate: '48000', + numberOfChannels: 3, + }, + }, + { + comment: 'Opus with more than two channels and with a description that is too short', + config: { + codec: 'opus', + sampleRate: '48000', + numberOfChannels: 3, + description: new Uint8Array(9), // at least 10 bytes are required for multichannel + }, + }, + { + comment: 'vorbis requires a description', + config: { + codec: 'vorbis', + sampleRate: '48000', + numberOfChannels: 2 + }, + }, + { + comment: 'flac requires a description', + config: { + codec: 'flac', + sampleRate: '48000', + numberOfChannels: 2 + }, + }, +]; + validButUnsupportedConfigs.forEach(entry => { promise_test( t => { @@ -134,10 +194,14 @@ validButUnsupportedConfigs.forEach(entry => { entry.comment); }); -validButUnsupportedConfigs.forEach(entry => { +var shouldError = validButUnsupportedConfigs.concat(supportedButErrorOnConfiguration); + +shouldError.forEach(entry => { promise_test( t => { let isErrorCallbackCalled = false; + let supported = AudioDecoder.isConfigSupported(entry.config); + assert_implements_optional(supported, entry.config.codec + ' unsupported'); let codec = new AudioDecoder({ output: t.unreached_func('unexpected output'), error: t.step_func_done(e => { diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.worker-expected.txt index f5776642e9643..947a7c0005976 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.worker-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-decoder.https.any.worker-expected.txt @@ -1,16 +1,22 @@ +Harness Error (FAIL), message = Unhandled rejection: Config is not valid + PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing codec PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Empty codec PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing sampleRate PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Missing numberOfChannels PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Zero sampleRate PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Zero channels +PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Opus with >2 channels but no description +PASS Test that AudioDecoder.isConfigSupported() rejects invalid config: Valid configuration except detached description PASS Test that AudioDecoder.configure() rejects invalid config: Missing codec PASS Test that AudioDecoder.configure() rejects invalid config: Empty codec PASS Test that AudioDecoder.configure() rejects invalid config: Missing sampleRate PASS Test that AudioDecoder.configure() rejects invalid config: Missing numberOfChannels PASS Test that AudioDecoder.configure() rejects invalid config: Zero sampleRate PASS Test that AudioDecoder.configure() rejects invalid config: Zero channels +PASS Test that AudioDecoder.configure() rejects invalid config: Opus with >2 channels but no description +PASS Test that AudioDecoder.configure() rejects invalid config: Valid configuration except detached description PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Unrecognized codec PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Video codec PASS Test that AudioDecoder.isConfigSupported() doesn't support config: Ambiguous codec @@ -23,6 +29,10 @@ PASS Test that AudioDecoder.configure() doesn't support config: Ambiguous codec PASS Test that AudioDecoder.configure() doesn't support config: Codec with MIME type PASS Test that AudioDecoder.configure() doesn't support config: Possible future opus codec string PASS Test that AudioDecoder.configure() doesn't support config: Possible future aac codec string +FAIL Test that AudioDecoder.configure() doesn't support config: Opus with more than two channels and without description Config is not valid +FAIL Test that AudioDecoder.configure() doesn't support config: Opus with more than two channels and with a description that is too short Config is not valid +PASS Test that AudioDecoder.configure() doesn't support config: vorbis requires a description +PASS Test that AudioDecoder.configure() doesn't support config: flac requires a description PASS Test AudioDecoder construction PASS Verify unconfigured AudioDecoder operations diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any-expected.txt index 7c21124715834..3cae87a6a3c5f 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any-expected.txt @@ -6,11 +6,13 @@ PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Missing PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Zero sampleRate PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Zero channels PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bit rate too big +PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bit rate present but equal to zero PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus complexity too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus packetlossperc too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus frame duration too small PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus frame duration too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Invalid Opus frameDuration +PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bitrate is too low for Opus PASS Test that AudioEncoder.configure() rejects invalid config: Missing codec PASS Test that AudioEncoder.configure() rejects invalid config: Empty codec PASS Test that AudioEncoder.configure() rejects invalid config: Missing sampleRate @@ -18,19 +20,19 @@ PASS Test that AudioEncoder.configure() rejects invalid config: Missing numberOf PASS Test that AudioEncoder.configure() rejects invalid config: Zero sampleRate PASS Test that AudioEncoder.configure() rejects invalid config: Zero channels PASS Test that AudioEncoder.configure() rejects invalid config: Bit rate too big +PASS Test that AudioEncoder.configure() rejects invalid config: Bit rate present but equal to zero PASS Test that AudioEncoder.configure() rejects invalid config: Opus complexity too big PASS Test that AudioEncoder.configure() rejects invalid config: Opus packetlossperc too big PASS Test that AudioEncoder.configure() rejects invalid config: Opus frame duration too small PASS Test that AudioEncoder.configure() rejects invalid config: Opus frame duration too big PASS Test that AudioEncoder.configure() rejects invalid config: Invalid Opus frameDuration -PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Bitrate is too low +PASS Test that AudioEncoder.configure() rejects invalid config: Bitrate is too low for Opus PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Unrecognized codec PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Sample rate is too small PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Sample rate is too large PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Way too many channels PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Possible future opus codec string PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Possible future aac codec string -PASS Test that AudioEncoder.configure() doesn't support config: Bitrate is too low PASS Test that AudioEncoder.configure() doesn't support config: Unrecognized codec PASS Test that AudioEncoder.configure() doesn't support config: Sample rate is too small PASS Test that AudioEncoder.configure() doesn't support config: Sample rate is too large @@ -41,7 +43,7 @@ PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":800 PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"bitrate":128000,"bitrateMode":"constant","bogus":123} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"bitrate":128000,"bitrateMode":"variable","bogus":123} -PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"complexity":5,"frameDuration":20000,"packetlossperc":10,"useinbandfec":true}} -PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"format":"opus","complexity":10,"frameDuration":60000,"packetlossperc":20,"usedtx":true,"bogus":456}} +PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"complexity":5,"signal":"music","application":"audio","frameDuration":20000,"packetlossperc":10,"useinbandfec":true}} +PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"format":"opus","signal":"voice","application":"lowdelay","complexity":10,"frameDuration":60000,"packetlossperc":20,"usedtx":true,"bogus":456}} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{}} diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.js b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.js index 3be8eb3f6d36d..ad5d56ca492a6 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.js +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.js @@ -56,6 +56,15 @@ const invalidConfigs = [ bitrate: 6e9, }, }, + { + comment: 'Bit rate present but equal to zero', + config: { + codec: 'opus', + sampleRate: 8000, + numberOfChannels: 2, + bitrate: 0, + }, + }, { comment: 'Opus complexity too big', config: { @@ -111,6 +120,15 @@ const invalidConfigs = [ }, }, }, + { + comment: 'Bitrate is too low for Opus', + config: { + codec: 'opus', + sampleRate: 48000, + numberOfChannels: 2, + bitrate: 1, + }, + }, ]; invalidConfigs.forEach(entry => { @@ -137,15 +155,6 @@ invalidConfigs.forEach(entry => { }); const validButUnsupportedConfigs = [ - { - comment: 'Bitrate is too low', - config: { - codec: 'opus', - sampleRate: 48000, - numberOfChannels: 2, - bitrate: 1, - }, - }, { comment: 'Unrecognized codec', config: { @@ -272,6 +281,8 @@ const validConfigs = [ numberOfChannels: 2, opus: { complexity: 5, + signal: 'music', + application: 'audio', frameDuration: 20000, packetlossperc: 10, useinbandfec: true, @@ -283,6 +294,8 @@ const validConfigs = [ numberOfChannels: 2, opus: { format: 'opus', + signal: 'voice', + application: 'lowdelay', complexity: 10, frameDuration: 60000, packetlossperc: 20, // Irrelevant without useinbandfec, but still valid. diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.worker-expected.txt index 7c21124715834..3cae87a6a3c5f 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.worker-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.worker-expected.txt @@ -6,11 +6,13 @@ PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Missing PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Zero sampleRate PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Zero channels PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bit rate too big +PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bit rate present but equal to zero PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus complexity too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus packetlossperc too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus frame duration too small PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Opus frame duration too big PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Invalid Opus frameDuration +PASS Test that AudioEncoder.isConfigSupported() rejects invalid config: Bitrate is too low for Opus PASS Test that AudioEncoder.configure() rejects invalid config: Missing codec PASS Test that AudioEncoder.configure() rejects invalid config: Empty codec PASS Test that AudioEncoder.configure() rejects invalid config: Missing sampleRate @@ -18,19 +20,19 @@ PASS Test that AudioEncoder.configure() rejects invalid config: Missing numberOf PASS Test that AudioEncoder.configure() rejects invalid config: Zero sampleRate PASS Test that AudioEncoder.configure() rejects invalid config: Zero channels PASS Test that AudioEncoder.configure() rejects invalid config: Bit rate too big +PASS Test that AudioEncoder.configure() rejects invalid config: Bit rate present but equal to zero PASS Test that AudioEncoder.configure() rejects invalid config: Opus complexity too big PASS Test that AudioEncoder.configure() rejects invalid config: Opus packetlossperc too big PASS Test that AudioEncoder.configure() rejects invalid config: Opus frame duration too small PASS Test that AudioEncoder.configure() rejects invalid config: Opus frame duration too big PASS Test that AudioEncoder.configure() rejects invalid config: Invalid Opus frameDuration -PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Bitrate is too low +PASS Test that AudioEncoder.configure() rejects invalid config: Bitrate is too low for Opus PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Unrecognized codec PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Sample rate is too small PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Sample rate is too large PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Way too many channels PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Possible future opus codec string PASS Test that AudioEncoder.isConfigSupported() doesn't support config: Possible future aac codec string -PASS Test that AudioEncoder.configure() doesn't support config: Bitrate is too low PASS Test that AudioEncoder.configure() doesn't support config: Unrecognized codec PASS Test that AudioEncoder.configure() doesn't support config: Sample rate is too small PASS Test that AudioEncoder.configure() doesn't support config: Sample rate is too large @@ -41,7 +43,7 @@ PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":800 PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"bitrate":128000,"bitrateMode":"constant","bogus":123} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"bitrate":128000,"bitrateMode":"variable","bogus":123} -PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"complexity":5,"frameDuration":20000,"packetlossperc":10,"useinbandfec":true}} -PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"format":"opus","complexity":10,"frameDuration":60000,"packetlossperc":20,"usedtx":true,"bogus":456}} +PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"complexity":5,"signal":"music","application":"audio","frameDuration":20000,"packetlossperc":10,"useinbandfec":true}} +PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{"format":"opus","signal":"voice","application":"lowdelay","complexity":10,"frameDuration":60000,"packetlossperc":20,"usedtx":true,"bogus":456}} PASS AudioEncoder.isConfigSupported() supports: {"codec":"opus","sampleRate":48000,"numberOfChannels":2,"opus":{}} diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html index a705d27672bd7..1863b4bf2e3a0 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html @@ -4,4 +4,11 @@ - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.js b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.js index 92513be087011..32eb6598c6645 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.js +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.js @@ -5,7 +5,14 @@ // META: variant=?mp3 // META: variant=?opus // META: variant=?pcm_alaw -// META: variant=?pcm_mulaw +// META: variant=?pcm_ulaw +// META: variant=?pcm_u8 +// META: variant=?pcm_s16 +// META: variant=?pcm_s24 +// META: variant=?pcm_s32 +// META: variant=?pcm_f32 +// META: variant=?flac +// META: variant=?vorbis const ADTS_AAC_DATA = { src: 'sfx.adts', @@ -82,37 +89,68 @@ const OPUS_DATA = { duration: 20000 }; -const PCM_ALAW_DATA = { - src: 'sfx-alaw.wav', +const FLAC_DATA = { + src: 'sfx.flac', config: { - codec: 'alaw', + codec: 'flac', sampleRate: 48000, numberOfChannels: 1, + description: { offset: 0, size: 8287 } }, - // Any arbitrary grouping should work. chunks: [ - {offset: 0, size: 2048}, {offset: 2048, size: 2048}, - {offset: 4096, size: 2048}, {offset: 6144, size: 2048}, - {offset: 8192, size: 2048}, {offset: 10240, size: 92} + { offset: 8288, size: 2276 }, + { offset: 10564, size: 2038 }, + { offset: 12602, size: 521 }, ], - duration: 35555 + duration: 20000 }; -const PCM_MULAW_DATA = { - src: 'sfx-mulaw.wav', +function pcm(codec, dataOffset) { + return { + src: `sfx-${codec}.wav`, + config: { + codec: codec, + sampleRate: 48000, + numberOfChannels: 1, + }, + + // Chunk are arbitrary and will be generated lazily + chunks: [], + offset: dataOffset, + duration: 0 + } +} + +const PCM_ULAW_DATA = pcm("ulaw", 0x5c); +const PCM_ALAW_DATA = pcm("alaw", 0x5c); +const PCM_U8_DATA = pcm("pcm-u8", 0x4e); +const PCM_S16_DATA = pcm("pcm-s16", 0x4e); +const PCM_S24_DATA = pcm("pcm-s24", 0x66); +const PCM_S32_DATA = pcm("pcm-s32", 0x66); +const PCM_F32_DATA = pcm("pcm-f32", 0x72); + +const VORBIS_DATA = { + src: 'sfx-vorbis.ogg', config: { - codec: 'ulaw', - sampleRate: 48000, + codec: 'vorbis', + description: [ + 2, + 30, + 62, + {offset: 28, size: 30}, + {offset: 101, size: 62}, + {offset: 163, size: 3771} + ], numberOfChannels: 1, + sampleRate: 48000, }, - - // Any arbitrary grouping should work. chunks: [ - {offset: 0, size: 2048}, {offset: 2048, size: 2048}, - {offset: 4096, size: 2048}, {offset: 6144, size: 2048}, - {offset: 8192, size: 2048}, {offset: 10240, size: 92} + {offset: 3968, size: 44}, {offset: 4012, size: 21}, + {offset: 4033, size: 57}, {offset: 4090, size: 37}, + {offset: 4127, size: 37}, {offset: 4164, size: 107}, + {offset: 4271, size: 172} ], - duration: 35555 + duration: 21333 }; // Allows mutating `callbacks` after constructing the AudioDecoder, wraps calls @@ -151,7 +189,14 @@ promise_setup(async () => { '?mp4_aac': MP4_AAC_DATA, '?opus': OPUS_DATA, '?pcm_alaw': PCM_ALAW_DATA, - '?pcm_mulaw': PCM_MULAW_DATA, + '?pcm_ulaw': PCM_ULAW_DATA, + '?pcm_u8': PCM_U8_DATA, + '?pcm_s16': PCM_S16_DATA, + '?pcm_s24': PCM_S24_DATA, + '?pcm_s32': PCM_S32_DATA, + '?pcm_f32': PCM_F32_DATA, + '?flac': FLAC_DATA, + '?vorbis': VORBIS_DATA, }[location.search]; // Don't run any tests if the codec is not supported. @@ -174,10 +219,55 @@ promise_setup(async () => { CONFIG = {...data.config}; if (data.config.description) { - CONFIG.description = view(buf, data.config.description); + // The description for decoding vorbis is expected to be in Xiph extradata format. + // https://w3c.github.io/webcodecs/vorbis_codec_registration.html#audiodecoderconfig-description + if (Array.isArray(data.config.description)) { + const length = data.config.description.reduce((sum, value) => sum + ((typeof value === 'number') ? 1 : value.size), 0); + const description = new Uint8Array(length); + + data.config.description.reduce((offset, value) => { + if (typeof value === 'number') { + description[offset] = value; + + return offset + 1; + } + + description.set(view(buf, value), offset); + + return offset + value.size; + }, 0); + + CONFIG.description = description; + } else { + CONFIG.description = view(buf, data.config.description); + } } - CHUNK_DATA = data.chunks.map((chunk, i) => view(buf, chunk)); + CHUNK_DATA = []; + // For PCM, split in chunks of 1200 bytes and compute the rest + if (data.chunks.length == 0) { + let offset = data.offset; + // 1200 is divisible by 2 and 3 and is a plausible packet length + // for PCM: this means that there won't be samples split in two packet + let PACKET_LENGTH = 1200; + let bytesPerSample = 0; + switch (data.config.codec) { + case "pcm-s16": bytesPerSample = 2; break; + case "pcm-s24": bytesPerSample = 3; break; + case "pcm-s32": bytesPerSample = 4; break; + case "pcm-f32": bytesPerSample = 4; break; + default: bytesPerSample = 1; break; + } + while (offset < buf.byteLength) { + let size = Math.min(buf.byteLength - offset, PACKET_LENGTH); + assert_equals(size % bytesPerSample, 0); + CHUNK_DATA.push(view(buf, {offset, size})); + offset += size; + } + data.duration = 1000 * 1000 * PACKET_LENGTH / data.config.sampleRate / bytesPerSample; + } else { + CHUNK_DATA = data.chunks.map((chunk, i) => view(buf, chunk)); + } CHUNKS = CHUNK_DATA.map((encodedData, i) => new EncodedAudioChunk({ type: 'key', @@ -257,7 +347,7 @@ promise_test(async t => { }); await decoder.flush(); - assert_equals(outputs, CHUNKS.length, 'outputs'); + assert_equals(outputs, CONFIG.codec === 'vorbis' ? CHUNKS.length - 1 : CHUNKS.length, 'outputs'); }, 'Test decoding'); promise_test(async t => { @@ -273,9 +363,11 @@ promise_test(async t => { decoder.configure(CONFIG); decoder.decode(new EncodedAudioChunk( {type: 'key', timestamp: -42, data: CHUNK_DATA[0]})); + decoder.decode(new EncodedAudioChunk( + {type: 'key', timestamp: CHUNKS[0].duration - 42, data: CHUNK_DATA[1]})); await decoder.flush(); - assert_equals(outputs, 1, 'outputs'); + assert_equals(outputs, CONFIG.codec === 'vorbis' ? 1 : 2, 'outputs'); }, 'Test decoding a with negative timestamp'); promise_test(async t => { @@ -290,13 +382,14 @@ promise_test(async t => { decoder.configure(CONFIG); decoder.decode(CHUNKS[0]); + decoder.decode(CHUNKS[1]); await decoder.flush(); - assert_equals(outputs, 1, 'outputs'); + assert_equals(outputs, CONFIG.codec === 'vorbis' ? 1 : 2, 'outputs'); - decoder.decode(CHUNKS[0]); + decoder.decode(CHUNKS[2]); await decoder.flush(); - assert_equals(outputs, 2, 'outputs'); + assert_equals(outputs, CONFIG.codec === 'vorbis' ? 2 : 3, 'outputs'); }, 'Test decoding after flush'); promise_test(async t => { diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html index a705d27672bd7..1863b4bf2e3a0 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html @@ -4,4 +4,11 @@ - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_mulaw-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_flac-expected.txt similarity index 100% rename from LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_mulaw-expected.txt rename to LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_flac-expected.txt diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_mulaw-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_f32-expected.txt similarity index 100% rename from LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_mulaw-expected.txt rename to LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_f32-expected.txt diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s16-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s16-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s16-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s24-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s24-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s24-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s32-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s32-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_s32-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_u8-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_u8-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_u8-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_ulaw-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_ulaw-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_pcm_ulaw-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_vorbis-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_vorbis-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker_vorbis-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_flac-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_flac-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_flac-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_f32-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_f32-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_f32-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s16-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s16-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s16-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s24-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s24-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s24-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s32-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s32-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_s32-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_u8-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_u8-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_u8-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_ulaw-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_ulaw-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_pcm_ulaw-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_vorbis-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_vorbis-expected.txt new file mode 100644 index 0000000000000..a897b642cb0de --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any_vorbis-expected.txt @@ -0,0 +1,11 @@ + +PASS Test isConfigSupported() +PASS Test that AudioDecoder.isConfigSupported() returns a parsed configuration +PASS Test configure() +PASS Verify closed AudioDecoder operations +PASS Test decoding +PASS Test decoding a with negative timestamp +PASS Test decoding after flush +PASS Test reset during flush +PASS AudioDecoder decodeQueueSize test + diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/idlharness.https.any.js b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/idlharness.https.any.js index b69a4c9fa7074..f1ed92a159831 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/idlharness.https.any.js +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/idlharness.https.any.js @@ -29,7 +29,7 @@ var defaultVideoChunkInit = { data: new Uint8Array([9, 10, 11, 12]) }; -idl_test(['webcodecs'], ['dom', 'html', 'WebIDL'], async idlArray => { +idl_test(['webcodecs'], ['dom', 'html', 'webidl'], async idlArray => { self.imageBody = await fetch('four-colors.png').then(response => response.arrayBuffer()); diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-f32.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-f32.wav new file mode 100644 index 0000000000000..d1c0fa2bd9354 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-f32.wav differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s16.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s16.wav new file mode 100644 index 0000000000000..34b6d982d2c83 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s16.wav differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s24.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s24.wav new file mode 100644 index 0000000000000..8a19b8c047c93 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s24.wav differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s32.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s32.wav new file mode 100644 index 0000000000000..85b33faff1401 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s32.wav differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-u8.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-u8.wav new file mode 100644 index 0000000000000..45dffc7db1af7 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-u8.wav differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-mulaw.wav b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-ulaw.wav similarity index 100% rename from LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-mulaw.wav rename to LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-ulaw.wav diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-vorbis.ogg b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-vorbis.ogg new file mode 100644 index 0000000000000..e3eb4fcae1a05 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-vorbis.ogg differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.flac b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.flac new file mode 100644 index 0000000000000..a8d313c562573 Binary files /dev/null and b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.flac differ diff --git a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/w3c-import.log index ce5dad1e151fb..abf1a2507be2a 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/webcodecs/w3c-import.log +++ b/LayoutTests/imported/w3c/web-platform-tests/webcodecs/w3c-import.log @@ -16,6 +16,7 @@ None List of files: /LayoutTests/imported/w3c/web-platform-tests/webcodecs/META.yml /LayoutTests/imported/w3c/web-platform-tests/webcodecs/README.md +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/WEB_FEATURES.yml /LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data-serialization.any.js /LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.any.js /LayoutTests/imported/w3c/web-platform-tests/webcodecs/audio-data.crossOriginIsolated.https.any.js @@ -69,9 +70,16 @@ List of files: /LayoutTests/imported/w3c/web-platform-tests/webcodecs/serialization.crossAgentCluster.serviceworker.js /LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-aac.mp4 /LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-alaw.wav -/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-mulaw.wav /LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-opus.ogg +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-f32.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s16.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s24.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-s32.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-pcm-u8.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-ulaw.wav +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx-vorbis.ogg /LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.adts +/LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.flac /LayoutTests/imported/w3c/web-platform-tests/webcodecs/sfx.mp3 /LayoutTests/imported/w3c/web-platform-tests/webcodecs/temporal-svc-encoding.https.any.js /LayoutTests/imported/w3c/web-platform-tests/webcodecs/transfering.https.any.js diff --git a/LayoutTests/platform/glib/TestExpectations b/LayoutTests/platform/glib/TestExpectations index 8dc0bc4591f05..39ea0f0e88330 100644 --- a/LayoutTests/platform/glib/TestExpectations +++ b/LayoutTests/platform/glib/TestExpectations @@ -1300,6 +1300,17 @@ imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any. # A bit flaky on Debug bot. imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?mp4_aac [ Pass Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?pcm_u8 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?pcm_f32 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?pcm_s16 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?pcm_s24 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.html?pcm_s32 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?pcm_u8 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?pcm_f32 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?pcm_s16 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?pcm_s24 [ Failure ] +webkit.org/b/284447 imported/w3c/web-platform-tests/webcodecs/audioDecoder-codec-specific.https.any.worker.html?pcm_s32 [ Failure ] + webkit.org/b/284426 imported/w3c/web-platform-tests/webcodecs/audio-encoder-codec-specific.https.any.html [ Failure ] webkit.org/b/284428 imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.html [ Failure ] webkit.org/b/284428 imported/w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.worker.html [ Failure ] diff --git a/Source/WebCore/Modules/webcodecs/WebCodecsAudioDecoder.cpp b/Source/WebCore/Modules/webcodecs/WebCodecsAudioDecoder.cpp index 56bdc0109fe92..e40f86eebc751 100644 --- a/Source/WebCore/Modules/webcodecs/WebCodecsAudioDecoder.cpp +++ b/Source/WebCore/Modules/webcodecs/WebCodecsAudioDecoder.cpp @@ -65,17 +65,6 @@ WebCodecsAudioDecoder::WebCodecsAudioDecoder(ScriptExecutionContext& context, In WebCodecsAudioDecoder::~WebCodecsAudioDecoder() = default; -static bool isValidDecoderConfig(const WebCodecsAudioDecoderConfig& config) -{ - if (StringView(config.codec).trim(isASCIIWhitespace).isEmpty()) - return false; - - if (!config.numberOfChannels || !config.sampleRate) - return false; - - return true; -} - static AudioDecoder::Config createAudioDecoderConfig(const WebCodecsAudioDecoderConfig& config) { std::span description; @@ -93,6 +82,31 @@ static AudioDecoder::Config createAudioDecoderConfig(const WebCodecsAudioDecoder return { description, config.sampleRate, config.numberOfChannels }; } +static bool isValidDecoderConfig(const WebCodecsAudioDecoderConfig& config) +{ + if (StringView(config.codec).trim(isASCIIWhitespace).isEmpty()) + return false; + + if (!config.numberOfChannels || !config.sampleRate) + return false; + + auto descriptionSize = createAudioDecoderConfig(config).description.size(); + + // FIXME: Not yet per spec, but being tested and tracked by https://github.com/w3c/webcodecs/issues/826 + // And handled that way by all other UAs. + // If we have a config.description, ensures it's not an empty one. + if (config.description && !descriptionSize) + return false; + + // FIXME: WPT issue: https://github.com/web-platform-tests/wpt/issues/49636 is causing a test to fail when it shouldn't + // Opus with more than two channels require a description + // Extra spec issue: https://github.com/w3c/webcodecs/issues/861 : configure shouldn't throw on invalid config. + if (config.codec == "opus"_s && config.numberOfChannels > 2 && descriptionSize < 10) + return false; + + return true; +} + ExceptionOr WebCodecsAudioDecoder::configure(ScriptExecutionContext&, WebCodecsAudioDecoderConfig&& config) { if (!isValidDecoderConfig(config)) diff --git a/Source/WebCore/Modules/webcodecs/WebCodecsAudioEncoder.cpp b/Source/WebCore/Modules/webcodecs/WebCodecsAudioEncoder.cpp index 68a16cb563a25..f38231853eb23 100644 --- a/Source/WebCore/Modules/webcodecs/WebCodecsAudioEncoder.cpp +++ b/Source/WebCore/Modules/webcodecs/WebCodecsAudioEncoder.cpp @@ -90,11 +90,6 @@ static bool isSupportedEncoderCodec(const WebCodecsAudioEncoderConfig& config) if (config.sampleRate < 3000 || config.sampleRate > 384000) return false; - // FIXME: New WPT requires this to reject as non valid. For now we just state that it's not supported (webkit.org/b/283900) - // https://w3c.github.io/webcodecs/opus_codec_registration.html#opus-encoder-config - if (codec == "opus"_s && config.bitrate && (*config.bitrate < 6000 || *config.bitrate > 510000)) - return false; - return true; } @@ -106,14 +101,22 @@ static bool isValidEncoderConfig(const WebCodecsAudioEncoderConfig& config) if (!config.sampleRate || !config.numberOfChannels) return false; - // FIXME: This isn't per spec, but both Chrome and Firefox checks that the bitrate is now greater than INT_MAX + // FIXME: This isn't per spec, but both Chrome and Firefox checks that the bitrate is not greater than INT_MAX // Even though the spec made it a `long long` // https://github.com/web-platform-tests/wpt/issues/49634 if (config.bitrate && *config.bitrate > std::numeric_limits::max()) return false; - // FIXME: The opus and flac checks will probably need to move so that they trigger NotSupported - // errors in the future. + // FIXME: https://github.com/w3c/webcodecs/issues/860 + // Not per spec yet, but tested by w3c/web-platform-tests/webcodecs/audio-encoder-config.https.any.js 'Bit rate present but equal to zero' + if (config.bitrate && !config.bitrate) + return false; + + // FIXME: New WPT requires this to reject as non valid. For now we just state that it's not supported (webkit.org/b/283900) + // https://w3c.github.io/webcodecs/opus_codec_registration.html#opus-encoder-config + if (config.codec == "opus"_s && config.bitrate && (*config.bitrate < 6000 || *config.bitrate > 510000)) + return false; + if (auto opusConfig = config.opus) { if (!opusConfig->isValid()) return false;