Firefox getUserMedia + 1080p issue reproduction

1080p cam request results in 720p stream at best or returns OverconstrainedError

by Sergii Lavrin

HTML

<label class="select">
  Video Input
  <select id="videoSource"></select>
</label>

<br>

<label>
  <input id="strictCheckbox" type="checkbox" />
  Strict
</label>

<pre id="logs"></pre>

<video id="video" muted autoplay />

JavaScript

const videoElement = document.querySelector("#video");
const videoInputSelect = document.querySelector("select#videoSource");
const strictCheckbox = document.querySelector("#strictCheckbox");
const logsElement = document.querySelector("#logs");
const selectors = [videoInputSelect];
const FULL_HD_HEIGHT = 1080;

function getDevices() {
  return navigator.mediaDevices.enumerateDevices().then(gotDevices);
}

function gotDevices(deviceInfos) {
  // Handles being called several times to update labels. Preserve values.
  const values = selectors.map((select) => select.value);
  selectors.forEach((select) => {
    while (select.firstChild) {
      select.removeChild(select.firstChild);
    }
  });

  for (let i = 0; i !== deviceInfos.length; ++i) {
    const deviceInfo = deviceInfos[i];
    const option = document.createElement("option");
    option.value = deviceInfo.deviceId;
    if (deviceInfo.kind === "videoinput") {
      option.text = deviceInfo.label || `input ${videoInputSelect.length + 1}`;
      videoInputSelect.appendChild(option);
    } else {
      console.log("Some other kind of source/device: ", deviceInfo);
    }
  }
  selectors.forEach((select, selectorIndex) => {
    if (
      Array.prototype.slice
        .call(select.childNodes)
        .some((n) => n.value === values[selectorIndex])
    ) {
      select.value = values[selectorIndex];
    }
  });
}

function log(data) {
  if (data instanceof Error) {
    logsElement.innerText = `${data.name}: ${data.message} (constraint: ${data.constraint})`;
    return;
  }
  logsElement.innerText = JSON.stringify(data, null, 2);
}

function start() {
  videoElement.srcObject = null;

  const videoSource = videoInputSelect.value;
  const constraints = {
    video: {
      deviceId: videoSource ? { exact: videoSource } : undefined,
      height: strictCheckbox.checked
        ? { exact: FULL_HD_HEIGHT }
        : FULL_HD_HEIGHT,
    },
  };

  window.navigator.mediaDevices
    .getUserMedia(constraints)
   ...