<!DOCTYPE html>
<html>
  <head>
    <style>
      body {
        color: white;
        background-color: black;
      }
    </style>
  </head>
  <body onload="main()">
    <div id="buttons"></div>
    <table>
      <tr>
        <td>Image</td>
        <td id="video_header"></td>
        <td>Absolute Diff</td>
        <td>Different Pixels</td>
      </tr>
      <tr>
        <td><img src="blackwhite.png"></div>
        <td><video autoplay></video></div>
        <td><canvas id="diff"></canvas></td>
        <td><canvas id="mask"></canvas></td>
      </tr>
    </div>

    <p id="result"></p>

    <script>
      function log(str) {
        document.getElementById('result').textContent = str;
        console.log(str);
      }

      function loadVideo(name) {
        var videoElem = document.querySelector('video');
        videoElem.src = 'blackwhite_' + name;

        document.getElementById('video_header').textContent = name;
        videoElem.addEventListener('ended', onVideoEnded);
      }

      function onVideoEnded(e) {
        document.title = verifyVideo() ? 'ENDED' : 'FAILED';
      }

      function onVideoError(e) {
        document.title = 'ERROR';
        document.getElementById('diff').style.visibility = 'hidden';
        document.getElementById('mask').style.visibility = 'hidden';
        log('Error playing video: ' + e.target.error.code + '.');
      }

      function main() {
        // Programatically create buttons for each clip for manual testing.
        var buttonsElem = document.getElementById('buttons');

        function createButton(name) {
          var buttonElem = document.createElement('button');
          buttonElem.textContent = name;
          buttonElem.addEventListener('click', function() {
            loadVideo(name);
          });
          buttonsElem.appendChild(buttonElem);
        }

        var VIDEOS = [
          'yuv420p.ogv',
          'yuv422p.ogv',
          'yuv444p.ogv',
          'yuv420p.webm',
          'yuv444p.webm',
          'yuv420p.mp4',
          'yuvj420p.mp4',
          'yuv422p.mp4',
          'yuv444p.mp4',
          'yuv420p.avi'
        ];

        for (var i = 0; i < VIDEOS.length; ++i) {
          createButton(VIDEOS[i]);
        }

        // Video event handlers.
        var videoElem = document.querySelector('video');
        videoElem.addEventListener('error', onVideoError);

        // Check if a query parameter was provided for automated tests.
        if (window.location.search.length > 1) {
          loadVideo(window.location.search.substr(1));
        } else {
          // If we're not an automated test, compute some pretty diffs.
          document.querySelector('video').addEventListener('ended',
                                                           computeDiffs);
        }
      }

      function getCanvasPixels(canvas) {
        try {
          return canvas.getContext('2d')
              .getImageData(0, 0, canvas.width, canvas.height)
              .data;
        } catch(e) {
          var message = 'ERROR: ' + e;
          if (e.name == 'SecurityError') {
            message += ' Couldn\'t get image pixels, try running with ' +
                       '--allow-file-access-from-files.';
          }
          log(message);
        }
      }

      function verifyVideo() {
        var videoElem = document.querySelector('video');
        var offscreen = document.createElement('canvas');
        offscreen.width = videoElem.videoWidth;
        offscreen.height = videoElem.videoHeight;
        offscreen.getContext('2d')
            .drawImage(videoElem, 0, 0, offscreen.width, offscreen.height);

        videoData = getCanvasPixels(offscreen);
        if (!videoData)
          return false;

        // Check the color of a givel pixel |x,y| in |imgData| against an
        // expected value, |expected|, with up to |allowedError| difference.
        function checkColor(imgData, x, y, stride, expected, allowedError) {
          for (var i = 0; i < 3; ++i) {
            if (Math.abs(imgData[(x + y * stride) * 4 + i] - expected) >
                allowedError) {
              return false;
            }
          }
          return true;
        }

        // Check one pixel in each quadrant (in the upper left, away from
        // boundaries and the text, to avoid compression artifacts).
        // Also allow a small error, for the same reason.

        // TODO(mtomasz): Once code.google.com/p/libyuv/issues/detail?id=324 is
        // fixed, the allowedError should be decreased to 1.
        var allowedError = 2;

        return checkColor(videoData, 30, 30, videoElem.videoWidth, 0xff,
                          allowedError) &&
               checkColor(videoData, 150, 30, videoElem.videoWidth, 0x00,
                          allowedError) &&
               checkColor(videoData, 30, 150, videoElem.videoWidth, 0x10,
                          allowedError) &&
               checkColor(videoData, 150, 150, videoElem.videoWidth, 0xef,
                          allowedError);
      }

      // Compute a standard diff image, plus a high-contrast mask that shows
      // each differing pixel more visibly.
      function computeDiffs() {
        var diffElem = document.getElementById('diff');
        var maskElem = document.getElementById('mask');
        var videoElem = document.querySelector('video');
        var imgElem = document.querySelector('img');

        var width = imgElem.width;
        var height = imgElem.height;

        if (videoElem.videoWidth != width || videoElem.videoHeight != height) {
          log('ERROR: video dimensions don\'t match reference image ' +
              'dimensions');
          return;
        }

        // Make an offscreen canvas to dump reference image pixels into.
        var offscreen = document.createElement('canvas');
        offscreen.width = width;
        offscreen.height = height;

        offscreen.getContext('2d').drawImage(imgElem, 0, 0, width, height);
        imgData = getCanvasPixels(offscreen);
        if (!imgData)
          return;

        // Scale and clear diff canvases.
        diffElem.width = maskElem.width = width;
        diffElem.height = maskElem.height = height;
        var diffCtx = diffElem.getContext('2d');
        var maskCtx = maskElem.getContext('2d');
        maskCtx.clearRect(0, 0, width, height);
        diffCtx.clearRect(0, 0, width, height);

        // Copy video pixels into diff.
        diffCtx.drawImage(videoElem, 0, 0, width, height);

        var diffIData = diffCtx.getImageData(0, 0, width, height);
        var diffData = diffIData.data;
        var maskIData = maskCtx.getImageData(0, 0, width, height);
        var maskData = maskIData.data;

        // Make diffs and collect stats.
        var meanSquaredError = 0;
        for (var i = 0; i < imgData.length; i += 4) {
          var difference = 0;
          for (var j = 0; j < 3; ++j) {
            diffData[i + j] = Math.abs(diffData[i + j] - imgData[i + j]);
            meanSquaredError += diffData[i + j] * diffData[i + j];
            if (diffData[i + j] != 0) {
              difference += diffData[i + j];
            }
          }
          if (difference > 0) {
            if (difference <= 3) {
              // If we're only off by a bit per channel or so, use darker red.
              maskData[i] = 128;
            } else {
              // Bright red to indicate a different pixel.
              maskData[i] = 255;
            }
            maskData[i+3] = 255;
          }
        }

        meanSquaredError /= width * height;
        log('Mean squared error: ' + meanSquaredError);
        diffCtx.putImageData(diffIData, 0, 0);
        maskCtx.putImageData(maskIData, 0, 0);
        document.getElementById('diff').style.visibility = 'visible';
        document.getElementById('mask').style.visibility = 'visible';
      }
    </script>
  </body>
</html>
