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