webrtc wpt: add tests related to two-byte RTP header extensions

which can exceed the 1-14 range.
The id 15 is checked for explicitly since it is disallowed by one-byte
header extensions
  https://www.rfc-editor.org/rfc/rfc8285#section-4.2
but should be supported otherwise.

Note that this is a grey area, neither RFC 8285 nor RFC 8834 explicitly
mandate support for two-byte extensions.

BUG=chromium:1051821

Change-Id: I8c521e07c9844447e289b31fcd7d8c3341e5e050
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4847027
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Harald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1200120}
diff --git a/webrtc/protocol/rtp-headerextensions.html b/webrtc/protocol/rtp-headerextensions.html
index c377a61..d1d8bb6 100644
--- a/webrtc/protocol/rtp-headerextensions.html
+++ b/webrtc/protocol/rtp-headerextensions.html
@@ -26,7 +26,7 @@
 a=mid:audio
 a=rtpmap:111 opus/48000/2
 a=setup:actpass
-` + extmaps.audio.map(ext => SDPUtils.writeExtmap(ext));
+` + extmaps.audio.map(ext => SDPUtils.writeExtmap(ext)).join('');
   }
   if (extmaps.video) {
     sdp += `m=video 9 RTP/SAVPF 112
@@ -36,7 +36,7 @@
 a=mid:video
 a=rtpmap:112 VP8/90000
 a=setup:actpass
-` + extmaps.video.map(ext => SDPUtils.writeExtmap(ext));
+` + extmaps.video.map(ext => SDPUtils.writeExtmap(ext)).join('');
   }
   return sdp;
 }
@@ -98,4 +98,36 @@
     assert_true(!!extensions.find(e => e.uri === answer_extension.uri));
   }
 }, 'Negotiates the subset of supported extensions offered');
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+
+  // Some implementations may refuse 15 as invalid id because of
+  // https://www.rfc-editor.org/rfc/rfc8285#section-4.2
+  // which only applies to one-byte extensions with ids 0-14.
+  const sdp = createOfferSdp({audio: [{
+    id: 15, uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
+  }]});
+  await pc.setRemoteDescription({type: 'offer', sdp});
+}, 'Supports header extensions with id=15');
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+
+  const sdp = createOfferSdp({audio: [{
+    id: 16, uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
+  }, {
+    id: 17, uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level',
+  }]});
+  await pc.setRemoteDescription({type: 'offer', sdp});
+  await pc.setLocalDescription();
+  const answer_section = SDPUtils.splitSections(pc.localDescription.sdp)[1];
+  const answer_extensions = SDPUtils.matchPrefix(answer_section, 'a=extmap:')
+    .map(line => SDPUtils.parseExtmap(line));
+  assert_equals(answer_extensions.length, 2);
+  assert_true(!!answer_extensions.find(e => e.uri === 'urn:ietf:params:rtp-hdrext:sdes:mid'));
+  assert_true(!!answer_extensions.find(e => e.uri === 'urn:ietf:params:rtp-hdrext:ssrc-audio-level'));
+}, 'Supports two-byte header extensions');
 </script>