summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html')
-rw-r--r--dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html258
1 files changed, 258 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html b/dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html
new file mode 100644
index 0000000000..029ce77dd0
--- /dev/null
+++ b/dom/media/webrtc/tests/mochitests/test_getUserMedia_mediaStreamClone.html
@@ -0,0 +1,258 @@
+<!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(async () => {
+ await pushPrefs(
+ ["media.getusermedia.camera.stop_on_disable.enabled", true],
+ ["media.getusermedia.camera.stop_on_disable.delay_ms", 0],
+ ["media.getusermedia.microphone.stop_on_disable.enabled", true],
+ ["media.getusermedia.microphone.stop_on_disable.delay_ms", 0]);
+
+ let gUMStream = await getUserMedia({audio: true, video: true});
+ {
+ info("Test clone()ing an audio/video gUM stream");
+ let clone = gUMStream.clone();
+
+ checkMediaStreamCloneAgainstOriginal(clone, gUMStream);
+ checkMediaStreamTrackCloneAgainstOriginal(clone.getAudioTracks()[0],
+ gUMStream.getAudioTracks()[0]);
+ checkMediaStreamTrackCloneAgainstOriginal(clone.getVideoTracks()[0],
+ gUMStream.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("Playing from track clones");
+ let test = createMediaElement('video', 'testClonePlayback');
+ let playback = new MediaStreamPlayback(test, clone);
+ await playback.playMedia(false);
+ }
+
+ {
+ info("Test addTrack()ing a video track to a stream without affecting its clone");
+ let stream = new MediaStream(gUMStream.getVideoTracks());
+ let otherStream = await getUserMedia({video: true});
+ let track = stream.getTracks()[0];
+ let otherTrack = otherStream.getTracks()[0];
+
+ let streamClone = stream.clone();
+ let 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();
+
+ let test = createMediaElement('video', 'testClonePlayback');
+ let playback = new MediaStreamPlayback(test, streamClone);
+ await playback.playMedia(false);
+ }
+
+ {
+ info("Test cloning a stream into inception");
+ let stream = gUMStream.clone()
+ let clone = stream;
+ let clones = Array(10).fill().map(() => clone = clone.clone());
+ let 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");
+
+ let test = createMediaElement('video', 'testClonePlayback');
+ let playback = new MediaStreamPlayback(test, inceptionClone);
+ await playback.playMedia(false);
+ clones.forEach(c => c.getTracks().forEach(t => t.stop()));
+ stream.getTracks().forEach(t => t.stop());
+ }
+
+ {
+ info("Test adding tracks from many stream clones to the original stream");
+ let stream = gUMStream.clone();
+
+ const LOOPS = 3;
+ for (let 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"));
+
+ let test = createMediaElement('video', 'testClonePlayback');
+ let playback = new MediaStreamPlayback(test, stream);
+ await playback.playMedia(false);
+ }
+
+ {
+ info("Testing audio content routing with MediaStream.clone()");
+ let ac = new AudioContext();
+
+ let osc1kOriginal = createOscillatorStream(ac, 1000);
+ let audioTrack1kOriginal = osc1kOriginal.getTracks()[0];
+ let audioTrack1kClone = osc1kOriginal.clone().getTracks()[0];
+
+ let osc5kOriginal = createOscillatorStream(ac, 5000);
+ let audioTrack5kOriginal = osc5kOriginal.getTracks()[0];
+ let audioTrack5kClone = osc5kOriginal.clone().getTracks()[0];
+
+ info("Analysing audio output of original stream (1k + 5k)");
+ let stream = new MediaStream();
+ stream.addTrack(audioTrack1kOriginal);
+ stream.addTrack(audioTrack5kOriginal);
+
+ let analyser = new AudioStreamAnalyser(ac, stream);
+ await 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);
+
+ info("Waiting for original tracks to stop");
+ stream.getTracks().forEach(t => t.stop());
+ await 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);
+ analyser.disconnect();
+
+ info("Analysing audio output of stream clone (1k + 5k)");
+ stream = new MediaStream();
+ stream.addTrack(audioTrack1kClone);
+ stream.addTrack(audioTrack5kClone);
+
+ analyser = new AudioStreamAnalyser(ac, stream);
+ await 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);
+ analyser.disconnect();
+
+ info("Analysing audio output of clone of clone (1k + 5k)");
+ stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]).clone();
+
+ analyser = new AudioStreamAnalyser(ac, stream);
+ await 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);
+ analyser.disconnect();
+
+ info("Analysing audio output of clone() + addTrack()ed tracks (1k + 5k)");
+ stream = new MediaStream(new MediaStream([ audioTrack1kClone
+ , audioTrack5kClone
+ ]).clone().getTracks());
+
+ analyser = new AudioStreamAnalyser(ac, stream);
+ await 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);
+ analyser.disconnect();
+
+ info("Analysing audio output of clone()d tracks in original stream (1k) " +
+ "and clone()d tracks in stream clone (5k)");
+ stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]);
+ let streamClone = stream.clone();
+
+ stream.getTracks().forEach(t => stream.removeTrack(t));
+ stream.addTrack(streamClone.getTracks()[0]);
+ streamClone.removeTrack(streamClone.getTracks()[0]);
+
+ analyser = new AudioStreamAnalyser(ac, stream);
+ await analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] < 50);
+ analyser.disconnect();
+
+ let cloneAnalyser = new AudioStreamAnalyser(ac, streamClone);
+ await cloneAnalyser.waitForAnalysisSuccess(array =>
+ array[cloneAnalyser.binIndexForFrequency(1000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(3000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(5000)] > 200 &&
+ array[cloneAnalyser.binIndexForFrequency(10000)] < 50);
+ cloneAnalyser.disconnect();
+
+ info("Analysing audio output enabled and disabled tracks that don't affect each other");
+ stream = new MediaStream([audioTrack1kClone, audioTrack5kClone]);
+ let clone = stream.clone();
+
+ stream.getTracks()[0].enabled = true;
+ stream.getTracks()[1].enabled = false;
+
+ clone.getTracks()[0].enabled = false;
+ clone.getTracks()[1].enabled = true;
+
+ analyser = new AudioStreamAnalyser(ac, stream);
+ await analyser.waitForAnalysisSuccess(array =>
+ array[analyser.binIndexForFrequency(50)] < 50 &&
+ array[analyser.binIndexForFrequency(1000)] > 200 &&
+ array[analyser.binIndexForFrequency(3000)] < 50 &&
+ array[analyser.binIndexForFrequency(5000)] < 50);
+ analyser.disconnect();
+
+ cloneAnalyser = new AudioStreamAnalyser(ac, clone);
+ await cloneAnalyser.waitForAnalysisSuccess(array =>
+ array[cloneAnalyser.binIndexForFrequency(1000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(3000)] < 50 &&
+ array[cloneAnalyser.binIndexForFrequency(5000)] > 200 &&
+ array[cloneAnalyser.binIndexForFrequency(10000)] < 50);
+ cloneAnalyser.disconnect();
+
+ // Restore original tracks
+ stream.getTracks().forEach(t => t.enabled = true);
+ }
+
+ gUMStream.getTracks().forEach(t => t.stop());
+});
+</script>
+</pre>
+</body>
+</html>