blob: cf9e6e12526534cb97edd4514335a21d7d32fea7 [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);
42 case RtcpFeedbackType::NACK:
43 if (!feedback.message_type) {
44 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
45 "Missing message type in NACK RtcpFeedback.");
46 }
47 switch (*feedback.message_type) {
48 case RtcpFeedbackMessageType::GENERIC_NACK:
49 return cricket::FeedbackParam(cricket::kRtcpFbParamNack);
50 case RtcpFeedbackMessageType::PLI:
51 return cricket::FeedbackParam(cricket::kRtcpFbParamNack,
52 cricket::kRtcpFbNackParamPli);
53 default:
54 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
55 "Invalid message type in NACK RtcpFeedback.");
56 }
57 case RtcpFeedbackType::REMB:
58 if (feedback.message_type) {
59 LOG_AND_RETURN_ERROR(
60 RTCErrorType::INVALID_PARAMETER,
61 "Didn't expect message type in REMB RtcpFeedback.");
62 }
63 return cricket::FeedbackParam(cricket::kRtcpFbParamRemb);
64 case RtcpFeedbackType::TRANSPORT_CC:
65 if (feedback.message_type) {
66 LOG_AND_RETURN_ERROR(
67 RTCErrorType::INVALID_PARAMETER,
68 "Didn't expect message type in transport-cc RtcpFeedback.");
69 }
70 return cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc);
71 }
72 // Not reached; avoids compile warning.
73 FATAL();
74}
75
76template <typename C>
77static RTCError ToCricketCodecTypeSpecific(const RtpCodecParameters& codec,
78 C* cricket_codec);
79
80template <>
81RTCError ToCricketCodecTypeSpecific<cricket::AudioCodec>(
82 const RtpCodecParameters& codec,
83 cricket::AudioCodec* cricket_codec) {
84 if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
85 LOG_AND_RETURN_ERROR(
86 RTCErrorType::INVALID_PARAMETER,
87 "Can't use video codec with audio sender or receiver.");
88 }
89 if (!codec.num_channels) {
90 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
91 "Missing number of channels for audio codec.");
92 }
93 if (*codec.num_channels <= 0) {
94 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
95 "Number of channels must be positive.");
96 }
97 cricket_codec->channels = *codec.num_channels;
98 if (!codec.clock_rate) {
99 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
100 "Missing codec clock rate.");
101 }
102 if (*codec.clock_rate <= 0) {
103 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
104 "Clock rate must be positive.");
105 }
106 cricket_codec->clockrate = *codec.clock_rate;
107 return RTCError::OK();
108}
109
110// Video codecs don't use num_channels or clock_rate, but they should at least
111// be validated to ensure the application isn't trying to do something it
112// doesn't intend to.
113template <>
114RTCError ToCricketCodecTypeSpecific<cricket::VideoCodec>(
115 const RtpCodecParameters& codec,
116 cricket::VideoCodec*) {
117 if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
118 LOG_AND_RETURN_ERROR(
119 RTCErrorType::INVALID_PARAMETER,
120 "Can't use audio codec with video sender or receiver.");
121 }
122 if (codec.num_channels) {
123 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
124 "Video codec shouldn't have num_channels.");
125 }
126 if (!codec.clock_rate) {
127 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
128 "Missing codec clock rate.");
129 }
130 if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
131 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
132 "Video clock rate must be 90000.");
133 }
134 return RTCError::OK();
135}
136
137template <typename C>
138RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec) {
139 C cricket_codec;
140 // Start with audio/video specific conversion.
141 RTCError err = ToCricketCodecTypeSpecific(codec, &cricket_codec);
142 if (!err.ok()) {
143 return std::move(err);
144 }
145 cricket_codec.name = codec.name;
146 if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200147 char buf[40];
148 rtc::SimpleStringBuilder sb(buf);
149 sb << "Invalid payload type: " << codec.payload_type;
150 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800151 }
152 cricket_codec.id = codec.payload_type;
153 for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
154 auto result = ToCricketFeedbackParam(feedback);
155 if (!result.ok()) {
156 return result.MoveError();
157 }
158 cricket_codec.AddFeedbackParam(result.MoveValue());
159 }
160 cricket_codec.params.insert(codec.parameters.begin(), codec.parameters.end());
161 return std::move(cricket_codec);
162}
163
164template RTCErrorOr<cricket::AudioCodec> ToCricketCodec(
165 const RtpCodecParameters& codec);
166template RTCErrorOr<cricket::VideoCodec> ToCricketCodec(
167 const RtpCodecParameters& codec);
168
169template <typename C>
170RTCErrorOr<std::vector<C>> ToCricketCodecs(
171 const std::vector<RtpCodecParameters>& codecs) {
172 std::vector<C> cricket_codecs;
173 std::set<int> seen_payload_types;
174 for (const RtpCodecParameters& codec : codecs) {
175 auto result = ToCricketCodec<C>(codec);
176 if (!result.ok()) {
177 return result.MoveError();
178 }
179 if (!seen_payload_types.insert(codec.payload_type).second) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200180 char buf[40];
181 rtc::SimpleStringBuilder sb(buf);
182 sb << "Duplicate payload type: " << codec.payload_type;
183 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800184 }
185 cricket_codecs.push_back(result.MoveValue());
186 }
187 return std::move(cricket_codecs);
188}
189
190template RTCErrorOr<std::vector<cricket::AudioCodec>> ToCricketCodecs<
191 cricket::AudioCodec>(const std::vector<RtpCodecParameters>& codecs);
192
193template RTCErrorOr<std::vector<cricket::VideoCodec>> ToCricketCodecs<
194 cricket::VideoCodec>(const std::vector<RtpCodecParameters>& codecs);
195
196RTCErrorOr<cricket::RtpHeaderExtensions> ToCricketRtpHeaderExtensions(
197 const std::vector<RtpHeaderExtensionParameters>& extensions) {
198 cricket::RtpHeaderExtensions cricket_extensions;
deadbeefe814a0d2017-02-25 18:15:09 -0800199 std::set<int> seen_header_extension_ids;
200 for (const RtpHeaderExtensionParameters& extension : extensions) {
201 if (extension.id < RtpHeaderExtensionParameters::kMinId ||
202 extension.id > RtpHeaderExtensionParameters::kMaxId) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200203 char buf[50];
204 rtc::SimpleStringBuilder sb(buf);
205 sb << "Invalid header extension id: " << extension.id;
206 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800207 }
208 if (!seen_header_extension_ids.insert(extension.id).second) {
Florent Castelli72b751a2018-06-28 14:09:33 +0200209 char buf[50];
210 rtc::SimpleStringBuilder sb(buf);
211 sb << "Duplicate header extension id: " << extension.id;
212 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, sb.str());
deadbeefe814a0d2017-02-25 18:15:09 -0800213 }
214 cricket_extensions.push_back(extension);
215 }
216 return std::move(cricket_extensions);
217}
218
219RTCErrorOr<cricket::StreamParamsVec> ToCricketStreamParamsVec(
220 const std::vector<RtpEncodingParameters>& encodings) {
221 if (encodings.size() > 1u) {
222 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
223 "ORTC API implementation doesn't currently "
224 "support simulcast or layered encodings.");
225 } else if (encodings.empty()) {
226 return cricket::StreamParamsVec();
227 }
228 cricket::StreamParamsVec cricket_streams;
229 const RtpEncodingParameters& encoding = encodings[0];
230 if (encoding.rtx && encoding.rtx->ssrc && !encoding.ssrc) {
231 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
232 "Setting an RTX SSRC explicitly while leaving the "
233 "primary SSRC unset is not currently supported.");
234 }
235 if (encoding.ssrc) {
236 cricket::StreamParams stream_params;
237 stream_params.add_ssrc(*encoding.ssrc);
238 if (encoding.rtx && encoding.rtx->ssrc) {
239 stream_params.AddFidSsrc(*encoding.ssrc, *encoding.rtx->ssrc);
240 }
241 cricket_streams.push_back(std::move(stream_params));
242 }
243 return std::move(cricket_streams);
244}
245
Danil Chapovalov00c71832018-06-15 15:58:38 +0200246absl::optional<RtcpFeedback> ToRtcpFeedback(
deadbeefe814a0d2017-02-25 18:15:09 -0800247 const cricket::FeedbackParam& cricket_feedback) {
248 if (cricket_feedback.id() == cricket::kRtcpFbParamCcm) {
249 if (cricket_feedback.param() == cricket::kRtcpFbCcmParamFir) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100250 return RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR);
deadbeefe814a0d2017-02-25 18:15:09 -0800251 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100252 RTC_LOG(LS_WARNING) << "Unsupported parameter for CCM RTCP feedback: "
253 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200254 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800255 }
256 } else if (cricket_feedback.id() == cricket::kRtcpFbParamNack) {
257 if (cricket_feedback.param().empty()) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100258 return RtcpFeedback(RtcpFeedbackType::NACK,
259 RtcpFeedbackMessageType::GENERIC_NACK);
deadbeefe814a0d2017-02-25 18:15:09 -0800260 } else if (cricket_feedback.param() == cricket::kRtcpFbNackParamPli) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100261 return RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI);
deadbeefe814a0d2017-02-25 18:15:09 -0800262 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100263 RTC_LOG(LS_WARNING) << "Unsupported parameter for NACK RTCP feedback: "
264 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200265 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800266 }
267 } else if (cricket_feedback.id() == cricket::kRtcpFbParamRemb) {
268 if (!cricket_feedback.param().empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100269 RTC_LOG(LS_WARNING) << "Unsupported parameter for REMB RTCP feedback: "
270 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200271 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800272 } else {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100273 return RtcpFeedback(RtcpFeedbackType::REMB);
deadbeefe814a0d2017-02-25 18:15:09 -0800274 }
275 } else if (cricket_feedback.id() == cricket::kRtcpFbParamTransportCc) {
276 if (!cricket_feedback.param().empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100277 RTC_LOG(LS_WARNING)
deadbeefe814a0d2017-02-25 18:15:09 -0800278 << "Unsupported parameter for transport-cc RTCP feedback: "
279 << cricket_feedback.param();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200280 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800281 } else {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100282 return RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC);
deadbeefe814a0d2017-02-25 18:15:09 -0800283 }
284 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100285 RTC_LOG(LS_WARNING) << "Unsupported RTCP feedback type: "
286 << cricket_feedback.id();
Danil Chapovalov00c71832018-06-15 15:58:38 +0200287 return absl::nullopt;
deadbeefe814a0d2017-02-25 18:15:09 -0800288}
289
zhihuang24366392017-03-08 17:15:06 -0800290std::vector<RtpEncodingParameters> ToRtpEncodings(
291 const cricket::StreamParamsVec& stream_params) {
292 std::vector<RtpEncodingParameters> rtp_encodings;
293 for (const cricket::StreamParams& stream_param : stream_params) {
294 RtpEncodingParameters rtp_encoding;
295 rtp_encoding.ssrc.emplace(stream_param.first_ssrc());
296 uint32_t rtx_ssrc = 0;
297 if (stream_param.GetFidSsrc(stream_param.first_ssrc(), &rtx_ssrc)) {
298 RtpRtxParameters rtx_param(rtx_ssrc);
299 rtp_encoding.rtx.emplace(rtx_param);
300 }
301 rtp_encodings.push_back(std::move(rtp_encoding));
302 }
303 return rtp_encodings;
304}
305
deadbeefe814a0d2017-02-25 18:15:09 -0800306template <typename C>
307cricket::MediaType KindOfCodec();
308
309template <>
310cricket::MediaType KindOfCodec<cricket::AudioCodec>() {
311 return cricket::MEDIA_TYPE_AUDIO;
312}
313
314template <>
315cricket::MediaType KindOfCodec<cricket::VideoCodec>() {
316 return cricket::MEDIA_TYPE_VIDEO;
317}
318
319template <typename C>
320static void ToRtpCodecCapabilityTypeSpecific(const C& cricket_codec,
321 RtpCodecCapability* codec);
322
323template <>
324void ToRtpCodecCapabilityTypeSpecific<cricket::AudioCodec>(
325 const cricket::AudioCodec& cricket_codec,
326 RtpCodecCapability* codec) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100327 codec->num_channels = static_cast<int>(cricket_codec.channels);
deadbeefe814a0d2017-02-25 18:15:09 -0800328}
329
330template <>
331void ToRtpCodecCapabilityTypeSpecific<cricket::VideoCodec>(
332 const cricket::VideoCodec& cricket_codec,
333 RtpCodecCapability* codec) {}
334
335template <typename C>
336RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec) {
337 RtpCodecCapability codec;
338 codec.name = cricket_codec.name;
339 codec.kind = KindOfCodec<C>();
340 codec.clock_rate.emplace(cricket_codec.clockrate);
341 codec.preferred_payload_type.emplace(cricket_codec.id);
342 for (const cricket::FeedbackParam& cricket_feedback :
343 cricket_codec.feedback_params.params()) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200344 absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
deadbeefe814a0d2017-02-25 18:15:09 -0800345 if (feedback) {
Danil Chapovalov57ff2732018-03-28 11:25:15 +0200346 codec.rtcp_feedback.push_back(feedback.value());
deadbeefe814a0d2017-02-25 18:15:09 -0800347 }
348 }
349 ToRtpCodecCapabilityTypeSpecific(cricket_codec, &codec);
350 codec.parameters.insert(cricket_codec.params.begin(),
351 cricket_codec.params.end());
352 return codec;
353}
354
355template RtpCodecCapability ToRtpCodecCapability<cricket::AudioCodec>(
356 const cricket::AudioCodec& cricket_codec);
357template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
358 const cricket::VideoCodec& cricket_codec);
359
zhihuang24366392017-03-08 17:15:06 -0800360template <typename C>
361static void ToRtpCodecParametersTypeSpecific(const C& cricket_codec,
362 RtpCodecParameters* codec);
363template <>
364void ToRtpCodecParametersTypeSpecific<cricket::AudioCodec>(
365 const cricket::AudioCodec& cricket_codec,
366 RtpCodecParameters* codec) {
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100367 codec->num_channels = static_cast<int>(cricket_codec.channels);
zhihuang24366392017-03-08 17:15:06 -0800368}
369
370template <>
371void ToRtpCodecParametersTypeSpecific<cricket::VideoCodec>(
372 const cricket::VideoCodec& cricket_codec,
373 RtpCodecParameters* codec) {}
374
375template <typename C>
376RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec) {
377 RtpCodecParameters codec_param;
378 codec_param.name = cricket_codec.name;
379 codec_param.kind = KindOfCodec<C>();
380 codec_param.clock_rate.emplace(cricket_codec.clockrate);
381 codec_param.payload_type = cricket_codec.id;
382 for (const cricket::FeedbackParam& cricket_feedback :
383 cricket_codec.feedback_params.params()) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200384 absl::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
zhihuang24366392017-03-08 17:15:06 -0800385 if (feedback) {
Danil Chapovalov57ff2732018-03-28 11:25:15 +0200386 codec_param.rtcp_feedback.push_back(feedback.value());
zhihuang24366392017-03-08 17:15:06 -0800387 }
388 }
389 ToRtpCodecParametersTypeSpecific(cricket_codec, &codec_param);
390 codec_param.parameters.insert(cricket_codec.params.begin(),
391 cricket_codec.params.end());
392 return codec_param;
393}
394
395template RtpCodecParameters ToRtpCodecParameters<cricket::AudioCodec>(
396 const cricket::AudioCodec& cricket_codec);
397template RtpCodecParameters ToRtpCodecParameters<cricket::VideoCodec>(
398 const cricket::VideoCodec& cricket_codec);
399
deadbeefe814a0d2017-02-25 18:15:09 -0800400template <class C>
401RtpCapabilities ToRtpCapabilities(
402 const std::vector<C>& cricket_codecs,
403 const cricket::RtpHeaderExtensions& cricket_extensions) {
404 RtpCapabilities capabilities;
405 bool have_red = false;
406 bool have_ulpfec = false;
407 bool have_flexfec = false;
Florent Castelli5473a452018-11-06 17:27:21 +0100408 bool have_rtx = false;
deadbeefe814a0d2017-02-25 18:15:09 -0800409 for (const C& cricket_codec : cricket_codecs) {
410 if (cricket_codec.name == cricket::kRedCodecName) {
411 have_red = true;
412 } else if (cricket_codec.name == cricket::kUlpfecCodecName) {
413 have_ulpfec = true;
414 } else if (cricket_codec.name == cricket::kFlexfecCodecName) {
415 have_flexfec = true;
Florent Castelli5473a452018-11-06 17:27:21 +0100416 } else if (cricket_codec.name == cricket::kRtxCodecName) {
417 if (have_rtx) {
418 // There should only be one RTX codec entry
419 continue;
420 }
421 have_rtx = true;
deadbeefe814a0d2017-02-25 18:15:09 -0800422 }
Florent Castelli5473a452018-11-06 17:27:21 +0100423 auto codec_capability = ToRtpCodecCapability(cricket_codec);
424 if (cricket_codec.name == cricket::kRtxCodecName) {
425 // RTX codec should not have any parameter
426 codec_capability.parameters.clear();
427 }
428 capabilities.codecs.push_back(codec_capability);
deadbeefe814a0d2017-02-25 18:15:09 -0800429 }
430 for (const RtpExtension& cricket_extension : cricket_extensions) {
431 capabilities.header_extensions.emplace_back(cricket_extension.uri,
432 cricket_extension.id);
433 }
434 if (have_red) {
435 capabilities.fec.push_back(FecMechanism::RED);
436 }
437 if (have_red && have_ulpfec) {
438 capabilities.fec.push_back(FecMechanism::RED_AND_ULPFEC);
439 }
440 if (have_flexfec) {
441 capabilities.fec.push_back(FecMechanism::FLEXFEC);
442 }
443 return capabilities;
444}
445
446template RtpCapabilities ToRtpCapabilities<cricket::AudioCodec>(
447 const std::vector<cricket::AudioCodec>& cricket_codecs,
448 const cricket::RtpHeaderExtensions& cricket_extensions);
449template RtpCapabilities ToRtpCapabilities<cricket::VideoCodec>(
450 const std::vector<cricket::VideoCodec>& cricket_codecs,
451 const cricket::RtpHeaderExtensions& cricket_extensions);
452
zhihuang24366392017-03-08 17:15:06 -0800453template <class C>
454RtpParameters ToRtpParameters(
455 const std::vector<C>& cricket_codecs,
456 const cricket::RtpHeaderExtensions& cricket_extensions,
457 const cricket::StreamParamsVec& stream_params) {
458 RtpParameters rtp_parameters;
459 for (const C& cricket_codec : cricket_codecs) {
460 rtp_parameters.codecs.push_back(ToRtpCodecParameters(cricket_codec));
461 }
462 for (const RtpExtension& cricket_extension : cricket_extensions) {
463 rtp_parameters.header_extensions.emplace_back(cricket_extension.uri,
464 cricket_extension.id);
465 }
466 rtp_parameters.encodings = ToRtpEncodings(stream_params);
467 return rtp_parameters;
468}
469
470template RtpParameters ToRtpParameters<cricket::AudioCodec>(
471 const std::vector<cricket::AudioCodec>& cricket_codecs,
472 const cricket::RtpHeaderExtensions& cricket_extensions,
473 const cricket::StreamParamsVec& stream_params);
474template RtpParameters ToRtpParameters<cricket::VideoCodec>(
475 const std::vector<cricket::VideoCodec>& cricket_codecs,
476 const cricket::RtpHeaderExtensions& cricket_extensions,
477 const cricket::StreamParamsVec& stream_params);
478
deadbeefe814a0d2017-02-25 18:15:09 -0800479} // namespace webrtc