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> |