blob: b7fb69175cdb0d3ee7f2872cbb693ec6640e3c00 [file] [log] [blame]
deadbeefe814a0d2017-02-25 18:15:09 -08001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtp_parameters_conversion.h"
deadbeefe814a0d2017-02-25 18:15:09 -080012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <cstdint>
deadbeefe814a0d2017-02-25 18:15:09 -080014#include <set>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string>
16#include <unordered_map>
deadbeefe814a0d2017-02-25 18:15:09 -080017#include <utility>
18
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/array_view.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "api/media_types.h"
21#include "media/base/media_constants.h"
22#include "media/base/rtp_utils.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "rtc_base/checks.h"
24#include "rtc_base/logging.h"
25#include "rtc_base/strings/string_builder.h"
deadbeefe814a0d2017-02-25 18:15:09 -080026
27namespace webrtc {
28
29RTCErrorOr<cricket::FeedbackParam> ToCricketFeedbackParam(
30 const RtcpFeedback& feedback) {
31 switch (feedback.type) {
32 case RtcpFeedbackType::CCM:
33 if (!feedback.message_type) {
34 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
35 "Missing message type in CCM RtcpFeedback.");
36 } else if (*feedback.message_type != RtcpFeedbackMessageType::FIR) {
37 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
38 "Invalid message type in CCM RtcpFeedback.");
39 }
40 return cricket::FeedbackParam(cricket::kRtcpFbParamCcm,
41 cricket::kRtcpFbCcmParamFir);
Elad Alonfadb1812019-05-24 13:40:02 +020042 case RtcpFeedbackType::LNTF:
43 if (feedback.message_type) {
44 LOG_AND_RETURN_ERROR(
45 RTCErrorType::INVALID_PARAMETER,
46 "Didn't expect message type in LNTF RtcpFeedback.");
47 }
48 return cricket::FeedbackParam(cricket::kRtcpFbParamLntf);
deadbeefe814a0d2017-02-25 18:15:09 -080049 case RtcpFeedbackType::NACK:
50 if (!feedback.message_type) {
51 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
52 "Missing message type in NACK RtcpFeedback.");
53 }
54 switch (*feedback.message_type) {
55 case RtcpFeedbackMessageType::GENERIC_NACK:
56 return cricket::FeedbackParam(cricket::kRtcpFbParamNack);
57 case RtcpFeedbackMessageType::PLI:
58 return cricket::FeedbackParam(cricket::kRtcpFbParamNack,
59 cricket::kRtcpFbNackParamPli);
60 default:
61 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
62 "Invalid message type in NACK RtcpFeedback.");
63 }
64 case RtcpFeedbackType::REMB:
65 if (feedback.message_type) {
66 LOG_AND_RETURN_ERROR(
67 RTCErrorType::INVALID_PARAMETER,
68 "Didn't expect message type in REMB RtcpFeedback.");
69 }
70 return cricket::FeedbackParam(cricket::kRtcpFbParamRemb);
71 case RtcpFeedbackType::TRANSPORT_CC:
72 if (feedback.message_type) {
73 LOG_AND_RETURN_ERROR(
74 RTCErrorType::INVALID_PARAMETER,
75 "Didn't expect message type in transport-cc RtcpFeedback.");
76 }
77 return cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc);
78 }
79 // Not reached; avoids compile warning.
80 FATAL();
81}
82
83template <typename C>
84static RTCError ToCricketCodecTypeSpecific(const RtpCodecParameters& codec,
85 C* cricket_codec);
86
87template <>
88RTCError ToCricketCodecTypeSpecific<cricket::AudioCodec>(
89 const RtpCodecParameters& codec,
90 cricket::AudioCodec* cricket_codec) {
91 if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
92 LOG_AND_RETURN_ERROR(
93 RTCErrorType::INVALID_PARAMETER,
94 "Can't use video codec with audio sender or receiver.");
95 }
96 if (!codec.num_channels) {
97 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
98 "Missing number of channels for audio codec.");
99 }
100 if (*codec.num_channels <= 0) {
101 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
102 "Number of channels must be positive.");
103 }
104 cricket_codec->channels = *codec.num_channels;
105 if (!codec.clock_rate) {
106 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
107 "Missing codec clock rate.");
108 }
109 if (*codec.clock_rate <= 0) {
110 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
111 "Clock rate must be positive.");
112 }
113 cricket_codec->clockrate = *codec.clock_rate;
114 return RTCError::OK();
115}
116
117// Video codecs don't use num_channels or clock_rate, but they should at least
118// be validated to ensure the application isn't trying to do something it
119// doesn't intend to.
120template <>
121RTCError ToCricketCodecTypeSpecific<cricket::VideoCodec>(
122 const RtpCodecParameters& codec,
123 cricket::VideoCodec*) {
124 if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
125 LOG_AND_RETURN_ERROR(
126 RTCErrorType::INVALID_PARAMETER,
127 "Can't use audio codec with video sender or receiver.");
128 }
129 if (codec.num_channels) {
130 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
131 "Video codec shouldn't have num_channels.");
132 }
133 if (!codec.clock_rate) {
134 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
135 "Missing codec clock rate.");
136 }
137 if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
138 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
139 "Video clock rate must be 90000.");
140 }
141 return RTCError::OK();
142}
143
144template <typename C>
145RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec) {
146 C cricket_codec;
147 // Start with audio/video specific conversion.
148 RTCError err = ToCricketCodecTypeSpecific(codec, &cricket_codec);
149 if (!err.ok()) {
150 return std::move(err);
151 }
152 cricket_codec.name = codec.name;
153 if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200154 char buf[40];
155 rtc::SimpleStringBuilder sb(buf);
156 sb << "Invalid payload type: " << codec.payload_type;
157 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800158 }
159 cricket_codec.id = codec.payload_type;
160 for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
161 auto result = ToCricketFeedbackParam(feedback);
162 if (!result.ok()) {
163 return result.MoveError();
164 }
165 cricket_codec.AddFeedbackParam(result.MoveValue());
166 }
167 cricket_codec.params.insert(codec.parameters.begin(), codec.parameters.end());
168 return std::move(cricket_codec);
169}
170
171template RTCErrorOr<cricket::AudioCodec> ToCricketCodec(
172 const RtpCodecParameters& codec);
173template RTCErrorOr<cricket::VideoCodec> ToCricketCodec(
174 const RtpCodecParameters& codec);
175
176template <typename C>
177RTCErrorOr<std::vector<C>> ToCricketCodecs(
178 const std::vector<RtpCodecParameters>& codecs) {
179 std::vector<C> cricket_codecs;
180 std::set<int> seen_payload_types;
181 for (const RtpCodecParameters& codec : codecs) {
182 auto result = ToCricketCodec<C>(codec);
183 if (!result.ok()) {
184 return result.MoveError();
185 }
186 if (!seen_payload_types.insert(codec.payload_type).second) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200187 char buf[40];
188 rtc::SimpleStringBuilder sb(buf);
189 sb << "Duplicate payload type: " << codec.payload_type;
190 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800191 }
192 cricket_codecs.push_back(result.MoveValue());
193 }
194 return std::move(cricket_codecs);
195}
196
197template RTCErrorOr<std::vector<cricket::AudioCodec>> ToCricketCodecs<
198 cricket::AudioCodec>(const std::vector<RtpCodecParameters>& codecs);
199
200template RTCErrorOr<std::vector<cricket::VideoCodec>> ToCricketCodecs<
201 cricket::VideoCodec>(const std::vector<RtpCodecParameters>& codecs);
202
203RTCErrorOr<cricket::RtpHeaderExtensions> ToCricketRtpHeaderExtensions(
204 const std::vector<RtpHeaderExtensionParameters>& extensions) {
205 cricket::RtpHeaderExtensions cricket_extensions;
deadbeefe814a0d2017-02-25 18:15:09 -0800206 std::set<int> seen_header_extension_ids;
207 for (const RtpHeaderExtensionParameters& extension : extensions) {
208 if (extension.id < RtpHeaderExtensionParameters::kMinId ||
209 extension.id > RtpHeaderExtensionParameters::kMaxId) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200210 char buf[50];
211 rtc::SimpleStringBuilder sb(buf);
212 sb << "Invalid header extension id: " << extension.id;
213 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800214 }
215 if (!seen_header_extension_ids.insert(extension.id).second) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200216 char buf[50];
217 rtc::SimpleStringBuilder sb(buf);
218 sb << "Duplicate header extension id: " << extension.id;
219 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800220 }
221 cricket_extensions.push_back(extension);
222 }
223 return std::move(cricket_extensions);
224}
225
226RTCErrorOr<cricket::StreamParamsVec> ToCricketStreamParamsVec(
227 const std::vector<RtpEncodingParameters>& encodings) {
228 if (encodings.size() > 1u) {
229 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
230 "ORTC API implementation doesn't currently "
231 "support simulcast or layered encodings.");
232 } else if (encodings.empty()) {
233 return cricket::StreamParamsVec();
234 }
235 cricket::StreamParamsVec cricket_streams;
236 const RtpEncodingParameters& encoding = encodings[0];
237 if (encoding.rtx && encoding.rtx->ssrc && !encoding.ssrc) {
238 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
239 "Setting an RTX SSRC explicitly while leaving the "
240 "primary SSRC unset is not currently supported.");
241 }
242 if (encoding.ssrc) {
243 cricket::StreamParams stream_params;
244 stream_params.add_ssrc(*encoding.ssrc);
245 if (encoding.rtx && encoding.rtx->ssrc) {
246 stream_params.AddFidSsrc(*encoding.ssrc, *encoding.rtx->ssrc);
247 }
248 cricket_streams.push_back(std::move(stream_params));
249 }
250 return std::move(cricket_streams);
251}
252
Danil Chapovalov00c71832018-06-15 15:58:38 +0200253absl::optional<RtcpFeedback> ToRtcpFeedback(
deadbeefe814a0d2017-02-25 18:15:09 -0800254 const cricket::FeedbackParam& cricket_feedback) {
255 if (cricket_feedback.id() == cricket::kRtcpFbParamCcm) {
256 if (cricket_feedback.param() == cricket::kRtcpFbCcmParamFir) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100257 return RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR);
deadbeefe814a0d2017-02-25 18:15:09 -0800258 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100259 RTC_LOG(LS_WARNING) << "Unsupported parameter for CCM RTCP feedback: "
260 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200261 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800262 }
Elad Alonfadb1812019-05-24 13:40:02 +0200263 } else if (cricket_feedback.id() == cricket::kRtcpFbParamLntf) {
264 if (cricket_feedback.param().empty()) {
265 return RtcpFeedback(RtcpFeedbackType::LNTF);
266 } else {
267 RTC_LOG(LS_WARNING) << "Unsupported parameter for LNTF RTCP feedback: "
268 << cricket_feedback.param();
269 return absl::nullopt;
270 }
deadbeefe814a0d2017-02-25 18:15:09 -0800271 } else if (cricket_feedback.id() == cricket::kRtcpFbParamNack) {
272 if (cricket_feedback.param().empty()) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100273 return RtcpFeedback(RtcpFeedbackType::NACK,
274 RtcpFeedbackMessageType::GENERIC_NACK);
deadbeefe814a0d2017-02-25 18:15:09 -0800275 } else if (cricket_feedback.param() == cricket::kRtcpFbNackParamPli) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100276 return RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI);
deadbeefe814a0d2017-02-25 18:15:09 -0800277 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100278 RTC_LOG(LS_WARNING) << "Unsupported parameter for NACK RTCP feedback: "
279 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200280 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800281 }
282 } else if (cricket_feedback.id() == cricket::kRtcpFbParamRemb) {
283 if (!cricket_feedback.param().empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100284 RTC_LOG(LS_WARNING) << "Unsupported parameter for REMB RTCP feedback: "
285 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200286 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800287 } else {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100288 return RtcpFeedback(RtcpFeedbackType::REMB);
deadbeefe814a0d2017-02-25 18:15:09 -0800289 }
290 } else if (cricket_feedback.id() == cricket::kRtcpFbParamTransportCc) {
291 if (!cricket_feedback.param().empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100292 RTC_LOG(LS_WARNING)
deadbeefe814a0d2017-02-25 18:15:09 -0800293 << "Unsupported parameter for transport-cc RTCP feedback: "
294 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200295 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800296 } else {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100297 return RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC);
deadbeefe814a0d2017-02-25 18:15:09 -0800298 }
299 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100300 RTC_LOG(LS_WARNING) << "Unsupported RTCP feedback type: "
301 << cricket_feedback.id();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200302 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800303}
304
zhihuang24366392017-03-08 17:15:06 -0800305std::vector<RtpEncodingParameters> ToRtpEncodings(
306 const cricket::StreamParamsVec& stream_params) {
307 std::vector<RtpEncodingParameters> rtp_encodings;
308 for (const cricket::StreamParams& stream_param : stream_params) {
309 RtpEncodingParameters rtp_encoding;
310 rtp_encoding.ssrc.emplace(stream_param.first_ssrc());
311 uint32_t rtx_ssrc = 0;
312 if (stream_param.GetFidSsrc(stream_param.first_ssrc(), &rtx_ssrc)) {
313 RtpRtxParameters rtx_param(rtx_ssrc);
314 rtp_encoding.rtx.emplace(rtx_param);
315 }
316 rtp_encodings.push_back(std::move(rtp_encoding));
317 }
318 return rtp_encodings;
319}
320
deadbeefe814a0d2017-02-25 18:15:09 -0800321template <typename C>
322cricket::MediaType KindOfCodec();
323
324template <>
325cricket::MediaType KindOfCodec<cricket::AudioCodec>() {
326 return cricket::MEDIA_TYPE_AUDIO;
327}
328
329template <>
330cricket::MediaType KindOfCodec<cricket::VideoCodec>() {
331 return cricket::MEDIA_TYPE_VIDEO;
332}
333
334template <typename C>
335static void ToRtpCodecCapabilityTypeSpecific(const C& cricket_codec,
336 RtpCodecCapability* codec);
337
338template <>
339void ToRtpCodecCapabilityTypeSpecific<cricket::AudioCodec>(
340 const cricket::AudioCodec& cricket_codec,
341 RtpCodecCapability* codec) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100342 codec->num_channels = static_cast<int>(cricket_codec.channels);
deadbeefe814a0d2017-02-25 18:15:09 -0800343}
344
345template <>
346void ToRtpCodecCapabilityTypeSpecific<cricket::VideoCodec>(
347 const cricket::VideoCodec& cricket_codec,
348 RtpCodecCapability* codec) {}
349
350template <typename C>
351RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec) {
352 RtpCodecCapability codec;
353 codec.name = cricket_codec.name;
354 codec.kind = KindOfCodec<C>();
355 codec.clock_rate.emplace(cricket_codec.clockrate);
356 codec.preferred_payload_type.emplace(cricket_codec.id);
357 for (const cricket::FeedbackParam& cricket_feedback :
358 cricket_codec.feedback_params.params()) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200359 absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
deadbeefe814a0d2017-02-25 18:15:09 -0800360 if (feedback) {
Danil Chapovalov57ff2732018-03-28 11:25:15 +0200361 codec.rtcp_feedback.push_back(feedback.value());
deadbeefe814a0d2017-02-25 18:15:09 -0800362 }
363 }
364 ToRtpCodecCapabilityTypeSpecific(cricket_codec, &codec);
365 codec.parameters.insert(cricket_codec.params.begin(),
366 cricket_codec.params.end());
367 return codec;
368}
369
370template RtpCodecCapability ToRtpCodecCapability<cricket::AudioCodec>(
371 const cricket::AudioCodec& cricket_codec);
372template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
373 const cricket::VideoCodec& cricket_codec);
374
zhihuang24366392017-03-08 17:15:06 -0800375template <typename C>
376static void ToRtpCodecParametersTypeSpecific(const C& cricket_codec,
377 RtpCodecParameters* codec);
378template <>
379void ToRtpCodecParametersTypeSpecific<cricket::AudioCodec>(
380 const cricket::AudioCodec& cricket_codec,
381 RtpCodecParameters* codec) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100382 codec->num_channels = static_cast<int>(cricket_codec.channels);
zhihuang24366392017-03-08 17:15:06 -0800383}
384
385template <>
386void ToRtpCodecParametersTypeSpecific<cricket::VideoCodec>(
387 const cricket::VideoCodec& cricket_codec,
388 RtpCodecParameters* codec) {}
389
390template <typename C>
391RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec) {
392 RtpCodecParameters codec_param;
393 codec_param.name = cricket_codec.name;
394 codec_param.kind = KindOfCodec<C>();
395 codec_param.clock_rate.emplace(cricket_codec.clockrate);
396 codec_param.payload_type = cricket_codec.id;
397 for (const cricket::FeedbackParam& cricket_feedback :
398 cricket_codec.feedback_params.params()) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200399 absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
zhihuang24366392017-03-08 17:15:06 -0800400 if (feedback) {
Danil Chapovalov57ff2732018-03-28 11:25:15 +0200401 codec_param.rtcp_feedback.push_back(feedback.value());
zhihuang24366392017-03-08 17:15:06 -0800402 }
403 }
404 ToRtpCodecParametersTypeSpecific(cricket_codec, &codec_param);
405 codec_param.parameters.insert(cricket_codec.params.begin(),
406 cricket_codec.params.end());
407 return codec_param;
408}
409
410template RtpCodecParameters ToRtpCodecParameters<cricket::AudioCodec>(
411 const cricket::AudioCodec& cricket_codec);
412template RtpCodecParameters ToRtpCodecParameters<cricket::VideoCodec>(
413 const cricket::VideoCodec& cricket_codec);
414
deadbeefe814a0d2017-02-25 18:15:09 -0800415template <class C>
416RtpCapabilities ToRtpCapabilities(
417 const std::vector<C>& cricket_codecs,
418 const cricket::RtpHeaderExtensions& cricket_extensions) {
419 RtpCapabilities capabilities;
420 bool have_red = false;
421 bool have_ulpfec = false;
422 bool have_flexfec = false;
Florent Castelli5473a452018-11-06 17:27:21 +0100423 bool have_rtx = false;
deadbeefe814a0d2017-02-25 18:15:09 -0800424 for (const C& cricket_codec : cricket_codecs) {
425 if (cricket_codec.name == cricket::kRedCodecName) {
426 have_red = true;
427 } else if (cricket_codec.name == cricket::kUlpfecCodecName) {
428 have_ulpfec = true;
429 } else if (cricket_codec.name == cricket::kFlexfecCodecName) {
430 have_flexfec = true;
Florent Castelli5473a452018-11-06 17:27:21 +0100431 } else if (cricket_codec.name == cricket::kRtxCodecName) {
432 if (have_rtx) {
433 // There should only be one RTX codec entry
434 continue;
435 }
436 have_rtx = true;
deadbeefe814a0d2017-02-25 18:15:09 -0800437 }
Florent Castelli5473a452018-11-06 17:27:21 +0100438 auto codec_capability = ToRtpCodecCapability(cricket_codec);
439 if (cricket_codec.name == cricket::kRtxCodecName) {
440 // RTX codec should not have any parameter
441 codec_capability.parameters.clear();
442 }
443 capabilities.codecs.push_back(codec_capability);
deadbeefe814a0d2017-02-25 18:15:09 -0800444 }
445 for (const RtpExtension& cricket_extension : cricket_extensions) {
446 capabilities.header_extensions.emplace_back(cricket_extension.uri,
447 cricket_extension.id);
448 }
449 if (have_red) {
450 capabilities.fec.push_back(FecMechanism::RED);
451 }
452 if (have_red && have_ulpfec) {
453 capabilities.fec.push_back(FecMechanism::RED_AND_ULPFEC);
454 }
455 if (have_flexfec) {
456 capabilities.fec.push_back(FecMechanism::FLEXFEC);
457 }
458 return capabilities;
459}
460
461template RtpCapabilities ToRtpCapabilities<cricket::AudioCodec>(
462 const std::vector<cricket::AudioCodec>& cricket_codecs,
463 const cricket::RtpHeaderExtensions& cricket_extensions);
464template RtpCapabilities ToRtpCapabilities<cricket::VideoCodec>(
465 const std::vector<cricket::VideoCodec>& cricket_codecs,
466 const cricket::RtpHeaderExtensions& cricket_extensions);
467
zhihuang24366392017-03-08 17:15:06 -0800468template <class C>
469RtpParameters ToRtpParameters(
470 const std::vector<C>& cricket_codecs,
471 const cricket::RtpHeaderExtensions& cricket_extensions,
472 const cricket::StreamParamsVec& stream_params) {
473 RtpParameters rtp_parameters;
474 for (const C& cricket_codec : cricket_codecs) {
475 rtp_parameters.codecs.push_back(ToRtpCodecParameters(cricket_codec));
476 }
477 for (const RtpExtension& cricket_extension : cricket_extensions) {
478 rtp_parameters.header_extensions.emplace_back(cricket_extension.uri,
479 cricket_extension.id);
480 }
481 rtp_parameters.encodings = ToRtpEncodings(stream_params);
482 return rtp_parameters;
483}
484
485template RtpParameters ToRtpParameters<cricket::AudioCodec>(
486 const std::vector<cricket::AudioCodec>& cricket_codecs,
487 const cricket::RtpHeaderExtensions& cricket_extensions,
488 const cricket::StreamParamsVec& stream_params);
489template RtpParameters ToRtpParameters<cricket::VideoCodec>(
490 const std::vector<cricket::VideoCodec>& cricket_codecs,
491 const cricket::RtpHeaderExtensions& cricket_extensions,
492 const cricket::StreamParamsVec& stream_params);
493
deadbeefe814a0d2017-02-25 18:15:09 -0800494} // namespace webrtc