Add PeerConnection GetRtpSender/ReceiverCapabilities

Those are static functions in the spec, so implemented as member functions
of the PeerConnectionFactory instead.

Bug: webrtc:7577, webrtc:9441
Change-Id: Iccb24180e096e713d24e7e25ecfd5d7bbd7638f9
Reviewed-on: https://webrtc-review.googlesource.com/85341
Commit-Queue: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23768}
diff --git a/api/peerconnectionfactoryproxy.h b/api/peerconnectionfactoryproxy.h
index eea5b55..db52083 100644
--- a/api/peerconnectionfactoryproxy.h
+++ b/api/peerconnectionfactoryproxy.h
@@ -48,6 +48,12 @@
               CreatePeerConnection,
               const PeerConnectionInterface::RTCConfiguration&,
               PeerConnectionDependencies);
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpSenderCapabilities,
+                   cricket::MediaType);
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpReceiverCapabilities,
+                   cricket::MediaType);
 PROXY_METHOD1(rtc::scoped_refptr<MediaStreamInterface>,
               CreateLocalMediaStream,
               const std::string&)
diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h
index cdc3266..2466300 100644
--- a/api/peerconnectioninterface.h
+++ b/api/peerconnectioninterface.h
@@ -1307,6 +1307,22 @@
     return nullptr;
   }
 
+  // Returns the capabilities of an RTP sender of type |kind|.
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  // TODO(orphis): Make pure virtual when all subclasses implement it.
+  virtual RtpCapabilities GetRtpSenderCapabilities(
+      cricket::MediaType kind) const {
+    return {};
+  }
+
+  // Returns the capabilities of an RTP receiver of type |kind|.
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  // TODO(orphis): Make pure virtual when all subclasses implement it.
+  virtual RtpCapabilities GetRtpReceiverCapabilities(
+      cricket::MediaType kind) const {
+    return {};
+  }
+
   virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
       const std::string& stream_id) = 0;
 
diff --git a/ortc/BUILD.gn b/ortc/BUILD.gn
index 08bdf8c..6ac2d81 100644
--- a/ortc/BUILD.gn
+++ b/ortc/BUILD.gn
@@ -21,8 +21,6 @@
     "ortcrtpreceiveradapter.h",
     "ortcrtpsenderadapter.cc",
     "ortcrtpsenderadapter.h",
-    "rtpparametersconversion.cc",
-    "rtpparametersconversion.h",
     "rtptransportadapter.cc",
     "rtptransportadapter.h",
     "rtptransportcontrolleradapter.cc",
@@ -71,7 +69,6 @@
       "ortcfactory_unittest.cc",
       "ortcrtpreceiver_unittest.cc",
       "ortcrtpsender_unittest.cc",
-      "rtpparametersconversion_unittest.cc",
       "rtptransport_unittest.cc",
       "rtptransportcontroller_unittest.cc",
       "srtptransport_unittest.cc",
diff --git a/ortc/ortcfactory.cc b/ortc/ortcfactory.cc
index fa2b05c..c0ae049 100644
--- a/ortc/ortcfactory.cc
+++ b/ortc/ortcfactory.cc
@@ -26,7 +26,6 @@
 #include "modules/audio_processing/include/audio_processing.h"
 #include "ortc/ortcrtpreceiveradapter.h"
 #include "ortc/ortcrtpsenderadapter.h"
-#include "ortc/rtpparametersconversion.h"
 #include "ortc/rtptransportadapter.h"
 #include "ortc/rtptransportcontrolleradapter.h"
 #include "p2p/base/basicpacketsocketfactory.h"
@@ -34,6 +33,7 @@
 #include "pc/audiotrack.h"
 #include "pc/channelmanager.h"
 #include "pc/localaudiosource.h"
+#include "pc/rtpparametersconversion.h"
 #include "pc/videotrack.h"
 #include "rtc_base/asyncpacketsocket.h"
 #include "rtc_base/bind.h"
diff --git a/ortc/rtptransportcontrolleradapter.cc b/ortc/rtptransportcontrolleradapter.cc
index 009b3ad..ad6a992 100644
--- a/ortc/rtptransportcontrolleradapter.cc
+++ b/ortc/rtptransportcontrolleradapter.cc
@@ -20,9 +20,9 @@
 #include "media/base/mediaconstants.h"
 #include "ortc/ortcrtpreceiveradapter.h"
 #include "ortc/ortcrtpsenderadapter.h"
-#include "ortc/rtpparametersconversion.h"
 #include "ortc/rtptransportadapter.h"
 #include "pc/rtpmediautils.h"
+#include "pc/rtpparametersconversion.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/ptr_util.h"
 
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 9d2a05a..084b240 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -153,6 +153,8 @@
     "rtcstatscollector.h",
     "rtcstatstraversal.cc",
     "rtcstatstraversal.h",
+    "rtpparametersconversion.cc",
+    "rtpparametersconversion.h",
     "rtpreceiver.cc",
     "rtpreceiver.h",
     "rtpsender.cc",
@@ -487,6 +489,7 @@
       "rtcstatscollector_unittest.cc",
       "rtcstatstraversal_unittest.cc",
       "rtpmediautils_unittest.cc",
+      "rtpparametersconversion_unittest.cc",
       "rtpsenderreceiver_unittest.cc",
       "sctputils_unittest.cc",
       "statscollector_unittest.cc",
diff --git a/pc/peerconnectionfactory.cc b/pc/peerconnectionfactory.cc
index 7e48a2f..cade31c 100644
--- a/pc/peerconnectionfactory.cc
+++ b/pc/peerconnectionfactory.cc
@@ -11,6 +11,7 @@
 #include "pc/peerconnectionfactory.h"
 
 #include <utility>
+#include <vector>
 
 #include "api/fec_controller.h"
 #include "api/mediaconstraintsinterface.h"
@@ -23,6 +24,7 @@
 #include "logging/rtc_event_log/rtc_event_log.h"
 #include "media/base/rtpdataengine.h"
 #include "media/sctp/sctptransport.h"
+#include "pc/rtpparametersconversion.h"
 #include "rtc_base/bind.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/ptr_util.h"
@@ -231,6 +233,60 @@
   options_ = options;
 }
 
+RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities(
+    cricket::MediaType kind) const {
+  RTC_DCHECK_RUN_ON(signaling_thread_);
+  switch (kind) {
+    case cricket::MEDIA_TYPE_AUDIO: {
+      cricket::AudioCodecs cricket_codecs;
+      cricket::RtpHeaderExtensions cricket_extensions;
+      channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs);
+      channel_manager_->GetSupportedAudioRtpHeaderExtensions(
+          &cricket_extensions);
+      return ToRtpCapabilities(cricket_codecs, cricket_extensions);
+    }
+    case cricket::MEDIA_TYPE_VIDEO: {
+      cricket::VideoCodecs cricket_codecs;
+      cricket::RtpHeaderExtensions cricket_extensions;
+      channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
+      channel_manager_->GetSupportedVideoRtpHeaderExtensions(
+          &cricket_extensions);
+      return ToRtpCapabilities(cricket_codecs, cricket_extensions);
+    }
+    case cricket::MEDIA_TYPE_DATA:
+      return RtpCapabilities();
+  }
+  // Not reached; avoids compile warning.
+  FATAL();
+}
+
+RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities(
+    cricket::MediaType kind) const {
+  RTC_DCHECK_RUN_ON(signaling_thread_);
+  switch (kind) {
+    case cricket::MEDIA_TYPE_AUDIO: {
+      cricket::AudioCodecs cricket_codecs;
+      cricket::RtpHeaderExtensions cricket_extensions;
+      channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs);
+      channel_manager_->GetSupportedAudioRtpHeaderExtensions(
+          &cricket_extensions);
+      return ToRtpCapabilities(cricket_codecs, cricket_extensions);
+    }
+    case cricket::MEDIA_TYPE_VIDEO: {
+      cricket::VideoCodecs cricket_codecs;
+      cricket::RtpHeaderExtensions cricket_extensions;
+      channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
+      channel_manager_->GetSupportedVideoRtpHeaderExtensions(
+          &cricket_extensions);
+      return ToRtpCapabilities(cricket_codecs, cricket_extensions);
+    }
+    case cricket::MEDIA_TYPE_DATA:
+      return RtpCapabilities();
+  }
+  // Not reached; avoids compile warning.
+  FATAL();
+}
+
 rtc::scoped_refptr<AudioSourceInterface>
 PeerConnectionFactory::CreateAudioSource(const cricket::AudioOptions& options) {
   RTC_DCHECK(signaling_thread_->IsCurrent());
diff --git a/pc/peerconnectionfactory.h b/pc/peerconnectionfactory.h
index af3fa24..82fa508 100644
--- a/pc/peerconnectionfactory.h
+++ b/pc/peerconnectionfactory.h
@@ -62,6 +62,12 @@
 
   bool Initialize();
 
+  RtpCapabilities GetRtpSenderCapabilities(
+      cricket::MediaType kind) const override;
+
+  RtpCapabilities GetRtpReceiverCapabilities(
+      cricket::MediaType kind) const override;
+
   rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
       const std::string& stream_id) override;
 
diff --git a/pc/peerconnectionfactory_unittest.cc b/pc/peerconnectionfactory_unittest.cc
index 9b1854e..773ba01 100644
--- a/pc/peerconnectionfactory_unittest.cc
+++ b/pc/peerconnectionfactory_unittest.cc
@@ -130,6 +130,19 @@
     }
   }
 
+  void VerifyAudioCodecCapability(const webrtc::RtpCodecCapability& codec) {
+    EXPECT_EQ(codec.kind, cricket::MEDIA_TYPE_AUDIO);
+    EXPECT_FALSE(codec.name.empty());
+    EXPECT_GT(codec.clock_rate, 0);
+    EXPECT_GT(codec.num_channels, 0);
+  }
+
+  void VerifyVideoCodecCapability(const webrtc::RtpCodecCapability& codec) {
+    EXPECT_EQ(codec.kind, cricket::MEDIA_TYPE_VIDEO);
+    EXPECT_FALSE(codec.name.empty());
+    EXPECT_GT(codec.clock_rate, 0);
+  }
+
   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory_;
   NullPeerConnectionObserver observer_;
   std::unique_ptr<cricket::FakePortAllocator> port_allocator_;
@@ -170,6 +183,72 @@
   EXPECT_TRUE(pc.get() != nullptr);
 }
 
+TEST_F(PeerConnectionFactoryTest, CheckRtpSenderAudioCapabilities) {
+  webrtc::RtpCapabilities audio_capabilities =
+      factory_->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO);
+  EXPECT_FALSE(audio_capabilities.codecs.empty());
+  for (const auto& codec : audio_capabilities.codecs) {
+    VerifyAudioCodecCapability(codec);
+  }
+  EXPECT_FALSE(audio_capabilities.header_extensions.empty());
+  for (const auto& header_extension : audio_capabilities.header_extensions) {
+    EXPECT_FALSE(header_extension.uri.empty());
+  }
+}
+
+TEST_F(PeerConnectionFactoryTest, CheckRtpSenderVideoCapabilities) {
+  webrtc::RtpCapabilities video_capabilities =
+      factory_->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO);
+  EXPECT_FALSE(video_capabilities.codecs.empty());
+  for (const auto& codec : video_capabilities.codecs) {
+    VerifyVideoCodecCapability(codec);
+  }
+  EXPECT_FALSE(video_capabilities.header_extensions.empty());
+  for (const auto& header_extension : video_capabilities.header_extensions) {
+    EXPECT_FALSE(header_extension.uri.empty());
+  }
+}
+
+TEST_F(PeerConnectionFactoryTest, CheckRtpSenderDataCapabilities) {
+  webrtc::RtpCapabilities data_capabilities =
+      factory_->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_DATA);
+  EXPECT_TRUE(data_capabilities.codecs.empty());
+  EXPECT_TRUE(data_capabilities.header_extensions.empty());
+}
+
+TEST_F(PeerConnectionFactoryTest, CheckRtpReceiverAudioCapabilities) {
+  webrtc::RtpCapabilities audio_capabilities =
+      factory_->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO);
+  EXPECT_FALSE(audio_capabilities.codecs.empty());
+  for (const auto& codec : audio_capabilities.codecs) {
+    VerifyAudioCodecCapability(codec);
+  }
+  EXPECT_FALSE(audio_capabilities.header_extensions.empty());
+  for (const auto& header_extension : audio_capabilities.header_extensions) {
+    EXPECT_FALSE(header_extension.uri.empty());
+  }
+}
+
+TEST_F(PeerConnectionFactoryTest, CheckRtpReceiverVideoCapabilities) {
+  webrtc::RtpCapabilities video_capabilities =
+      factory_->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_VIDEO);
+  EXPECT_FALSE(video_capabilities.codecs.empty());
+  for (const auto& codec : video_capabilities.codecs) {
+    VerifyVideoCodecCapability(codec);
+  }
+  EXPECT_FALSE(video_capabilities.header_extensions.empty());
+  for (const auto& header_extension : video_capabilities.header_extensions) {
+    EXPECT_FALSE(header_extension.uri.empty());
+  }
+}
+
+TEST_F(PeerConnectionFactoryTest, CheckRtpReceiverDataCapabilities) {
+  webrtc::RtpCapabilities data_capabilities =
+      factory_->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_DATA);
+  EXPECT_TRUE(data_capabilities.codecs.empty());
+  EXPECT_TRUE(data_capabilities.header_extensions.empty());
+}
+
 // This test verifies creation of PeerConnection with valid STUN and TURN
 // configuration. Also verifies the URL's parsed correctly as expected.
 TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) {
diff --git a/ortc/rtpparametersconversion.cc b/pc/rtpparametersconversion.cc
similarity index 95%
rename from ortc/rtpparametersconversion.cc
rename to pc/rtpparametersconversion.cc
index ff5bece..a57066e 100644
--- a/ortc/rtpparametersconversion.cc
+++ b/pc/rtpparametersconversion.cc
@@ -8,10 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "ortc/rtpparametersconversion.h"
+#include "pc/rtpparametersconversion.h"
 
 #include <set>
-#include <sstream>
 #include <utility>
 
 #include "media/base/rtputils.h"
@@ -136,9 +135,10 @@
   }
   cricket_codec.name = codec.name;
   if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
-    std::ostringstream oss;
-    oss << "Invalid payload type: " << codec.payload_type;
-    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, oss.str());
+    char buf[40];
+    rtc::SimpleStringBuilder sb(buf);
+    sb << "Invalid payload type: " << codec.payload_type;
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
   }
   cricket_codec.id = codec.payload_type;
   for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
@@ -168,9 +168,10 @@
       return result.MoveError();
     }
     if (!seen_payload_types.insert(codec.payload_type).second) {
-      std::ostringstream oss;
-      oss << "Duplicate payload type: " << codec.payload_type;
-      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, oss.str());
+      char buf[40];
+      rtc::SimpleStringBuilder sb(buf);
+      sb << "Duplicate payload type: " << codec.payload_type;
+      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
     }
     cricket_codecs.push_back(result.MoveValue());
   }
@@ -186,17 +187,20 @@
 RTCErrorOr<cricket::RtpHeaderExtensions> ToCricketRtpHeaderExtensions(
     const std::vector<RtpHeaderExtensionParameters>& extensions) {
   cricket::RtpHeaderExtensions cricket_extensions;
-  std::ostringstream err_writer;
   std::set<int> seen_header_extension_ids;
   for (const RtpHeaderExtensionParameters& extension : extensions) {
     if (extension.id < RtpHeaderExtensionParameters::kMinId ||
         extension.id > RtpHeaderExtensionParameters::kMaxId) {
-      err_writer << "Invalid header extension id: " << extension.id;
-      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, err_writer.str());
+      char buf[50];
+      rtc::SimpleStringBuilder sb(buf);
+      sb << "Invalid header extension id: " << extension.id;
+      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
     }
     if (!seen_header_extension_ids.insert(extension.id).second) {
-      err_writer << "Duplicate header extension id: " << extension.id;
-      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, err_writer.str());
+      char buf[50];
+      rtc::SimpleStringBuilder sb(buf);
+      sb << "Duplicate header extension id: " << extension.id;
+      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
     }
     cricket_extensions.push_back(extension);
   }
diff --git a/ortc/rtpparametersconversion.h b/pc/rtpparametersconversion.h
similarity index 96%
rename from ortc/rtpparametersconversion.h
rename to pc/rtpparametersconversion.h
index c5aa16b..d2d13ae 100644
--- a/ortc/rtpparametersconversion.h
+++ b/pc/rtpparametersconversion.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef ORTC_RTPPARAMETERSCONVERSION_H_
-#define ORTC_RTPPARAMETERSCONVERSION_H_
+#ifndef PC_RTPPARAMETERSCONVERSION_H_
+#define PC_RTPPARAMETERSCONVERSION_H_
 
 #include <memory>
 #include <vector>
@@ -105,4 +105,4 @@
 
 }  // namespace webrtc
 
-#endif  // ORTC_RTPPARAMETERSCONVERSION_H_
+#endif  // PC_RTPPARAMETERSCONVERSION_H_
diff --git a/ortc/rtpparametersconversion_unittest.cc b/pc/rtpparametersconversion_unittest.cc
similarity index 99%
rename from ortc/rtpparametersconversion_unittest.cc
rename to pc/rtpparametersconversion_unittest.cc
index ddf761d..649fe97 100644
--- a/ortc/rtpparametersconversion_unittest.cc
+++ b/pc/rtpparametersconversion_unittest.cc
@@ -10,8 +10,7 @@
 
 #include <algorithm>
 
-#include "ortc/rtpparametersconversion.h"
-#include "ortc/testrtpparameters.h"
+#include "pc/rtpparametersconversion.h"
 #include "rtc_base/gunit.h"
 
 namespace webrtc {