mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1219711 - Refactor captureStream_common.js to accept generic pixel testing method. r=jib
--HG-- extra : commitid : 1Lds1zOCtPn extra : rebase_source : 391f0a9871e0f5c26d5480a10344e6a1c5fcb608
This commit is contained in:
parent
1b50326426
commit
6b40da9ca1
@ -25,6 +25,7 @@ function CaptureStreamTestHelper(width, height) {
|
||||
CaptureStreamTestHelper.prototype = {
|
||||
/* Predefined colors for use in the methods below. */
|
||||
black: { data: [0, 0, 0, 255], name: "black" },
|
||||
blackTransparent: { data: [0, 0, 0, 0], name: "blackTransparent" },
|
||||
green: { data: [0, 255, 0, 255], name: "green" },
|
||||
red: { data: [255, 0, 0, 255], name: "red" },
|
||||
|
||||
@ -52,55 +53,90 @@ CaptureStreamTestHelper.prototype = {
|
||||
video.srcObject.requestFrame();
|
||||
},
|
||||
|
||||
/* Tests the top left pixel of |video| against |refData|. Format [R,G,B,A]. */
|
||||
testPixel: function (video, refData, threshold) {
|
||||
/*
|
||||
* Returns the pixel at (|offsetX|, |offsetY|) (from top left corner) of
|
||||
* |video| as an array of the pixel's color channels: [R,G,B,A].
|
||||
*/
|
||||
getPixel: function (video, offsetX, offsetY) {
|
||||
offsetX = offsetX || 0; // Set to 0 if not passed in.
|
||||
offsetY = offsetY || 0; // Set to 0 if not passed in.
|
||||
var ctxout = this.cout.getContext('2d');
|
||||
ctxout.drawImage(video, 0, 0);
|
||||
var pixel = ctxout.getImageData(0, 0, 1, 1).data;
|
||||
return pixel.every((val, i) => Math.abs(val - refData[i]) <= threshold);
|
||||
return ctxout.getImageData(offsetX, offsetY, 1, 1).data;
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns a promise that resolves when the pixel matches. Use |threshold|
|
||||
* for fuzzy matching the color on each channel, in the range [0,255].
|
||||
* Returns true if px lies within the per-channel |threshold| of the
|
||||
* referenced color for all channels. px is on the form of an array of color
|
||||
* channels, [R,G,B,A]. Each channel is in the range [0, 255].
|
||||
*/
|
||||
waitForPixel: function (video, refColor, threshold, infoString) {
|
||||
isPixel: function (px, refColor, threshold) {
|
||||
threshold = threshold || 0; // Default to 0 (exact match) if not passed in.
|
||||
return px.every((ch, i) => Math.abs(ch - refColor.data[i]) <= threshold);
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns true if px lies further away than |threshold| of the
|
||||
* referenced color for any channel. px is on the form of an array of color
|
||||
* channels, [R,G,B,A]. Each channel is in the range [0, 255].
|
||||
*/
|
||||
isPixelNot: function (px, refColor, threshold) {
|
||||
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);
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns a promise that resolves when the provided function |test|
|
||||
* returns true.
|
||||
*/
|
||||
waitForPixel: function (video, offsetX, offsetY, test, timeout) {
|
||||
return new Promise(resolve => {
|
||||
info("Testing " + video.id + " against [" + refColor.data.join(',') + "]");
|
||||
const startTime = video.currentTime;
|
||||
CaptureStreamTestHelper2D.prototype.clear.call(this, this.cout);
|
||||
video.ontimeupdate = () => {
|
||||
if (this.testPixel(video, refColor.data, threshold)) {
|
||||
ok(true, video.id + " " + infoString);
|
||||
video.ontimeupdate = null;
|
||||
resolve();
|
||||
var ontimeupdate = () => {
|
||||
const pixelMatch = test(this.getPixel(video, offsetX, offsetY));
|
||||
if (!pixelMatch &&
|
||||
(!timeout || video.currentTime < startTime + (timeout / 1000.0))) {
|
||||
// No match yet and,
|
||||
// No timeout (waiting indefinitely) or |timeout| has not passed yet.
|
||||
return;
|
||||
}
|
||||
video.removeEventListener("timeupdate", ontimeupdate);
|
||||
resolve(pixelMatch);
|
||||
};
|
||||
video.addEventListener("timeupdate", ontimeupdate);
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns a promise that resolves after |timeout| ms of playback or when a
|
||||
* pixel of |video| becomes the color |refData|. The test is failed if the
|
||||
* Returns a promise that resolves when the top left pixel of |video| matches
|
||||
* on all channels. Use |threshold| for fuzzy matching the color on each
|
||||
* channel, in the range [0,255].
|
||||
*/
|
||||
waitForPixelColor: function (video, refColor, threshold, infoString) {
|
||||
info("Waiting for video " + video.id + " to match [" +
|
||||
refColor.data.join(',') + "] - " + refColor.name +
|
||||
" (" + infoString + ")");
|
||||
return this.waitForPixel(video, 0, 0,
|
||||
px => this.isPixel(px, refColor, threshold))
|
||||
.then(() => ok(true, video.id + " " + infoString));
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns a promise that resolves after |timeout| ms of playback or when the
|
||||
* top left pixel of |video| becomes |refColor|. The test is failed if the
|
||||
* timeout is not reached.
|
||||
*/
|
||||
waitForPixelToTimeout: function (video, refColor, threshold, timeout, infoString) {
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for " + video.id + " to time out after " + timeout +
|
||||
"ms against [" + refColor.data.join(',') + "] - " + refColor.name);
|
||||
CaptureStreamTestHelper2D.prototype.clear.call(this, this.cout);
|
||||
var startTime = video.currentTime;
|
||||
video.ontimeupdate = () => {
|
||||
if (this.testPixel(video, refColor.data, threshold)) {
|
||||
ok(false, video.id + " " + infoString);
|
||||
video.ontimeupdate = null;
|
||||
resolve();
|
||||
} else if (video.currentTime > startTime + (timeout / 1000.0)) {
|
||||
ok(true, video.id + " " + infoString);
|
||||
video.ontimeupdate = null;
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
});
|
||||
waitForPixelColorTimeout: function (video, refColor, threshold, timeout, infoString) {
|
||||
info("Waiting for " + video.id + " to time out after " + timeout +
|
||||
"ms against [" + refColor.data.join(',') + "] - " + refColor.name);
|
||||
return this.waitForPixel(video, 0, 0,
|
||||
px => this.isPixel(px, refColor, threshold),
|
||||
timeout)
|
||||
.then(result => ok(!result, video.id + " " + infoString));
|
||||
},
|
||||
|
||||
/* Create an element of type |type| with id |id| and append it to the body. */
|
||||
|
@ -23,15 +23,21 @@ function checkDrawColorInitialRed() {
|
||||
vmanual.srcObject = c.captureStream(0);
|
||||
vrate.srcObject = c.captureStream(10);
|
||||
|
||||
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "vauto hould not be drawn to before stable state");
|
||||
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "vrate Should not be drawn to before stable state");
|
||||
ok(h.testPixel(vmanual, [0, 0, 0, 0], 0), "vmanual Should not be drawn to before stable state");
|
||||
ok(h.isPixel(h.getPixel(vauto), h.blackTransparent, 0),
|
||||
"vauto should not be drawn to before stable state");
|
||||
ok(h.isPixel(h.getPixel(vrate), h.blackTransparent, 0),
|
||||
"vrate should not be drawn to before stable state");
|
||||
ok(h.isPixel(h.getPixel(vmanual), h.blackTransparent, 0),
|
||||
"vmanual should not be drawn to before stable state");
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should become red when we get" +
|
||||
" to stable state (first frame)"));
|
||||
.then(() => h.waitForPixelColor(vauto, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vrate, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should become red when we get" +
|
||||
" to stable state (first frame)"));
|
||||
}
|
||||
|
||||
function checkDrawColorGreen() {
|
||||
@ -40,11 +46,15 @@ function checkDrawColorGreen() {
|
||||
var drawing = h.startDrawing(() => h.drawColor(c, h.green));
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vauto, h.green, 0, "should become green automatically"))
|
||||
.then(() => h.waitForPixel(vrate, h.green, 0, "should become green automatically"))
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
|
||||
.then(() => h.waitForPixelColor(vauto, h.green, 0,
|
||||
"should become green automatically"))
|
||||
.then(() => h.waitForPixelColor(vrate, h.green, 0,
|
||||
"should become green automatically"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should still be red"))
|
||||
.then(() => h.requestFrame(vmanual))
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after requstFrame()"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0,
|
||||
"should become green after requstFrame()"))
|
||||
.catch(err => ok(false, "checkDrawColorGreen failed: ", err))
|
||||
.then(() => drawing.stop());
|
||||
}
|
||||
@ -54,10 +64,12 @@ function checkRequestFrameOrderGuarantee() {
|
||||
"call results in the expected frame seen in the stream.");
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0,
|
||||
"should still be green"))
|
||||
.then(() => h.drawColor(c, h.red)) // 1. Draw canvas red
|
||||
.then(() => h.requestFrame(vmanual)) // 2. Immediately request a frame
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should become red after call order test"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should become red after call order test"))
|
||||
}
|
||||
|
||||
function checkDrawImageNotCleanRed() {
|
||||
@ -74,11 +86,14 @@ function checkDrawImageNotCleanRed() {
|
||||
})
|
||||
.then(() => drawing = h.startDrawing(() => ctx.drawImage(notCleanRed, 0, 0, c.width, c.height)))
|
||||
.then(() => h.testNotClean(c))
|
||||
.then(() => h.waitForPixelToTimeout(vauto, h.red, 0, 1000, "should not become red"))
|
||||
.then(() => h.waitForPixelToTimeout(vrate, h.red, 0, 0, "should not become red"))
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
|
||||
.then(() => h.waitForPixelColorTimeout(vauto, h.red, 0, 1000,
|
||||
"should not become red"))
|
||||
.then(() => h.isPixelNot(h.getPixel(vrate), h.red, 250,
|
||||
"should not have become red"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0, "should still be green"))
|
||||
.then(() => h.requestFrame(vmanual))
|
||||
.then(() => h.waitForPixelToTimeout(vmanual, h.red, 0, 1000, "should not become red"))
|
||||
.then(() => h.waitForPixelColorTimeout(vmanual, h.red, 0, 1000,
|
||||
"should not become red"))
|
||||
.catch(err => ok(false, "checkDrawImageNotCleanRed failed: ", err))
|
||||
.then(() => drawing.stop());
|
||||
}
|
||||
|
@ -54,14 +54,21 @@ function checkClearColorInitialRed() {
|
||||
vmanual.srcObject = c.captureStream(0);
|
||||
vrate.srcObject = c.captureStream(10);
|
||||
|
||||
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
|
||||
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
|
||||
ok(h.testPixel(vmanual, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
|
||||
ok(h.isPixel(h.getPixel(vauto), h.blackTransparent, 0,
|
||||
"vauto should not be drawn to before stable state"));
|
||||
ok(h.isPixel(h.getPixel(vrate), h.blackTransparent, 0,
|
||||
"vrate should not be drawn to before stable state"));
|
||||
ok(h.isPixel(h.getPixel(vmanual), h.blackTransparent, 0,
|
||||
"vmanual should not be drawn to before stable state"));
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should become red when we get to stable state (first frame)"))
|
||||
.then(() => h.waitForPixelColor(vauto, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vrate, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should become red when we get to stable " +
|
||||
"state (first frame)"))
|
||||
}
|
||||
|
||||
function checkDrawColorGreen() {
|
||||
@ -69,11 +76,15 @@ function checkDrawColorGreen() {
|
||||
var drawing = h.startDrawing(h.drawColor.bind(h, c, h.green));
|
||||
checkGLError('after DrawColor');
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vauto, h.green, 0, "should become green automatically"))
|
||||
.then(() => h.waitForPixel(vrate, h.green, 0, "should become green automatically"))
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
|
||||
.then(() => h.waitForPixelColor(vauto, h.green, 0,
|
||||
"should become green automatically"))
|
||||
.then(() => h.waitForPixelColor(vrate, h.green, 0,
|
||||
"should become green automatically"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should still be red"))
|
||||
.then(() => h.requestFrame(vmanual))
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after requstFrame()"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0,
|
||||
"should become green after requstFrame()"))
|
||||
.then(() => drawing.stop());
|
||||
}
|
||||
|
||||
@ -81,11 +92,15 @@ function checkClearColorRed() {
|
||||
info("Checking that clearing to red works.");
|
||||
var drawing = h.startDrawing(h.clearColor.bind(h, c, h.red));
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vauto, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vrate, h.red, 0, "should become red automatically"))
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should still be green"))
|
||||
.then(() => h.waitForPixelColor(vauto, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vrate, h.red, 0,
|
||||
"should become red automatically"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0,
|
||||
"should still be green"))
|
||||
.then(() => h.requestFrame(vmanual))
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should become red after requestFrame()"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0,
|
||||
"should become red after requestFrame()"))
|
||||
.then(() => drawing.stop());
|
||||
}
|
||||
|
||||
@ -93,10 +108,11 @@ function checkRequestFrameOrderGuarantee() {
|
||||
info("Checking that requestFrame() immediately after a draw " +
|
||||
"call results in the expected frame seen in the stream.");
|
||||
return Promise.resolve()
|
||||
.then(() => h.waitForPixel(vmanual, h.red, 0, "should still be red"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.red, 0, "should still be red"))
|
||||
.then(() => h.drawColor(c, h.green)) // 1. Draw canvas green
|
||||
.then(() => h.requestFrame(vmanual)) // 2. Immediately request a frame
|
||||
.then(() => h.waitForPixel(vmanual, h.green, 0, "should become green after call order test"))
|
||||
.then(() => h.waitForPixelColor(vmanual, h.green, 0,
|
||||
"should become green after call order test"))
|
||||
}
|
||||
|
||||
function finish() {
|
||||
|
@ -56,7 +56,7 @@ function startTest() {
|
||||
SimpleTest.finish();
|
||||
};
|
||||
document.getElementById("content").appendChild(video);
|
||||
helper.waitForPixel(video, helper.red, 128, "Should become red")
|
||||
helper.waitForPixelColor(video, helper.red, 128, "Should become red")
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,8 @@ runNetworkTest(() => {
|
||||
ok(!!vremote, "Should have remote video element for pcRemote");
|
||||
},
|
||||
function WAIT_FOR_REMOTE_GREEN() {
|
||||
return h.waitForPixel(vremote, h.green, 128, "pcRemote's remote should become green");
|
||||
return h.waitForPixelColor(vremote, h.green, 128,
|
||||
"pcRemote's remote should become green");
|
||||
},
|
||||
function DRAW_LOCAL_RED() {
|
||||
// After requesting a frame it will be captured at the time of next render.
|
||||
@ -49,7 +50,8 @@ runNetworkTest(() => {
|
||||
h.drawColor(canvas, h.red);
|
||||
},
|
||||
function WAIT_FOR_REMOTE_RED() {
|
||||
return h.waitForPixel(vremote, h.red, 128, "pcRemote's remote should become red");
|
||||
return h.waitForPixelColor(vremote, h.red, 128,
|
||||
"pcRemote's remote should become red");
|
||||
}
|
||||
]);
|
||||
test.run();
|
||||
|
@ -89,7 +89,8 @@ runNetworkTest(() => {
|
||||
ok(!!vremote, "Should have remote video element for pcRemote");
|
||||
},
|
||||
function WAIT_FOR_REMOTE_GREEN() {
|
||||
return h.waitForPixel(vremote, h.green, 128, "pcRemote's remote should become green");
|
||||
return h.waitForPixelColor(vremote, h.green, 128,
|
||||
"pcRemote's remote should become green");
|
||||
},
|
||||
function REQUEST_FRAME(test) {
|
||||
// After requesting a frame it will be captured at the time of next render.
|
||||
@ -101,7 +102,8 @@ runNetworkTest(() => {
|
||||
h.drawColor(canvas, h.red);
|
||||
},
|
||||
function WAIT_FOR_REMOTE_RED() {
|
||||
return h.waitForPixel(vremote, h.red, 128, "pcRemote's remote should become red");
|
||||
return h.waitForPixelColor(vremote, h.red, 128,
|
||||
"pcRemote's remote should become red");
|
||||
}
|
||||
]);
|
||||
test.run();
|
||||
|
Loading…
Reference in New Issue
Block a user