Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: chrome/test/data/extensions/api_test/tab_capture/presentation.js

Issue 1221483002: New tabCapture.captureOffscreenTab API, initially for Presentation API 1UA mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Tests that offscreen presentations can be created and captured. The
6 // offscreen presentation page generates video test patterns that rotate
7 // cyclicly, and the rendering output of the tab is captured into a
8 // LocalMediaStream. This stream is then piped into a video element for
9 // playback, and a canvas is used to examine the frames of the video for
10 // expected content.
11
12 // The offscreen page content for this test is provided as a data URI.
13 var offscreenPageUri = 'data:text/html;charset=UTF-8,' + encodeURIComponent('\n\
14 <html><body></body><script>\n\
15 // The test pattern cycles as a color fill of red, then green, then blue.\n\
16 var colors = [ [ 255, 0, 0 ], [ 0, 255, 0 ], [ 0, 0, 255 ] ];\n\
17 var curIdx = 0;\n\
18 \n\
19 function updateTestPattern() {\n\
20 if (!this.canvas) {\n\
21 this.canvas = document.createElement("canvas");\n\
22 this.canvas.width = 320;\n\
23 this.canvas.height = 200;\n\
24 this.canvas.style.position = "absolute";\n\
25 this.canvas.style.top = "0px";\n\
26 this.canvas.style.left = "0px";\n\
27 this.canvas.style.width = "100%";\n\
28 this.canvas.style.height = "100%";\n\
29 document.body.appendChild(this.canvas);\n\
30 }\n\
31 var context = this.canvas.getContext("2d");\n\
32 // Fill with solid color.\n\
33 context.fillStyle = "rgb(" + colors[curIdx] + ")";\n\
34 context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n\
35 // Draw the circle that moves around the page.\n\
36 context.fillStyle = "rgb(" + colors[(curIdx + 1) % colors.length] + ")";\n\
37 context.beginPath();\n\
38 if (!this.frameNumber) {\n\
39 this.frameNumber = 1;\n\
40 } else {\n\
41 ++this.frameNumber;\n\
42 }\n\
43 var i = this.frameNumber % 200;\n\
44 var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);\n\
45 var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;\n\
46 var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;\n\
47 context.arc(x, y, 16, 0, 2 * Math.PI, false);\n\
48 context.closePath();\n\
49 context.fill();\n\
50 }\n\
51 \n\
52 function renderTestPatternLoop() {\n\
53 requestAnimationFrame(renderTestPatternLoop);\n\
54 updateTestPattern();\n\
55 \n\
56 if (!this.stepTimeMillis) {\n\
57 this.stepTimeMillis = 100;\n\
58 }\n\
59 var now = new Date().getTime();\n\
60 if (!this.nextSteppingAt) {\n\
61 this.nextSteppingAt = now + this.stepTimeMillis;\n\
62 } else if (now >= this.nextSteppingAt) {\n\
63 ++curIdx;\n\
64 if (curIdx >= colors.length) { // Completed a cycle.\n\
65 curIdx = 0;\n\
66 // Increase the wait time between switching test patterns for\n\
67 // overloaded bots that are not capturing all the frames of video.\n\
68 this.stepTimeMillis *= 1.25;\n\
69 }\n\
70 this.nextSteppingAt = now + this.stepTimeMillis;\n\
71 }\n\
72 }\n\
73 \n\
74 renderTestPatternLoop();\n\
75 </script></body></html>');
76
77 // Capture parameters.
78 var width = 64;
79 var height = 48;
80 var frameRate = 15;
81
82 // The stream to playback in the video element.
83 var receiveStream = null;
84
85 // waitForExpectedColors() removes elements from this array as each is observed.
86 // When it becomes empty, the test succeeds.
87 var expectedColors = [ [ 255, 0, 0 ], [ 0, 255, 0 ], [ 0, 0, 255 ] ];
88
89 function waitForExpectedColors(colorDeviation) {
90 // If needed, create the video and canvas elements, but no need to append them
91 // to the DOM.
92 if (!this.video) {
93 this.video = document.createElement("video");
94 this.video.width = width;
95 this.video.height = height;
96 this.video.addEventListener("error", chrome.test.fail);
97 this.video.src = URL.createObjectURL(receiveStream);
98 this.video.play();
99
100 this.readbackCanvas = document.createElement("canvas");
101 this.readbackCanvas.width = width;
102 this.readbackCanvas.height = height;
103 }
104
105 // Only bother examining a video frame if the video timestamp has advanced.
106 var currentVideoTimestamp = this.video.currentTime;
107 if (!this.lastVideoTimestamp ||
108 this.lastVideoTimestamp < currentVideoTimestamp) {
109 this.lastVideoTimestamp = currentVideoTimestamp;
110
111 // Grab a snapshot of the center pixel of the video.
112 var ctx = this.readbackCanvas.getContext("2d");
113 ctx.drawImage(video, 0, 0, width, height);
114 var imageData = ctx.getImageData(width / 2, height / 2, 1, 1);
115 var pixel = [ imageData.data[0], imageData.data[1], imageData.data[2] ];
116
117 // Does the pixel match one of the expected colors?
118 for (var i = 0; i < expectedColors.length; ++i) {
119 var curColor = expectedColors[i];
120 if (Math.abs(pixel[0] - curColor[0]) <= colorDeviation &&
121 Math.abs(pixel[1] - curColor[1]) <= colorDeviation &&
122 Math.abs(pixel[2] - curColor[2]) <= colorDeviation) {
123 console.debug("Observed expected color RGB(" + curColor +
124 ") in the video as RGB(" + pixel + ")");
125 expectedColors.splice(i, 1);
126 }
127 }
128 }
129
130 if (expectedColors.length == 0) {
131 chrome.test.succeed();
132 } else {
133 setTimeout(function () { waitForExpectedColors(colorDeviation); },
134 1000 / frameRate);
135 }
136 }
137
138 chrome.test.runTests([
139 function presentationTest() {
140 // Parse colorDeviation query parameter.
141 var colorDeviation; // How far from the expected intensity ([0,255] scale)?
142 try {
143 colorDeviation = parseInt(
144 window.location.search.match(/(\?|&)colorDeviation=(\d+)/)[2]);
145 chrome.test.assertTrue(colorDeviation >= 0 && colorDeviation <= 255);
146 } catch (err) {
147 chrome.test.fail("Error parsing query params -- " + err.message);
148 return;
149 }
150
151 chrome.tabCapture.capturePresentation(
152 offscreenPageUri,
153 "bubbles",
154 { video: true,
155 audio: false,
156 videoConstraints: {
157 mandatory: {
158 minWidth: width,
159 minHeight: height,
160 maxWidth: width,
161 maxHeight: height,
162 maxFrameRate: frameRate,
163 }
164 }
165 },
166 function examineTheOffscreenCaptureVideo(captureStream) {
167 chrome.test.assertTrue(!!captureStream);
168 receiveStream = captureStream;
169 waitForExpectedColors(colorDeviation);
170 });
171 }
172 ]);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698