<!DOCTYPE html>
<meta charset="utf-8">
<title>RTCRtpEncodingParameters scaleResolutionDownTo attribute</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../webrtc/simulcast/simulcast.js"></script>
<script src="../webrtc/third_party/sdp/sdp.js"></script>
<script>
'use strict';

// Creates a track that can be resized with `track.resize(w,h)`.
function createResizableTrack(width, height) {
  // Draw to a canvas with a 30 fps interval.
  const canvas = Object.assign(
      document.createElement('canvas'), {width, height});
  const ctx = canvas.getContext('2d');
  ctx.fillStyle = 'rgb(255,0,0)';
  const interval = setInterval(() => {
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  }, 1000 / 30);
  // Capture the canvas and add/modify reize() and stop() methods.
  const stream = canvas.captureStream();
  const [track] = stream.getTracks();
  track.resize = (w, h) => {
    canvas.width = w;
    canvas.height = h;
  };
  const nativeStop = track.stop;
  track.stop = () => {
    clearInterval(interval);
    nativeStop.apply(track);
  };
  return track;
}

async function getLastEncodedResolution(pc, rid = null) {
  const report = await pc.getStats();
  for (const stats of report.values()) {
    if (stats.type != 'outbound-rtp') {
      continue;
    }
    if (rid && stats.rid != rid) {
      continue;
    }
    if (!stats.frameWidth || !stats.frameWidth) {
      // The resolution is missing until the first frame has been encoded.
      break;
    }
    return { width: stats.frameWidth, height: stats.frameHeight };
  }
  return { width: null, height: null };
}

async function waitForFrameWithResolution(t, pc, width, height, rid = null) {
  let resolution;
  do {
    resolution = await getLastEncodedResolution(pc, rid);
    await new Promise(r => t.step_timeout(r, 50));
  } while (resolution.width != width || resolution.height != height);
}

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  assert_throws_dom('OperationError', () => {
    pc.addTransceiver(track, {
          sendEncodings:[{
              scaleResolutionDownTo: { maxWidth: 0, maxHeight: 0 }
          }]
        });
  });
}, `addTransceiver: Invalid scaling throws`);

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc.addTransceiver(track, {sendEncodings:[{}]});

  const params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 0, maxHeight: 0 };
  const p = sender.setParameters(params);

  promise_rejects_dom(t, 'InvalidModificationError', p);
}, `setParameters: Invalid scaling throws`);

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  assert_throws_dom('OperationError', () => {
    pc.addTransceiver(track, {
          sendEncodings:[{
              scaleResolutionDownTo: undefined,
          }, {
              scaleResolutionDownTo: { maxWidth: 120, maxHeight: 60 }
          }]
        });
  });
}, `addTransceiver: Specifying scaling on a subset of active encodings throws`);

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  pc.addTransceiver(track, {
        sendEncodings:[{
            active: true,
            scaleResolutionDownTo: { maxWidth: 120, maxHeight: 60 },
        }, {
            active: false,
            scaleResolutionDownTo: undefined
        }]
      });
}, `addTransceiver: Specifying scaling on inactive encodings is optional`);

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc.addTransceiver(track, {sendEncodings:[{},{}]});

  const params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = undefined;
  params.encodings[1].scaleResolutionDownTo = { maxWidth: 120, maxHeight: 60 };
  const p = sender.setParameters(params);

  promise_rejects_dom(t, 'InvalidModificationError', p);
}, `setParameters: Specifying scaling on a subset of active encodings throws`);

promise_test(async t => {
  const pc = new RTCPeerConnection();
  t.add_cleanup(() => pc.close());

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc.addTransceiver(track, {sendEncodings:[{},{}]});

  const params = sender.getParameters();
  params.encodings[0].active = true;
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 120, maxHeight: 60 };
  params.encodings[1].active = false;
  params.encodings[1].scaleResolutionDownTo = undefined;
  await sender.setParameters(params);
}, `setParameters: Specifying scaling on inactive encodings is optional`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());

  let {sender} = pc1.addTransceiver(track, {
        sendEncodings:[{
            scaleResolutionDownTo: { maxWidth: 120, maxHeight: 60 }
        }]
      });

  // Get the initial value set.
  let params = sender.getParameters();
  assert_equals(params.encodings[0].scaleResolutionDownTo?.maxWidth, 120);
  assert_equals(params.encodings[0].scaleResolutionDownTo?.maxHeight, 60);
  // Set parameters and get the result.
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 60, maxHeight: 30 };
  await sender.setParameters(params);
  params = sender.getParameters();
  assert_equals(params.encodings[0].scaleResolutionDownTo?.maxWidth, 60);
  assert_equals(params.encodings[0].scaleResolutionDownTo?.maxHeight, 30);
}, `getParameters reflect the current scaleResolutionDownTo`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());

  pc1.addTransceiver(track, {
        sendEncodings:[{
            scaleResolutionDownBy: 2.0,
            scaleResolutionDownTo: { maxWidth: 120, maxHeight: 60 }
        }]
      });

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  await waitForFrameWithResolution(t, pc1, 120, 60);
}, `addTransceiver: scaleResolutionDownBy is ignored when ` +
   `scaleResolutionDownTo is specified`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track);

  const params = sender.getParameters();
  params.encodings[0].scaleResolutionDownBy = 2.0;
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 120, maxHeight: 60 };
  const p = sender.setParameters(params);

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  await waitForFrameWithResolution(t, pc1, 120, 60);
}, `setParameters: scaleResolutionDownBy is ignored when ` +
   `scaleResolutionDownTo is specified`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track, {
      sendEncodings: [{
          scaleResolutionDownTo: { maxWidth: 60, maxHeight: 30 }
      }]
  });

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  await waitForFrameWithResolution(t, pc1, 60, 30);
}, `addTransceiver: scaleResolutionDownTo with half resolution`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track);

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  // Request full resolution.
  let params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 120, maxHeight: 60 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 120, 60);

  // Request half resolution.
  params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 60, maxHeight: 30 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 60, 30);

  // Request full resolution again.
  params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 120, maxHeight: 60 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 120, 60);
}, `setParameters: Modify scaleResolutionDownTo while sending`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(80, 40);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track);

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  // scaleTo is portrait, track is landscape, but no scaling should happen due
  // to orientation agnosticism.
  let params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 40, maxHeight: 80 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 80, 40);

  // Change orientation of the track: still no downscale, but encoder begins to
  // produce the new orientation.
  track.resize(40, 80);
  await waitForFrameWithResolution(t, pc1, 40, 80);

  // scaleTo in landscape, reducing to half size. Verify track, which is
  // portrait, is scaled down by 2.
  params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 40, maxHeight: 20 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 20, 40);
}, `scaleResolutionDownTo is orientation agnostic`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(120, 60);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track);

  await pc1.setLocalDescription();
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription();
  await pc1.setRemoteDescription(pc2.localDescription);

  // Restrict to 60x60. This results in 60x30 due to maintaining aspect ratio.
  let params = sender.getParameters();
  params.encodings[0].scaleResolutionDownTo = { maxWidth: 60, maxHeight: 60 };
  await sender.setParameters(params);
  await waitForFrameWithResolution(t, pc1, 60, 30);
}, `scaleResolutionDownTo does not change aspect ratio`);

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());
  pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

  const track = createResizableTrack(160, 80);
  t.add_cleanup(() => track.stop());
  const {sender} = pc1.addTransceiver(track, {
      sendEncodings: [{
          rid: '0',
          scaleResolutionDownTo: { maxWidth: 40, maxHeight: 20 }
      }, {
          rid: '1',
          scaleResolutionDownTo: { maxWidth: 80, maxHeight: 40 }
      }, {
          rid: '2',
          scaleResolutionDownTo: { maxWidth: 160, maxHeight: 80 }
      }]
  });

  // Negotiate with simulcast tweaks.
  await doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']);

  await waitForFrameWithResolution(t, pc1, 40, 20, '0');
  await waitForFrameWithResolution(t, pc1, 80, 40, '1');
  await waitForFrameWithResolution(t, pc1, 160, 80, '2');
}, `scaleResolutionDownTo with simulcast`);
</script>
