• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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