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