webrtc: Implement and ship RTCRtpEncodingParameters.maxFramerate

Intent: https://groups.google.com/a/chromium.org/g/blink-dev/c/SV8evGSU_dw/m/DIrx9XzvDQAJ

Bug: 1043655
Change-Id: I340ad755fe4a33c566a4374e1f45bc9014f5e2d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2010845
Commit-Queue: Florent Castelli <orphis@chromium.org>
Reviewed-by: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734030}
diff --git a/webrtc-extensions/RTCRtpParameters-maxFramerate.html b/webrtc-extensions/RTCRtpParameters-maxFramerate.html
new file mode 100644
index 0000000..7067fbc
--- /dev/null
+++ b/webrtc-extensions/RTCRtpParameters-maxFramerate.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCRtpParameters encodings</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/webrtc/dictionary-helper.js"></script>
+<script src="/webrtc/RTCRtpParameters-helper.js"></script>
+<script>
+'use strict';
+
+test(function(t) {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  assert_throws(new RangeError(), () => pc.addTransceiver('video', {
+    sendEncodings: [{
+      maxFramerate: -10
+    }]
+  }));
+}, `addTransceiver() with sendEncoding.maxFramerate field set to less than 0 should reject with RangeError`);
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const { sender } = pc.addTransceiver('video');
+  await doOfferAnswerExchange(t, pc);
+
+  const param = sender.getParameters();
+  validateSenderRtpParameters(param);
+  const encoding = getFirstEncoding(param);
+
+  encoding.maxFramerate = -10;
+  return promise_rejects(t, new RangeError(),
+    sender.setParameters(param));
+}, `setParameters() with encoding.maxFramerate field set to less than 0 should reject with RangeError`);
+
+test_modified_encoding('video', 'maxFramerate', 24, 16,
+  'setParameters() with modified encoding.maxFramerate should succeed');
+
+</script>
diff --git a/webrtc/RTCRtpParameters-encodings.html b/webrtc/RTCRtpParameters-encodings.html
index c9e14cb..f719644 100644
--- a/webrtc/RTCRtpParameters-encodings.html
+++ b/webrtc/RTCRtpParameters-encodings.html
@@ -49,7 +49,6 @@
         RTCPriorityType     priority;
         RTCPriorityType     networkPriority;
         unsigned long       maxBitrate;
-        double              maxFramerate;
 
         [readonly]
         DOMString           rid;
@@ -68,14 +67,6 @@
         - 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
@@ -155,7 +146,6 @@
     assert_equals(encoding.priority, 'low');
     assert_equals(encoding.networkPriority, 'low');
     assert_equals(encoding.maxBitrate, 8);
-    assert_equals(encoding.maxFramerate, 25);
     assert_not_own_property(encoding, "rid", "rid should be removed with a single encoding");
 
   }, `sender.getParameters() should return sendEncodings set by addTransceiver()`);
@@ -267,58 +257,6 @@
     });
   }, `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', 'active', false, true,
     'setParameters() with modified encoding.active should succeed');
 
@@ -331,9 +269,6 @@
   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');
-
   test_modified_encoding('video', 'scaleResolutionDownBy', 2, 4,
     'setParameters() with modified encoding.scaleResolutionDownBy should succeed');
 
diff --git a/webrtc/RTCRtpParameters-helper.js b/webrtc/RTCRtpParameters-helper.js
index d706949..d61d8e1 100644
--- a/webrtc/RTCRtpParameters-helper.js
+++ b/webrtc/RTCRtpParameters-helper.js
@@ -242,3 +242,69 @@
   assert_optional_unsigned_int_field(codec, 'channels');
   assert_optional_string_field(codec, 'sdpFmtpLine');
 }
+
+// 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];
+}
+
+// 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');
+}
\ No newline at end of file