-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1917721 - Make AAC-w/o-description WPT a mozilla-specific WPT r=m…
…edia-playback-reviewers,padenot Due to the ongoing discussion in issue 832 [1], which has not yet reached a consensus among all parties, the AAC-without-description WPT introduced in the previous patch should be relocated to the *mozilla* folder under WPT. This ensures that the test remains specific to Mozilla and avoids unintentionally causing failures in other browers' test suites. [1] w3c/webcodecs#832 Differential Revision: https://phabricator.services.mozilla.com/D222712 UltraBlame original commit: c81481c06eac3165b72e7bb2c3040a48b3994a0a
- Loading branch information
Showing
7 changed files
with
581 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
prefs: [dom.media.webcodecs.enabled:true, dom.media.webcodecs.image-decoder.enabled:true, media.ffmpeg.encoder.enabled:true, media.rvfc.enabled:true] | ||
tags: [webcodecs] | ||
disabled: | ||
if (os == "linux") and (bits == 32): Not implemented | ||
lsan-allowed: [PLDHashTable::MakeEntryHandle, mozilla::RemoteDecoderManagerChild::OpenRemoteDecoderManagerChildForProcess, mozilla::ipc::MessageChannel::MessageChannel, mozilla::layers::GPUVideoImage::GPUVideoImage] |
38 changes: 38 additions & 0 deletions
38
testing/web-platform/mozilla/meta/webcodecs/audioDecoder-codec-specific.https.any.js.ini
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
[audioDecoder-codec-specific.https.any.worker.html?mp4_raw_aac_no_desc] | ||
expected: | ||
if os == "android": ERROR | ||
[Test isConfigSupported()] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test that AudioDecoder.isConfigSupported() returns a parsed configuration] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test configure()] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Verify closed AudioDecoder operations] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test decoding] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test decoding a with negative timestamp] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test decoding after flush] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[Test reset during flush] | ||
expected: | ||
if os == "android": NOTRUN | ||
|
||
[AudioDecoder decodeQueueSize test] | ||
expected: | ||
if os == "android": NOTRUN |
301 changes: 301 additions & 0 deletions
301
testing/web-platform/mozilla/tests/webcodecs/audioDecoder-codec-specific.https.any.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,301 @@ | ||
|
||
|
||
|
||
|
||
|
||
|
||
const MP4_AAC_DATA_NO_DESCRIPTION = { | ||
src: 'sfx-aac.mp4', | ||
config: { | ||
codec: 'mp4a.40.2', | ||
sampleRate: 48000, | ||
numberOfChannels: 1, | ||
}, | ||
chunks: [ | ||
{offset: 44, size: 241}, | ||
{offset: 285, size: 273}, | ||
{offset: 558, size: 251}, | ||
{offset: 809, size: 118}, | ||
{offset: 927, size: 223}, | ||
{offset: 1150, size: 141}, | ||
{offset: 1291, size: 217}, | ||
{offset: 1508, size: 159}, | ||
{offset: 1667, size: 209}, | ||
{offset: 1876, size: 176}, | ||
], | ||
duration: 21333 | ||
}; | ||
|
||
|
||
|
||
function createAudioDecoder(t, callbacks) { | ||
return new AudioDecoder({ | ||
output(frame) { | ||
if (callbacks && callbacks.output) { | ||
t.step(() => callbacks.output(frame)); | ||
} else { | ||
t.unreached_func('unexpected output()'); | ||
} | ||
}, | ||
error(e) { | ||
if (callbacks && callbacks.error) { | ||
t.step(() => callbacks.error(e)); | ||
} else { | ||
t.unreached_func('unexpected error()'); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
|
||
function view(buffer, {offset, size}) { | ||
return new Uint8Array(buffer, offset, size); | ||
} | ||
|
||
let CONFIG = null; | ||
let CHUNK_DATA = null; | ||
let CHUNKS = null; | ||
promise_setup(async () => { | ||
const data = { | ||
'?mp4_raw_aac_no_desc': MP4_AAC_DATA_NO_DESCRIPTION, | ||
}[location.search]; | ||
|
||
|
||
assert_equals("function", typeof AudioDecoder.isConfigSupported); | ||
let supported = false; | ||
try { | ||
const support = await AudioDecoder.isConfigSupported({ | ||
codec: data.config.codec, | ||
sampleRate: data.config.sampleRate, | ||
numberOfChannels: data.config.numberOfChannels | ||
}); | ||
supported = support.supported; | ||
} catch (e) { | ||
} | ||
assert_implements_optional(supported, data.config.codec + ' unsupported'); | ||
|
||
|
||
const response = await fetch(data.src); | ||
const buf = await response.arrayBuffer(); | ||
|
||
CONFIG = {...data.config}; | ||
if (data.config.description) { | ||
CONFIG.description = view(buf, data.config.description); | ||
} | ||
|
||
CHUNK_DATA = []; | ||
|
||
if (data.chunks.length == 0) { | ||
let offset = data.offset; | ||
|
||
|
||
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', | ||
timestamp: i * data.duration, | ||
duration: data.duration, | ||
data: encodedData | ||
})); | ||
}); | ||
|
||
promise_test(t => { | ||
return AudioDecoder.isConfigSupported(CONFIG); | ||
}, 'Test isConfigSupported()'); | ||
|
||
promise_test(t => { | ||
|
||
|
||
const validConfig = { | ||
...CONFIG, | ||
futureConfigFeature: 'foo', | ||
}; | ||
|
||
|
||
|
||
return AudioDecoder.isConfigSupported(validConfig).then((decoderSupport) => { | ||
|
||
assert_true(decoderSupport.hasOwnProperty('supported')); | ||
assert_true(decoderSupport.hasOwnProperty('config')); | ||
|
||
|
||
assert_false(decoderSupport.config.hasOwnProperty('futureConfigFeature')); | ||
|
||
|
||
assert_equals(decoderSupport.config.codec, validConfig.codec); | ||
assert_equals(decoderSupport.config.sampleRate, validConfig.sampleRate); | ||
assert_equals( | ||
decoderSupport.config.numberOfChannels, validConfig.numberOfChannels); | ||
|
||
if (validConfig.description) { | ||
|
||
assert_false( | ||
decoderSupport.config.description === validConfig.description, | ||
'description is unique'); | ||
assert_array_equals( | ||
new Uint8Array(decoderSupport.config.description, 0), | ||
new Uint8Array(validConfig.description, 0), 'description'); | ||
} else { | ||
assert_false( | ||
decoderSupport.config.hasOwnProperty('description'), 'description'); | ||
} | ||
}); | ||
}, 'Test that AudioDecoder.isConfigSupported() returns a parsed configuration'); | ||
|
||
promise_test(async t => { | ||
const decoder = createAudioDecoder(t); | ||
decoder.configure(CONFIG); | ||
assert_equals(decoder.state, 'configured', 'state'); | ||
}, 'Test configure()'); | ||
|
||
promise_test(t => { | ||
const decoder = createAudioDecoder(t); | ||
return testClosedCodec(t, decoder, CONFIG, CHUNKS[0]); | ||
}, 'Verify closed AudioDecoder operations'); | ||
|
||
promise_test(async t => { | ||
const callbacks = {}; | ||
const decoder = createAudioDecoder(t, callbacks); | ||
|
||
let outputs = 0; | ||
callbacks.output = frame => { | ||
outputs++; | ||
frame.close(); | ||
}; | ||
|
||
decoder.configure(CONFIG); | ||
CHUNKS.forEach(chunk => { | ||
decoder.decode(chunk); | ||
}); | ||
|
||
await decoder.flush(); | ||
assert_equals(outputs, CHUNKS.length, 'outputs'); | ||
}, 'Test decoding'); | ||
|
||
promise_test(async t => { | ||
const callbacks = {}; | ||
const decoder = createAudioDecoder(t, callbacks); | ||
|
||
let outputs = 0; | ||
callbacks.output = frame => { | ||
outputs++; | ||
frame.close(); | ||
}; | ||
|
||
decoder.configure(CONFIG); | ||
decoder.decode(new EncodedAudioChunk( | ||
{type: 'key', timestamp: -42, data: CHUNK_DATA[0]})); | ||
|
||
await decoder.flush(); | ||
assert_equals(outputs, 1, 'outputs'); | ||
}, 'Test decoding a with negative timestamp'); | ||
|
||
promise_test(async t => { | ||
const callbacks = {}; | ||
const decoder = createAudioDecoder(t, callbacks); | ||
|
||
let outputs = 0; | ||
callbacks.output = frame => { | ||
outputs++; | ||
frame.close(); | ||
}; | ||
|
||
decoder.configure(CONFIG); | ||
decoder.decode(CHUNKS[0]); | ||
|
||
await decoder.flush(); | ||
assert_equals(outputs, 1, 'outputs'); | ||
|
||
decoder.decode(CHUNKS[0]); | ||
await decoder.flush(); | ||
assert_equals(outputs, 2, 'outputs'); | ||
}, 'Test decoding after flush'); | ||
|
||
promise_test(async t => { | ||
const callbacks = {}; | ||
const decoder = createAudioDecoder(t, callbacks); | ||
|
||
decoder.configure(CONFIG); | ||
decoder.decode(CHUNKS[0]); | ||
decoder.decode(CHUNKS[1]); | ||
const flushDone = decoder.flush(); | ||
|
||
|
||
let outputs = 0; | ||
await new Promise(resolve => { | ||
callbacks.output = frame => { | ||
outputs++; | ||
assert_equals(outputs, 1, 'outputs'); | ||
decoder.reset(); | ||
frame.close(); | ||
resolve(); | ||
}; | ||
}); | ||
|
||
|
||
await promise_rejects_dom(t, 'AbortError', flushDone); | ||
|
||
assert_equals(outputs, 1, 'outputs'); | ||
}, 'Test reset during flush'); | ||
|
||
promise_test(async t => { | ||
const callbacks = {}; | ||
const decoder = createAudioDecoder(t, callbacks); | ||
|
||
|
||
assert_equals(decoder.decodeQueueSize, 0); | ||
|
||
decoder.configure(CONFIG); | ||
|
||
|
||
assert_equals(decoder.decodeQueueSize, 0); | ||
|
||
let lastDequeueSize = Infinity; | ||
decoder.ondequeue = () => { | ||
assert_greater_than(lastDequeueSize, 0, "Dequeue event after queue empty"); | ||
assert_greater_than(lastDequeueSize, decoder.decodeQueueSize, | ||
"Dequeue event without decreased queue size"); | ||
lastDequeueSize = decoder.decodeQueueSize; | ||
}; | ||
|
||
for (let chunk of CHUNKS) | ||
decoder.decode(chunk); | ||
|
||
assert_greater_than_equal(decoder.decodeQueueSize, 0); | ||
assert_less_than_equal(decoder.decodeQueueSize, CHUNKS.length); | ||
|
||
await decoder.flush(); | ||
|
||
assert_equals(decoder.decodeQueueSize, 0); | ||
|
||
assert_equals(lastDequeueSize, 0); | ||
|
||
|
||
|
||
lastDequeueSize = Infinity; | ||
|
||
for (let chunk of CHUNKS) | ||
decoder.decode(chunk); | ||
|
||
assert_greater_than_equal(decoder.decodeQueueSize, 0); | ||
decoder.reset(); | ||
assert_equals(decoder.decodeQueueSize, 0); | ||
}, 'AudioDecoder decodeQueueSize test'); |
Binary file not shown.
Oops, something went wrong.