forked from mirrors/gecko-dev
269 lines
7 KiB
JavaScript
269 lines
7 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
/* import-globals-from head.js */
|
|
|
|
const Telemetry = Services.telemetry;
|
|
|
|
const { TelemetryController } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/TelemetryController.sys.mjs"
|
|
);
|
|
|
|
/* eslint-disable mozilla/no-redeclare-with-import-autofix */
|
|
const { ContentTaskUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/ContentTaskUtils.sys.mjs"
|
|
);
|
|
|
|
const MEDIA_AUDIO_PROCESS = "media.audio_process_per_codec_name";
|
|
|
|
const utilityPerCodecs = {
|
|
Linux: [
|
|
{
|
|
process: "utility+audioDecoder_Generic",
|
|
codecs: ["vorbis", "mp3", "aac", "flac"],
|
|
},
|
|
],
|
|
WINNT: [
|
|
{
|
|
process: "utility+audioDecoder_Generic",
|
|
codecs: ["vorbis", "mp3", "flac"],
|
|
},
|
|
{
|
|
process: "utility+audioDecoder_WMF",
|
|
codecs: ["aac"],
|
|
},
|
|
],
|
|
Darwin: [
|
|
{
|
|
process: "utility+audioDecoder_Generic",
|
|
codecs: ["vorbis", "mp3", "flac"],
|
|
},
|
|
{
|
|
process: "utility+audioDecoder_AppleMedia",
|
|
codecs: ["aac"],
|
|
},
|
|
],
|
|
};
|
|
|
|
const kInterval = 300; /* ms */
|
|
const kRetries = 5;
|
|
|
|
/**
|
|
* This function waits until utility scalars are reported into the
|
|
* scalar snapshot.
|
|
*/
|
|
async function waitForKeyedScalars(process) {
|
|
await ContentTaskUtils.waitForCondition(
|
|
() => {
|
|
const scalars = Telemetry.getSnapshotForKeyedScalars("main", false);
|
|
return Object.keys(scalars).includes("content");
|
|
},
|
|
`Waiting for ${process} scalars to have been set`,
|
|
kInterval,
|
|
kRetries
|
|
);
|
|
}
|
|
|
|
async function waitForValue(process, codecNames, extra = "") {
|
|
await ContentTaskUtils.waitForCondition(
|
|
() => {
|
|
const telemetry = Telemetry.getSnapshotForKeyedScalars(
|
|
"main",
|
|
false
|
|
).content;
|
|
if (telemetry && MEDIA_AUDIO_PROCESS in telemetry) {
|
|
const keyProcMimeTypes = Object.keys(telemetry[MEDIA_AUDIO_PROCESS]);
|
|
const found = codecNames.every(item =>
|
|
keyProcMimeTypes.includes(`${process},${item}${extra}`)
|
|
);
|
|
return found;
|
|
}
|
|
return false;
|
|
},
|
|
`Waiting for ${MEDIA_AUDIO_PROCESS} [${process}, ${codecNames}, ${extra}]`,
|
|
kInterval,
|
|
kRetries
|
|
);
|
|
}
|
|
|
|
async function runTest({
|
|
expectUtility = false,
|
|
expectRDD = false,
|
|
expectError = false,
|
|
}) {
|
|
info(
|
|
`Running tests with decoding from Utility or RDD: expectUtility=${expectUtility} expectRDD=${expectRDD} expectError=${expectError}`
|
|
);
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["media.utility-process.enabled", expectUtility],
|
|
["media.rdd-process.enabled", expectRDD],
|
|
["toolkit.telemetry.ipcBatchTimeout", 0],
|
|
],
|
|
});
|
|
|
|
const platform = Services.appinfo.OS;
|
|
|
|
for (let { src, expectations } of audioTestData()) {
|
|
if (!(platform in expectations)) {
|
|
info(`Skipping ${src} for ${platform}`);
|
|
continue;
|
|
}
|
|
|
|
const expectation = expectations[platform];
|
|
|
|
info(`Add media tab: ${src}`);
|
|
let tab = await addMediaTab(src);
|
|
|
|
info("Play tab");
|
|
await play(
|
|
tab,
|
|
expectUtility ? expectation.process : "RDD",
|
|
expectation.decoder,
|
|
!expectUtility && !expectRDD,
|
|
false,
|
|
expectError
|
|
);
|
|
|
|
info("Stop tab");
|
|
await stop(tab);
|
|
|
|
info("Remove tab");
|
|
await BrowserTestUtils.removeTab(tab);
|
|
}
|
|
}
|
|
|
|
async function runTestWithEME() {
|
|
info(`Running tests with decoding from Utility for EME`);
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["media.utility-process.enabled", true],
|
|
["toolkit.telemetry.ipcBatchTimeout", 0],
|
|
],
|
|
});
|
|
|
|
const platform = Services.appinfo.OS;
|
|
|
|
for (let { src, expectations } of audioTestDataEME()) {
|
|
if (!(platform in expectations)) {
|
|
info(`Skipping ${src} for ${platform}`);
|
|
continue;
|
|
}
|
|
|
|
const expectation = expectations[platform];
|
|
|
|
info(`Add EME media tab`);
|
|
let tab = await addMediaTabWithEME(src.sourceBuffer, src.audioFile);
|
|
|
|
info("Play tab");
|
|
await play(
|
|
tab,
|
|
expectation.process,
|
|
expectation.decoder,
|
|
false, // expectContent
|
|
false, // expectJava
|
|
false, // expectError
|
|
true // withEME
|
|
);
|
|
|
|
info("Stop tab");
|
|
await stop(tab);
|
|
|
|
info("Remove tab");
|
|
await BrowserTestUtils.removeTab(tab);
|
|
}
|
|
}
|
|
|
|
function getTelemetry() {
|
|
const telemetry = Telemetry.getSnapshotForKeyedScalars("main", false).content;
|
|
return telemetry;
|
|
}
|
|
|
|
async function verifyTelemetryForProcess(process, codecNames, extraKey = "") {
|
|
// Once scalars are set by the utility process, they don't immediately get
|
|
// sent to the parent process. Wait for the Telemetry IPC Timer to trigger
|
|
// and batch send the data back to the parent process.
|
|
await waitForKeyedScalars(process);
|
|
await waitForValue(process, codecNames, extraKey);
|
|
|
|
const telemetry = getTelemetry();
|
|
|
|
// The amount here depends on how many times RemoteAudioDecoderParent::RemoteAudioDecoderParent
|
|
// gets called, which might be more than actual audio files being playback, e.g., we would get one for metadata loading, then one for playback etc.
|
|
// But we dont care really we just want to ensure 0 on RDD, Content and others
|
|
// in the wild.[${codecName}]
|
|
codecNames.forEach(codecName => {
|
|
Assert.equal(
|
|
telemetry[MEDIA_AUDIO_PROCESS][`${process},${codecName}${extraKey}`],
|
|
1,
|
|
`${MEDIA_AUDIO_PROCESS} must have the correct value (${process}, ${codecName}).`
|
|
);
|
|
});
|
|
}
|
|
|
|
async function verifyNoTelemetryForProcess(process, codecNames, extraKey = "") {
|
|
try {
|
|
await waitForKeyedScalars(process);
|
|
await waitForValue(process, codecNames, extraKey);
|
|
} catch (ex) {
|
|
if (ex.indexOf("timed out after") > 0) {
|
|
Assert.ok(
|
|
true,
|
|
`Expected timeout ${process}[${MEDIA_AUDIO_PROCESS}] for ${codecNames}`
|
|
);
|
|
} else {
|
|
Assert.ok(
|
|
false,
|
|
`Unexpected exception on ${process}[${MEDIA_AUDIO_PROCESS}] for ${codecNames}: ${ex}`
|
|
);
|
|
}
|
|
}
|
|
|
|
const telemetry = getTelemetry();
|
|
|
|
// There could be races with telemetry for power usage coming up
|
|
codecNames.forEach(codecName => {
|
|
if (telemetry) {
|
|
if (telemetry && MEDIA_AUDIO_PROCESS in telemetry) {
|
|
Assert.ok(
|
|
!(
|
|
`${process},${codecName}${extraKey}` in
|
|
telemetry[MEDIA_AUDIO_PROCESS]
|
|
),
|
|
`Some telemetry but no ${process}[${MEDIA_AUDIO_PROCESS}][${codecName}]`
|
|
);
|
|
} else {
|
|
Assert.ok(
|
|
!(MEDIA_AUDIO_PROCESS in telemetry),
|
|
`No telemetry for ${process}[${MEDIA_AUDIO_PROCESS}][${codecName}]`
|
|
);
|
|
}
|
|
} else {
|
|
Assert.equal(
|
|
undefined,
|
|
telemetry,
|
|
`No telemetry for ${process}[${MEDIA_AUDIO_PROCESS}][${codecName}]`
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
function getExtraKey({ utilityPref, rddPref, allowNonUtility }) {
|
|
let extraKey = "";
|
|
if (!rddPref) {
|
|
extraKey += ",rdd-disabled";
|
|
}
|
|
if (!utilityPref) {
|
|
extraKey += ",utility-disabled";
|
|
}
|
|
// TODO: This needs to be removed when getting rid of ability to decode on
|
|
// non utility at all
|
|
if (allowNonUtility || !isNightlyOrEalyBeta()) {
|
|
extraKey += ",allow-non-utility";
|
|
}
|
|
return extraKey;
|
|
}
|