Bug 1259788 - Add test for output MediaStreamTracks when media element captures MediaStream. r?jib draft
authorAndreas Pehrson <pehrsons@gmail.com>
Mon, 22 Aug 2016 12:01:54 +0200
changeset 404498 52319b2a47758038ebc98b41fa2bc7ca870ed44e
parent 404497 0fdd7558d26411b4cf9e5df3236682059136f958
child 404499 6375ed5980b530b203b56264e96dab384a303329
child 404922 61b807c526b0cb5dd2be33fc6a809c00212741d9
push id27223
push userpehrsons@gmail.com
push dateTue, 23 Aug 2016 16:22:06 +0000
reviewersjib
bugs1259788
milestone51.0a1
Bug 1259788 - Add test for output MediaStreamTracks when media element captures MediaStream. r?jib MozReview-Commit-ID: CikbebBmpQp
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_tracks.html
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -65,16 +65,18 @@ skip-if = (toolkit == 'gonk' || buildapp
 [test_getUserMedia_constraints.html]
 [test_getUserMedia_callbacks.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # Bug 1063290, intermittent timeout # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
 [test_getUserMedia_getTrackById.html]
 [test_getUserMedia_gumWithinGum.html]
 [test_getUserMedia_loadedmetadata.html]
 [test_getUserMedia_mediaElementCapture_audio.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g emulator seems to be too slow (Bug 1016498 and 1008080), android(Bug 1189784, timeouts on 4.3 emulator)
+[test_getUserMedia_mediaElementCapture_tracks.html]
+skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g emulator seems to be too slow (Bug 1016498 and 1008080), android(Bug 1189784, timeouts on 4.3 emulator)
 [test_getUserMedia_mediaElementCapture_video.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g emulator seems to be too slow (Bug 1016498 and 1008080), android(Bug 1189784, timeouts on 4.3 emulator)
 [test_getUserMedia_mediaStreamClone.html]
 [test_getUserMedia_mediaStreamConstructors.html]
 [test_getUserMedia_mediaStreamTrackClone.html]
 [test_getUserMedia_playAudioTwice.html]
 [test_getUserMedia_playVideoAudioTwice.html]
 [test_getUserMedia_playVideoTwice.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_tracks.html
@@ -0,0 +1,185 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+  <script type="application/javascript" src="head.js"></script>
+</head>
+<body>
+<pre id="test">
+<script>
+
+createHTML({
+  bug: "1259788",
+  title: "Test CaptureStream track output on HTMLMediaElement playing a gUM MediaStream",
+  visible: true
+});
+
+var audioElement;
+var audioCaptureStream;
+var videoElement;
+var videoCaptureStream;
+var untilEndedElement;
+var streamUntilEnded;
+var tracks = [];
+runTest(() => getUserMedia({audio: true, video: true})
+  .then(stream => {
+    // We need to test with multiple tracks. We add an extra of each kind.
+    stream.getTracks().forEach(t => stream.addTrack(t.clone()));
+
+    audioElement = createMediaElement("gUMAudio", "local", "gUMAudio", true);
+    audioElement.srcObject = stream;
+
+    return haveEvent(audioElement, "loadedmetadata", wait(5000, new Error("Timeout")));
+  })
+  .then(() => {
+    info("Capturing audio element (loadedmetadata -> captureStream)");
+    audioCaptureStream = audioElement.mozCaptureStream();
+
+    is(audioCaptureStream.getAudioTracks().length, 2,
+       "audio element should capture two audio tracks");
+    is(audioCaptureStream.getVideoTracks().length, 0,
+       "audio element should not capture any video tracks");
+
+    return haveNoEvent(audioCaptureStream, "addtrack");
+  })
+  .then(() => {
+    videoElement = createMediaElement("gUMVideo", "local", "gUMVideo", false);
+
+    info("Capturing video element (captureStream -> loadedmetadata)");
+    videoCaptureStream = videoElement.mozCaptureStream();
+    videoElement.srcObject = audioElement.srcObject.clone();
+
+    is(videoCaptureStream.getTracks().length, 0,
+       "video element should have no tracks before metadata known");
+
+    return haveEventsButNoMore(
+        videoCaptureStream, "addtrack", 3, wait(5000, new Error("No event")));
+  })
+  .then(() => {
+    is(videoCaptureStream.getAudioTracks().length, 2,
+       "video element should capture two audio tracks");
+    is(videoCaptureStream.getVideoTracks().length, 1,
+       "video element should capture one video track at most");
+
+    info("Testing dynamically adding audio track to audio element");
+    audioElement.srcObject.addTrack(
+        audioElement.srcObject.getAudioTracks()[0].clone());
+    return haveEventsButNoMore(
+        audioCaptureStream, "addtrack", 1, wait(5000, new Error("No event")));
+  })
+  .then(() => {
+    is(audioCaptureStream.getAudioTracks().length, 3,
+       "Audio element should have three audio tracks captured.");
+
+    info("Testing dynamically adding video track to audio element");
+    audioElement.srcObject.addTrack(
+        audioElement.srcObject.getVideoTracks()[0].clone());
+    return haveNoEvent(audioCaptureStream, "addtrack");
+  })
+  .then(() => {
+    is(audioCaptureStream.getVideoTracks().length, 0,
+       "Audio element should have no video tracks captured.");
+
+    info("Testing dynamically adding audio track to video element");
+    videoElement.srcObject.addTrack(
+        videoElement.srcObject.getAudioTracks()[0].clone());
+    return haveEventsButNoMore(
+        videoCaptureStream, "addtrack", 1, wait(5000, new Error("Timeout")));
+  })
+  .then(() => {
+    is(videoCaptureStream.getAudioTracks().length, 3,
+       "Captured video stream should have three audio tracks captured.");
+
+    info("Testing dynamically adding video track to video element");
+    videoElement.srcObject.addTrack(
+        videoElement.srcObject.getVideoTracks()[0].clone());
+    return haveNoEvent(videoCaptureStream, "addtrack");
+  })
+  .then(() => {
+    is(videoCaptureStream.getVideoTracks().length, 1,
+       "Captured video stream should have at most one video tracks captured.");
+
+    info("Testing track removal.");
+    tracks.push(...videoElement.srcObject.getTracks());
+    videoElement.srcObject.getVideoTracks().reverse().forEach(t =>
+        videoElement.srcObject.removeTrack(t));
+    is(videoCaptureStream.getVideoTracks()
+                         .filter(t => t.readyState == "live").length, 1,
+       "Captured video should have still have one video track captured.");
+
+    return haveEvent(videoCaptureStream.getVideoTracks()[0], "ended",
+                     wait(5000, new Error("Timeout")));
+  })
+  .then(() => {
+    is(videoCaptureStream.getVideoTracks()
+                         .filter(t => t.readyState == "live").length, 0,
+       "Captured video stream should have no video tracks captured after removal.");
+
+    info("Testing source reset.");
+  })
+  .then(() => getUserMedia({audio: true, video: true}))
+  .then(stream => {
+    videoElement.srcObject = stream;
+    return Promise.all(videoCaptureStream.getTracks()
+        .filter(t => t.readyState == "live")
+        .map(t => haveEvent(t, "ended", wait(5000, new Error("Timeout")))));
+  })
+  .then(() => haveEventsButNoMore(
+                  videoCaptureStream, "addtrack", 2, wait(5000, new Error("Timeout"))))
+  .then(() => {
+    is(videoCaptureStream.getAudioTracks()
+        .filter(t => t.readyState == "ended").length, 3,
+       "Captured video stream should have three ended audio tracks");
+    is(videoCaptureStream.getAudioTracks()
+        .filter(t => t.readyState == "live").length, 1,
+       "Captured video stream should have one live audio track");
+
+    is(videoCaptureStream.getVideoTracks()
+        .filter(t => t.readyState == "ended").length, 1,
+       "Captured video stream should have one ended video tracks");
+    is(videoCaptureStream.getVideoTracks()
+        .filter(t => t.readyState == "live").length, 1,
+       "Captured video stream should have one live video track");
+
+    info("Testing CaptureStreamUntilEnded");
+    untilEndedElement =
+      createMediaElement("gUMVideoUntilEnded", "local", "gUMVideoUntilEnded", false);
+    untilEndedElement.srcObject = audioElement.srcObject;
+
+    return haveEvent(untilEndedElement, "loadedmetadata",
+                     wait(5000, new Error("Timeout")));
+  })
+  .then(() => {
+    streamUntilEnded = untilEndedElement.mozCaptureStreamUntilEnded();
+
+    is(streamUntilEnded.getAudioTracks().length, 3,
+       "video element should capture all 3 audio tracks until ended");
+    is(streamUntilEnded.getVideoTracks().length, 1,
+       "video element should capture only 1 video track until ended");
+
+    untilEndedElement.srcObject.getTracks().forEach(t => t.stop());
+    // TODO(1208316) We stop the stream to make the media element end.
+    untilEndedElement.srcObject.stop();
+
+    return Promise.all([
+      haveEvent(untilEndedElement, "ended", wait(5000, new Error("Timeout"))),
+      ...streamUntilEnded.getTracks()
+           .map(t => haveEvent(t, "ended", wait(5000, new Error("Timeout"))))
+    ]);
+  })
+  .then(() => {
+    info("Element and tracks ended. Ensuring that new tracks aren't created.");
+    untilEndedElement.srcObject = videoElement.srcObject;
+    return haveEventsButNoMore(
+        untilEndedElement, "loadedmetadata", 1, wait(5000, new Error("Timeout")));
+  })
+  .then(() => is(streamUntilEnded.getTracks().length, 4,
+                 "Should still have 4 tracks"))
+  .catch(e => ok(false, "Test failed: " + e + (e && e.stack ? "\n" + e.stack : "")))
+  .then(() => [...tracks,
+               ...videoElement.srcObject.getTracks()].forEach(t => t.stop())));
+
+</script>
+</pre>
+</body>
+</html>