summaryrefslogtreecommitdiffstats
path: root/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html')
-rw-r--r--dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html251
1 files changed, 251 insertions, 0 deletions
diff --git a/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html b/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
new file mode 100644
index 000000000..8d4d5e559
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaStreamClone.html
@@ -0,0 +1,251 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+ "use strict";
+
+ createHTML({
+ title: "MediaStream.clone()",
+ bug: "1208371"
+ });
+
+ runTest(() => Promise.resolve()
+ .then(() => getUserMedia({audio: true, video: true})).then(stream => {
+ info("Test clone()ing an audio/video gUM stream");
+ var clone = stream.clone();
+
+ checkMediaStreamCloneAgainstOriginal(clone, stream);
+ checkMediaStreamTrackCloneAgainstOriginal(clone.getAudioTracks()[0],
+ stream.getAudioTracks()[0]);
+ checkMediaStreamTrackCloneAgainstOriginal(clone.getVideoTracks()[0],
+ stream.getVideoTracks()[0]);
+
+ isnot(clone.id.length, 0, "Stream clone should have an id string");
+ isnot(clone.getAudioTracks()[0].id.length, 0,
+ "Audio track clone should have an id string");
+ isnot(clone.getVideoTracks()[0].id.length, 0,
+ "Audio track clone should have an id string");
+
+ info("Stopping original tracks");
+ stream.getTracks().forEach(t => t.stop());
+
+ info("Playing from track clones");
+ var test = createMediaElement('video', 'testClonePlayback');
+ var playback = new MediaStreamPlayback(test, clone);
+ return playback.playMedia(false);
+ })
+ .then(() => getUserMedia({video: true})).then(stream =>
+ getUserMedia({video: true}).then(otherStream => {
+ info("Test addTrack()ing a video track to a stream without affecting its clone");
+ var track = stream.getTracks()[0];
+ var otherTrack = otherStream.getTracks()[0];
+
+ var streamClone = stream.clone();
+ var trackClone = streamClone.getTracks()[0];
+ checkMediaStreamContains(streamClone, [trackClone], "Initial clone");
+
+ stream.addTrack(otherTrack);
+ checkMediaStreamContains(stream, [track, otherTrack],
+ "Added video to original");
+ checkMediaStreamContains(streamClone, [trackClone],
+ "Clone not affected");
+
+ stream.removeTrack(track);
+ streamClone.addTrack(track);
+ checkMediaStreamContains(streamClone, [trackClone, track],
+ "Added video to clone");
+ checkMediaStreamContains(stream, [otherTrack],
+ "Original not affected");
+
+ // Not part of streamClone. Does not get stopped by the playback test.
+ otherTrack.stop();
+ otherStream.stop();
+
+ var test = createMediaElement('video', 'testClonePlayback');
+ var playback = new MediaStreamPlayback(test, streamClone);
+ return playback.playMedia(false)
+ .then(() => stream.getTracks().forEach(t => t.stop()))
+ .then(() => stream.stop());
+ }))
+ .then(() => getUserMedia({audio: true, video: true})).then(stream => {
+ info("Test cloning a stream into inception");
+ var clone = stream;
+ var clones = Array(10).fill().map(() => clone = clone.clone());
+ var inceptionClone = clones.pop();
+ checkMediaStreamCloneAgainstOriginal(inceptionClone, stream);
+ stream.getTracks().forEach(t => (stream.removeTrack(t),
+ inceptionClone.addTrack(t)));
+ is(inceptionClone.getAudioTracks().length, 2,
+ "The inception clone should contain the original audio track and a track clone");
+ is(inceptionClone.getVideoTracks().length, 2,
+ "The inception clone should contain the original video track and a track clone");
+
+ var test = createMediaElement('video', 'testClonePlayback');
+ var playback = new MediaStreamPlayback(test, inceptionClone);
+ return playback.playMedia(false)
+ .then(() => clones.forEach(c => c.getTracks().forEach(t => t.stop())));
+ })
+ .then(() => getUserMedia({audio: true, video: true})).then(stream => {
+ info("Test adding tracks from many stream clones to the original stream");
+
+ const LOOPS = 3;
+ for (var i = 0; i < LOOPS; i++) {
+ stream.clone().getTracks().forEach(t => stream.addTrack(t));
+ }
+ is(stream.getAudioTracks().length, Math.pow(2, LOOPS),
+ "The original track should contain the original audio track and all the audio clones");
+ is(stream.getVideoTracks().length, Math.pow(2, LOOPS),
+ "The original track should contain the original video track and all the video clones");
+ stream.getTracks().forEach(t1 => is(stream.getTracks()
+ .filter(t2 => t1.id == t2.id)
+ .length,
+ 1, "Each track should be unique"));
+
+ var test = createMediaElement('video', 'testClonePlayback');
+ var playback = new MediaStreamPlayback(test, stream);
+ return playback.playMedia(false);
+ })
+ .then(() => {
+ info("Testing audio content routing with MediaStream.clone()");
+ var ac = new AudioContext();
+
+ var osc1kOriginal = createOscillatorStream(ac, 1000);
+ var audioTrack1kOriginal = osc1kOriginal.getTracks()[0];
+ var audioTrack1kClone = osc1kOriginal.clone().getTracks()[0];
+
+ var osc5kOriginal = createOscillatorStream(ac, 5000);
+ var audioTrack5kOriginal = osc5kOriginal.getTracks()[0];
+ var audioTrack5kClone = osc5kOriginal.clone().getTracks()[0];
+
+ return Promise.resolve().then(() => {
+ info("Analysing audio output of original stream (1k + 5k)");
+ var stream = new MediaStream();
+ stream.addTrack(audioTrack1kOriginal);
+ stream.addTrack(audioTrack5kOriginal);
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] > 200 &&
+ array[analyser.binIndexForFrequency(10000)] < 50)
+ .then(() => {
+ info("Waiting for original tracks to stop");
+ stream.getTracks().forEach(t => t.stop());
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ // WebAudioDestination streams do not handle stop()
+ // XXX Should they? Plan to resolve that in bug 1208384.
+ // array[analyser.binIndexForFrequency(1000)] < 50 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ // array[analyser.binIndexForFrequency(5000)] < 50 &&
+ array[analyser.binIndexForFrequency(10000)] < 50);
+ })
+ .then(() => analyser.disconnect());
+ }).then(() => {
+ info("Analysing audio output of stream clone (1k + 5k)");
+ var stream = new MediaStream();
+ stream.addTrack(audioTrack1kClone);
+ stream.addTrack(audioTrack5kClone);
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] > 200 &&
+ array[analyser.binIndexForFrequency(10000)] < 50)
+ .then(() => analyser.disconnect());
+ }).then(() => {
+ info("Analysing audio output of clone of clone (1k + 5k)");
+ var stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]).clone();
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] > 200 &&
+ array[analyser.binIndexForFrequency(10000)] < 50)
+ .then(() => analyser.disconnect());
+ }).then(() => {
+ info("Analysing audio output of clone() + addTrack()ed tracks (1k + 5k)");
+ var stream =
+ new MediaStream(new MediaStream([ audioTrack1kClone
+ , audioTrack5kClone
+ ]).clone().getTracks());
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] > 200 &&
+ array[analyser.binIndexForFrequency(10000)] < 50)
+ .then(() => analyser.disconnect());
+ }).then(() => {
+ info("Analysing audio output of clone()d tracks in original stream (1k) " +
+ "and clone()d tracks in stream clone (5k)");
+ var stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]);
+ var streamClone = stream.clone();
+
+ stream.getTracks().forEach(t => stream.removeTrack(t));
+ stream.addTrack(streamClone.getTracks()[0]);
+ streamClone.removeTrack(streamClone.getTracks()[0]);
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] < 50)
+ .then(() => {
+ analyser.disconnect();
+ var cloneAnalyser = new AudioStreamAnalyser(ac, streamClone);
+ return cloneAnalyser.waitForAnalysisSuccess(array =>
+ array[cloneAnalyser.binIndexForFrequency(1000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(3000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(5000)] > 200 &&
+ array[cloneAnalyser.binIndexForFrequency(10000)] < 50)
+ .then(() => cloneAnalyser.disconnect());
+ });
+ }).then(() => {
+ info("Analysing audio output enabled and disabled tracks that don't affect each other");
+ var stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]);
+ var clone = stream.clone();
+
+ stream.getTracks()[0].enabled = true;
+ stream.getTracks()[1].enabled = false;
+
+ clone.getTracks()[0].enabled = false;
+ clone.getTracks()[1].enabled = true;
+
+ var analyser = new AudioStreamAnalyser(ac, stream);
+ return analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] < 50)
+ .then(() => {
+ analyser.disconnect();
+ var cloneAnalyser = new AudioStreamAnalyser(ac, clone);
+ return cloneAnalyser.waitForAnalysisSuccess(array =>
+ array[cloneAnalyser.binIndexForFrequency(1000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(3000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(5000)] > 200 &&
+ array[cloneAnalyser.binIndexForFrequency(10000)] < 50)
+ .then(() => cloneAnalyser.disconnect());
+ })
+ // Restore original tracks
+ .then(() => stream.getTracks().forEach(t => t.enabled = true));
+ });
+ }));
+</script>
+</pre>
+</body>
+</html>