зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1553215 - Start testing MediaStreamAudioSourceNode in WPT. r=karlt,pehrsons
It's not complete I think, but it covers the constructor and some bits of behaviour. Differential Revision: https://phabricator.services.mozilla.com/D32175 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e990bc2fe0
Коммит
f86c650449
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html class="a">
|
||||
<head>
|
||||
<title>MediaStreamAudioSourceNode</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body class="a">
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
setup({explicit_done: true});
|
||||
// Wait until the DOM is ready to be able to get a reference to the canvas
|
||||
// element.
|
||||
window.addEventListener("load", function() {
|
||||
const ac = new AudioContext();
|
||||
const emptyStream = new MediaStream();
|
||||
|
||||
test(function() {
|
||||
assert_throws(
|
||||
"InvalidStateError",
|
||||
function() {
|
||||
ac.createMediaStreamSource(emptyStream);
|
||||
},
|
||||
`A MediaStreamAudioSourceNode can only be constructed via the factory
|
||||
method with a MediaStream that has at least one track of kind "audio"`
|
||||
);
|
||||
}, "MediaStreamAudioSourceNode created with factory method and MediaStream with no tracks");
|
||||
|
||||
test(function() {
|
||||
assert_throws(
|
||||
"InvalidStateError",
|
||||
function() {
|
||||
new MediaStreamAudioSourceNode(ac, { mediaStream: emptyStream });
|
||||
},
|
||||
`A MediaStreamAudioSourceNode can only be constructed via the constructor
|
||||
with a MediaStream that has at least one track of kind "audio"`
|
||||
);
|
||||
}, "MediaStreamAudioSourceNode created with constructor and MediaStream with no tracks");
|
||||
|
||||
const canvas = document.querySelector("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const videoOnlyStream = canvas.captureStream();
|
||||
|
||||
test(function() {
|
||||
assert_throws(
|
||||
"InvalidStateError",
|
||||
function() {
|
||||
ac.createMediaStreamSource(videoOnlyStream);
|
||||
},
|
||||
`A MediaStreamAudioSourceNode can only be constructed via the factory with a
|
||||
MediaStream that has at least one track of kind "audio"`
|
||||
);
|
||||
}, `MediaStreamAudioSourceNode created with the factory method and MediaStream with only a video track`);
|
||||
|
||||
test(function() {
|
||||
assert_throws(
|
||||
"InvalidStateError",
|
||||
function() {
|
||||
new MediaStreamAudioSourceNode(ac, {
|
||||
mediaStream: videoOnlyStream,
|
||||
});
|
||||
},
|
||||
`A MediaStreamAudioSourceNode can only be constructed via the factory with a
|
||||
MediaStream that has at least one track of kind "audio"`
|
||||
);
|
||||
}, `MediaStreamAudioSourceNode created with constructor and MediaStream with only a video track`);
|
||||
done();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
<canvas></canvas>
|
||||
</html>
|
|
@ -0,0 +1,134 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html class="a">
|
||||
<head>
|
||||
<title>MediaStreamAudioSourceNode</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body class="a">
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
function binIndexForFrequency(frequency, analyser) {
|
||||
return (
|
||||
1 +
|
||||
Math.round(
|
||||
(frequency * analyser.fftSize) / analyser.context.sampleRate
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const t = async_test(
|
||||
"MediaStreamAudioSourceNode captures the right track."
|
||||
);
|
||||
const ac = new AudioContext();
|
||||
// Test that the right track is captured. Set up a MediaStream that has two
|
||||
// tracks, one with a tone at 100Hz and one with a tone at 1000Hz.
|
||||
const dest0 = ac.createMediaStreamDestination();
|
||||
const dest1 = ac.createMediaStreamDestination();
|
||||
const osc0 = ac.createOscillator();
|
||||
const osc1 = ac.createOscillator();
|
||||
osc0.frequency.value = 100;
|
||||
osc1.frequency.value = 1000;
|
||||
osc0.connect(dest0);
|
||||
osc1.connect(dest1);
|
||||
osc0.start(0);
|
||||
osc1.start(0);
|
||||
const track0 = dest0.stream.getAudioTracks()[0];
|
||||
const track0id = track0.id;
|
||||
const track1 = dest1.stream.getAudioTracks()[0];
|
||||
const track1id = track1.id;
|
||||
|
||||
let ids = [track0id, track1id];
|
||||
ids.sort();
|
||||
let targetFrequency;
|
||||
let otherFrequency;
|
||||
if (ids[0] == track0id) {
|
||||
targetFrequency = 100;
|
||||
otherFrequency = 1000;
|
||||
} else {
|
||||
targetFrequency = 1000;
|
||||
otherFrequency = 100;
|
||||
}
|
||||
|
||||
let twoTrackMediaStream = new MediaStream();
|
||||
twoTrackMediaStream.addTrack(track0);
|
||||
twoTrackMediaStream.addTrack(track1);
|
||||
|
||||
const twoTrackSource = ac.createMediaStreamSource(twoTrackMediaStream);
|
||||
const analyser = ac.createAnalyser();
|
||||
|
||||
twoTrackSource.connect(analyser);
|
||||
|
||||
const indexToCheckForHighEnergy = binIndexForFrequency(
|
||||
targetFrequency,
|
||||
analyser
|
||||
);
|
||||
const indexToCheckForLowEnergy = binIndexForFrequency(
|
||||
otherFrequency,
|
||||
analyser
|
||||
);
|
||||
let frequencyData = new Float32Array(1024);
|
||||
let checkCount = 0;
|
||||
let numberOfRemovals = 0;
|
||||
let stopped = false;
|
||||
function analyse() {
|
||||
analyser.getFloatFrequencyData(frequencyData);
|
||||
// there should be high energy in the right bin, higher than 40dbfs because
|
||||
// it's supposed to be a sine wave at 0dbfs
|
||||
if (frequencyData[indexToCheckForHighEnergy] > -40 && !stopped) {
|
||||
assert_true(true, "Correct track routed to the AudioContext.");
|
||||
checkCount++;
|
||||
}
|
||||
if (stopped && frequencyData[indexToCheckForHighEnergy] < -40) {
|
||||
assert_true(
|
||||
true,
|
||||
`After stopping the track, low energy is found in the
|
||||
same bin`
|
||||
);
|
||||
checkCount++;
|
||||
}
|
||||
// Don't assert(false) immediately here if the bin is still higher than
|
||||
// -40db the analyzer node has a window and it's expecte that it takes some
|
||||
// time for the volume of this bin to decrease.
|
||||
if (frequencyData[indexToCheckForLowEnergy] < -80) {
|
||||
assert_true(true, "Correct track routed to the AudioContext.");
|
||||
} else {
|
||||
assert_true(
|
||||
false,
|
||||
"Other track seem to be routed to the AudioContext?"
|
||||
);
|
||||
}
|
||||
if (checkCount > 5 && checkCount < 20) {
|
||||
twoTrackMediaStream.getAudioTracks().forEach(track => {
|
||||
if (track.id == ids[0]) {
|
||||
numberOfRemovals++;
|
||||
window.removedTrack = track;
|
||||
twoTrackMediaStream.removeTrack(track);
|
||||
}
|
||||
});
|
||||
assert_true(
|
||||
numberOfRemovals == 1,
|
||||
`The mediastreamtrack can only be
|
||||
removed once from the mediastream`
|
||||
);
|
||||
} else if (checkCount >= 20 && checkCount < 30) {
|
||||
window.removedTrack.stop();
|
||||
stopped = true;
|
||||
} else if (checkCount >= 30) {
|
||||
assert_true(
|
||||
numberOfRemovals == 1,
|
||||
`After removing the track from the
|
||||
mediastream, it's still routed to the graph.`
|
||||
);
|
||||
// After some time, consider that it worked.
|
||||
t.done();
|
||||
return;
|
||||
}
|
||||
|
||||
t.step_timeout(analyse, 100);
|
||||
}
|
||||
t.step_timeout(analyse, 100);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче