/** * Copyright (c) 2012 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ // This file requires the functions defined in test_functions.js. var gFingerprints = []; var gDetectorInterval = null; // Public interface. /** * Starts capturing frames from a video tag. The algorithm will fingerprint a * a frame every now and then. After calling this function and running for a * while (at least 200 ms) you will be able to call isVideoPlaying to see if * we detected any video. * * @param {string} videoElementId The video element to analyze. * @param {int} width The video element's width. * @param {int} width The video element's height. * * @return {string} Returns ok-started to the test. */ // function startDetection(videoElementId, width, height) { var video = document.getElementById(videoElementId); if (!video) throw failTest('Could not find video element with id ' + videoElementId); if (gDetectorInterval) throw failTest('Detector is already running.'); var NUM_FINGERPRINTS_TO_SAVE = 5; var canvas = document.createElement('canvas'); canvas.style.display = 'none'; gFingerprints = []; gDetectorInterval = setInterval(function() { var context = canvas.getContext('2d'); if (video.videoWidth == 0) return; // The video element isn't playing anything. captureFrame_(video, context, width, height); gFingerprints.push(fingerprint_(context, width, height)); if (gFingerprints.length > NUM_FINGERPRINTS_TO_SAVE) { gFingerprints.shift(); } }, 100); returnToTest('ok-started'); } /** * Checks if we have detected any video so far. * * @return {string} video-playing if we detected video, otherwise * video-not-playing. */ function isVideoPlaying() { // Video is considered to be playing if at least one finger print has changed // since the oldest fingerprint. Even small blips in the pixel data will cause // this check to pass. We only check for rough equality though to account for // rounding errors. try { if (gFingerprints.length > 1) { if (!allElementsRoughlyEqualTo_(gFingerprints, gFingerprints[0])) { clearInterval(gDetectorInterval); gDetectorInterval = null; returnToTest('video-playing'); return; } } } catch (exception) { throw failTest('Failed to detect video: ' + exception.message); } returnToTest('video-not-playing'); } /** * Queries for the stream size (not necessarily the size at which the video tag * is rendered). * * @param videoElementId The video element to check. * @return {string} ok-x, e.g. ok-640x480 for VGA. */ function getStreamSize(videoElementId) { var video = document.getElementById(videoElementId); if (!video) throw failTest('Could not find video element with id ' + videoElementId); returnToTest('ok-' + video.videoWidth + 'x' + video.videoHeight); } // Internals. /** @private */ function allElementsRoughlyEqualTo_(elements, element_to_compare) { if (elements.length == 0) return false; var PIXEL_DIFF_TOLERANCE = 100; for (var i = 0; i < elements.length; i++) { if (Math.abs(elements[i] - element_to_compare) > PIXEL_DIFF_TOLERANCE) { return false; } } return true; } /** @private */ function captureFrame_(video, canvasContext, width, height) { canvasContext.drawImage(video, 0, 0, width, height); } /** @private */ function fingerprint_(canvasContext, width, height) { var imageData = canvasContext.getImageData(0, 0, width, height); var pixels = imageData.data; var fingerprint = 0; for (var i = 0; i < pixels.length; i++) { fingerprint += pixels[i]; } return fingerprint; }