Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / test / data / blackwhite.html
blob8230b6baf1e561c14997340ac5dcfee8934ffe1d
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <style>
5 body {
6 color: white;
7 background-color: black;
9 </style>
10 </head>
11 <body onload="main()">
12 <div id="buttons"></div>
13 <table>
14 <tr>
15 <td>Image</td>
16 <td id="video_header"></td>
17 <td>Absolute Diff</td>
18 <td>Different Pixels</td>
19 </tr>
20 <tr>
21 <td><img src="blackwhite.png"></div>
22 <td><video autoplay></video></div>
23 <td><canvas id="diff"></canvas></td>
24 <td><canvas id="mask"></canvas></td>
25 </tr>
26 </div>
28 <p id="result"></p>
30 <script>
31 function log(str) {
32 document.getElementById('result').textContent = str;
33 console.log(str);
36 function loadVideo(name) {
37 var videoElem = document.querySelector('video');
38 videoElem.src = 'blackwhite_' + name;
40 document.getElementById('video_header').textContent = name;
41 videoElem.addEventListener('ended', onVideoEnded);
44 function onVideoEnded(e) {
45 document.title = verifyVideo() ? 'ENDED' : 'FAILED';
48 function onVideoError(e) {
49 document.title = 'ERROR';
50 document.getElementById('diff').style.visibility = 'hidden';
51 document.getElementById('mask').style.visibility = 'hidden';
52 log('Error playing video: ' + e.target.error.code + '.');
55 function main() {
56 // Programatically create buttons for each clip for manual testing.
57 var buttonsElem = document.getElementById('buttons');
59 function createButton(name) {
60 var buttonElem = document.createElement('button');
61 buttonElem.textContent = name;
62 buttonElem.addEventListener('click', function() {
63 loadVideo(name);
64 });
65 buttonsElem.appendChild(buttonElem);
68 var VIDEOS = [
69 'yuv420p.ogv',
70 'yuv422p.ogv',
71 'yuv444p.ogv',
72 'yuv420p.webm',
73 'yuv444p.webm',
74 'yuv420p.mp4',
75 'yuv420p_rec709.mp4',
76 'yuvj420p.mp4',
77 'yuv422p.mp4',
78 'yuv444p.mp4',
79 'yuv420p.avi'
82 for (var i = 0; i < VIDEOS.length; ++i) {
83 createButton(VIDEOS[i]);
86 // Video event handlers.
87 var videoElem = document.querySelector('video');
88 videoElem.addEventListener('error', onVideoError);
90 // Check if a query parameter was provided for automated tests.
91 if (window.location.search.length > 1) {
92 loadVideo(window.location.search.substr(1));
93 } else {
94 // If we're not an automated test, compute some pretty diffs.
95 document.querySelector('video').addEventListener('ended',
96 computeDiffs);
100 function getCanvasPixels(canvas) {
101 try {
102 return canvas.getContext('2d')
103 .getImageData(0, 0, canvas.width, canvas.height)
104 .data;
105 } catch(e) {
106 var message = 'ERROR: ' + e;
107 if (e.name == 'SecurityError') {
108 message += ' Couldn\'t get image pixels, try running with ' +
109 '--allow-file-access-from-files.';
111 log(message);
115 function verifyVideo() {
116 var videoElem = document.querySelector('video');
117 var offscreen = document.createElement('canvas');
118 offscreen.width = videoElem.videoWidth;
119 offscreen.height = videoElem.videoHeight;
120 offscreen.getContext('2d')
121 .drawImage(videoElem, 0, 0, offscreen.width, offscreen.height);
123 videoData = getCanvasPixels(offscreen);
124 if (!videoData)
125 return false;
127 // Check the color of a givel pixel |x,y| in |imgData| against an
128 // expected value, |expected|, with up to |allowedError| difference.
129 function checkColor(imgData, x, y, stride, expected, allowedError) {
130 for (var i = 0; i < 3; ++i) {
131 if (Math.abs(imgData[(x + y * stride) * 4 + i] - expected) >
132 allowedError) {
133 return false;
136 return true;
139 // Check one pixel in each quadrant (in the upper left, away from
140 // boundaries and the text, to avoid compression artifacts).
141 // Also allow a small error, for the same reason.
143 // TODO(mtomasz): Once code.google.com/p/libyuv/issues/detail?id=324 is
144 // fixed, the allowedError should be decreased to 1.
145 var allowedError = 2;
147 return checkColor(videoData, 30, 30, videoElem.videoWidth, 0xff,
148 allowedError) &&
149 checkColor(videoData, 150, 30, videoElem.videoWidth, 0x00,
150 allowedError) &&
151 checkColor(videoData, 30, 150, videoElem.videoWidth, 0x10,
152 allowedError) &&
153 checkColor(videoData, 150, 150, videoElem.videoWidth, 0xef,
154 allowedError);
157 // Compute a standard diff image, plus a high-contrast mask that shows
158 // each differing pixel more visibly.
159 function computeDiffs() {
160 var diffElem = document.getElementById('diff');
161 var maskElem = document.getElementById('mask');
162 var videoElem = document.querySelector('video');
163 var imgElem = document.querySelector('img');
165 var width = imgElem.width;
166 var height = imgElem.height;
168 if (videoElem.videoWidth != width || videoElem.videoHeight != height) {
169 log('ERROR: video dimensions don\'t match reference image ' +
170 'dimensions');
171 return;
174 // Make an offscreen canvas to dump reference image pixels into.
175 var offscreen = document.createElement('canvas');
176 offscreen.width = width;
177 offscreen.height = height;
179 offscreen.getContext('2d').drawImage(imgElem, 0, 0, width, height);
180 imgData = getCanvasPixels(offscreen);
181 if (!imgData)
182 return;
184 // Scale and clear diff canvases.
185 diffElem.width = maskElem.width = width;
186 diffElem.height = maskElem.height = height;
187 var diffCtx = diffElem.getContext('2d');
188 var maskCtx = maskElem.getContext('2d');
189 maskCtx.clearRect(0, 0, width, height);
190 diffCtx.clearRect(0, 0, width, height);
192 // Copy video pixels into diff.
193 diffCtx.drawImage(videoElem, 0, 0, width, height);
195 var diffIData = diffCtx.getImageData(0, 0, width, height);
196 var diffData = diffIData.data;
197 var maskIData = maskCtx.getImageData(0, 0, width, height);
198 var maskData = maskIData.data;
200 // Make diffs and collect stats.
201 var meanSquaredError = 0;
202 for (var i = 0; i < imgData.length; i += 4) {
203 var difference = 0;
204 for (var j = 0; j < 3; ++j) {
205 diffData[i + j] = Math.abs(diffData[i + j] - imgData[i + j]);
206 meanSquaredError += diffData[i + j] * diffData[i + j];
207 if (diffData[i + j] != 0) {
208 difference += diffData[i + j];
211 if (difference > 0) {
212 if (difference <= 3) {
213 // If we're only off by a bit per channel or so, use darker red.
214 maskData[i] = 128;
215 } else {
216 // Bright red to indicate a different pixel.
217 maskData[i] = 255;
219 maskData[i+3] = 255;
223 meanSquaredError /= width * height;
224 log('Mean squared error: ' + meanSquaredError);
225 diffCtx.putImageData(diffIData, 0, 0);
226 maskCtx.putImageData(maskIData, 0, 0);
227 document.getElementById('diff').style.visibility = 'visible';
228 document.getElementById('mask').style.visibility = 'visible';
230 </script>
231 </body>
232 </html>