Bug 1259788 - Add video content test for captureStream of MediaElement playing a MediaStream. r?jib
MozReview-Commit-ID: F6X0E0VeqP9
--- 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>