Dynamically assign ids to header extensions not enabled by default

by creating an id collision and letting UsedIds resolve it.

Also avoid id=15 which is forbidden by
  https://www.rfc-editor.org/rfc/rfc8285#section-4.2
so might cause interop issues in offers to implementations
not supporting two-byte extensions.

BUG=webrtc:15378

Change-Id: I27926f065f8e396257294da7acf2be9802169805
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/319280
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#41696}
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 902b536..a313407 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -811,6 +811,8 @@
 std::vector<webrtc::RtpHeaderExtensionCapability>
 WebRtcVideoEngine::GetRtpHeaderExtensions() const {
   std::vector<webrtc::RtpHeaderExtensionCapability> result;
+  // id is *not* incremented for non-default extensions, UsedIds needs to
+  // resolve conflicts.
   int id = 1;
   for (const auto& uri :
        {webrtc::RtpExtension::kTimestampOffsetUri,
@@ -825,27 +827,26 @@
     result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
   }
   for (const auto& uri : {webrtc::RtpExtension::kAbsoluteCaptureTimeUri}) {
-    result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kStopped);
+    result.emplace_back(uri, id, webrtc::RtpTransceiverDirection::kStopped);
   }
-  result.emplace_back(webrtc::RtpExtension::kGenericFrameDescriptorUri00, id++,
+  result.emplace_back(webrtc::RtpExtension::kGenericFrameDescriptorUri00, id,
                       IsEnabled(trials_, "WebRTC-GenericDescriptorAdvertised")
                           ? webrtc::RtpTransceiverDirection::kSendRecv
                           : webrtc::RtpTransceiverDirection::kStopped);
   result.emplace_back(
-      webrtc::RtpExtension::kDependencyDescriptorUri, id++,
+      webrtc::RtpExtension::kDependencyDescriptorUri, id,
       IsEnabled(trials_, "WebRTC-DependencyDescriptorAdvertised")
           ? webrtc::RtpTransceiverDirection::kSendRecv
           : webrtc::RtpTransceiverDirection::kStopped);
-
   result.emplace_back(
-      webrtc::RtpExtension::kVideoLayersAllocationUri, id++,
+      webrtc::RtpExtension::kVideoLayersAllocationUri, id,
       IsEnabled(trials_, "WebRTC-VideoLayersAllocationAdvertised")
           ? webrtc::RtpTransceiverDirection::kSendRecv
           : webrtc::RtpTransceiverDirection::kStopped);
 
   // VideoFrameTrackingId is a test-only extension.
   if (IsEnabled(trials_, "WebRTC-VideoFrameTrackingIdAdvertised")) {
-    result.emplace_back(webrtc::RtpExtension::kVideoFrameTrackingIdUri, id++,
+    result.emplace_back(webrtc::RtpExtension::kVideoFrameTrackingIdUri, id,
                         webrtc::RtpTransceiverDirection::kSendRecv);
   }
   return result;
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index fcc2703..23a1b19 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -643,6 +643,8 @@
 WebRtcVoiceEngine::GetRtpHeaderExtensions() const {
   RTC_DCHECK(signal_thread_checker_.IsCurrent());
   std::vector<webrtc::RtpHeaderExtensionCapability> result;
+  // id is *not* incremented for non-default extensions, UsedIds needs to
+  // resolve conflicts.
   int id = 1;
   for (const auto& uri : {webrtc::RtpExtension::kAudioLevelUri,
                           webrtc::RtpExtension::kAbsSendTimeUri,
@@ -651,7 +653,7 @@
     result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kSendRecv);
   }
   for (const auto& uri : {webrtc::RtpExtension::kAbsoluteCaptureTimeUri}) {
-    result.emplace_back(uri, id++, webrtc::RtpTransceiverDirection::kStopped);
+    result.emplace_back(uri, id, webrtc::RtpTransceiverDirection::kStopped);
   }
   return result;
 }
diff --git a/pc/used_ids.h b/pc/used_ids.h
index 6b342cb..42ef00a 100644
--- a/pc/used_ids.h
+++ b/pc/used_ids.h
@@ -147,15 +147,15 @@
 
  private:
   // Returns the first unused id in reverse order from the max id of one byte
-  // header extensions. This hopefully reduce the risk of more collisions. We
+  // header extensions. This hopefully reduces the risk of more collisions. We
   // want to change the default ids as little as possible. If no unused id is
   // found and two byte header extensions are enabled (i.e.,
-  // `extmap_allow_mixed_` is true), search for unused ids from 15 to 255.
+  // `extmap_allow_mixed_` is true), search for unused ids from 16 to 255.
   int FindUnusedId() override {
     if (next_extension_id_ <=
         webrtc::RtpExtension::kOneByteHeaderExtensionMaxId) {
       // First search in reverse order from the max id of one byte header
-      // extensions.
+      // extensions (14).
       while (IsIdUsed(next_extension_id_) &&
              next_extension_id_ >= min_allowed_id_) {
         --next_extension_id_;
@@ -165,9 +165,10 @@
     if (id_domain_ == IdDomain::kTwoByteAllowed) {
       if (next_extension_id_ < min_allowed_id_) {
         // We have searched among all one-byte IDs without finding an unused ID,
-        // continue at the first two-byte ID.
+        // continue at the first two-byte ID (16; avoid 15 since it is somewhat
+        // special per https://www.rfc-editor.org/rfc/rfc8285#section-4.2
         next_extension_id_ =
-            webrtc::RtpExtension::kOneByteHeaderExtensionMaxId + 1;
+            webrtc::RtpExtension::kOneByteHeaderExtensionMaxId + 2;
       }
 
       if (next_extension_id_ >
diff --git a/pc/used_ids_unittest.cc b/pc/used_ids_unittest.cc
index 6362f27..df3790b 100644
--- a/pc/used_ids_unittest.cc
+++ b/pc/used_ids_unittest.cc
@@ -119,7 +119,8 @@
       UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed);
 
   // Fill all one byte IDs.
-  for (int i = 1; i < 15; ++i) {
+  for (int i = 1; i <= webrtc::RtpExtension::kOneByteHeaderExtensionMaxId;
+       ++i) {
     webrtc::RtpExtension id("", i);
     used_ids.FindAndSetIdUsed(&id);
   }
@@ -131,11 +132,11 @@
 
   // Expect to reassign to two-byte header extension IDs.
   used_ids.FindAndSetIdUsed(&id1_collision);
-  EXPECT_EQ(id1_collision.id, 15);
+  EXPECT_EQ(id1_collision.id, 16);
   used_ids.FindAndSetIdUsed(&id2_collision);
-  EXPECT_EQ(id2_collision.id, 16);
+  EXPECT_EQ(id2_collision.id, 17);
   used_ids.FindAndSetIdUsed(&id3_collision);
-  EXPECT_EQ(id3_collision.id, 17);
+  EXPECT_EQ(id3_collision.id, 18);
 }
 
 // Death tests.