Add the function ToRtpParameters.

The function converts the cricket::Codec, cricket::RtpHeaderExtensions
and cricket::StreamParamsVec to webrtc::RtpParameters.

BUG=webrtc:7311

Review-Url: https://codereview.webrtc.org/2735853004
Cr-Commit-Position: refs/heads/master@{#17124}
diff --git a/webrtc/ortc/rtpparametersconversion.cc b/webrtc/ortc/rtpparametersconversion.cc
index 63ee9c7..083c3b0 100644
--- a/webrtc/ortc/rtpparametersconversion.cc
+++ b/webrtc/ortc/rtpparametersconversion.cc
@@ -277,6 +277,22 @@
   return rtc::Optional<RtcpFeedback>();
 }
 
+std::vector<RtpEncodingParameters> ToRtpEncodings(
+    const cricket::StreamParamsVec& stream_params) {
+  std::vector<RtpEncodingParameters> rtp_encodings;
+  for (const cricket::StreamParams& stream_param : stream_params) {
+    RtpEncodingParameters rtp_encoding;
+    rtp_encoding.ssrc.emplace(stream_param.first_ssrc());
+    uint32_t rtx_ssrc = 0;
+    if (stream_param.GetFidSsrc(stream_param.first_ssrc(), &rtx_ssrc)) {
+      RtpRtxParameters rtx_param(rtx_ssrc);
+      rtp_encoding.rtx.emplace(rtx_param);
+    }
+    rtp_encodings.push_back(std::move(rtp_encoding));
+  }
+  return rtp_encodings;
+}
+
 template <typename C>
 cricket::MediaType KindOfCodec();
 
@@ -332,6 +348,47 @@
 template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
     const cricket::VideoCodec& cricket_codec);
 
+template <typename C>
+static void ToRtpCodecParametersTypeSpecific(const C& cricket_codec,
+                                             RtpCodecParameters* codec);
+template <>
+void ToRtpCodecParametersTypeSpecific<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec,
+    RtpCodecParameters* codec) {
+  codec->num_channels =
+      rtc::Optional<int>(static_cast<int>(cricket_codec.channels));
+}
+
+template <>
+void ToRtpCodecParametersTypeSpecific<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec,
+    RtpCodecParameters* codec) {}
+
+template <typename C>
+RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec) {
+  RtpCodecParameters codec_param;
+  codec_param.name = cricket_codec.name;
+  codec_param.kind = KindOfCodec<C>();
+  codec_param.clock_rate.emplace(cricket_codec.clockrate);
+  codec_param.payload_type = cricket_codec.id;
+  for (const cricket::FeedbackParam& cricket_feedback :
+       cricket_codec.feedback_params.params()) {
+    rtc::Optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
+    if (feedback) {
+      codec_param.rtcp_feedback.push_back(feedback.MoveValue());
+    }
+  }
+  ToRtpCodecParametersTypeSpecific(cricket_codec, &codec_param);
+  codec_param.parameters.insert(cricket_codec.params.begin(),
+                                cricket_codec.params.end());
+  return codec_param;
+}
+
+template RtpCodecParameters ToRtpCodecParameters<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec);
+template RtpCodecParameters ToRtpCodecParameters<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec);
+
 template <class C>
 RtpCapabilities ToRtpCapabilities(
     const std::vector<C>& cricket_codecs,
@@ -373,4 +430,30 @@
     const std::vector<cricket::VideoCodec>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions);
 
+template <class C>
+RtpParameters ToRtpParameters(
+    const std::vector<C>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params) {
+  RtpParameters rtp_parameters;
+  for (const C& cricket_codec : cricket_codecs) {
+    rtp_parameters.codecs.push_back(ToRtpCodecParameters(cricket_codec));
+  }
+  for (const RtpExtension& cricket_extension : cricket_extensions) {
+    rtp_parameters.header_extensions.emplace_back(cricket_extension.uri,
+                                                  cricket_extension.id);
+  }
+  rtp_parameters.encodings = ToRtpEncodings(stream_params);
+  return rtp_parameters;
+}
+
+template RtpParameters ToRtpParameters<cricket::AudioCodec>(
+    const std::vector<cricket::AudioCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params);
+template RtpParameters ToRtpParameters<cricket::VideoCodec>(
+    const std::vector<cricket::VideoCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params);
+
 }  // namespace webrtc
diff --git a/webrtc/ortc/rtpparametersconversion.h b/webrtc/ortc/rtpparametersconversion.h
index a466895..d2c9129 100644
--- a/webrtc/ortc/rtpparametersconversion.h
+++ b/webrtc/ortc/rtpparametersconversion.h
@@ -83,6 +83,12 @@
 rtc::Optional<RtcpFeedback> ToRtcpFeedback(
     const cricket::FeedbackParam& cricket_feedback);
 
+std::vector<RtpEncodingParameters> ToRtpEncodings(
+    const cricket::StreamParamsVec& stream_params);
+
+template <typename C>
+RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec);
+
 template <typename C>
 RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec);
 
@@ -91,6 +97,12 @@
     const std::vector<C>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions);
 
+template <class C>
+RtpParameters ToRtpParameters(
+    const std::vector<C>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params);
+
 }  // namespace webrtc
 
 #endif  // WEBRTC_ORTC_RTPPARAMETERSCONVERSION_H_
diff --git a/webrtc/ortc/rtpparametersconversion_unittest.cc b/webrtc/ortc/rtpparametersconversion_unittest.cc
index 6bb335c..3268406 100644
--- a/webrtc/ortc/rtpparametersconversion_unittest.cc
+++ b/webrtc/ortc/rtpparametersconversion_unittest.cc
@@ -456,6 +456,80 @@
             codec.rtcp_feedback[1]);
 }
 
+TEST(RtpParametersConversionTest, ToRtpEncodingsWithEmptyStreamParamsVec) {
+  cricket::StreamParamsVec streams;
+  auto rtp_encodings = ToRtpEncodings(streams);
+  ASSERT_EQ(0u, rtp_encodings.size());
+}
+
+TEST(RtpParametersConversionTest, ToRtpEncodingsWithMultipleStreamParams) {
+  cricket::StreamParamsVec streams;
+  cricket::StreamParams stream1;
+  stream1.ssrcs.push_back(1111u);
+  stream1.AddFidSsrc(1111u, 0xaaaaaaaa);
+
+  cricket::StreamParams stream2;
+  stream2.ssrcs.push_back(2222u);
+  stream2.AddFidSsrc(2222u, 0xaaaaaaab);
+
+  streams.push_back(stream1);
+  streams.push_back(stream2);
+
+  auto rtp_encodings = ToRtpEncodings(streams);
+  ASSERT_EQ(2u, rtp_encodings.size());
+  EXPECT_EQ(1111u, rtp_encodings[0].ssrc);
+  EXPECT_EQ(0xaaaaaaaa, rtp_encodings[0].rtx->ssrc);
+  EXPECT_EQ(2222u, rtp_encodings[1].ssrc);
+  EXPECT_EQ(0xaaaaaaab, rtp_encodings[1].rtx->ssrc);
+}
+
+TEST(RtpParametersConversionTest, ToAudioRtpCodecParameters) {
+  cricket::AudioCodec cricket_codec;
+  cricket_codec.name = "foo";
+  cricket_codec.id = 50;
+  cricket_codec.clockrate = 22222;
+  cricket_codec.channels = 4;
+  cricket_codec.params["foo"] = "bar";
+  cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
+  RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
+
+  EXPECT_EQ("foo", codec.name);
+  EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
+  EXPECT_EQ(50, codec.payload_type);
+  EXPECT_EQ(rtc::Optional<int>(22222), codec.clock_rate);
+  EXPECT_EQ(rtc::Optional<int>(4), codec.num_channels);
+  ASSERT_EQ(1u, codec.parameters.size());
+  EXPECT_EQ("bar", codec.parameters["foo"]);
+  EXPECT_EQ(1u, codec.rtcp_feedback.size());
+  EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
+            codec.rtcp_feedback[0]);
+}
+
+TEST(RtpParametersConversionTest, ToVideoRtpCodecParameters) {
+  cricket::VideoCodec cricket_codec;
+  cricket_codec.name = "VID";
+  cricket_codec.id = 101;
+  cricket_codec.clockrate = 80000;
+  cricket_codec.params["foo"] = "bar";
+  cricket_codec.params["ANOTHER"] = "param";
+  cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
+  cricket_codec.feedback_params.Add({"nack", "pli"});
+  RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
+
+  EXPECT_EQ("VID", codec.name);
+  EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
+  EXPECT_EQ(101, codec.payload_type);
+  EXPECT_EQ(rtc::Optional<int>(80000), codec.clock_rate);
+  ASSERT_EQ(2u, codec.parameters.size());
+  EXPECT_EQ("bar", codec.parameters["foo"]);
+  EXPECT_EQ("param", codec.parameters["ANOTHER"]);
+  EXPECT_EQ(2u, codec.rtcp_feedback.size());
+  EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
+            codec.rtcp_feedback[0]);
+  EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
+            codec.rtcp_feedback[1]);
+}
+
 // An unknown feedback param should just be ignored.
 TEST(RtpParametersConversionTest, ToRtpCodecCapabilityUnknownFeedbackParam) {
   cricket::AudioCodec cricket_codec;
@@ -532,4 +606,40 @@
                       FecMechanism::FLEXFEC));
 }
 
+TEST(RtpParametersConversionTest, ToRtpParameters) {
+  cricket::VideoCodec vp8;
+  vp8.name = "VP8";
+  vp8.id = 101;
+  vp8.clockrate = 90000;
+
+  cricket::VideoCodec red;
+  red.name = "red";
+  red.id = 102;
+  red.clockrate = 90000;
+
+  cricket::VideoCodec ulpfec;
+  ulpfec.name = "ulpfec";
+  ulpfec.id = 103;
+  ulpfec.clockrate = 90000;
+
+  cricket::StreamParamsVec streams;
+  cricket::StreamParams stream;
+  stream.ssrcs.push_back(1234u);
+  streams.push_back(stream);
+
+  RtpParameters rtp_parameters = ToRtpParameters<cricket::VideoCodec>(
+      {vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
+  ASSERT_EQ(3u, rtp_parameters.codecs.size());
+  EXPECT_EQ("VP8", rtp_parameters.codecs[0].name);
+  EXPECT_EQ("red", rtp_parameters.codecs[1].name);
+  EXPECT_EQ("ulpfec", rtp_parameters.codecs[2].name);
+  ASSERT_EQ(2u, rtp_parameters.header_extensions.size());
+  EXPECT_EQ("uri", rtp_parameters.header_extensions[0].uri);
+  EXPECT_EQ(1, rtp_parameters.header_extensions[0].id);
+  EXPECT_EQ("uri2", rtp_parameters.header_extensions[1].uri);
+  EXPECT_EQ(3, rtp_parameters.header_extensions[1].id);
+  ASSERT_EQ(1u, rtp_parameters.encodings.size());
+  EXPECT_EQ(1234u, rtp_parameters.encodings[0].ssrc);
+}
+
 }  // namespace webrtc