Home | History | Annotate | Download | only in video_WebRtcCamera
      1 <!DOCTYPE html>
      2 <html>
      3 <head><title>GetUserMedia test</title></head>
      4 <body>
      5   <script src="ssim.js"></script>
      6   <script src="blackframe.js"></script>
      7 <script>
      8 
      9 var resolutions = [[640, 480],
     10                    [1280, 720]];
     11 var isVideoInputFound = false;
     12 var results = {};
     13 var isTestDone = false;
     14 var durationMs = 20000;
     15 
     16 function testNextResolution() {
     17   var nextResolution = resolutions.shift();
     18   if (nextResolution == undefined) {
     19     reportTestDone();
     20     return;
     21   }
     22   var test = new CameraTest(nextResolution);
     23   test.start();
     24   setTimeout(
     25     function() {
     26       test.stop();
     27       testNextResolution();
     28     },
     29     durationMs);
     30 }
     31 
     32 function reportTestDone() {
     33   console.log('tests completed');
     34   isTestDone = true;
     35 }
     36 
     37 function getResults() {
     38   return results;
     39 }
     40 
     41 function resolutionMatchesIndependentOfRotation(aWidth, aHeight,
     42                                                 bWidth, bHeight) {
     43   return (aWidth === bWidth && aHeight === bHeight) ||
     44          (aWidth === bHeight && aHeight === bWidth);
     45 }
     46 
     47 function saveResult(resolution, verdict) {
     48   results[resolution] = verdict;
     49 }
     50 
     51 // Check if a video input exists
     52 function checkVideoInput() {
     53   navigator.mediaDevices.enumerateDevices()
     54       .then(findVideoInput)
     55       .catch(gotEnumerateDevicesError);
     56 }
     57 
     58 function findVideoInput(devices) {
     59   isVideoInputFound = devices.some(dev => dev.kind == 'videoinput');
     60 }
     61 
     62 function gotEnumerateDevicesError(error) {
     63   console.log('navigator.mediaDevices.enumerateDevices error: ', error);
     64   results.cameraErrors.push('EnumerateDevices error: ' + error.toString());
     65 }
     66 
     67 function CameraTest(resolution) {
     68   this.resolution = resolution;
     69   this.localVideo = document.createElement('video');
     70   this.localVideo.id = 'local-video';
     71   this.localVideo.autoplay = true;
     72   document.body.appendChild(this.localVideo);
     73   this.localStream = null;
     74   this.canvas = document.createElement('canvas');
     75   this.context = this.canvas.getContext('2d');
     76   this.previousFrame = [];
     77   this.identicalFrameSsimThreshold = 0.985;
     78   this.frameComparator = new Ssim();
     79   this.results = {cameraErrors: [],
     80       frameStats: {numBlackFrames: 0, numFrozenFrames:0, numFrames: 0}};
     81 
     82   this.constraints = {
     83     "audio": false,
     84     "video": {
     85       "mandatory" : {
     86           "maxWidth": this.resolution[0].toString(),
     87           "maxHeight": this.resolution[1].toString(),
     88           "minWidth": this.resolution[0].toString(),
     89           "minHeight": this.resolution[1].toString()
     90       },
     91     }
     92   };
     93 }
     94 
     95 CameraTest.prototype = {
     96 
     97   start: function() {
     98     this.localVideo.addEventListener('play',
     99         this.startCheckingVideoFrames.bind(this), false);
    100 
    101     navigator.mediaDevices.getUserMedia(this.constraints)
    102         .then(this.gotLocalStream.bind(this))
    103         .catch(this.gotUserMediaError.bind(this));
    104   },
    105 
    106   gotLocalStream: function(stream) {
    107     this.localStream = stream;
    108     this.localVideo.srcObject = stream;
    109   },
    110 
    111   gotUserMediaError: function(error) {
    112     console.log('navigator.mediaDevices.getUserMedia error: ', error);
    113     this.results.cameraErrors.push('GetUserMedia error: ' + error.toString());
    114   },
    115 
    116   startCheckingVideoFrames: function() {
    117     if (!resolutionMatchesIndependentOfRotation(this.localVideo.videoWidth,
    118         this.localVideo.videoHeight, this.resolution[0], this.resolution[1])) {
    119       this.results.cameraErrors.push('resolution', 'Got ' +
    120           this.localVideo.videoWidth + 'x' + this.localVideo.videoHeight +
    121           ', expected ' + this.resolution[0] + 'x' + this.resolution[1] +
    122           ' or rotated version thereof');
    123     }
    124 
    125     this.videoFrameChecker = setInterval(this.checkVideoFrame.bind(this), 20);
    126   },
    127 
    128   checkVideoFrame: function() {
    129     this.context.drawImage(this.localVideo, 0, 0, this.canvas.width,
    130       this.canvas.height);
    131     var imageData = this.context.getImageData(0, 0, this.canvas.width,
    132       this.canvas.height);
    133 
    134     if (isBlackFrame(imageData.data, imageData.data.length)) {
    135       this.results.frameStats.numBlackFrames++;
    136     }
    137 
    138     if (this.frameComparator.calculate(this.previousFrame, imageData.data) >
    139       this.identicalFrameSsimThreshold) {
    140       this.results.frameStats.numFrozenFrames++;
    141     }
    142 
    143     this.previousFrame = imageData.data;
    144     this.results.frameStats.numFrames++;
    145   },
    146 
    147   stop: function() {
    148     clearInterval(this.videoFrameChecker);
    149     saveResult(this.resolution, this.results);
    150     this.localStream.getTracks().forEach(function(track) {
    151       track.stop();
    152     });
    153     document.body.removeChild(this.localVideo);
    154   },
    155 }
    156 
    157 window.onload = testNextResolution;
    158 window.onerror = function (message, filename, lineno, colno, error) {
    159   console.log("Something went wrong, here is the stack trace --> %s",
    160       error.stack);
    161 };
    162 </script>
    163 </body>
    164 </html>
    165