Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <!DOCTYPE html> | |
| 2 <html> | |
| 3 <head> | |
| 4 <title>Canvas Capture FPS Test</title> | |
| 5 </head> | |
| 6 <body> | |
| 7 <div> Canvas capture FPS test.</div> | |
| 8 <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.
| |
| 9 <source src='bear-640x360.webm' type='video/webm'> | |
| 10 </video> | |
| 11 <br></br> | |
| 12 <label>Canvas</label> | |
| 13 <canvas id='canvas' width=640 height=360></canvas> | |
| 14 <br></br> | |
| 15 <label>Captured canvas stream</label> | |
| 16 <video id='captured_video' autoplay></video> | |
| 17 <script> | |
| 18 | |
| 19 'use strict'; | |
| 20 | |
| 21 var DEFAULT_FRAME_RATE = 10; | |
| 22 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.
| |
| 23 | |
| 24 // Define video event listener when document is loaded. | |
| 25 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.
| |
| 26 var video = document.getElementById('local_video'); | |
| 27 var canvas = document.getElementById('canvas'); | |
| 28 var context = canvas.getContext('2d'); | |
| 29 video.addEventListener('play', function() { | |
| 30 draw(this, context, canvas.clientWidth, canvas.clientHeight); | |
| 31 }, false); | |
| 32 }, false); | |
| 33 | |
| 34 // This function draws the video frame on the canvas. | |
| 35 function draw(video, context, width, height) { | |
| 36 if (video.paused || video.ended) return false; | |
| 37 context.drawImage(video, 0, 0, width, height); | |
| 38 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
| |
| 39 } | |
| 40 | |
| 41 // Test class that measures the frame rate of a stream originated from | |
| 42 // canvas capture. | |
| 43 function CanvasFpsTest() { | |
| 44 this.theCanvasStream = null; | |
| 45 this.decodedFrames = 0; | |
| 46 this.droppedFrames = 0; | |
| 47 this.decodedFPS = []; | |
| 48 this.droppedFPS = []; | |
| 49 this.startTime = {}; | |
| 50 this.interval = {}; | |
| 51 this.targetFPS = 0; | |
| 52 } | |
| 53 | |
| 54 // This function starts the canvas capture of the local video stream. | |
| 55 CanvasFpsTest.prototype.startCanvasCapture = function(frameRate) { | |
| 56 var test = this; | |
| 57 test.targetFPS = frameRate ? frameRate : DEFAULT_FRAME_RATE; | |
| 58 test.theCanvasStream = document.getElementById('canvas').captureStream( | |
| 59 test.targetFPS); | |
| 60 var testVideo = document.getElementById('captured_video'); | |
| 61 testVideo.addEventListener('play', function(event) { | |
| 62 test.startTime = new Date().getTime(); | |
| 63 test.interval = setInterval(test.calculateStats.bind(test, testVideo), | |
| 64 1000); | |
| 65 }); | |
| 66 testVideo.src = URL.createObjectURL(test.theCanvasStream); | |
| 67 }; | |
| 68 | |
| 69 // 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.
| |
| 70 CanvasFpsTest.prototype.calculateStats = function(video) { | |
| 71 // We calculate stats on 6 seconds worth of video, that should be | |
| 72 // reasonable. | |
| 73 if (this.decodedFPS.length == 6) { | |
| 74 clearInterval(this.interval); | |
| 75 return this.validateResults(); | |
| 76 } | |
| 77 if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA || | |
| 78 video.paused || video.ended) | |
| 79 return; | |
| 80 var currentTime = new Date().getTime(); | |
| 81 var deltaTime = (currentTime - this.startTime) / 1000; | |
| 82 | |
| 83 this.startTime = currentTime; | |
| 84 | |
| 85 // Calculate decoded frames per second. | |
| 86 var fps = (video.webkitDecodedFrameCount - this.decodedFrames) / deltaTime; | |
| 87 this.decodedFrames = video.webkitDecodedFrameCount; | |
| 88 this.decodedFPS.push(fps); | |
| 89 | |
| 90 // Calculate dropped frames per second. | |
| 91 fps = (video.webkitDroppedFrameCount - this.droppedFrames) / deltaTime; | |
| 92 this.droppedFrames = video.webkitDroppedFrameCount; | |
| 93 this.droppedFPS.push(fps); | |
| 94 }; | |
| 95 | |
| 96 // This function validates the frameRate against accepted error tolerance. | |
| 97 CanvasFpsTest.prototype.validateResults = function() { | |
| 98 // Pop out the first value as it could be a bit off. | |
| 99 this.decodedFPS.shift; | |
| 100 this.droppedFPS.shift; | |
| 101 var averageFPS = average(this.decodedFPS); | |
| 102 var averageDroppedFPS = average(this.droppedFPS); | |
| 103 var errorFPS = Math.abs(averageFPS - this.targetFPS) / this.targetFPS; | |
| 104 if (errorFPS > ERROR_RATE) { | |
| 105 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.
| |
| 106 } else if (averageDroppedFPS != 0) { | |
| 107 console.log('ERROR: Some frames where dropped'); | |
| 108 reportResult('FAIL', 'ERROR: Some frames where dropped'); | |
| 109 } else { | |
| 110 reportResult('OK', 'Test Passed'); | |
| 111 } | |
| 112 }; | |
| 113 | |
| 114 // This function calculates average of array values. | |
| 115 function average(array) { | |
| 116 var count = array.length; | |
| 117 var total = 0; | |
| 118 for (var i = 0; i < count; i++) { | |
| 119 total += parseInt(array[i]); | |
| 120 } | |
| 121 return Math.floor(total / count); | |
| 122 } | |
| 123 | |
| 124 // This function logs and reports result to Test Environment. | |
| 125 function reportResult(verdict, message) { | |
| 126 console.log(verdict, message); | |
| 127 if (!window.domAutomationController) | |
| 128 throw 'Expected to run in an automated context.'; | |
| 129 window.domAutomationController.send(verdict); | |
| 130 } | |
| 131 | |
| 132 // Tests that canvas capture will approximately honor the given frame rate. | |
| 133 function testFrameRateOfCanvasCapture(frameRate) { | |
| 134 var fpsTest = new CanvasFpsTest(); | |
| 135 fpsTest.startCanvasCapture(frameRate); | |
| 136 } | |
| 137 | |
| 138 </script> | |
| 139 </body> | |
| 140 </html> | |
| OLD | NEW |