<!doctype html>
<meta charset=utf-8>
<title>RTCRtpParameters encodings</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="dictionary-helper.js"></script>
<script src="RTCRtpParameters-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html

  // The following helper functions are called from RTCRtpParameters-helper.js:
  //   doOfferAnswerExchange
  //   validateSenderRtpParameters

  /*
    5.1.  RTCPeerConnection Interface Extensions
      partial interface RTCPeerConnection {
        RTCRtpTransceiver           addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                                   optional RTCRtpTransceiverInit init);
        ...
      };

      dictionary RTCRtpTransceiverInit {
        RTCRtpTransceiverDirection         direction = "sendrecv";
        sequence<MediaStream>              streams;
        sequence<RTCRtpEncodingParameters> sendEncodings;
      };

    5.2.  RTCRtpSender Interface
      interface RTCRtpSender {
        Promise<void>           setParameters(optional RTCRtpParameters parameters);
        RTCRtpParameters        getParameters();
      };

      dictionary RTCRtpParameters {
        DOMString                                 transactionId;
        sequence<RTCRtpEncodingParameters>        encodings;
        sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
        RTCRtcpParameters                         rtcp;
        sequence<RTCRtpCodecParameters>           codecs;
        RTCDegradationPreference                  degradationPreference;
      };

      dictionary RTCRtpEncodingParameters {
        RTCDtxStatus        dtx;
        boolean             active;
        RTCPriorityType     priority;
        RTCPriorityType     networkPriority;
        unsigned long       ptime;
        unsigned long       maxBitrate;
        double              maxFramerate;

        [readonly]
        DOMString           rid;

        double              scaleResolutionDownBy;
      };

      enum RTCDtxStatus {
        "disabled",
        "enabled"
      };

      enum RTCPriorityType {
        "very-low",
        "low",
        "medium",
        "high"
      };

      getParameters
        - encodings is set to the value of the [[send encodings]] internal slot.
   */

  // Get the first encoding in param.encodings.
  // Asserts that param.encodings has at least one element.
  function getFirstEncoding(param) {
    const { encodings } = param;
    assert_equals(encodings.length, 1);
    return encodings[0];
  }

  /*
    5.1.  addTransceiver
      7. Create an RTCRtpSender with track, streams and sendEncodings and let sender
         be the result.

    5.2.  create an RTCRtpSender
      5.  Let sender have a [[send encodings]] internal slot, representing a list
          of RTCRtpEncodingParameters dictionaries.
      6.  If sendEncodings is given as input to this algorithm, and is non-empty,
          set the [[send encodings]] slot to sendEncodings.

          Otherwise, set it to a list containing a single RTCRtpEncodingParameters
          with active set to true.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const transceiver = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = transceiver.sender.getParameters();
    validateSenderRtpParameters(param);
    const { encodings } = param;
    const encoding = getFirstEncoding(param);

    assert_equals(encoding.active, true);
  }, 'addTransceiver() with undefined sendEncodings should have default encoding parameter with active set to true');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const transceiver = pc.addTransceiver('audio', { sendEncodings: [] });
    await doOfferAnswerExchange(t, pc);

    const param = transceiver.sender.getParameters();
    validateSenderRtpParameters(param);
    const { encodings } = param;
    const encoding = getFirstEncoding(param);

    assert_equals(encoding.active, true);
  }, 'addTransceiver() with empty list sendEncodings should have default encoding parameter with active set to true');

  /*
    5.2.  create an RTCRtpSender
      To create an RTCRtpSender with a MediaStreamTrack , track, a list of MediaStream
      objects, streams, and optionally a list of RTCRtpEncodingParameters objects,
      sendEncodings, run the following steps:
        5.  Let sender have a [[send encodings]] internal slot, representing a list
            of RTCRtpEncodingParameters dictionaries.

        6.  If sendEncodings is given as input to this algorithm, and is non-empty,
            set the [[send encodings]] slot to sendEncodings.

    5.2.  getParameters
      - encodings is set to the value of the [[send encodings]] internal slot.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio', {
      sendEncodings: [{
        dtx: 'enabled',
        active: false,
        priority: 'low',
        networkPriority: 'low',
        ptime: 5,
        maxBitrate: 8,
        maxFramerate: 25,
        rid: 'foo'
      }]
    });
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);
    const encoding = getFirstEncoding(param);

    assert_equals(encoding.dtx, 'enabled');
    assert_equals(encoding.active, false);
    assert_equals(encoding.priority, 'low');
    assert_equals(encoding.networkPriority, 'low');
    assert_equals(encoding.ptime, 5);
    assert_equals(encoding.maxBitrate, 8);
    assert_equals(encoding.maxFramerate, 25);
    assert_equals(encoding.rid, 'foo');

  }, `sender.getParameters() should return sendEncodings set by addTransceiver()`);

  /*
    5.2.  setParameters
      3.  Let N be the number of RTCRtpEncodingParameters stored in sender's internal
          [[send encodings]] slot.
      7.  If parameters.encodings.length is different from N, or if any parameter
          in the parameters argument, marked as a Read-only parameter, has a value
          that is different from the corresponding parameter value returned from
          sender.getParameters(), abort these steps and return a promise rejected
          with a newly created InvalidModificationError. Note that this also applies
          to transactionId.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);

    const { encodings } = param;
    assert_equals(encodings.length, 1);

    // {} is valid RTCRtpEncodingParameters because all fields are optional
    encodings.push({});
    assert_equals(param.encodings.length, 2);

    return promise_rejects(t, 'InvalidModificationError',
      sender.setParameters(param));
  }, `sender.setParameters() with mismatch number of encodings should reject with InvalidModificationError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);

    param.encodings = undefined;

    return promise_rejects(t, new TypeError(),
      sender.setParameters(param));
  }, `sender.setParameters() with encodings unset should reject with TypeError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('video', {
      sendEncodings: [{ rid: 'foo' }, { rid: 'baz' }],
    });
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);
    const encoding = getFirstEncoding(param);

    assert_equals(encoding.rid, 'foo');

    encoding.rid = 'bar';
    return promise_rejects(t, 'InvalidModificationError',
      sender.setParameters(param));
  }, `setParameters() with modified encoding.rid field should reject with InvalidModificationError`);

  /*
    5.2.  setParameters
      8.  If the scaleResolutionDownBy parameter in the parameters argument has a
          value less than 1.0, abort these steps and return a promise rejected with
          a newly created RangeError.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);
    const encoding = getFirstEncoding(param);

    encoding.scaleResolutionDownBy = 0.5;
    return promise_rejects(t, new RangeError(),
      sender.setParameters(param));
  }, `setParameters() with encoding.scaleResolutionDownBy field set to less than 1.0 should reject with RangeError`);

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const { sender } = pc.addTransceiver('audio');
    await doOfferAnswerExchange(t, pc);

    const param = sender.getParameters();
    validateSenderRtpParameters(param);
    const encoding = getFirstEncoding(param);

    encoding.scaleResolutionDownBy = 1.5;
    return sender.setParameters(param)
    .then(() => {
      const param = sender.getParameters();
      validateSenderRtpParameters(param);
      const encoding = getFirstEncoding(param);

      assert_approx_equals(encoding.scaleResolutionDownBy, 1.5, 0.01);
    });
  }, `setParameters() with encoding.scaleResolutionDownBy field set to greater than 1.0 should succeed`);

  // Helper function to test that modifying an encoding field should succeed
  function test_modified_encoding(kind, field, value1, value2, desc) {
    promise_test(async t => {
      const pc = new RTCPeerConnection();
      t.add_cleanup(() => pc.close());
      const { sender } = pc.addTransceiver(kind, {
        sendEncodings: [{
          [field]: value1
        }]
      });
      await doOfferAnswerExchange(t, pc);

      const param1 = sender.getParameters();
      validateSenderRtpParameters(param1);
      const encoding1 = getFirstEncoding(param1);

      assert_equals(encoding1[field], value1);
      encoding1[field] = value2;

      await sender.setParameters(param1);
      const param2 = sender.getParameters();
      validateSenderRtpParameters(param2);
      const encoding2 = getFirstEncoding(param2);
      assert_equals(encoding2[field], value2);
    }, desc + ' with RTCRtpTransceiverInit');

    promise_test(async t => {
      const pc = new RTCPeerConnection();
      t.add_cleanup(() => pc.close());
      const { sender } = pc.addTransceiver(kind);
      await doOfferAnswerExchange(t, pc);

      const initParam = sender.getParameters();
      validateSenderRtpParameters(initParam);
      initParam.encodings[0][field] = value1;
      await sender.setParameters(initParam);

      const param1 = sender.getParameters();
      validateSenderRtpParameters(param1);
      const encoding1 = getFirstEncoding(param1);

      assert_equals(encoding1[field], value1);
      encoding1[field] = value2;

      await sender.setParameters(param1);
      const param2 = sender.getParameters();
      validateSenderRtpParameters(param2);
      const encoding2 = getFirstEncoding(param2);
      assert_equals(encoding2[field], value2);
    }, desc + ' without RTCRtpTransceiverInit');
  }

  test_modified_encoding('audio', 'dtx', 'enabled', 'disabled',
    'setParameters() with modified encoding.dtx should succeed');

  test_modified_encoding('audio', 'dtx', 'enabled', undefined,
    'setParameters() with unset encoding.dtx should succeed');

  test_modified_encoding('audio', 'active', false, true,
    'setParameters() with modified encoding.active should succeed');

  test_modified_encoding('audio', 'priority', 'very-low', 'high',
    'setParameters() with modified encoding.priority should succeed');

  test_modified_encoding('audio', 'networkPriority', 'very-low', 'high',
    'setParameters() with modified encoding.networkPriority should succeed');

  test_modified_encoding('audio', 'ptime', 2, 4,
    'setParameters() with modified encoding.ptime should succeed');

  test_modified_encoding('audio', 'maxBitrate', 10000, 20000,
    'setParameters() with modified encoding.maxBitrate should succeed');

  test_modified_encoding('video', 'maxFramerate', 24, 16,
    'setParameters() with modified encoding.maxFramerate should succeed');

</script>
