xref: /aosp_15_r20/external/webrtc/pc/rtp_parameters_conversion.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_parameters_conversion.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
14*d9f75844SAndroid Build Coastguard Worker #include <set>
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
21*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
22*d9f75844SAndroid Build Coastguard Worker #include "media/base/rtp_utils.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
26*d9f75844SAndroid Build Coastguard Worker 
27*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
28*d9f75844SAndroid Build Coastguard Worker 
ToCricketFeedbackParam(const RtcpFeedback & feedback)29*d9f75844SAndroid Build Coastguard Worker RTCErrorOr<cricket::FeedbackParam> ToCricketFeedbackParam(
30*d9f75844SAndroid Build Coastguard Worker     const RtcpFeedback& feedback) {
31*d9f75844SAndroid Build Coastguard Worker   switch (feedback.type) {
32*d9f75844SAndroid Build Coastguard Worker     case RtcpFeedbackType::CCM:
33*d9f75844SAndroid Build Coastguard Worker       if (!feedback.message_type) {
34*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
35*d9f75844SAndroid Build Coastguard Worker                              "Missing message type in CCM RtcpFeedback.");
36*d9f75844SAndroid Build Coastguard Worker       } else if (*feedback.message_type != RtcpFeedbackMessageType::FIR) {
37*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
38*d9f75844SAndroid Build Coastguard Worker                              "Invalid message type in CCM RtcpFeedback.");
39*d9f75844SAndroid Build Coastguard Worker       }
40*d9f75844SAndroid Build Coastguard Worker       return cricket::FeedbackParam(cricket::kRtcpFbParamCcm,
41*d9f75844SAndroid Build Coastguard Worker                                     cricket::kRtcpFbCcmParamFir);
42*d9f75844SAndroid Build Coastguard Worker     case RtcpFeedbackType::LNTF:
43*d9f75844SAndroid Build Coastguard Worker       if (feedback.message_type) {
44*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(
45*d9f75844SAndroid Build Coastguard Worker             RTCErrorType::INVALID_PARAMETER,
46*d9f75844SAndroid Build Coastguard Worker             "Didn't expect message type in LNTF RtcpFeedback.");
47*d9f75844SAndroid Build Coastguard Worker       }
48*d9f75844SAndroid Build Coastguard Worker       return cricket::FeedbackParam(cricket::kRtcpFbParamLntf);
49*d9f75844SAndroid Build Coastguard Worker     case RtcpFeedbackType::NACK:
50*d9f75844SAndroid Build Coastguard Worker       if (!feedback.message_type) {
51*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
52*d9f75844SAndroid Build Coastguard Worker                              "Missing message type in NACK RtcpFeedback.");
53*d9f75844SAndroid Build Coastguard Worker       }
54*d9f75844SAndroid Build Coastguard Worker       switch (*feedback.message_type) {
55*d9f75844SAndroid Build Coastguard Worker         case RtcpFeedbackMessageType::GENERIC_NACK:
56*d9f75844SAndroid Build Coastguard Worker           return cricket::FeedbackParam(cricket::kRtcpFbParamNack);
57*d9f75844SAndroid Build Coastguard Worker         case RtcpFeedbackMessageType::PLI:
58*d9f75844SAndroid Build Coastguard Worker           return cricket::FeedbackParam(cricket::kRtcpFbParamNack,
59*d9f75844SAndroid Build Coastguard Worker                                         cricket::kRtcpFbNackParamPli);
60*d9f75844SAndroid Build Coastguard Worker         default:
61*d9f75844SAndroid Build Coastguard Worker           LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
62*d9f75844SAndroid Build Coastguard Worker                                "Invalid message type in NACK RtcpFeedback.");
63*d9f75844SAndroid Build Coastguard Worker       }
64*d9f75844SAndroid Build Coastguard Worker     case RtcpFeedbackType::REMB:
65*d9f75844SAndroid Build Coastguard Worker       if (feedback.message_type) {
66*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(
67*d9f75844SAndroid Build Coastguard Worker             RTCErrorType::INVALID_PARAMETER,
68*d9f75844SAndroid Build Coastguard Worker             "Didn't expect message type in REMB RtcpFeedback.");
69*d9f75844SAndroid Build Coastguard Worker       }
70*d9f75844SAndroid Build Coastguard Worker       return cricket::FeedbackParam(cricket::kRtcpFbParamRemb);
71*d9f75844SAndroid Build Coastguard Worker     case RtcpFeedbackType::TRANSPORT_CC:
72*d9f75844SAndroid Build Coastguard Worker       if (feedback.message_type) {
73*d9f75844SAndroid Build Coastguard Worker         LOG_AND_RETURN_ERROR(
74*d9f75844SAndroid Build Coastguard Worker             RTCErrorType::INVALID_PARAMETER,
75*d9f75844SAndroid Build Coastguard Worker             "Didn't expect message type in transport-cc RtcpFeedback.");
76*d9f75844SAndroid Build Coastguard Worker       }
77*d9f75844SAndroid Build Coastguard Worker       return cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc);
78*d9f75844SAndroid Build Coastguard Worker   }
79*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_NOTREACHED();
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker 
82*d9f75844SAndroid Build Coastguard Worker template <typename C>
83*d9f75844SAndroid Build Coastguard Worker static RTCError ToCricketCodecTypeSpecific(const RtpCodecParameters& codec,
84*d9f75844SAndroid Build Coastguard Worker                                            C* cricket_codec);
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker template <>
ToCricketCodecTypeSpecific(const RtpCodecParameters & codec,cricket::AudioCodec * cricket_codec)87*d9f75844SAndroid Build Coastguard Worker RTCError ToCricketCodecTypeSpecific<cricket::AudioCodec>(
88*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec,
89*d9f75844SAndroid Build Coastguard Worker     cricket::AudioCodec* cricket_codec) {
90*d9f75844SAndroid Build Coastguard Worker   if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
91*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(
92*d9f75844SAndroid Build Coastguard Worker         RTCErrorType::INVALID_PARAMETER,
93*d9f75844SAndroid Build Coastguard Worker         "Can't use video codec with audio sender or receiver.");
94*d9f75844SAndroid Build Coastguard Worker   }
95*d9f75844SAndroid Build Coastguard Worker   if (!codec.num_channels) {
96*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
97*d9f75844SAndroid Build Coastguard Worker                          "Missing number of channels for audio codec.");
98*d9f75844SAndroid Build Coastguard Worker   }
99*d9f75844SAndroid Build Coastguard Worker   if (*codec.num_channels <= 0) {
100*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
101*d9f75844SAndroid Build Coastguard Worker                          "Number of channels must be positive.");
102*d9f75844SAndroid Build Coastguard Worker   }
103*d9f75844SAndroid Build Coastguard Worker   cricket_codec->channels = *codec.num_channels;
104*d9f75844SAndroid Build Coastguard Worker   if (!codec.clock_rate) {
105*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
106*d9f75844SAndroid Build Coastguard Worker                          "Missing codec clock rate.");
107*d9f75844SAndroid Build Coastguard Worker   }
108*d9f75844SAndroid Build Coastguard Worker   if (*codec.clock_rate <= 0) {
109*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
110*d9f75844SAndroid Build Coastguard Worker                          "Clock rate must be positive.");
111*d9f75844SAndroid Build Coastguard Worker   }
112*d9f75844SAndroid Build Coastguard Worker   cricket_codec->clockrate = *codec.clock_rate;
113*d9f75844SAndroid Build Coastguard Worker   return RTCError::OK();
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker // Video codecs don't use num_channels or clock_rate, but they should at least
117*d9f75844SAndroid Build Coastguard Worker // be validated to ensure the application isn't trying to do something it
118*d9f75844SAndroid Build Coastguard Worker // doesn't intend to.
119*d9f75844SAndroid Build Coastguard Worker template <>
ToCricketCodecTypeSpecific(const RtpCodecParameters & codec,cricket::VideoCodec *)120*d9f75844SAndroid Build Coastguard Worker RTCError ToCricketCodecTypeSpecific<cricket::VideoCodec>(
121*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec,
122*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec*) {
123*d9f75844SAndroid Build Coastguard Worker   if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
124*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(
125*d9f75844SAndroid Build Coastguard Worker         RTCErrorType::INVALID_PARAMETER,
126*d9f75844SAndroid Build Coastguard Worker         "Can't use audio codec with video sender or receiver.");
127*d9f75844SAndroid Build Coastguard Worker   }
128*d9f75844SAndroid Build Coastguard Worker   if (codec.num_channels) {
129*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
130*d9f75844SAndroid Build Coastguard Worker                          "Video codec shouldn't have num_channels.");
131*d9f75844SAndroid Build Coastguard Worker   }
132*d9f75844SAndroid Build Coastguard Worker   if (!codec.clock_rate) {
133*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
134*d9f75844SAndroid Build Coastguard Worker                          "Missing codec clock rate.");
135*d9f75844SAndroid Build Coastguard Worker   }
136*d9f75844SAndroid Build Coastguard Worker   if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
137*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
138*d9f75844SAndroid Build Coastguard Worker                          "Video clock rate must be 90000.");
139*d9f75844SAndroid Build Coastguard Worker   }
140*d9f75844SAndroid Build Coastguard Worker   return RTCError::OK();
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker template <typename C>
ToCricketCodec(const RtpCodecParameters & codec)144*d9f75844SAndroid Build Coastguard Worker RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec) {
145*d9f75844SAndroid Build Coastguard Worker   C cricket_codec;
146*d9f75844SAndroid Build Coastguard Worker   // Start with audio/video specific conversion.
147*d9f75844SAndroid Build Coastguard Worker   RTCError err = ToCricketCodecTypeSpecific(codec, &cricket_codec);
148*d9f75844SAndroid Build Coastguard Worker   if (!err.ok()) {
149*d9f75844SAndroid Build Coastguard Worker     return std::move(err);
150*d9f75844SAndroid Build Coastguard Worker   }
151*d9f75844SAndroid Build Coastguard Worker   cricket_codec.name = codec.name;
152*d9f75844SAndroid Build Coastguard Worker   if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
153*d9f75844SAndroid Build Coastguard Worker     char buf[40];
154*d9f75844SAndroid Build Coastguard Worker     rtc::SimpleStringBuilder sb(buf);
155*d9f75844SAndroid Build Coastguard Worker     sb << "Invalid payload type: " << codec.payload_type;
156*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
157*d9f75844SAndroid Build Coastguard Worker   }
158*d9f75844SAndroid Build Coastguard Worker   cricket_codec.id = codec.payload_type;
159*d9f75844SAndroid Build Coastguard Worker   for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
160*d9f75844SAndroid Build Coastguard Worker     auto result = ToCricketFeedbackParam(feedback);
161*d9f75844SAndroid Build Coastguard Worker     if (!result.ok()) {
162*d9f75844SAndroid Build Coastguard Worker       return result.MoveError();
163*d9f75844SAndroid Build Coastguard Worker     }
164*d9f75844SAndroid Build Coastguard Worker     cricket_codec.AddFeedbackParam(result.MoveValue());
165*d9f75844SAndroid Build Coastguard Worker   }
166*d9f75844SAndroid Build Coastguard Worker   cricket_codec.params = codec.parameters;
167*d9f75844SAndroid Build Coastguard Worker   return std::move(cricket_codec);
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker 
170*d9f75844SAndroid Build Coastguard Worker template RTCErrorOr<cricket::AudioCodec> ToCricketCodec(
171*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec);
172*d9f75844SAndroid Build Coastguard Worker template RTCErrorOr<cricket::VideoCodec> ToCricketCodec(
173*d9f75844SAndroid Build Coastguard Worker     const RtpCodecParameters& codec);
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker template <typename C>
ToCricketCodecs(const std::vector<RtpCodecParameters> & codecs)176*d9f75844SAndroid Build Coastguard Worker RTCErrorOr<std::vector<C>> ToCricketCodecs(
177*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpCodecParameters>& codecs) {
178*d9f75844SAndroid Build Coastguard Worker   std::vector<C> cricket_codecs;
179*d9f75844SAndroid Build Coastguard Worker   std::set<int> seen_payload_types;
180*d9f75844SAndroid Build Coastguard Worker   for (const RtpCodecParameters& codec : codecs) {
181*d9f75844SAndroid Build Coastguard Worker     auto result = ToCricketCodec<C>(codec);
182*d9f75844SAndroid Build Coastguard Worker     if (!result.ok()) {
183*d9f75844SAndroid Build Coastguard Worker       return result.MoveError();
184*d9f75844SAndroid Build Coastguard Worker     }
185*d9f75844SAndroid Build Coastguard Worker     if (!seen_payload_types.insert(codec.payload_type).second) {
186*d9f75844SAndroid Build Coastguard Worker       char buf[40];
187*d9f75844SAndroid Build Coastguard Worker       rtc::SimpleStringBuilder sb(buf);
188*d9f75844SAndroid Build Coastguard Worker       sb << "Duplicate payload type: " << codec.payload_type;
189*d9f75844SAndroid Build Coastguard Worker       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
190*d9f75844SAndroid Build Coastguard Worker     }
191*d9f75844SAndroid Build Coastguard Worker     cricket_codecs.push_back(result.MoveValue());
192*d9f75844SAndroid Build Coastguard Worker   }
193*d9f75844SAndroid Build Coastguard Worker   return std::move(cricket_codecs);
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker template RTCErrorOr<std::vector<cricket::AudioCodec>> ToCricketCodecs<
197*d9f75844SAndroid Build Coastguard Worker     cricket::AudioCodec>(const std::vector<RtpCodecParameters>& codecs);
198*d9f75844SAndroid Build Coastguard Worker 
199*d9f75844SAndroid Build Coastguard Worker template RTCErrorOr<std::vector<cricket::VideoCodec>> ToCricketCodecs<
200*d9f75844SAndroid Build Coastguard Worker     cricket::VideoCodec>(const std::vector<RtpCodecParameters>& codecs);
201*d9f75844SAndroid Build Coastguard Worker 
ToCricketStreamParamsVec(const std::vector<RtpEncodingParameters> & encodings)202*d9f75844SAndroid Build Coastguard Worker RTCErrorOr<cricket::StreamParamsVec> ToCricketStreamParamsVec(
203*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpEncodingParameters>& encodings) {
204*d9f75844SAndroid Build Coastguard Worker   if (encodings.size() > 1u) {
205*d9f75844SAndroid Build Coastguard Worker     LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
206*d9f75844SAndroid Build Coastguard Worker                          "ORTC API implementation doesn't currently "
207*d9f75844SAndroid Build Coastguard Worker                          "support simulcast or layered encodings.");
208*d9f75844SAndroid Build Coastguard Worker   } else if (encodings.empty()) {
209*d9f75844SAndroid Build Coastguard Worker     return cricket::StreamParamsVec();
210*d9f75844SAndroid Build Coastguard Worker   }
211*d9f75844SAndroid Build Coastguard Worker   cricket::StreamParamsVec cricket_streams;
212*d9f75844SAndroid Build Coastguard Worker   const RtpEncodingParameters& encoding = encodings[0];
213*d9f75844SAndroid Build Coastguard Worker   if (encoding.ssrc) {
214*d9f75844SAndroid Build Coastguard Worker     cricket::StreamParams stream_params;
215*d9f75844SAndroid Build Coastguard Worker     stream_params.add_ssrc(*encoding.ssrc);
216*d9f75844SAndroid Build Coastguard Worker     cricket_streams.push_back(std::move(stream_params));
217*d9f75844SAndroid Build Coastguard Worker   }
218*d9f75844SAndroid Build Coastguard Worker   return std::move(cricket_streams);
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker 
ToRtcpFeedback(const cricket::FeedbackParam & cricket_feedback)221*d9f75844SAndroid Build Coastguard Worker absl::optional<RtcpFeedback> ToRtcpFeedback(
222*d9f75844SAndroid Build Coastguard Worker     const cricket::FeedbackParam& cricket_feedback) {
223*d9f75844SAndroid Build Coastguard Worker   if (cricket_feedback.id() == cricket::kRtcpFbParamCcm) {
224*d9f75844SAndroid Build Coastguard Worker     if (cricket_feedback.param() == cricket::kRtcpFbCcmParamFir) {
225*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR);
226*d9f75844SAndroid Build Coastguard Worker     } else {
227*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Unsupported parameter for CCM RTCP feedback: "
228*d9f75844SAndroid Build Coastguard Worker                           << cricket_feedback.param();
229*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
230*d9f75844SAndroid Build Coastguard Worker     }
231*d9f75844SAndroid Build Coastguard Worker   } else if (cricket_feedback.id() == cricket::kRtcpFbParamLntf) {
232*d9f75844SAndroid Build Coastguard Worker     if (cricket_feedback.param().empty()) {
233*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::LNTF);
234*d9f75844SAndroid Build Coastguard Worker     } else {
235*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Unsupported parameter for LNTF RTCP feedback: "
236*d9f75844SAndroid Build Coastguard Worker                           << cricket_feedback.param();
237*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
238*d9f75844SAndroid Build Coastguard Worker     }
239*d9f75844SAndroid Build Coastguard Worker   } else if (cricket_feedback.id() == cricket::kRtcpFbParamNack) {
240*d9f75844SAndroid Build Coastguard Worker     if (cricket_feedback.param().empty()) {
241*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::NACK,
242*d9f75844SAndroid Build Coastguard Worker                           RtcpFeedbackMessageType::GENERIC_NACK);
243*d9f75844SAndroid Build Coastguard Worker     } else if (cricket_feedback.param() == cricket::kRtcpFbNackParamPli) {
244*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI);
245*d9f75844SAndroid Build Coastguard Worker     } else {
246*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Unsupported parameter for NACK RTCP feedback: "
247*d9f75844SAndroid Build Coastguard Worker                           << cricket_feedback.param();
248*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
249*d9f75844SAndroid Build Coastguard Worker     }
250*d9f75844SAndroid Build Coastguard Worker   } else if (cricket_feedback.id() == cricket::kRtcpFbParamRemb) {
251*d9f75844SAndroid Build Coastguard Worker     if (!cricket_feedback.param().empty()) {
252*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Unsupported parameter for REMB RTCP feedback: "
253*d9f75844SAndroid Build Coastguard Worker                           << cricket_feedback.param();
254*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
255*d9f75844SAndroid Build Coastguard Worker     } else {
256*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::REMB);
257*d9f75844SAndroid Build Coastguard Worker     }
258*d9f75844SAndroid Build Coastguard Worker   } else if (cricket_feedback.id() == cricket::kRtcpFbParamTransportCc) {
259*d9f75844SAndroid Build Coastguard Worker     if (!cricket_feedback.param().empty()) {
260*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING)
261*d9f75844SAndroid Build Coastguard Worker           << "Unsupported parameter for transport-cc RTCP feedback: "
262*d9f75844SAndroid Build Coastguard Worker           << cricket_feedback.param();
263*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
264*d9f75844SAndroid Build Coastguard Worker     } else {
265*d9f75844SAndroid Build Coastguard Worker       return RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC);
266*d9f75844SAndroid Build Coastguard Worker     }
267*d9f75844SAndroid Build Coastguard Worker   }
268*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << "Unsupported RTCP feedback type: "
269*d9f75844SAndroid Build Coastguard Worker                       << cricket_feedback.id();
270*d9f75844SAndroid Build Coastguard Worker   return absl::nullopt;
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker 
ToRtpEncodings(const cricket::StreamParamsVec & stream_params)273*d9f75844SAndroid Build Coastguard Worker std::vector<RtpEncodingParameters> ToRtpEncodings(
274*d9f75844SAndroid Build Coastguard Worker     const cricket::StreamParamsVec& stream_params) {
275*d9f75844SAndroid Build Coastguard Worker   std::vector<RtpEncodingParameters> rtp_encodings;
276*d9f75844SAndroid Build Coastguard Worker   for (const cricket::StreamParams& stream_param : stream_params) {
277*d9f75844SAndroid Build Coastguard Worker     RtpEncodingParameters rtp_encoding;
278*d9f75844SAndroid Build Coastguard Worker     rtp_encoding.ssrc.emplace(stream_param.first_ssrc());
279*d9f75844SAndroid Build Coastguard Worker     rtp_encodings.push_back(std::move(rtp_encoding));
280*d9f75844SAndroid Build Coastguard Worker   }
281*d9f75844SAndroid Build Coastguard Worker   return rtp_encodings;
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker 
284*d9f75844SAndroid Build Coastguard Worker template <typename C>
285*d9f75844SAndroid Build Coastguard Worker cricket::MediaType KindOfCodec();
286*d9f75844SAndroid Build Coastguard Worker 
287*d9f75844SAndroid Build Coastguard Worker template <>
KindOfCodec()288*d9f75844SAndroid Build Coastguard Worker cricket::MediaType KindOfCodec<cricket::AudioCodec>() {
289*d9f75844SAndroid Build Coastguard Worker   return cricket::MEDIA_TYPE_AUDIO;
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker 
292*d9f75844SAndroid Build Coastguard Worker template <>
KindOfCodec()293*d9f75844SAndroid Build Coastguard Worker cricket::MediaType KindOfCodec<cricket::VideoCodec>() {
294*d9f75844SAndroid Build Coastguard Worker   return cricket::MEDIA_TYPE_VIDEO;
295*d9f75844SAndroid Build Coastguard Worker }
296*d9f75844SAndroid Build Coastguard Worker 
297*d9f75844SAndroid Build Coastguard Worker template <typename C>
298*d9f75844SAndroid Build Coastguard Worker static void ToRtpCodecCapabilityTypeSpecific(const C& cricket_codec,
299*d9f75844SAndroid Build Coastguard Worker                                              RtpCodecCapability* codec);
300*d9f75844SAndroid Build Coastguard Worker 
301*d9f75844SAndroid Build Coastguard Worker template <>
ToRtpCodecCapabilityTypeSpecific(const cricket::AudioCodec & cricket_codec,RtpCodecCapability * codec)302*d9f75844SAndroid Build Coastguard Worker void ToRtpCodecCapabilityTypeSpecific<cricket::AudioCodec>(
303*d9f75844SAndroid Build Coastguard Worker     const cricket::AudioCodec& cricket_codec,
304*d9f75844SAndroid Build Coastguard Worker     RtpCodecCapability* codec) {
305*d9f75844SAndroid Build Coastguard Worker   codec->num_channels = static_cast<int>(cricket_codec.channels);
306*d9f75844SAndroid Build Coastguard Worker }
307*d9f75844SAndroid Build Coastguard Worker 
308*d9f75844SAndroid Build Coastguard Worker template <>
ToRtpCodecCapabilityTypeSpecific(const cricket::VideoCodec & cricket_codec,RtpCodecCapability * codec)309*d9f75844SAndroid Build Coastguard Worker void ToRtpCodecCapabilityTypeSpecific<cricket::VideoCodec>(
310*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoCodec& cricket_codec,
311*d9f75844SAndroid Build Coastguard Worker     RtpCodecCapability* codec) {
312*d9f75844SAndroid Build Coastguard Worker   if (cricket_codec.scalability_modes.empty() ||
313*d9f75844SAndroid Build Coastguard Worker       (cricket_codec.scalability_modes.size() == 1 &&
314*d9f75844SAndroid Build Coastguard Worker        cricket_codec.scalability_modes[0] == ScalabilityMode::kL1T1)) {
315*d9f75844SAndroid Build Coastguard Worker     // https://w3c.github.io/webrtc-svc/#dom-rtcrtpcodeccapability-scalabilitymodes
316*d9f75844SAndroid Build Coastguard Worker     // If a codec does not support encoding of scalability modes other than
317*d9f75844SAndroid Build Coastguard Worker     // "L1T1", then the scalabilityModes member is not provided.
318*d9f75844SAndroid Build Coastguard Worker     return;
319*d9f75844SAndroid Build Coastguard Worker   }
320*d9f75844SAndroid Build Coastguard Worker 
321*d9f75844SAndroid Build Coastguard Worker   codec->scalability_modes = cricket_codec.scalability_modes;
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker 
324*d9f75844SAndroid Build Coastguard Worker template <typename C>
ToRtpCodecCapability(const C & cricket_codec)325*d9f75844SAndroid Build Coastguard Worker RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec) {
326*d9f75844SAndroid Build Coastguard Worker   RtpCodecCapability codec;
327*d9f75844SAndroid Build Coastguard Worker   codec.name = cricket_codec.name;
328*d9f75844SAndroid Build Coastguard Worker   codec.kind = KindOfCodec<C>();
329*d9f75844SAndroid Build Coastguard Worker   codec.clock_rate.emplace(cricket_codec.clockrate);
330*d9f75844SAndroid Build Coastguard Worker   codec.preferred_payload_type.emplace(cricket_codec.id);
331*d9f75844SAndroid Build Coastguard Worker   for (const cricket::FeedbackParam& cricket_feedback :
332*d9f75844SAndroid Build Coastguard Worker        cricket_codec.feedback_params.params()) {
333*d9f75844SAndroid Build Coastguard Worker     absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
334*d9f75844SAndroid Build Coastguard Worker     if (feedback) {
335*d9f75844SAndroid Build Coastguard Worker       codec.rtcp_feedback.push_back(feedback.value());
336*d9f75844SAndroid Build Coastguard Worker     }
337*d9f75844SAndroid Build Coastguard Worker   }
338*d9f75844SAndroid Build Coastguard Worker   ToRtpCodecCapabilityTypeSpecific(cricket_codec, &codec);
339*d9f75844SAndroid Build Coastguard Worker   codec.parameters.insert(cricket_codec.params.begin(),
340*d9f75844SAndroid Build Coastguard Worker                           cricket_codec.params.end());
341*d9f75844SAndroid Build Coastguard Worker   return codec;
342*d9f75844SAndroid Build Coastguard Worker }
343*d9f75844SAndroid Build Coastguard Worker 
344*d9f75844SAndroid Build Coastguard Worker template RtpCodecCapability ToRtpCodecCapability<cricket::AudioCodec>(
345*d9f75844SAndroid Build Coastguard Worker     const cricket::AudioCodec& cricket_codec);
346*d9f75844SAndroid Build Coastguard Worker template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
347*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoCodec& cricket_codec);
348*d9f75844SAndroid Build Coastguard Worker 
349*d9f75844SAndroid Build Coastguard Worker template <typename C>
350*d9f75844SAndroid Build Coastguard Worker static void ToRtpCodecParametersTypeSpecific(const C& cricket_codec,
351*d9f75844SAndroid Build Coastguard Worker                                              RtpCodecParameters* codec);
352*d9f75844SAndroid Build Coastguard Worker template <>
ToRtpCodecParametersTypeSpecific(const cricket::AudioCodec & cricket_codec,RtpCodecParameters * codec)353*d9f75844SAndroid Build Coastguard Worker void ToRtpCodecParametersTypeSpecific<cricket::AudioCodec>(
354*d9f75844SAndroid Build Coastguard Worker     const cricket::AudioCodec& cricket_codec,
355*d9f75844SAndroid Build Coastguard Worker     RtpCodecParameters* codec) {
356*d9f75844SAndroid Build Coastguard Worker   codec->num_channels = static_cast<int>(cricket_codec.channels);
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker 
359*d9f75844SAndroid Build Coastguard Worker template <>
ToRtpCodecParametersTypeSpecific(const cricket::VideoCodec & cricket_codec,RtpCodecParameters * codec)360*d9f75844SAndroid Build Coastguard Worker void ToRtpCodecParametersTypeSpecific<cricket::VideoCodec>(
361*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoCodec& cricket_codec,
362*d9f75844SAndroid Build Coastguard Worker     RtpCodecParameters* codec) {}
363*d9f75844SAndroid Build Coastguard Worker 
364*d9f75844SAndroid Build Coastguard Worker template <typename C>
ToRtpCodecParameters(const C & cricket_codec)365*d9f75844SAndroid Build Coastguard Worker RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec) {
366*d9f75844SAndroid Build Coastguard Worker   RtpCodecParameters codec_param;
367*d9f75844SAndroid Build Coastguard Worker   codec_param.name = cricket_codec.name;
368*d9f75844SAndroid Build Coastguard Worker   codec_param.kind = KindOfCodec<C>();
369*d9f75844SAndroid Build Coastguard Worker   codec_param.clock_rate.emplace(cricket_codec.clockrate);
370*d9f75844SAndroid Build Coastguard Worker   codec_param.payload_type = cricket_codec.id;
371*d9f75844SAndroid Build Coastguard Worker   for (const cricket::FeedbackParam& cricket_feedback :
372*d9f75844SAndroid Build Coastguard Worker        cricket_codec.feedback_params.params()) {
373*d9f75844SAndroid Build Coastguard Worker     absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
374*d9f75844SAndroid Build Coastguard Worker     if (feedback) {
375*d9f75844SAndroid Build Coastguard Worker       codec_param.rtcp_feedback.push_back(feedback.value());
376*d9f75844SAndroid Build Coastguard Worker     }
377*d9f75844SAndroid Build Coastguard Worker   }
378*d9f75844SAndroid Build Coastguard Worker   ToRtpCodecParametersTypeSpecific(cricket_codec, &codec_param);
379*d9f75844SAndroid Build Coastguard Worker   codec_param.parameters = cricket_codec.params;
380*d9f75844SAndroid Build Coastguard Worker   return codec_param;
381*d9f75844SAndroid Build Coastguard Worker }
382*d9f75844SAndroid Build Coastguard Worker 
383*d9f75844SAndroid Build Coastguard Worker template RtpCodecParameters ToRtpCodecParameters<cricket::AudioCodec>(
384*d9f75844SAndroid Build Coastguard Worker     const cricket::AudioCodec& cricket_codec);
385*d9f75844SAndroid Build Coastguard Worker template RtpCodecParameters ToRtpCodecParameters<cricket::VideoCodec>(
386*d9f75844SAndroid Build Coastguard Worker     const cricket::VideoCodec& cricket_codec);
387*d9f75844SAndroid Build Coastguard Worker 
388*d9f75844SAndroid Build Coastguard Worker template <class C>
ToRtpCapabilities(const std::vector<C> & cricket_codecs,const cricket::RtpHeaderExtensions & cricket_extensions)389*d9f75844SAndroid Build Coastguard Worker RtpCapabilities ToRtpCapabilities(
390*d9f75844SAndroid Build Coastguard Worker     const std::vector<C>& cricket_codecs,
391*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions) {
392*d9f75844SAndroid Build Coastguard Worker   RtpCapabilities capabilities;
393*d9f75844SAndroid Build Coastguard Worker   bool have_red = false;
394*d9f75844SAndroid Build Coastguard Worker   bool have_ulpfec = false;
395*d9f75844SAndroid Build Coastguard Worker   bool have_flexfec = false;
396*d9f75844SAndroid Build Coastguard Worker   bool have_rtx = false;
397*d9f75844SAndroid Build Coastguard Worker   for (const C& cricket_codec : cricket_codecs) {
398*d9f75844SAndroid Build Coastguard Worker     if (cricket_codec.name == cricket::kRedCodecName) {
399*d9f75844SAndroid Build Coastguard Worker       have_red = true;
400*d9f75844SAndroid Build Coastguard Worker     } else if (cricket_codec.name == cricket::kUlpfecCodecName) {
401*d9f75844SAndroid Build Coastguard Worker       have_ulpfec = true;
402*d9f75844SAndroid Build Coastguard Worker     } else if (cricket_codec.name == cricket::kFlexfecCodecName) {
403*d9f75844SAndroid Build Coastguard Worker       have_flexfec = true;
404*d9f75844SAndroid Build Coastguard Worker     } else if (cricket_codec.name == cricket::kRtxCodecName) {
405*d9f75844SAndroid Build Coastguard Worker       if (have_rtx) {
406*d9f75844SAndroid Build Coastguard Worker         // There should only be one RTX codec entry
407*d9f75844SAndroid Build Coastguard Worker         continue;
408*d9f75844SAndroid Build Coastguard Worker       }
409*d9f75844SAndroid Build Coastguard Worker       have_rtx = true;
410*d9f75844SAndroid Build Coastguard Worker     }
411*d9f75844SAndroid Build Coastguard Worker     auto codec_capability = ToRtpCodecCapability(cricket_codec);
412*d9f75844SAndroid Build Coastguard Worker     if (cricket_codec.name == cricket::kRtxCodecName) {
413*d9f75844SAndroid Build Coastguard Worker       // RTX codec should not have any parameter
414*d9f75844SAndroid Build Coastguard Worker       codec_capability.parameters.clear();
415*d9f75844SAndroid Build Coastguard Worker     }
416*d9f75844SAndroid Build Coastguard Worker     capabilities.codecs.push_back(codec_capability);
417*d9f75844SAndroid Build Coastguard Worker   }
418*d9f75844SAndroid Build Coastguard Worker   for (const RtpExtension& cricket_extension : cricket_extensions) {
419*d9f75844SAndroid Build Coastguard Worker     capabilities.header_extensions.emplace_back(cricket_extension.uri,
420*d9f75844SAndroid Build Coastguard Worker                                                 cricket_extension.id);
421*d9f75844SAndroid Build Coastguard Worker   }
422*d9f75844SAndroid Build Coastguard Worker   if (have_red) {
423*d9f75844SAndroid Build Coastguard Worker     capabilities.fec.push_back(FecMechanism::RED);
424*d9f75844SAndroid Build Coastguard Worker   }
425*d9f75844SAndroid Build Coastguard Worker   if (have_red && have_ulpfec) {
426*d9f75844SAndroid Build Coastguard Worker     capabilities.fec.push_back(FecMechanism::RED_AND_ULPFEC);
427*d9f75844SAndroid Build Coastguard Worker   }
428*d9f75844SAndroid Build Coastguard Worker   if (have_flexfec) {
429*d9f75844SAndroid Build Coastguard Worker     capabilities.fec.push_back(FecMechanism::FLEXFEC);
430*d9f75844SAndroid Build Coastguard Worker   }
431*d9f75844SAndroid Build Coastguard Worker   return capabilities;
432*d9f75844SAndroid Build Coastguard Worker }
433*d9f75844SAndroid Build Coastguard Worker 
434*d9f75844SAndroid Build Coastguard Worker template RtpCapabilities ToRtpCapabilities<cricket::AudioCodec>(
435*d9f75844SAndroid Build Coastguard Worker     const std::vector<cricket::AudioCodec>& cricket_codecs,
436*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions);
437*d9f75844SAndroid Build Coastguard Worker template RtpCapabilities ToRtpCapabilities<cricket::VideoCodec>(
438*d9f75844SAndroid Build Coastguard Worker     const std::vector<cricket::VideoCodec>& cricket_codecs,
439*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions);
440*d9f75844SAndroid Build Coastguard Worker 
441*d9f75844SAndroid Build Coastguard Worker template <class C>
ToRtpParameters(const std::vector<C> & cricket_codecs,const cricket::RtpHeaderExtensions & cricket_extensions,const cricket::StreamParamsVec & stream_params)442*d9f75844SAndroid Build Coastguard Worker RtpParameters ToRtpParameters(
443*d9f75844SAndroid Build Coastguard Worker     const std::vector<C>& cricket_codecs,
444*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions,
445*d9f75844SAndroid Build Coastguard Worker     const cricket::StreamParamsVec& stream_params) {
446*d9f75844SAndroid Build Coastguard Worker   RtpParameters rtp_parameters;
447*d9f75844SAndroid Build Coastguard Worker   for (const C& cricket_codec : cricket_codecs) {
448*d9f75844SAndroid Build Coastguard Worker     rtp_parameters.codecs.push_back(ToRtpCodecParameters(cricket_codec));
449*d9f75844SAndroid Build Coastguard Worker   }
450*d9f75844SAndroid Build Coastguard Worker   for (const RtpExtension& cricket_extension : cricket_extensions) {
451*d9f75844SAndroid Build Coastguard Worker     rtp_parameters.header_extensions.emplace_back(cricket_extension.uri,
452*d9f75844SAndroid Build Coastguard Worker                                                   cricket_extension.id);
453*d9f75844SAndroid Build Coastguard Worker   }
454*d9f75844SAndroid Build Coastguard Worker   rtp_parameters.encodings = ToRtpEncodings(stream_params);
455*d9f75844SAndroid Build Coastguard Worker   return rtp_parameters;
456*d9f75844SAndroid Build Coastguard Worker }
457*d9f75844SAndroid Build Coastguard Worker 
458*d9f75844SAndroid Build Coastguard Worker template RtpParameters ToRtpParameters<cricket::AudioCodec>(
459*d9f75844SAndroid Build Coastguard Worker     const std::vector<cricket::AudioCodec>& cricket_codecs,
460*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions,
461*d9f75844SAndroid Build Coastguard Worker     const cricket::StreamParamsVec& stream_params);
462*d9f75844SAndroid Build Coastguard Worker template RtpParameters ToRtpParameters<cricket::VideoCodec>(
463*d9f75844SAndroid Build Coastguard Worker     const std::vector<cricket::VideoCodec>& cricket_codecs,
464*d9f75844SAndroid Build Coastguard Worker     const cricket::RtpHeaderExtensions& cricket_extensions,
465*d9f75844SAndroid Build Coastguard Worker     const cricket::StreamParamsVec& stream_params);
466*d9f75844SAndroid Build Coastguard Worker 
467*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
468