<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title>RTCRtpSendParameters degradationPreference effect</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../webrtc/RTCPeerConnection-helper.js"></script>
<script>
  'use strict';

// This file contains tests that check that degradation preference
// actually has the desired effect. These tests take a long time to run.

// Returns incoming bandwidth usage between stats1 and stats2
// in bits per second.
function bandwidth(stats1, stats2) {
  const transport1 = [...stats1.values()].filter(({type}) => type === 'transport')[0];
  const transport2 = [...stats2.values()].filter(({type}) => type === 'transport')[0];
  const bytes = transport2.bytesReceived - transport1.bytesReceived;
  // Multiply by 1000 to get per second, divide by 8 to get bits.
  const bandwidth = 1000 * 8 * bytes /
        (transport2.timestamp - transport1.timestamp);
  return bandwidth;
}

// Returns tuple of { bandwidth, fps, x-res, y-res }
async function measureStuff(t, pc, intervalMs) {
  const stats1 = await pc.getStats();
  await new Promise(r => t.step_timeout(r, intervalMs));
  const stats2 = await pc.getStats();
  // RTCInboundStreamStats
  const inboundRtp1List = [...stats1.values()].filter(({type}) => type === 'inbound-rtp');
  const inboundRtp2List = [...stats2.values()].filter(({type}) => type === 'inbound-rtp');
  const inboundRtp1 = inboundRtp1List[0];
  const inboundRtp2 = inboundRtp2List[0];
  const fps = 1000 * (inboundRtp2.framesReceived - inboundRtp1.framesReceived) /
        (inboundRtp2.timestamp - inboundRtp1.timestamp);
  const result = {
    bandwidth: bandwidth(stats1, stats2),
    fps: fps,
    width: inboundRtp2.frameWidth,
    height: inboundRtp2.frameHeight
  };
  // Unbreak for debugging.
  // con sole.log('Measure: ', performance.now(), " ", JSON.stringify(result));
  return result;
}

// Wait for a certain condition to be true on the traffic measures
// on the PC. Will typically be conditions on resolution, framerate
// or bandwidth.
async function waitForCondition(t, pc, condition, maxWait, stepName) {
  let counter = 1;
  let measure = await measureStuff(t, pc, 1000);
  while (counter < maxWait && !condition(measure)) {
    measure = await measureStuff(t, pc, 1000);
    counter += 1;
  }
  assert_true(condition(measure),
              `failure in ${stepName}, measure is ${JSON.stringify(measure)}`);
  return condition(measure);
}

promise_test(async t => {
  const pc1 = new RTCPeerConnection();
  t.add_cleanup(() => pc1.close());
  const stream = await getNoiseStream({video: true});
  t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
  const track = stream.getTracks()[0];
  const { sender } = pc1.addTransceiver(track);

  let param = sender.getParameters();

  assert_equals(param.degradationPreference, undefined,
    'Expect initial param.degradationPreference to be undefined');

  param.degradationPreference = 'maintain-framerate';
  await sender.setParameters(param);

  const pc2 = new RTCPeerConnection();
  t.add_cleanup(() => pc2.close());

  exchangeIceCandidates(pc1, pc2);
  await exchangeOfferAnswer(pc1, pc2);
  await listenToConnected(pc1);
  // Wait a few seconds to allow things to settle (rampup)
  // We know that the generator is supposed to produce 640x480
  // at 10 fps with a bandwidth exceeding 30 kbits/second.
  assert_true(await waitForCondition(t, pc2, (measure) => {
    return (measure.bandwidth > 30000 &&
            measure.width == 640 &&
            measure.fps > 9);
  }, 60, 'preconditions'));

  // Measure BW, resolution and frame rate over one second
  const stats1 = await measureStuff(t, pc2, 1000);

  // Constrain BW to 1/2 of measured value
  const newBandwidth = stats1.bandwidth / 2;

  const parameters = sender.getParameters();
  parameters.encodings[0].maxBitrate = newBandwidth;
  await sender.setParameters(parameters);
  // Wait until the expected result happens.
  let stats2 = await measureStuff(t, pc2, 1000);
  let counter = 1;
  const maxWaitCount = 20;
  const kBandwidthMargin = 1.3;
  // It takes time to adapt to a new bandwidth, time to scale down,
  // and time to acknowledge that framerate should not be reduced.
  // Measured time is around 16 seconds.
  assert_true(await waitForCondition(t, pc2, (measure) => {
    return (measure.bandwidth < newBandwidth * kBandwidthMargin &&
            measure.width < stats1.width &&
            measure.fps > stats1.fps * 0.9);
  }, 60, 'adaptation'),
             `Target bandwidth ${newBandwidth * kBandwidthMargin}, target min FPS ${stats1.fps * 0.9}`);
}, 'Maintain-framerate reduces resolution on bandwidth cut', { timeout: 35000 });

</script>
