• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9var resolutions = [[640, 480],
10                   [1280, 720]];
11var isVideoInputFound = false;
12var results = {};
13var isTestDone = false;
14var durationMs = 20000;
15
16function 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
32function reportTestDone() {
33  console.log('tests completed');
34  isTestDone = true;
35}
36
37function getResults() {
38  return results;
39}
40
41function resolutionMatchesIndependentOfRotation(aWidth, aHeight,
42                                                bWidth, bHeight) {
43  return (aWidth === bWidth && aHeight === bHeight) ||
44         (aWidth === bHeight && aHeight === bWidth);
45}
46
47function saveResult(resolution, verdict) {
48  results[resolution] = verdict;
49}
50
51// Check if a video input exists
52function checkVideoInput() {
53  navigator.mediaDevices.enumerateDevices()
54      .then(findVideoInput)
55      .catch(gotEnumerateDevicesError);
56}
57
58function findVideoInput(devices) {
59  isVideoInputFound = devices.some(dev => dev.kind == 'videoinput');
60}
61
62function gotEnumerateDevicesError(error) {
63  console.log('navigator.mediaDevices.enumerateDevices error: ', error);
64  results.cameraErrors.push('EnumerateDevices error: ' + error.toString());
65}
66
67function 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
95CameraTest.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
157window.onload = testNextResolution;
158window.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