Bug 1259788 - Add video content test for captureStream of MediaElement playing a MediaStream. r?jib draft
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 18 Aug 2016 17:37:19 +0200
changeset 404497 0fdd7558d26411b4cf9e5df3236682059136f958
parent 404496 20c3efb1f9e809b2684c3f9e604270c540ecccd1
child 404498 52319b2a47758038ebc98b41fa2bc7ca870ed44e
push id27223
push userpehrsons@gmail.com
push dateTue, 23 Aug 2016 16:22:06 +0000
reviewersjib
bugs1259788
milestone51.0a1
Bug 1259788 - Add video content test for captureStream of MediaElement playing a MediaStream. r?jib MozReview-Commit-ID: F6X0E0VeqP9
dom/canvas/test/captureStream_common.js
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html
--- a/dom/canvas/test/captureStream_common.js
+++ b/dom/canvas/test/captureStream_common.js
@@ -98,16 +98,24 @@ CaptureStreamTestHelper.prototype = {
     if (threshold === undefined) {
       // Default to 127 (should be sufficiently far away) if not passed in.
       threshold = 127;
     }
     return px.some((ch, i) => Math.abs(ch - refColor.data[i]) > threshold);
   },
 
   /*
+   * Behaves like isPixelNot but ignores the alpha channel.
+   */
+  isOpaquePixelNot: function(px, refColor, threshold) {
+    px[3] = refColor.data[3];
+    return h.isPixelNot(px, refColor, threshold);
+  },
+
+  /*
    * Returns a promise that resolves when the provided function |test|
    * returns true.
    */
   waitForPixel: function (video, offsetX, offsetY, test, timeout, width, height) {
     return new Promise(resolve => {
       const startTime = video.currentTime;
       var ontimeupdate = () => {
         var pixelMatch = false;
--- 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_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]
 [test_getUserMedia_spinEventLoop.html]
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # copied from basicAudio
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_mediaElementCapture_video.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
+  <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 video content on HTMLMediaElement playing a gUM MediaStream",
+  visible: true
+});
+
+var gUMVideoElement;
+var captureStreamElement;
+
+// We check a pixel somewhere away from the top left corner since
+// MediaEngineDefault puts semi-transparent time indicators there.
+const offsetX = 20;
+const offsetY = 20;
+const threshold = 16;
+const pausedTimeout = 1000;
+const h = new CaptureStreamTestHelper2D(50, 50);
+
+var checkHasFrame = video => h.waitForPixel(video, offsetX, offsetY, px => {
+  let result = h.isOpaquePixelNot(px, h.black, threshold);
+  info("Checking that we have a frame, got [" +
+       Array.slice(px) + "]. Pass=" + result);
+  return result;
+});
+
+var checkVideoPlaying = video => checkHasFrame(video)
+  .then(() => {
+    let startPixel = { data: h.getPixel(video, offsetX, offsetY)
+                     , name: "startcolor"
+                     };
+    return h.waitForPixel(video, offsetX, offsetY, px => {
+      let result = h.isPixelNot(px, startPixel, threshold)
+      info("Checking playing, [" + Array.slice(px) + "] vs [" +
+           Array.slice(startPixel.data) + "]. Pass=" + result);
+      return result;
+    });
+  });
+
+var checkVideoPaused = video => checkHasFrame(video)
+  .then(() => {
+    let startPixel = { data: h.getPixel(video, offsetX, offsetY)
+                     , name: "startcolor"
+                     };
+    return h.waitForPixel(video, offsetX, offsetY, px => {
+      let result = h.isOpaquePixelNot(px, startPixel, threshold);
+      info("Checking paused, [" + Array.slice(px) + "] vs [" +
+           Array.slice(startPixel.data) + "]. Pass=" + result);
+      return result;
+    }, pausedTimeout);
+  }).then(result => ok(!result, "Frame shouldn't change within " + pausedTimeout / 1000 + " seconds."));
+
+runTest(() => getUserMedia({video: true, fake: true})
+  .then(stream => {
+    gUMVideoElement =
+      createMediaElement("gUMVideo", "local", "gUMVideo", false);
+    gUMVideoElement.srcObject = stream;
+    gUMVideoElement.play();
+
+    info("Capturing");
+    captureStreamElement =
+      createMediaElement("captureStream", "local", "captureStream", false);
+    captureStreamElement.srcObject = gUMVideoElement.mozCaptureStream();
+    captureStreamElement.play();
+
+    return checkVideoPlaying(captureStreamElement);
+  })
+  .then(() => {
+    info("Video flowing. Pausing.");
+    gUMVideoElement.pause();
+
+    return checkVideoPaused(captureStreamElement);
+  })
+  .then(() => {
+    info("Video stopped flowing. Playing.");
+    gUMVideoElement.play();
+
+    return checkVideoPlaying(captureStreamElement);
+  })
+  .then(() => {
+    info("Video flowing. Removing source.");
+    var stream = gUMVideoElement.srcObject;
+    gUMVideoElement.srcObject = null;
+
+    return checkVideoPaused(captureStreamElement).then(() => stream);
+  })
+  .then(stream => {
+    info("Video stopped flowing. Setting source.");
+    gUMVideoElement.srcObject = stream;
+    return checkVideoPlaying(captureStreamElement);
+  })
+  .then(() => {
+    info("Video flowing. Changing source by track manipulation. Remove first.");
+    var track = gUMVideoElement.srcObject.getTracks()[0];
+    gUMVideoElement.srcObject.removeTrack(track);
+    return checkVideoPaused(captureStreamElement).then(() => track);
+  })
+  .then(track => {
+    info("Video paused. Changing source by track manipulation. Add first.");
+    gUMVideoElement.srcObject.addTrack(track);
+    gUMVideoElement.play();
+    return checkVideoPlaying(captureStreamElement);
+  })
+  .then(() => ok(true, "Test passed."))
+  .catch(e => ok(false, "Test failed: " + e + (e.stack ? "\n" + e.stack : ""))));
+
+</script>
+</pre>
+</body>
+</html>