Enable DD and VLA header extensions by default for Simulcast/SVC

When Simulcast (more than one encoding) or SVC (a scalability mode
other than the default L1T1) is used, enable the AV1 Dependency
Descriptor and the video-layer-allocations RTP header extensions by
default.

The RTP header extensions API can be used to disable them if needed.

BUG=webrtc:15378

Change-Id: I587ac32c9d681461496a136f6950b007e72da86d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/326100
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#41332}
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc
index ca626cc9..ec58847 100644
--- a/pc/rtp_transceiver.cc
+++ b/pc/rtp_transceiver.cc
@@ -177,6 +177,23 @@
           : media_engine()->voice().send_codecs());
   senders_.push_back(sender);
   receivers_.push_back(receiver);
+
+  // Set default header extensions depending on whether simulcast/SVC is used.
+  RtpParameters parameters = sender->internal()->GetParametersInternal();
+  bool uses_simulcast = parameters.encodings.size() > 1;
+  bool uses_svc = !parameters.encodings.empty() &&
+                  parameters.encodings[0].scalability_mode.has_value() &&
+                  parameters.encodings[0].scalability_mode !=
+                      ScalabilityModeToString(ScalabilityMode::kL1T1);
+  if (uses_simulcast || uses_svc) {
+    // Enable DD and VLA extensions, can be deactivated by the API.
+    for (RtpHeaderExtensionCapability& ext : header_extensions_to_negotiate_) {
+      if (ext.uri == RtpExtension::kVideoLayersAllocationUri ||
+          ext.uri == RtpExtension::kDependencyDescriptorUri) {
+        ext.direction = RtpTransceiverDirection::kSendRecv;
+      }
+    }
+  }
 }
 
 RtpTransceiver::~RtpTransceiver() {
diff --git a/pc/rtp_transceiver_unittest.cc b/pc/rtp_transceiver_unittest.cc
index d75e9645..b6dc7b2 100644
--- a/pc/rtp_transceiver_unittest.cc
+++ b/pc/rtp_transceiver_unittest.cc
@@ -481,6 +481,81 @@
                                 RtpTransceiverDirection::kStopped)));
 }
 
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+       SimulcastOrSvcEnablesExtensionsByDefault) {
+  std::vector<RtpHeaderExtensionCapability> extensions = {
+      {RtpExtension::kDependencyDescriptorUri, 1,
+       RtpTransceiverDirection::kStopped},
+      {RtpExtension::kVideoLayersAllocationUri, 2,
+       RtpTransceiverDirection::kStopped},
+  };
+
+  // Default is stopped.
+  auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+  auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
+      RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+          rtc::Thread::Current(), sender),
+      RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+          rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+      context(), extensions,
+      /* on_negotiation_needed= */ [] {});
+  std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions =
+      transceiver->GetHeaderExtensionsToNegotiate();
+  ASSERT_EQ(header_extensions.size(), 2u);
+  EXPECT_EQ(header_extensions[0].uri, RtpExtension::kDependencyDescriptorUri);
+  EXPECT_EQ(header_extensions[0].direction, RtpTransceiverDirection::kStopped);
+  EXPECT_EQ(header_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri);
+  EXPECT_EQ(header_extensions[1].direction, RtpTransceiverDirection::kStopped);
+
+  // Simulcast, i.e. more than one encoding.
+  RtpParameters simulcast_parameters;
+  simulcast_parameters.encodings.resize(2);
+  auto simulcast_sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+  EXPECT_CALL(*simulcast_sender, GetParametersInternal())
+      .WillRepeatedly(Return(simulcast_parameters));
+  auto simulcast_transceiver = rtc::make_ref_counted<RtpTransceiver>(
+      RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+          rtc::Thread::Current(), simulcast_sender),
+      RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+          rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+      context(), extensions,
+      /* on_negotiation_needed= */ [] {});
+  auto simulcast_extensions =
+      simulcast_transceiver->GetHeaderExtensionsToNegotiate();
+  ASSERT_EQ(simulcast_extensions.size(), 2u);
+  EXPECT_EQ(simulcast_extensions[0].uri,
+            RtpExtension::kDependencyDescriptorUri);
+  EXPECT_EQ(simulcast_extensions[0].direction,
+            RtpTransceiverDirection::kSendRecv);
+  EXPECT_EQ(simulcast_extensions[1].uri,
+            RtpExtension::kVideoLayersAllocationUri);
+  EXPECT_EQ(simulcast_extensions[1].direction,
+            RtpTransceiverDirection::kSendRecv);
+
+  // SVC, a single encoding with a scalabilityMode other than L1T1.
+  webrtc::RtpParameters svc_parameters;
+  svc_parameters.encodings.resize(1);
+  svc_parameters.encodings[0].scalability_mode = "L3T3";
+
+  auto svc_sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+  EXPECT_CALL(*svc_sender, GetParametersInternal())
+      .WillRepeatedly(Return(svc_parameters));
+  auto svc_transceiver = rtc::make_ref_counted<RtpTransceiver>(
+      RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+          rtc::Thread::Current(), svc_sender),
+      RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+          rtc::Thread::Current(), rtc::Thread::Current(), receiver_),
+      context(), extensions,
+      /* on_negotiation_needed= */ [] {});
+  std::vector<webrtc::RtpHeaderExtensionCapability> svc_extensions =
+      svc_transceiver->GetHeaderExtensionsToNegotiate();
+  ASSERT_EQ(svc_extensions.size(), 2u);
+  EXPECT_EQ(svc_extensions[0].uri, RtpExtension::kDependencyDescriptorUri);
+  EXPECT_EQ(svc_extensions[0].direction, RtpTransceiverDirection::kSendRecv);
+  EXPECT_EQ(svc_extensions[1].uri, RtpExtension::kVideoLayersAllocationUri);
+  EXPECT_EQ(svc_extensions[1].direction, RtpTransceiverDirection::kSendRecv);
+}
+
 }  // namespace
 
 }  // namespace webrtc