Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: webrtc/ortc/rtpparametersconversion.cc

Issue 2675173003: Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc. (Closed)
Patch Set: More sender/receiver tests. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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
11 #include "webrtc/ortc/rtpparametersconversion.h"
12
13 #include <set>
14 #include <sstream>
15 #include <utility>
16
17 #include "webrtc/media/base/rtputils.h"
18
19 namespace webrtc {
20
21 RTCErrorOr<cricket::FeedbackParam> ToFeedbackParam(
22 const RtcpFeedback& feedback) {
23 switch (feedback.type) {
24 case RtcpFeedbackType::CCM:
25 if (!feedback.message_type) {
26 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
27 "Missing message type in CCM RtcpFeedback.");
28 } else if (*feedback.message_type != RtcpFeedbackMessageType::FIR) {
29 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
30 "Invalid message type in CCM RtcpFeedback.");
31 }
32 return cricket::FeedbackParam(cricket::kRtcpFbParamCcm,
33 cricket::kRtcpFbCcmParamFir);
34 case RtcpFeedbackType::NACK:
35 if (!feedback.message_type) {
36 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
37 "Missing message type in NACK RtcpFeedback.");
38 }
39 switch (*feedback.message_type) {
40 case RtcpFeedbackMessageType::GENERIC_NACK:
41 return cricket::FeedbackParam(cricket::kRtcpFbParamNack);
42 case RtcpFeedbackMessageType::PLI:
43 return cricket::FeedbackParam(cricket::kRtcpFbParamNack,
44 cricket::kRtcpFbNackParamPli);
45 default:
46 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
47 "Invalid message type in NACK RtcpFeedback.");
48 }
49 case RtcpFeedbackType::REMB:
50 if (feedback.message_type) {
51 LOG_AND_RETURN_ERROR(
52 RTCErrorType::INVALID_PARAMETER,
53 "Didn't expect message type in REMB RtcpFeedback.");
54 }
55 return cricket::FeedbackParam(cricket::kRtcpFbParamRemb);
56 case RtcpFeedbackType::TRANSPORT_CC:
57 if (feedback.message_type) {
58 LOG_AND_RETURN_ERROR(
59 RTCErrorType::INVALID_PARAMETER,
60 "Didn't expect message type in transport-cc RtcpFeedback.");
61 }
62 return cricket::FeedbackParam(cricket::kRtcpFbParamTransportCc);
63 }
64 }
65
66 template <typename C>
67 static RTCError ToCricketCodecTypeSpecific(const RtpCodecParameters& codec,
68 C* cricket_codec);
69
70 template <>
71 RTCError ToCricketCodecTypeSpecific<cricket::AudioCodec>(
72 const RtpCodecParameters& codec,
73 cricket::AudioCodec* cricket_codec) {
74 if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
75 LOG_AND_RETURN_ERROR(
76 RTCErrorType::INVALID_PARAMETER,
77 "Can't use video codec with audio sender or receiver.");
78 }
79 if (!codec.num_channels) {
80 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
81 "Missing number of channels for audio codec.");
82 }
83 if (*codec.num_channels <= 0) {
84 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
85 "Number of channels must be positive.");
86 }
87 cricket_codec->channels = *codec.num_channels;
88 if (!codec.clock_rate) {
89 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
90 "Missing codec clock rate.");
91 }
92 if (*codec.clock_rate <= 0) {
93 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
94 "Clock rate must be positive.");
95 }
96 cricket_codec->clockrate = *codec.clock_rate;
97 return RTCError::OK();
98 }
99
100 // Video codec doesn't use num_channels or clock_rate, but they should at least
101 // be validated.
102 template <>
103 RTCError ToCricketCodecTypeSpecific<cricket::VideoCodec>(
104 const RtpCodecParameters& codec,
105 cricket::VideoCodec*) {
106 if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
107 LOG_AND_RETURN_ERROR(
108 RTCErrorType::INVALID_PARAMETER,
109 "Can't use audio codec with video sender or receiver.");
110 }
111 if (codec.num_channels) {
112 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
113 "Video codec shouldn't have num_channels.");
114 }
115 if (!codec.clock_rate) {
116 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
117 "Missing codec clock rate.");
118 }
119 if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
120 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
121 "Video clock rate must be 90000.");
122 }
123 return RTCError::OK();
124 }
125
126 template <typename C>
127 RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec) {
128 C cricket_codec;
129 // Start with audio/video specific conversion.
130 RTCError err = ToCricketCodecTypeSpecific(codec, &cricket_codec);
131 if (!err.ok()) {
132 return err;
133 }
134 cricket_codec.name = codec.name;
135 if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
136 std::ostringstream oss;
137 oss << "Invalid payload type: " << codec.payload_type;
138 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, oss.str());
139 }
140 cricket_codec.id = codec.payload_type;
141 for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
142 auto result = ToFeedbackParam(feedback);
143 if (!result.ok()) {
144 return result.MoveError();
145 }
146 cricket_codec.AddFeedbackParam(result.MoveValue());
147 }
148 cricket_codec.params.insert(codec.parameters.begin(), codec.parameters.end());
149 return cricket_codec;
150 }
151
152 template RTCErrorOr<cricket::AudioCodec> ToCricketCodec(
153 const RtpCodecParameters& codec);
154 template RTCErrorOr<cricket::VideoCodec> ToCricketCodec(
155 const RtpCodecParameters& codec);
156
157 template <typename C>
158 RTCErrorOr<std::vector<C>> ToCricketCodecs(
159 const std::vector<RtpCodecParameters>& codecs) {
160 std::vector<C> cricket_codecs;
161 std::set<int> seen_payload_types;
162 for (const RtpCodecParameters& codec : codecs) {
163 auto result = ToCricketCodec<C>(codec);
164 if (!result.ok()) {
165 return result.MoveError();
166 }
167 if (!seen_payload_types.insert(codec.payload_type).second) {
168 std::ostringstream oss;
169 oss << "Duplicate payload type: " << codec.payload_type;
170 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, oss.str());
171 }
172 cricket_codecs.push_back(result.MoveValue());
173 }
174 return cricket_codecs;
175 }
176
177 template RTCErrorOr<std::vector<cricket::AudioCodec>> ToCricketCodecs<
178 cricket::AudioCodec>(const std::vector<RtpCodecParameters>& codecs);
179
180 template RTCErrorOr<std::vector<cricket::VideoCodec>> ToCricketCodecs<
181 cricket::VideoCodec>(const std::vector<RtpCodecParameters>& codecs);
182
183 RTCErrorOr<cricket::RtpHeaderExtensions> ToRtpHeaderExtensions(
184 const std::vector<RtpHeaderExtensionParameters>& extensions) {
185 cricket::RtpHeaderExtensions cricket_extensions;
186 std::ostringstream err_writer;
187 std::set<int> seen_header_extension_ids;
188 for (const RtpHeaderExtensionParameters& extension : extensions) {
189 if (extension.id < RtpHeaderExtensionParameters::kMinId ||
190 extension.id > RtpHeaderExtensionParameters::kMaxId) {
191 err_writer << "Invalid header extension id: " << extension.id;
192 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, err_writer.str());
193 }
194 if (!seen_header_extension_ids.insert(extension.id).second) {
195 err_writer << "Duplicate header extension id: " << extension.id;
196 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, err_writer.str());
197 }
198 cricket_extensions.push_back(extension);
199 }
200 return cricket_extensions;
201 }
202
203 RTCErrorOr<cricket::StreamParamsVec> ToStreamParamsVec(
204 const std::vector<RtpEncodingParameters>& encodings) {
205 if (encodings.size() > 1u) {
206 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_PARAMETER,
207 "ORTC API implementation doesn't currently "
208 "support simulcast or layered encodings.");
209 } else if (encodings.empty()) {
210 return cricket::StreamParamsVec();
211 }
212 cricket::StreamParamsVec cricket_streams;
213 const RtpEncodingParameters& encoding = encodings[0];
214 if (encoding.ssrc) {
215 cricket::StreamParams stream_params;
216 stream_params.add_ssrc(*encoding.ssrc);
217 if (encoding.rtx && encoding.rtx->ssrc) {
218 stream_params.AddFidSsrc(*encoding.ssrc, *encoding.rtx->ssrc);
219 }
220 cricket_streams.push_back(std::move(stream_params));
221 }
222 return cricket_streams;
223 }
224
225 rtc::Optional<RtcpFeedback> ToRtcpFeedback(
226 const cricket::FeedbackParam& cricket_feedback) {
227 if (cricket_feedback.id() == cricket::kRtcpFbParamCcm) {
228 if (cricket_feedback.param() == cricket::kRtcpFbCcmParamFir) {
229 return rtc::Optional<RtcpFeedback>(
230 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR});
231 } else {
232 LOG(LS_WARNING) << "Unsupported parameter for CCM RTCP feedback: "
233 << cricket_feedback.param();
234 return rtc::Optional<RtcpFeedback>();
235 }
236 } else if (cricket_feedback.id() == cricket::kRtcpFbParamNack) {
237 if (cricket_feedback.param().empty()) {
238 return rtc::Optional<RtcpFeedback>(
239 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK});
240 } else if (cricket_feedback.param() == cricket::kRtcpFbNackParamPli) {
241 return rtc::Optional<RtcpFeedback>(
242 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI});
243 } else {
244 LOG(LS_WARNING) << "Unsupported parameter for NACK RTCP feedback: "
245 << cricket_feedback.param();
246 return rtc::Optional<RtcpFeedback>();
247 }
248 } else if (cricket_feedback.id() == cricket::kRtcpFbParamRemb) {
249 if (!cricket_feedback.param().empty()) {
250 LOG(LS_WARNING) << "Unsupported parameter for REMB RTCP feedback: "
251 << cricket_feedback.param();
252 return rtc::Optional<RtcpFeedback>();
253 } else {
254 return rtc::Optional<RtcpFeedback>(RtcpFeedback(RtcpFeedbackType::REMB));
255 }
256 } else if (cricket_feedback.id() == cricket::kRtcpFbParamTransportCc) {
257 if (!cricket_feedback.param().empty()) {
258 LOG(LS_WARNING)
259 << "Unsupported parameter for transport-cc RTCP feedback: "
260 << cricket_feedback.param();
261 return rtc::Optional<RtcpFeedback>();
262 } else {
263 return rtc::Optional<RtcpFeedback>(
264 RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC));
265 }
266 }
267 LOG(LS_WARNING) << "Unsupported RTCP feedback type: "
268 << cricket_feedback.id();
269 return rtc::Optional<RtcpFeedback>();
270 }
271
272 template <typename C>
273 cricket::MediaType KindOfCodec();
274
275 template <>
276 cricket::MediaType KindOfCodec<cricket::AudioCodec>() {
277 return cricket::MEDIA_TYPE_AUDIO;
278 }
279
280 template <>
281 cricket::MediaType KindOfCodec<cricket::VideoCodec>() {
282 return cricket::MEDIA_TYPE_VIDEO;
283 }
284
285 template <typename C>
286 static void ToRtpCodecCapabilityTypeSpecific(const C& cricket_codec,
287 RtpCodecCapability* codec);
288
289 template <>
290 void ToRtpCodecCapabilityTypeSpecific<cricket::AudioCodec>(
291 const cricket::AudioCodec& cricket_codec,
292 RtpCodecCapability* codec) {
293 codec->num_channels = rtc::Optional<int>(cricket_codec.channels);
294 }
295
296 template <>
297 void ToRtpCodecCapabilityTypeSpecific<cricket::VideoCodec>(
298 const cricket::VideoCodec& cricket_codec,
299 RtpCodecCapability* codec) {}
300
301 template <typename C>
302 RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec) {
303 RtpCodecCapability codec;
304 codec.name = cricket_codec.name;
305 codec.kind = KindOfCodec<C>();
306 codec.clock_rate.emplace(cricket_codec.clockrate);
307 codec.preferred_payload_type.emplace(cricket_codec.id);
308 for (const cricket::FeedbackParam& cricket_feedback :
309 cricket_codec.feedback_params.params()) {
310 rtc::Optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
311 if (feedback) {
312 codec.rtcp_feedback.push_back(feedback.MoveValue());
313 }
314 }
315 ToRtpCodecCapabilityTypeSpecific(cricket_codec, &codec);
316 codec.parameters.insert(cricket_codec.params.begin(),
317 cricket_codec.params.end());
318 return codec;
319 }
320
321 template RtpCodecCapability ToRtpCodecCapability<cricket::AudioCodec>(
322 const cricket::AudioCodec& cricket_codec);
323 template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
324 const cricket::VideoCodec& cricket_codec);
325
326 template <class C>
327 RtpCapabilities ToRtpCapabilities(
328 const std::vector<C>& cricket_codecs,
329 const cricket::RtpHeaderExtensions& cricket_extensions) {
330 RtpCapabilities capabilities;
331 bool have_red = false;
332 bool have_ulpfec = false;
333 bool have_flexfec = false;
334 for (const C& cricket_codec : cricket_codecs) {
335 if (cricket_codec.name == cricket::kRedCodecName) {
336 have_red = true;
337 } else if (cricket_codec.name == cricket::kUlpfecCodecName) {
338 have_ulpfec = true;
339 } else if (cricket_codec.name == cricket::kFlexfecCodecName) {
340 have_flexfec = true;
341 }
342 capabilities.codecs.push_back(ToRtpCodecCapability(cricket_codec));
343 }
344 for (const RtpExtension& cricket_extension : cricket_extensions) {
345 capabilities.header_extensions.emplace_back(cricket_extension.uri,
346 cricket_extension.id);
347 }
348 if (have_red) {
349 capabilities.fec.push_back(FecMechanism::RED);
350 }
351 if (have_red && have_ulpfec) {
352 capabilities.fec.push_back(FecMechanism::RED_AND_ULPFEC);
353 }
354 if (have_flexfec) {
355 capabilities.fec.push_back(FecMechanism::FLEXFEC);
356 }
357 return capabilities;
358 }
359
360 template RtpCapabilities ToRtpCapabilities<cricket::AudioCodec>(
361 const std::vector<cricket::AudioCodec>& cricket_codecs,
362 const cricket::RtpHeaderExtensions& cricket_extensions);
363 template RtpCapabilities ToRtpCapabilities<cricket::VideoCodec>(
364 const std::vector<cricket::VideoCodec>& cricket_codecs,
365 const cricket::RtpHeaderExtensions& cricket_extensions);
366
367 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698