| <!DOCTYPE html> |
| <html> |
| <head><title>GetUserMedia test</title></head> |
| <body> |
| <script src="ssim.js"></script> |
| <script src="blackframe.js"></script> |
| <script> |
| |
| var resolutions = [[640, 480], |
| [1280, 720]]; |
| var results = {}; |
| var isTestDone = 0; |
| var durationMs = 20000; |
| |
| function testNextResolution() { |
| var nextResolution = resolutions.shift(); |
| if (nextResolution == undefined) { |
| reportTestDone(); |
| return; |
| } |
| var test = new CameraTest(nextResolution); |
| test.start(); |
| setTimeout( |
| function() { |
| test.stop(); |
| testNextResolution(); |
| }, |
| durationMs); |
| } |
| |
| function reportTestDone() { |
| console.log('tests completed'); |
| isTestDone = 1; |
| } |
| |
| function getResults() { |
| return results; |
| } |
| |
| function resolutionMatchesIndependentOfRotation(aWidth, aHeight, |
| bWidth, bHeight) { |
| return (aWidth === bWidth && aHeight === bHeight) || |
| (aWidth === bHeight && aHeight === bWidth); |
| } |
| |
| function saveResult(resolution, verdict) { |
| results[resolution] = verdict; |
| } |
| |
| function CameraTest(resolution) { |
| this.resolution = resolution; |
| this.localVideo = document.createElement('video'); |
| this.localVideo.id = 'local-video'; |
| this.localVideo.autoplay = true; |
| document.body.appendChild(this.localVideo); |
| this.localStream = null; |
| this.canvas = document.createElement('canvas'); |
| this.context = this.canvas.getContext('2d'); |
| this.previousFrame = []; |
| this.identicalFrameSsimThreshold = 0.985; |
| this.frameComparator = new Ssim(); |
| this.results = {cameraErrors: [], |
| frameStats: {numBlackFrames: 0, numFrozenFrames:0, numFrames: 0}}; |
| |
| this.constraints = { |
| "audio": false, |
| "video": { |
| "mandatory" : { |
| "maxWidth": this.resolution[0].toString(), |
| "maxHeight": this.resolution[1].toString(), |
| "minWidth": this.resolution[0].toString(), |
| "minHeight": this.resolution[1].toString() |
| }, |
| } |
| }; |
| } |
| |
| CameraTest.prototype = { |
| |
| start: function() { |
| this.localVideo.addEventListener('play', |
| this.startCheckingVideoFrames.bind(this), false); |
| navigator.getUserMedia = navigator.getUserMedia || |
| navigator.webkitGetUserMedia || navigator.mozGetUserMedia; |
| |
| navigator.getUserMedia(this.constraints, this.gotLocalStream.bind(this), |
| this.gotUserMediaError.bind(this)); |
| }, |
| |
| gotLocalStream: function(stream) { |
| this.localStream = stream; |
| this.localVideo.src = window.URL.createObjectURL(stream); |
| }, |
| |
| gotUserMediaError: function(error) { |
| console.log('navigator.getUserMedia error: ', error); |
| this.results.cameraErrors.push('GetUserMedia error: ' + error.toString()); |
| }, |
| |
| startCheckingVideoFrames: function() { |
| if (!resolutionMatchesIndependentOfRotation(this.localVideo.videoWidth, |
| this.localVideo.videoHeight, this.resolution[0], this.resolution[1])) { |
| this.results.cameraErrors.push('resolution', 'Got ' + |
| this.localVideo.videoWidth + 'x' + this.localVideo.videoHeight + |
| ', expected ' + this.resolution[0] + 'x' + this.resolution[1] + |
| ' or rotated version thereof'); |
| } |
| |
| this.videoFrameChecker = setInterval(this.checkVideoFrame.bind(this), 20); |
| }, |
| |
| checkVideoFrame: function() { |
| this.context.drawImage(this.localVideo, 0, 0, this.canvas.width, |
| this.canvas.height); |
| var imageData = this.context.getImageData(0, 0, this.canvas.width, |
| this.canvas.height); |
| |
| if (isBlackFrame(imageData.data, imageData.data.length)) { |
| this.results.frameStats.numBlackFrames++; |
| } |
| |
| if (this.frameComparator.calculate(this.previousFrame, imageData.data) > |
| this.identicalFrameSsimThreshold) { |
| this.results.frameStats.numFrozenFrames++; |
| } |
| |
| this.previousFrame = imageData.data; |
| this.results.frameStats.numFrames++; |
| }, |
| |
| stop: function() { |
| clearInterval(this.videoFrameChecker); |
| saveResult(this.resolution, this.results); |
| this.localStream.getTracks().forEach(function(track) { |
| track.stop(); |
| }); |
| document.body.removeChild(this.localVideo); |
| }, |
| } |
| |
| window.onload = testNextResolution; |
| window.onerror = function (message, filename, lineno, colno, error) { |
| console.log("Something went wrong, here is the stack trace --> %s", |
| error.stack); |
| }; |
| </script> |
| </body> |
| </html> |