Bug 1449832 - P2 - screen share scale mochitest draft
authorNico Grunbaum <na-g@nostrum.com>
Thu, 05 Apr 2018 19:23:26 -0700
changeset 781392 f3f70536c5c710365c40387ab7243c365ca24098
parent 781391 105e361d465933fa863a5396eb90cd495175f32e
push id106290
push userbmo:na-g@nostrum.com
push dateThu, 12 Apr 2018 21:57:43 +0000
bugs1449832
milestone61.0a1
Bug 1449832 - P2 - screen share scale mochitest MozReview-Commit-ID: GbEbdUDsR8T
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/test_getUserMedia_bug1449832.html
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -61,16 +61,18 @@ skip-if = os == 'mac' || os == 'win' || 
 skip-if = toolkit == 'android' || (webrender && toolkit == 'windows') # no screenshare on android; bug 1405083 permafail on webrender
 [test_getUserMedia_basicTabshare.html]
 skip-if = toolkit == 'android' # no windowshare on android
 [test_getUserMedia_basicWindowshare.html]
 skip-if = toolkit == 'android' # no windowshare on android
 [test_getUserMedia_basicVideoAudio.html]
 [test_getUserMedia_bug1223696.html]
 [test_getUserMedia_constraints.html]
+[test_getUserMedia_bug1449832.html]
+skip-if = toolkit == 'android' || (webrender && toolkit == 'windows') # no screenshare on android; bug 1405083 permafail on webrender
 [test_getUserMedia_callbacks.html]
 [test_getUserMedia_cubebDisabled.html]
 [test_getUserMedia_cubebDisabledFakeStreams.html]
 [test_getUserMedia_GC_MediaStream.html]
 [test_getUserMedia_getTrackById.html]
 [test_getUserMedia_gumWithinGum.html]
 [test_getUserMedia_loadedmetadata.html]
 [test_getUserMedia_mediaElementCapture_audio.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_bug1449832.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script src="mediaStreamPlayback.js"></script>
+  <script src="constraints.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+createHTML({ title: "Test getUserMedia for screen, window, and application sharing scales not crops when given a single dimension constraint", bug: "1449832" });
+
+let calcGCD = (a, b) => {
+  if (a == b) {
+    return a;
+  }
+  if (a > b) {
+    return calcGCD(a - b, b);
+  }
+  return calcGCD(a, b - a);
+};
+
+runTest(async () => {
+  const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
+  if (IsMacOSX10_6orOlder() || isWinXP) {
+      ok(true, "Screensharing disabled for OSX10.6 and WinXP");
+      return;
+  }
+  let view = createMediaElement("video", "view");
+  let constraints = { video: {mediaSource: "screen" } };
+  info(`Non-dimensional constraints ${JSON.stringify(constraints)}`);
+  view.srcObject = await getUserMedia(constraints);
+  info("Waiting for stream to be ready.");
+  await haveEvent(view, 'loadedmetadata');
+  // Reference width and height
+  let [width, height] = [view.videoWidth, view.videoHeight];
+  let gcd = calcGCD(width, height);
+  // Smallest natural width in aspect ratio
+  let minRatioWidth = width / gcd;
+  // Smallest natural height in aspect ratio
+  let minRatioHeight = height / gcd;
+  let initDimentions = JSON.stringify({
+      width: width,
+      height: height,
+      ratio:`${minRatioWidth}:${minRatioHeight}`,
+  });
+  info(`Unscaled dimensions ${initDimentions}`);
+  if (width < 128 || height < 128) {
+    ok(false, `Screen size is large enough for test. Dimensions are ` +
+       `${initDimentions}; at least 128 x 128 is required.`);
+    return;
+  }
+  view.srcObject.getTracks().forEach(track => track.stop());
+  view.srcObject = null;
+
+  let testScaling = async (vidConstraints, expectedWidth, expectedHeight) => {
+    let constraints = {
+      video: Object.assign({mediaSource: "screen"}, vidConstraints),
+    };
+    let constr =  JSON.stringify(constraints);
+    info(`Test constraints: ${constr}`);
+    view.srcObject = await getUserMedia(constraints);
+    info("Waiting for stream to be ready.");
+    await haveEvent(view, 'loadedmetadata');
+    info(`New dimensions: ${JSON.stringify({width: view.videoWidth,
+                                           height: view.videoHeight})}`);
+    is(view.videoHeight, expectedHeight, `Height is expected for ${constr}.`);
+    is(view.videoWidth, expectedWidth, `Width is expected for ${constr}.`);
+    view.srcObject.getTracks().forEach(track => track.stop());
+    view.srcObject = null;
+  };
+  // test 1:1
+  await testScaling({width: width, height: height}, width, height);
+  // test 1x?
+  // The resulting resolution should be the minimum resolution that
+  // perfectly fits the aspect ratio.
+  await testScaling({width: 1}, minRatioWidth, minRatioHeight);
+  await testScaling({height: 1}, minRatioWidth, minRatioHeight);
+  // The resulting resolution should clamp back down to the minimum resolution
+  await testScaling({width: minRatioWidth + 1}, minRatioWidth, minRatioHeight);
+  await testScaling({height: minRatioHeight + 1}, minRatioWidth, minRatioHeight);
+  // Again, the resulting resolution should clamp back down to the minimum resolution
+  await testScaling({width: minRatioWidth * 2 - 1}, minRatioWidth, minRatioHeight);
+  await testScaling({height: minRatioHeight * 2 - 1}, minRatioWidth, minRatioHeight);
+  // test 0x?
+  await testScaling({width: 0}, width, height);
+  await testScaling({height: 0}, width, height);
+  // test 65535, MAX(u16)
+  // don't scale beyond input height
+  await testScaling({width: 65535}, width, height);
+  await testScaling({height: 65535}, width, height);
+  // test 65536, MAX(u16) + 1
+  await testScaling({width: 65536}, width, height);
+  await testScaling({height: 65536}, width, height);
+  for (let dimensionDivisor of [2, 3, 4, 5, 6, 7]) {
+    let resultWidth = Math.floor(width / dimensionDivisor);
+    resultWidth = resultWidth - (resultWidth % minRatioWidth);
+    resultWidth = resultWidth < minRatioWidth ? minRatioWidth : resultWidth;
+    let resultHeight = Math.floor(height / dimensionDivisor);
+    resultHeight = resultHeight - (resultHeight % minRatioHeight);
+    resultHeight = resultHeight < minRatioHeight ? minRatioHeight : resultHeight
+    await testScaling({width: resultWidth}, resultWidth, resultHeight);
+    await testScaling({height: resultHeight}, resultWidth, resultHeight);
+  }
+});
+</script>
+</pre>
+</body>
+</html>
\ No newline at end of file