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