Chromium Code Reviews| Index: chrome/test/data/media/canvas_capture_test.html |
| diff --git a/chrome/test/data/media/canvas_capture_test.html b/chrome/test/data/media/canvas_capture_test.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6f1dd42a329f6445b24883c114cad48c04144a7e |
| --- /dev/null |
| +++ b/chrome/test/data/media/canvas_capture_test.html |
| @@ -0,0 +1,140 @@ |
| +<!DOCTYPE html> |
| +<html> |
| +<head> |
| +<title>Canvas Capture FPS Test</title> |
| +</head> |
| +<body> |
| + <div> Canvas capture FPS test.</div> |
| + <video id='local_video' muted='true' hidden loop autoplay> |
|
phoglund_chromium
2016/02/12 08:38:53
In javascript, IDs should be on the form local-vid
cpaulin (no longer in chrome)
2016/02/12 20:14:32
Done.
|
| + <source src='bear-640x360.webm' type='video/webm'> |
| + </video> |
| + <br></br> |
| + <label>Canvas</label> |
| + <canvas id='canvas' width=640 height=360></canvas> |
| + <br></br> |
| + <label>Captured canvas stream</label> |
| + <video id='captured_video' autoplay></video> |
| +<script> |
| + |
| +'use strict'; |
| + |
| +var DEFAULT_FRAME_RATE = 10; |
| +var ERROR_RATE = 15 / 100; |
|
phoglund_chromium
2016/02/12 08:38:53
TOLERANCE_PERCENT would be a better name for this
cpaulin (no longer in chrome)
2016/02/12 20:14:32
Done.
|
| + |
| +// Define video event listener when document is loaded. |
| +document.addEventListener('DOMContentLoaded', function() { |
|
phoglund_chromium
2016/02/12 08:38:53
It's more common to use document.onload for this (
cpaulin (no longer in chrome)
2016/02/12 20:14:32
I am using window.onload now
Done.
|
| + var video = document.getElementById('local_video'); |
| + var canvas = document.getElementById('canvas'); |
| + var context = canvas.getContext('2d'); |
| + video.addEventListener('play', function() { |
| + draw(this, context, canvas.clientWidth, canvas.clientHeight); |
| + }, false); |
| + }, false); |
| + |
| +// This function draws the video frame on the canvas. |
| +function draw(video, context, width, height) { |
| + if (video.paused || video.ended) return false; |
| + context.drawImage(video, 0, 0, width, height); |
| + setTimeout(draw, 20, video, context, width, height); |
|
phoglund_chromium
2016/02/12 08:38:53
Is it important for the fps computations that the
cpaulin (no longer in chrome)
2016/02/12 20:14:32
Thanks for the tip, I am using requestAnimationFra
|
| +} |
| + |
| +// Test class that measures the frame rate of a stream originated from |
| +// canvas capture. |
| +function CanvasFpsTest() { |
| + this.theCanvasStream = null; |
| + this.decodedFrames = 0; |
| + this.droppedFrames = 0; |
| + this.decodedFPS = []; |
| + this.droppedFPS = []; |
| + this.startTime = {}; |
| + this.interval = {}; |
| + this.targetFPS = 0; |
| +} |
| + |
| +// This function starts the canvas capture of the local video stream. |
| +CanvasFpsTest.prototype.startCanvasCapture = function(frameRate) { |
| + var test = this; |
| + test.targetFPS = frameRate ? frameRate : DEFAULT_FRAME_RATE; |
| + test.theCanvasStream = document.getElementById('canvas').captureStream( |
| + test.targetFPS); |
| + var testVideo = document.getElementById('captured_video'); |
| + testVideo.addEventListener('play', function(event) { |
| + test.startTime = new Date().getTime(); |
| + test.interval = setInterval(test.calculateStats.bind(test, testVideo), |
| + 1000); |
| + }); |
| + testVideo.src = URL.createObjectURL(test.theCanvasStream); |
| +}; |
| + |
| +// This functi0on calculates the FPS for decoded frames and dropped frames. |
|
phoglund_chromium
2016/02/12 08:38:53
Nit: function
cpaulin (no longer in chrome)
2016/02/12 20:14:32
Done.
|
| +CanvasFpsTest.prototype.calculateStats = function(video) { |
| + // We calculate stats on 6 seconds worth of video, that should be |
| + // reasonable. |
| + if (this.decodedFPS.length == 6) { |
| + clearInterval(this.interval); |
| + return this.validateResults(); |
| + } |
| + if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA || |
| + video.paused || video.ended) |
| + return; |
| + var currentTime = new Date().getTime(); |
| + var deltaTime = (currentTime - this.startTime) / 1000; |
| + |
| + this.startTime = currentTime; |
| + |
| + // Calculate decoded frames per second. |
| + var fps = (video.webkitDecodedFrameCount - this.decodedFrames) / deltaTime; |
| + this.decodedFrames = video.webkitDecodedFrameCount; |
| + this.decodedFPS.push(fps); |
| + |
| + // Calculate dropped frames per second. |
| + fps = (video.webkitDroppedFrameCount - this.droppedFrames) / deltaTime; |
| + this.droppedFrames = video.webkitDroppedFrameCount; |
| + this.droppedFPS.push(fps); |
| +}; |
| + |
| +// This function validates the frameRate against accepted error tolerance. |
| +CanvasFpsTest.prototype.validateResults = function() { |
| + // Pop out the first value as it could be a bit off. |
| + this.decodedFPS.shift; |
| + this.droppedFPS.shift; |
| + var averageFPS = average(this.decodedFPS); |
| + var averageDroppedFPS = average(this.droppedFPS); |
| + var errorFPS = Math.abs(averageFPS - this.targetFPS) / this.targetFPS; |
| + if (errorFPS > ERROR_RATE) { |
| + reportResult('FAIL', 'ERROR: FPS value error beyond acceptable value'); |
|
phoglund_chromium
2016/02/12 08:38:53
Simplify this. It's better to just return the seco
cpaulin (no longer in chrome)
2016/02/12 20:14:32
That's true, I fixed it.
Done.
|
| + } else if (averageDroppedFPS != 0) { |
| + console.log('ERROR: Some frames where dropped'); |
| + reportResult('FAIL', 'ERROR: Some frames where dropped'); |
| + } else { |
| + reportResult('OK', 'Test Passed'); |
| + } |
| +}; |
| + |
| +// This function calculates average of array values. |
| +function average(array) { |
| + var count = array.length; |
| + var total = 0; |
| + for (var i = 0; i < count; i++) { |
| + total += parseInt(array[i]); |
| + } |
| + return Math.floor(total / count); |
| +} |
| + |
| +// This function logs and reports result to Test Environment. |
| +function reportResult(verdict, message) { |
| + console.log(verdict, message); |
| + if (!window.domAutomationController) |
| + throw 'Expected to run in an automated context.'; |
| + window.domAutomationController.send(verdict); |
| +} |
| + |
| +// Tests that canvas capture will approximately honor the given frame rate. |
| +function testFrameRateOfCanvasCapture(frameRate) { |
| + var fpsTest = new CanvasFpsTest(); |
| + fpsTest.startCanvasCapture(frameRate); |
| +} |
| + |
| +</script> |
| +</body> |
| +</html> |