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 "pc/rtp_parameters_conversion.h"
12
13 #include <cstdint>
14 #include <map>
15 #include <string>
16
17 #include "api/media_types.h"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20
21 using ::testing::UnorderedElementsAre;
22
23 namespace webrtc {
24
TEST(RtpParametersConversionTest,ToCricketFeedbackParam)25 TEST(RtpParametersConversionTest, ToCricketFeedbackParam) {
26 auto result = ToCricketFeedbackParam(
27 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR});
28 EXPECT_EQ(cricket::FeedbackParam("ccm", "fir"), result.value());
29
30 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::LNTF));
31 EXPECT_EQ(cricket::FeedbackParam("goog-lntf"), result.value());
32
33 result = ToCricketFeedbackParam(
34 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK});
35 EXPECT_EQ(cricket::FeedbackParam("nack"), result.value());
36
37 result = ToCricketFeedbackParam(
38 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI});
39 EXPECT_EQ(cricket::FeedbackParam("nack", "pli"), result.value());
40
41 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::REMB));
42 EXPECT_EQ(cricket::FeedbackParam("goog-remb"), result.value());
43
44 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC));
45 EXPECT_EQ(cricket::FeedbackParam("transport-cc"), result.value());
46 }
47
TEST(RtpParametersConversionTest,ToCricketFeedbackParamErrors)48 TEST(RtpParametersConversionTest, ToCricketFeedbackParamErrors) {
49 // CCM with missing or invalid message type.
50 auto result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::CCM));
51 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
52
53 result = ToCricketFeedbackParam(
54 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::PLI});
55 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
56
57 // LNTF with message type (should be left empty).
58 result = ToCricketFeedbackParam(
59 {RtcpFeedbackType::LNTF, RtcpFeedbackMessageType::GENERIC_NACK});
60 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
61
62 // NACK with missing or invalid message type.
63 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::NACK));
64 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
65
66 result = ToCricketFeedbackParam(
67 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::FIR});
68 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
69
70 // REMB with message type (should be left empty).
71 result = ToCricketFeedbackParam(
72 {RtcpFeedbackType::REMB, RtcpFeedbackMessageType::GENERIC_NACK});
73 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
74
75 // TRANSPORT_CC with message type (should be left empty).
76 result = ToCricketFeedbackParam(
77 {RtcpFeedbackType::TRANSPORT_CC, RtcpFeedbackMessageType::FIR});
78 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
79 }
80
TEST(RtpParametersConversionTest,ToAudioCodec)81 TEST(RtpParametersConversionTest, ToAudioCodec) {
82 RtpCodecParameters codec;
83 codec.name = "AuDiO";
84 codec.kind = cricket::MEDIA_TYPE_AUDIO;
85 codec.payload_type = 120;
86 codec.clock_rate.emplace(36000);
87 codec.num_channels.emplace(6);
88 codec.parameters["foo"] = "bar";
89 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
90 auto result = ToCricketCodec<cricket::AudioCodec>(codec);
91 ASSERT_TRUE(result.ok());
92
93 EXPECT_EQ("AuDiO", result.value().name);
94 EXPECT_EQ(120, result.value().id);
95 EXPECT_EQ(36000, result.value().clockrate);
96 EXPECT_EQ(6u, result.value().channels);
97 ASSERT_EQ(1u, result.value().params.size());
98 EXPECT_EQ("bar", result.value().params["foo"]);
99 EXPECT_EQ(1u, result.value().feedback_params.params().size());
100 EXPECT_TRUE(result.value().feedback_params.Has(
101 cricket::FeedbackParam("transport-cc")));
102 }
103
TEST(RtpParametersConversionTest,ToVideoCodec)104 TEST(RtpParametersConversionTest, ToVideoCodec) {
105 RtpCodecParameters codec;
106 codec.name = "coolcodec";
107 codec.kind = cricket::MEDIA_TYPE_VIDEO;
108 codec.payload_type = 101;
109 codec.clock_rate.emplace(90000);
110 codec.parameters["foo"] = "bar";
111 codec.parameters["PING"] = "PONG";
112 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::LNTF);
113 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
114 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK,
115 RtcpFeedbackMessageType::PLI);
116 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
117 ASSERT_TRUE(result.ok());
118
119 EXPECT_EQ("coolcodec", result.value().name);
120 EXPECT_EQ(101, result.value().id);
121 EXPECT_EQ(90000, result.value().clockrate);
122 ASSERT_EQ(2u, result.value().params.size());
123 EXPECT_EQ("bar", result.value().params["foo"]);
124 EXPECT_EQ("PONG", result.value().params["PING"]);
125 EXPECT_EQ(3u, result.value().feedback_params.params().size());
126 EXPECT_TRUE(
127 result.value().feedback_params.Has(cricket::FeedbackParam("goog-lntf")));
128 EXPECT_TRUE(result.value().feedback_params.Has(
129 cricket::FeedbackParam("transport-cc")));
130 EXPECT_TRUE(result.value().feedback_params.Has(
131 cricket::FeedbackParam("nack", "pli")));
132 }
133
134 // Trying to convert to an AudioCodec if the kind is "video" should fail.
TEST(RtpParametersConversionTest,ToCricketCodecInvalidKind)135 TEST(RtpParametersConversionTest, ToCricketCodecInvalidKind) {
136 RtpCodecParameters audio_codec;
137 audio_codec.name = "opus";
138 audio_codec.kind = cricket::MEDIA_TYPE_VIDEO;
139 audio_codec.payload_type = 111;
140 audio_codec.clock_rate.emplace(48000);
141 audio_codec.num_channels.emplace(2);
142
143 RtpCodecParameters video_codec;
144 video_codec.name = "VP8";
145 video_codec.kind = cricket::MEDIA_TYPE_AUDIO;
146 video_codec.payload_type = 102;
147 video_codec.clock_rate.emplace(90000);
148
149 auto audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
150 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, audio_result.error().type());
151
152 auto video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
153 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_result.error().type());
154
155 // Sanity check that if the kind is correct, the conversion succeeds.
156 audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
157 video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
158 audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
159 EXPECT_TRUE(audio_result.ok());
160 video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
161 EXPECT_TRUE(video_result.ok());
162 }
163
TEST(RtpParametersConversionTest,ToAudioCodecInvalidParameters)164 TEST(RtpParametersConversionTest, ToAudioCodecInvalidParameters) {
165 // Missing channels.
166 RtpCodecParameters codec;
167 codec.name = "opus";
168 codec.kind = cricket::MEDIA_TYPE_AUDIO;
169 codec.payload_type = 111;
170 codec.clock_rate.emplace(48000);
171 auto result = ToCricketCodec<cricket::AudioCodec>(codec);
172 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
173
174 // Negative number of channels.
175 codec.num_channels.emplace(-1);
176 result = ToCricketCodec<cricket::AudioCodec>(codec);
177 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
178
179 // Missing clock rate.
180 codec.num_channels.emplace(2);
181 codec.clock_rate.reset();
182 result = ToCricketCodec<cricket::AudioCodec>(codec);
183 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
184
185 // Negative clock rate.
186 codec.clock_rate.emplace(-48000);
187 result = ToCricketCodec<cricket::AudioCodec>(codec);
188 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
189
190 // Sanity check that conversion succeeds if these errors are fixed.
191 codec.clock_rate.emplace(48000);
192 result = ToCricketCodec<cricket::AudioCodec>(codec);
193 EXPECT_TRUE(result.ok());
194 }
195
TEST(RtpParametersConversionTest,ToVideoCodecInvalidParameters)196 TEST(RtpParametersConversionTest, ToVideoCodecInvalidParameters) {
197 // Missing clock rate.
198 RtpCodecParameters codec;
199 codec.name = "VP8";
200 codec.kind = cricket::MEDIA_TYPE_VIDEO;
201 codec.payload_type = 102;
202 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
203 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
204
205 // Invalid clock rate.
206 codec.clock_rate.emplace(48000);
207 result = ToCricketCodec<cricket::VideoCodec>(codec);
208 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
209
210 // Channels set (should be unset).
211 codec.clock_rate.emplace(90000);
212 codec.num_channels.emplace(2);
213 result = ToCricketCodec<cricket::VideoCodec>(codec);
214 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
215
216 // Sanity check that conversion succeeds if these errors are fixed.
217 codec.num_channels.reset();
218 result = ToCricketCodec<cricket::VideoCodec>(codec);
219 EXPECT_TRUE(result.ok());
220 }
221
TEST(RtpParametersConversionTest,ToCricketCodecInvalidPayloadType)222 TEST(RtpParametersConversionTest, ToCricketCodecInvalidPayloadType) {
223 RtpCodecParameters codec;
224 codec.name = "VP8";
225 codec.kind = cricket::MEDIA_TYPE_VIDEO;
226 codec.clock_rate.emplace(90000);
227
228 codec.payload_type = -1000;
229 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
230 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
231
232 // Max payload type is 127.
233 codec.payload_type = 128;
234 result = ToCricketCodec<cricket::VideoCodec>(codec);
235 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
236
237 // Sanity check that conversion succeeds with a valid payload type.
238 codec.payload_type = 127;
239 result = ToCricketCodec<cricket::VideoCodec>(codec);
240 EXPECT_TRUE(result.ok());
241 }
242
243 // There are already tests for ToCricketFeedbackParam, but ensure that those
244 // errors are propagated from ToCricketCodec.
TEST(RtpParametersConversionTest,ToCricketCodecInvalidRtcpFeedback)245 TEST(RtpParametersConversionTest, ToCricketCodecInvalidRtcpFeedback) {
246 RtpCodecParameters codec;
247 codec.name = "VP8";
248 codec.kind = cricket::MEDIA_TYPE_VIDEO;
249 codec.clock_rate.emplace(90000);
250 codec.payload_type = 99;
251 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM,
252 RtcpFeedbackMessageType::PLI);
253
254 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
255 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
256
257 // Sanity check that conversion succeeds without invalid feedback.
258 codec.rtcp_feedback.clear();
259 result = ToCricketCodec<cricket::VideoCodec>(codec);
260 EXPECT_TRUE(result.ok());
261 }
262
TEST(RtpParametersConversionTest,ToCricketCodecs)263 TEST(RtpParametersConversionTest, ToCricketCodecs) {
264 std::vector<RtpCodecParameters> codecs;
265 RtpCodecParameters codec;
266 codec.name = "VP8";
267 codec.kind = cricket::MEDIA_TYPE_VIDEO;
268 codec.clock_rate.emplace(90000);
269 codec.payload_type = 99;
270 codecs.push_back(codec);
271
272 codec.name = "VP9";
273 codec.payload_type = 100;
274 codecs.push_back(codec);
275
276 auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
277 ASSERT_TRUE(result.ok());
278 ASSERT_EQ(2u, result.value().size());
279 EXPECT_EQ("VP8", result.value()[0].name);
280 EXPECT_EQ(99, result.value()[0].id);
281 EXPECT_EQ("VP9", result.value()[1].name);
282 EXPECT_EQ(100, result.value()[1].id);
283 }
284
TEST(RtpParametersConversionTest,ToCricketCodecsDuplicatePayloadType)285 TEST(RtpParametersConversionTest, ToCricketCodecsDuplicatePayloadType) {
286 std::vector<RtpCodecParameters> codecs;
287 RtpCodecParameters codec;
288 codec.name = "VP8";
289 codec.kind = cricket::MEDIA_TYPE_VIDEO;
290 codec.clock_rate.emplace(90000);
291 codec.payload_type = 99;
292 codecs.push_back(codec);
293
294 codec.name = "VP9";
295 codec.payload_type = 99;
296 codecs.push_back(codec);
297
298 auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
299 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
300
301 // Sanity check that this succeeds without the duplicate payload type.
302 codecs[1].payload_type = 120;
303 result = ToCricketCodecs<cricket::VideoCodec>(codecs);
304 EXPECT_TRUE(result.ok());
305 }
306
TEST(RtpParametersConversionTest,ToCricketStreamParamsVecSimple)307 TEST(RtpParametersConversionTest, ToCricketStreamParamsVecSimple) {
308 std::vector<RtpEncodingParameters> encodings;
309 RtpEncodingParameters encoding;
310 encoding.ssrc.emplace(0xbaadf00d);
311 encodings.push_back(encoding);
312 auto result = ToCricketStreamParamsVec(encodings);
313 ASSERT_TRUE(result.ok());
314 ASSERT_EQ(1u, result.value().size());
315 EXPECT_EQ(1u, result.value()[0].ssrcs.size());
316 EXPECT_EQ(0xbaadf00d, result.value()[0].first_ssrc());
317 }
318
319 // No encodings should be accepted; an endpoint may want to prepare a
320 // decoder/encoder without having something to receive/send yet.
TEST(RtpParametersConversionTest,ToCricketStreamParamsVecNoEncodings)321 TEST(RtpParametersConversionTest, ToCricketStreamParamsVecNoEncodings) {
322 std::vector<RtpEncodingParameters> encodings;
323 auto result = ToCricketStreamParamsVec(encodings);
324 ASSERT_TRUE(result.ok());
325 EXPECT_EQ(0u, result.value().size());
326 }
327
328 // An encoding without SSRCs should be accepted. This could be the case when
329 // SSRCs aren't signaled and payload-type based demuxing is used.
TEST(RtpParametersConversionTest,ToCricketStreamParamsVecMissingSsrcs)330 TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMissingSsrcs) {
331 std::vector<RtpEncodingParameters> encodings = {{}};
332 // Creates RtxParameters with empty SSRC.
333 auto result = ToCricketStreamParamsVec(encodings);
334 ASSERT_TRUE(result.ok());
335 EXPECT_EQ(0u, result.value().size());
336 }
337
338 // TODO(deadbeef): Update this test when we support multiple encodings.
TEST(RtpParametersConversionTest,ToCricketStreamParamsVecMultipleEncodings)339 TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMultipleEncodings) {
340 std::vector<RtpEncodingParameters> encodings = {{}, {}};
341 auto result = ToCricketStreamParamsVec(encodings);
342 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, result.error().type());
343 }
344
TEST(RtpParametersConversionTest,ToRtcpFeedback)345 TEST(RtpParametersConversionTest, ToRtcpFeedback) {
346 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "fir"});
347 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR),
348 *result);
349
350 result = ToRtcpFeedback(cricket::FeedbackParam("goog-lntf"));
351 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), *result);
352
353 result = ToRtcpFeedback(cricket::FeedbackParam("nack"));
354 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK,
355 RtcpFeedbackMessageType::GENERIC_NACK),
356 *result);
357
358 result = ToRtcpFeedback({"nack", "pli"});
359 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
360 *result);
361
362 result = ToRtcpFeedback(cricket::FeedbackParam("goog-remb"));
363 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::REMB), *result);
364
365 result = ToRtcpFeedback(cricket::FeedbackParam("transport-cc"));
366 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), *result);
367 }
368
TEST(RtpParametersConversionTest,ToRtcpFeedbackErrors)369 TEST(RtpParametersConversionTest, ToRtcpFeedbackErrors) {
370 // CCM with missing or invalid message type.
371 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "pli"});
372 EXPECT_FALSE(result);
373
374 result = ToRtcpFeedback(cricket::FeedbackParam("ccm"));
375 EXPECT_FALSE(result);
376
377 // LNTF with message type (should be left empty).
378 result = ToRtcpFeedback({"goog-lntf", "pli"});
379 EXPECT_FALSE(result);
380
381 // NACK with missing or invalid message type.
382 result = ToRtcpFeedback({"nack", "fir"});
383 EXPECT_FALSE(result);
384
385 // REMB with message type (should be left empty).
386 result = ToRtcpFeedback({"goog-remb", "pli"});
387 EXPECT_FALSE(result);
388
389 // TRANSPORT_CC with message type (should be left empty).
390 result = ToRtcpFeedback({"transport-cc", "fir"});
391 EXPECT_FALSE(result);
392
393 // Unknown message type.
394 result = ToRtcpFeedback(cricket::FeedbackParam("foo"));
395 EXPECT_FALSE(result);
396 }
397
TEST(RtpParametersConversionTest,ToAudioRtpCodecCapability)398 TEST(RtpParametersConversionTest, ToAudioRtpCodecCapability) {
399 cricket::AudioCodec cricket_codec;
400 cricket_codec.name = "foo";
401 cricket_codec.id = 50;
402 cricket_codec.clockrate = 22222;
403 cricket_codec.channels = 4;
404 cricket_codec.params["foo"] = "bar";
405 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
406 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
407
408 EXPECT_EQ("foo", codec.name);
409 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
410 EXPECT_EQ(50, codec.preferred_payload_type);
411 EXPECT_EQ(22222, codec.clock_rate);
412 EXPECT_EQ(4, codec.num_channels);
413 ASSERT_EQ(1u, codec.parameters.size());
414 EXPECT_EQ("bar", codec.parameters["foo"]);
415 EXPECT_EQ(1u, codec.rtcp_feedback.size());
416 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
417 codec.rtcp_feedback[0]);
418 }
419
TEST(RtpParametersConversionTest,ToVideoRtpCodecCapability)420 TEST(RtpParametersConversionTest, ToVideoRtpCodecCapability) {
421 cricket::VideoCodec cricket_codec;
422 cricket_codec.name = "VID";
423 cricket_codec.id = 101;
424 cricket_codec.clockrate = 80000;
425 cricket_codec.params["foo"] = "bar";
426 cricket_codec.params["ANOTHER"] = "param";
427 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
428 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
429 cricket_codec.feedback_params.Add({"nack", "pli"});
430 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
431
432 EXPECT_EQ("VID", codec.name);
433 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
434 EXPECT_EQ(101, codec.preferred_payload_type);
435 EXPECT_EQ(80000, codec.clock_rate);
436 ASSERT_EQ(2u, codec.parameters.size());
437 EXPECT_EQ("bar", codec.parameters["foo"]);
438 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
439 EXPECT_EQ(3u, codec.rtcp_feedback.size());
440 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
441 codec.rtcp_feedback[0]);
442 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
443 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
444 codec.rtcp_feedback[2]);
445 }
446
TEST(RtpParametersConversionTest,ToRtpEncodingsWithEmptyStreamParamsVec)447 TEST(RtpParametersConversionTest, ToRtpEncodingsWithEmptyStreamParamsVec) {
448 cricket::StreamParamsVec streams;
449 auto rtp_encodings = ToRtpEncodings(streams);
450 ASSERT_EQ(0u, rtp_encodings.size());
451 }
452
TEST(RtpParametersConversionTest,ToRtpEncodingsWithMultipleStreamParams)453 TEST(RtpParametersConversionTest, ToRtpEncodingsWithMultipleStreamParams) {
454 cricket::StreamParamsVec streams;
455 cricket::StreamParams stream1;
456 stream1.ssrcs.push_back(1111u);
457
458 cricket::StreamParams stream2;
459 stream2.ssrcs.push_back(2222u);
460
461 streams.push_back(stream1);
462 streams.push_back(stream2);
463
464 auto rtp_encodings = ToRtpEncodings(streams);
465 ASSERT_EQ(2u, rtp_encodings.size());
466 EXPECT_EQ(1111u, rtp_encodings[0].ssrc);
467 EXPECT_EQ(2222u, rtp_encodings[1].ssrc);
468 }
469
TEST(RtpParametersConversionTest,ToAudioRtpCodecParameters)470 TEST(RtpParametersConversionTest, ToAudioRtpCodecParameters) {
471 cricket::AudioCodec cricket_codec;
472 cricket_codec.name = "foo";
473 cricket_codec.id = 50;
474 cricket_codec.clockrate = 22222;
475 cricket_codec.channels = 4;
476 cricket_codec.params["foo"] = "bar";
477 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
478 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
479
480 EXPECT_EQ("foo", codec.name);
481 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
482 EXPECT_EQ(50, codec.payload_type);
483 EXPECT_EQ(22222, codec.clock_rate);
484 EXPECT_EQ(4, codec.num_channels);
485 ASSERT_EQ(1u, codec.parameters.size());
486 EXPECT_EQ("bar", codec.parameters["foo"]);
487 EXPECT_EQ(1u, codec.rtcp_feedback.size());
488 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
489 codec.rtcp_feedback[0]);
490 }
491
TEST(RtpParametersConversionTest,ToVideoRtpCodecParameters)492 TEST(RtpParametersConversionTest, ToVideoRtpCodecParameters) {
493 cricket::VideoCodec cricket_codec;
494 cricket_codec.name = "VID";
495 cricket_codec.id = 101;
496 cricket_codec.clockrate = 80000;
497 cricket_codec.params["foo"] = "bar";
498 cricket_codec.params["ANOTHER"] = "param";
499 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
500 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
501 cricket_codec.feedback_params.Add({"nack", "pli"});
502 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
503
504 EXPECT_EQ("VID", codec.name);
505 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
506 EXPECT_EQ(101, codec.payload_type);
507 EXPECT_EQ(80000, codec.clock_rate);
508 ASSERT_EQ(2u, codec.parameters.size());
509 EXPECT_EQ("bar", codec.parameters["foo"]);
510 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
511 EXPECT_EQ(3u, codec.rtcp_feedback.size());
512 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
513 codec.rtcp_feedback[0]);
514 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
515 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
516 codec.rtcp_feedback[2]);
517 }
518
519 // An unknown feedback param should just be ignored.
TEST(RtpParametersConversionTest,ToRtpCodecCapabilityUnknownFeedbackParam)520 TEST(RtpParametersConversionTest, ToRtpCodecCapabilityUnknownFeedbackParam) {
521 cricket::AudioCodec cricket_codec;
522 cricket_codec.name = "foo";
523 cricket_codec.id = 50;
524 cricket_codec.clockrate = 22222;
525 cricket_codec.channels = 4;
526 cricket_codec.params["foo"] = "bar";
527 cricket_codec.feedback_params.Add({"unknown", "param"});
528 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
529 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
530
531 ASSERT_EQ(1u, codec.rtcp_feedback.size());
532 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
533 codec.rtcp_feedback[0]);
534 }
535
536 // Most of ToRtpCapabilities is tested by ToRtpCodecCapability, but we need to
537 // test that the result of ToRtpCodecCapability ends up in the result, and that
538 // the "fec" list is assembled correctly.
TEST(RtpParametersConversionTest,ToRtpCapabilities)539 TEST(RtpParametersConversionTest, ToRtpCapabilities) {
540 cricket::VideoCodec vp8;
541 vp8.name = "VP8";
542 vp8.id = 101;
543 vp8.clockrate = 90000;
544
545 cricket::VideoCodec red;
546 red.name = "red";
547 red.id = 102;
548 red.clockrate = 90000;
549
550 cricket::VideoCodec ulpfec;
551 ulpfec.name = "ulpfec";
552 ulpfec.id = 103;
553 ulpfec.clockrate = 90000;
554
555 cricket::VideoCodec flexfec;
556 flexfec.name = "flexfec-03";
557 flexfec.id = 102;
558 flexfec.clockrate = 90000;
559
560 cricket::VideoCodec rtx;
561 rtx.name = "rtx";
562 rtx.id = 104;
563 rtx.params.insert({"apt", "101"});
564
565 cricket::VideoCodec rtx2;
566 rtx2.name = "rtx";
567 rtx2.id = 105;
568 rtx2.params.insert({"apt", "109"});
569
570 RtpCapabilities capabilities = ToRtpCapabilities<cricket::VideoCodec>(
571 {vp8, ulpfec, rtx, rtx2}, {{"uri", 1}, {"uri2", 3}});
572 ASSERT_EQ(3u, capabilities.codecs.size());
573 EXPECT_EQ("VP8", capabilities.codecs[0].name);
574 EXPECT_EQ("ulpfec", capabilities.codecs[1].name);
575 EXPECT_EQ("rtx", capabilities.codecs[2].name);
576 EXPECT_EQ(0u, capabilities.codecs[2].parameters.size());
577 ASSERT_EQ(2u, capabilities.header_extensions.size());
578 EXPECT_EQ("uri", capabilities.header_extensions[0].uri);
579 EXPECT_EQ(1, capabilities.header_extensions[0].preferred_id);
580 EXPECT_EQ("uri2", capabilities.header_extensions[1].uri);
581 EXPECT_EQ(3, capabilities.header_extensions[1].preferred_id);
582 EXPECT_EQ(0u, capabilities.fec.size());
583
584 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
585 {vp8, red, ulpfec, rtx}, cricket::RtpHeaderExtensions());
586 EXPECT_EQ(4u, capabilities.codecs.size());
587 EXPECT_THAT(
588 capabilities.fec,
589 UnorderedElementsAre(FecMechanism::RED, FecMechanism::RED_AND_ULPFEC));
590
591 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
592 {vp8, red, flexfec}, cricket::RtpHeaderExtensions());
593 EXPECT_EQ(3u, capabilities.codecs.size());
594 EXPECT_THAT(capabilities.fec,
595 UnorderedElementsAre(FecMechanism::RED, FecMechanism::FLEXFEC));
596 }
597
TEST(RtpParametersConversionTest,ToRtpParameters)598 TEST(RtpParametersConversionTest, ToRtpParameters) {
599 cricket::VideoCodec vp8;
600 vp8.name = "VP8";
601 vp8.id = 101;
602 vp8.clockrate = 90000;
603
604 cricket::VideoCodec red;
605 red.name = "red";
606 red.id = 102;
607 red.clockrate = 90000;
608
609 cricket::VideoCodec ulpfec;
610 ulpfec.name = "ulpfec";
611 ulpfec.id = 103;
612 ulpfec.clockrate = 90000;
613
614 cricket::StreamParamsVec streams;
615 cricket::StreamParams stream;
616 stream.ssrcs.push_back(1234u);
617 streams.push_back(stream);
618
619 RtpParameters rtp_parameters = ToRtpParameters<cricket::VideoCodec>(
620 {vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
621 ASSERT_EQ(3u, rtp_parameters.codecs.size());
622 EXPECT_EQ("VP8", rtp_parameters.codecs[0].name);
623 EXPECT_EQ("red", rtp_parameters.codecs[1].name);
624 EXPECT_EQ("ulpfec", rtp_parameters.codecs[2].name);
625 ASSERT_EQ(2u, rtp_parameters.header_extensions.size());
626 EXPECT_EQ("uri", rtp_parameters.header_extensions[0].uri);
627 EXPECT_EQ(1, rtp_parameters.header_extensions[0].id);
628 EXPECT_EQ("uri2", rtp_parameters.header_extensions[1].uri);
629 EXPECT_EQ(3, rtp_parameters.header_extensions[1].id);
630 ASSERT_EQ(1u, rtp_parameters.encodings.size());
631 EXPECT_EQ(1234u, rtp_parameters.encodings[0].ssrc);
632 }
633
634 } // namespace webrtc
635