blob: 3d64d62d780852fcde35e38037473c898284b4fc [file] [log] [blame]
deadbeefe814a0d2017-02-25 18:15:09 -08001/*
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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "pc/rtp_parameters_conversion.h"
12
deadbeefe814a0d2017-02-25 18:15:09 -080013#include <algorithm>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/gunit.h"
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "test/gmock.h"
17
18using ::testing::UnorderedElementsAre;
deadbeefe814a0d2017-02-25 18:15:09 -080019
20namespace webrtc {
21
22TEST(RtpParametersConversionTest, ToCricketFeedbackParam) {
23 auto result = ToCricketFeedbackParam(
24 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR});
25 EXPECT_EQ(cricket::FeedbackParam("ccm", "fir"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020026
27 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::LNTF));
28 EXPECT_EQ(cricket::FeedbackParam("goog-lntf"), result.value());
29
deadbeefe814a0d2017-02-25 18:15:09 -080030 result = ToCricketFeedbackParam(
31 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK});
32 EXPECT_EQ(cricket::FeedbackParam("nack"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020033
deadbeefe814a0d2017-02-25 18:15:09 -080034 result = ToCricketFeedbackParam(
35 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI});
36 EXPECT_EQ(cricket::FeedbackParam("nack", "pli"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020037
deadbeefe814a0d2017-02-25 18:15:09 -080038 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::REMB));
39 EXPECT_EQ(cricket::FeedbackParam("goog-remb"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020040
deadbeefe814a0d2017-02-25 18:15:09 -080041 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC));
42 EXPECT_EQ(cricket::FeedbackParam("transport-cc"), result.value());
43}
44
45TEST(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());
Elad Alonfadb1812019-05-24 13:40:02 +020049
deadbeefe814a0d2017-02-25 18:15:09 -080050 result = ToCricketFeedbackParam(
51 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::PLI});
52 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020053
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
deadbeefe814a0d2017-02-25 18:15:09 -080059 // NACK with missing or invalid message type.
60 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::NACK));
61 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020062
deadbeefe814a0d2017-02-25 18:15:09 -080063 result = ToCricketFeedbackParam(
64 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::FIR});
65 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020066
deadbeefe814a0d2017-02-25 18:15:09 -080067 // 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());
Elad Alonfadb1812019-05-24 13:40:02 +020071
deadbeefe814a0d2017-02-25 18:15:09 -080072 // 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
78TEST(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
101TEST(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";
Elad Alonfadb1812019-05-24 13:40:02 +0200109 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::LNTF);
deadbeefe814a0d2017-02-25 18:15:09 -0800110 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"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200122 EXPECT_EQ(3u, result.value().feedback_params.params().size());
123 EXPECT_TRUE(
124 result.value().feedback_params.Has(cricket::FeedbackParam("goog-lntf")));
deadbeefe814a0d2017-02-25 18:15:09 -0800125 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.
132TEST(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
161TEST(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
193TEST(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
219TEST(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.
242TEST(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
260TEST(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
282TEST(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
304TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensions) {
305 std::vector<RtpHeaderExtensionParameters> extensions = {
Johannes Kron07ba2b92018-09-26 13:33:35 +0200306 {"http://example.com", 1},
307 {"urn:foo:bar", 14},
308 {"urn:first:two-byte-only:id", 15}};
deadbeefe814a0d2017-02-25 18:15:09 -0800309 auto result = ToCricketRtpHeaderExtensions(extensions);
310 ASSERT_TRUE(result.ok());
Johannes Kron07ba2b92018-09-26 13:33:35 +0200311 ASSERT_EQ(3u, result.value().size());
deadbeefe814a0d2017-02-25 18:15:09 -0800312 EXPECT_EQ("http://example.com", result.value()[0].uri);
313 EXPECT_EQ(1, result.value()[0].id);
314 EXPECT_EQ("urn:foo:bar", result.value()[1].uri);
315 EXPECT_EQ(14, result.value()[1].id);
Johannes Kron07ba2b92018-09-26 13:33:35 +0200316 EXPECT_EQ("urn:first:two-byte-only:id", result.value()[2].uri);
317 EXPECT_EQ(15, result.value()[2].id);
deadbeefe814a0d2017-02-25 18:15:09 -0800318}
319
320TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensionsErrors) {
Johannes Kron07ba2b92018-09-26 13:33:35 +0200321 // First, IDs outside the range 1-255.
deadbeefe814a0d2017-02-25 18:15:09 -0800322 std::vector<RtpHeaderExtensionParameters> extensions = {
323 {"http://example.com", 0}};
324 auto result = ToCricketRtpHeaderExtensions(extensions);
325 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
326
Johannes Kron07ba2b92018-09-26 13:33:35 +0200327 extensions[0].id = 256;
deadbeefe814a0d2017-02-25 18:15:09 -0800328 result = ToCricketRtpHeaderExtensions(extensions);
329 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
330
331 // Duplicate IDs.
332 extensions = {{"http://example.com", 1}, {"urn:foo:bar", 1}};
333 result = ToCricketRtpHeaderExtensions(extensions);
334 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
335}
336
337TEST(RtpParametersConversionTest, ToCricketStreamParamsVecSimple) {
338 std::vector<RtpEncodingParameters> encodings;
339 RtpEncodingParameters encoding;
340 encoding.ssrc.emplace(0xbaadf00d);
341 encodings.push_back(encoding);
342 auto result = ToCricketStreamParamsVec(encodings);
343 ASSERT_TRUE(result.ok());
344 ASSERT_EQ(1u, result.value().size());
345 EXPECT_EQ(1u, result.value()[0].ssrcs.size());
346 EXPECT_EQ(0xbaadf00d, result.value()[0].first_ssrc());
347}
348
349TEST(RtpParametersConversionTest, ToCricketStreamParamsVecWithRtx) {
350 std::vector<RtpEncodingParameters> encodings;
351 RtpEncodingParameters encoding;
352 // Test a corner case SSRC of 0.
353 encoding.ssrc.emplace(0u);
354 encoding.rtx.emplace(0xdeadbeef);
355 encodings.push_back(encoding);
356 auto result = ToCricketStreamParamsVec(encodings);
357 ASSERT_TRUE(result.ok());
358 ASSERT_EQ(1u, result.value().size());
359 EXPECT_EQ(2u, result.value()[0].ssrcs.size());
360 EXPECT_EQ(0u, result.value()[0].first_ssrc());
361 uint32_t rtx_ssrc = 0;
362 EXPECT_TRUE(result.value()[0].GetFidSsrc(0u, &rtx_ssrc));
363 EXPECT_EQ(0xdeadbeef, rtx_ssrc);
364}
365
366// No encodings should be accepted; an endpoint may want to prepare a
367// decoder/encoder without having something to receive/send yet.
368TEST(RtpParametersConversionTest, ToCricketStreamParamsVecNoEncodings) {
369 std::vector<RtpEncodingParameters> encodings;
370 auto result = ToCricketStreamParamsVec(encodings);
371 ASSERT_TRUE(result.ok());
372 EXPECT_EQ(0u, result.value().size());
373}
374
375// An encoding without SSRCs should be accepted. This could be the case when
376// SSRCs aren't signaled and payload-type based demuxing is used.
377TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMissingSsrcs) {
378 std::vector<RtpEncodingParameters> encodings = {{}};
379 // Creates RtxParameters with empty SSRC.
380 encodings[0].rtx.emplace();
381 auto result = ToCricketStreamParamsVec(encodings);
382 ASSERT_TRUE(result.ok());
383 EXPECT_EQ(0u, result.value().size());
384}
385
386// The media engine doesn't have a way of receiving an RTX SSRC that's known
387// with a primary SSRC that's unknown, so this should produce an error.
388TEST(RtpParametersConversionTest, ToStreamParamsWithPrimarySsrcSetAndRtxUnset) {
389 std::vector<RtpEncodingParameters> encodings = {{}};
390 encodings[0].rtx.emplace(0xdeadbeef);
391 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
392 ToCricketStreamParamsVec(encodings).error().type());
393}
394
395// TODO(deadbeef): Update this test when we support multiple encodings.
396TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMultipleEncodings) {
397 std::vector<RtpEncodingParameters> encodings = {{}, {}};
398 auto result = ToCricketStreamParamsVec(encodings);
399 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, result.error().type());
400}
401
402TEST(RtpParametersConversionTest, ToRtcpFeedback) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200403 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "fir"});
deadbeefe814a0d2017-02-25 18:15:09 -0800404 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR),
405 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200406
407 result = ToRtcpFeedback(cricket::FeedbackParam("goog-lntf"));
408 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), *result);
409
deadbeefe814a0d2017-02-25 18:15:09 -0800410 result = ToRtcpFeedback(cricket::FeedbackParam("nack"));
411 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK,
412 RtcpFeedbackMessageType::GENERIC_NACK),
413 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200414
deadbeefe814a0d2017-02-25 18:15:09 -0800415 result = ToRtcpFeedback({"nack", "pli"});
416 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
417 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200418
deadbeefe814a0d2017-02-25 18:15:09 -0800419 result = ToRtcpFeedback(cricket::FeedbackParam("goog-remb"));
420 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::REMB), *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200421
deadbeefe814a0d2017-02-25 18:15:09 -0800422 result = ToRtcpFeedback(cricket::FeedbackParam("transport-cc"));
423 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), *result);
424}
425
426TEST(RtpParametersConversionTest, ToRtcpFeedbackErrors) {
427 // CCM with missing or invalid message type.
Danil Chapovalov00c71832018-06-15 15:58:38 +0200428 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "pli"});
deadbeefe814a0d2017-02-25 18:15:09 -0800429 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200430
deadbeefe814a0d2017-02-25 18:15:09 -0800431 result = ToRtcpFeedback(cricket::FeedbackParam("ccm"));
432 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200433
434 // LNTF with message type (should be left empty).
435 result = ToRtcpFeedback({"goog-lntf", "pli"});
436 EXPECT_FALSE(result);
437
deadbeefe814a0d2017-02-25 18:15:09 -0800438 // NACK with missing or invalid message type.
439 result = ToRtcpFeedback({"nack", "fir"});
440 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200441
deadbeefe814a0d2017-02-25 18:15:09 -0800442 // REMB with message type (should be left empty).
443 result = ToRtcpFeedback({"goog-remb", "pli"});
444 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200445
deadbeefe814a0d2017-02-25 18:15:09 -0800446 // TRANSPORT_CC with message type (should be left empty).
447 result = ToRtcpFeedback({"transport-cc", "fir"});
448 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200449
deadbeefe814a0d2017-02-25 18:15:09 -0800450 // Unknown message type.
451 result = ToRtcpFeedback(cricket::FeedbackParam("foo"));
452 EXPECT_FALSE(result);
453}
454
455TEST(RtpParametersConversionTest, ToAudioRtpCodecCapability) {
456 cricket::AudioCodec cricket_codec;
457 cricket_codec.name = "foo";
458 cricket_codec.id = 50;
459 cricket_codec.clockrate = 22222;
460 cricket_codec.channels = 4;
461 cricket_codec.params["foo"] = "bar";
462 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
463 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
464
465 EXPECT_EQ("foo", codec.name);
466 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100467 EXPECT_EQ(50, codec.preferred_payload_type);
468 EXPECT_EQ(22222, codec.clock_rate);
469 EXPECT_EQ(4, codec.num_channels);
deadbeefe814a0d2017-02-25 18:15:09 -0800470 ASSERT_EQ(1u, codec.parameters.size());
471 EXPECT_EQ("bar", codec.parameters["foo"]);
472 EXPECT_EQ(1u, codec.rtcp_feedback.size());
473 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
474 codec.rtcp_feedback[0]);
475}
476
477TEST(RtpParametersConversionTest, ToVideoRtpCodecCapability) {
478 cricket::VideoCodec cricket_codec;
479 cricket_codec.name = "VID";
480 cricket_codec.id = 101;
481 cricket_codec.clockrate = 80000;
482 cricket_codec.params["foo"] = "bar";
483 cricket_codec.params["ANOTHER"] = "param";
484 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
Elad Alonfadb1812019-05-24 13:40:02 +0200485 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
deadbeefe814a0d2017-02-25 18:15:09 -0800486 cricket_codec.feedback_params.Add({"nack", "pli"});
487 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
488
489 EXPECT_EQ("VID", codec.name);
490 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100491 EXPECT_EQ(101, codec.preferred_payload_type);
492 EXPECT_EQ(80000, codec.clock_rate);
deadbeefe814a0d2017-02-25 18:15:09 -0800493 ASSERT_EQ(2u, codec.parameters.size());
494 EXPECT_EQ("bar", codec.parameters["foo"]);
495 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200496 EXPECT_EQ(3u, codec.rtcp_feedback.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800497 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
498 codec.rtcp_feedback[0]);
Elad Alonfadb1812019-05-24 13:40:02 +0200499 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
deadbeefe814a0d2017-02-25 18:15:09 -0800500 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
Elad Alonfadb1812019-05-24 13:40:02 +0200501 codec.rtcp_feedback[2]);
deadbeefe814a0d2017-02-25 18:15:09 -0800502}
503
zhihuang24366392017-03-08 17:15:06 -0800504TEST(RtpParametersConversionTest, ToRtpEncodingsWithEmptyStreamParamsVec) {
505 cricket::StreamParamsVec streams;
506 auto rtp_encodings = ToRtpEncodings(streams);
507 ASSERT_EQ(0u, rtp_encodings.size());
508}
509
510TEST(RtpParametersConversionTest, ToRtpEncodingsWithMultipleStreamParams) {
511 cricket::StreamParamsVec streams;
512 cricket::StreamParams stream1;
513 stream1.ssrcs.push_back(1111u);
514 stream1.AddFidSsrc(1111u, 0xaaaaaaaa);
515
516 cricket::StreamParams stream2;
517 stream2.ssrcs.push_back(2222u);
518 stream2.AddFidSsrc(2222u, 0xaaaaaaab);
519
520 streams.push_back(stream1);
521 streams.push_back(stream2);
522
523 auto rtp_encodings = ToRtpEncodings(streams);
524 ASSERT_EQ(2u, rtp_encodings.size());
525 EXPECT_EQ(1111u, rtp_encodings[0].ssrc);
526 EXPECT_EQ(0xaaaaaaaa, rtp_encodings[0].rtx->ssrc);
527 EXPECT_EQ(2222u, rtp_encodings[1].ssrc);
528 EXPECT_EQ(0xaaaaaaab, rtp_encodings[1].rtx->ssrc);
529}
530
531TEST(RtpParametersConversionTest, ToAudioRtpCodecParameters) {
532 cricket::AudioCodec cricket_codec;
533 cricket_codec.name = "foo";
534 cricket_codec.id = 50;
535 cricket_codec.clockrate = 22222;
536 cricket_codec.channels = 4;
537 cricket_codec.params["foo"] = "bar";
538 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
539 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
540
541 EXPECT_EQ("foo", codec.name);
542 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
543 EXPECT_EQ(50, codec.payload_type);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100544 EXPECT_EQ(22222, codec.clock_rate);
545 EXPECT_EQ(4, codec.num_channels);
zhihuang24366392017-03-08 17:15:06 -0800546 ASSERT_EQ(1u, codec.parameters.size());
547 EXPECT_EQ("bar", codec.parameters["foo"]);
548 EXPECT_EQ(1u, codec.rtcp_feedback.size());
549 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
550 codec.rtcp_feedback[0]);
551}
552
553TEST(RtpParametersConversionTest, ToVideoRtpCodecParameters) {
554 cricket::VideoCodec cricket_codec;
555 cricket_codec.name = "VID";
556 cricket_codec.id = 101;
557 cricket_codec.clockrate = 80000;
558 cricket_codec.params["foo"] = "bar";
559 cricket_codec.params["ANOTHER"] = "param";
560 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
Elad Alonfadb1812019-05-24 13:40:02 +0200561 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
zhihuang24366392017-03-08 17:15:06 -0800562 cricket_codec.feedback_params.Add({"nack", "pli"});
563 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
564
565 EXPECT_EQ("VID", codec.name);
566 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
567 EXPECT_EQ(101, codec.payload_type);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100568 EXPECT_EQ(80000, codec.clock_rate);
zhihuang24366392017-03-08 17:15:06 -0800569 ASSERT_EQ(2u, codec.parameters.size());
570 EXPECT_EQ("bar", codec.parameters["foo"]);
571 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200572 EXPECT_EQ(3u, codec.rtcp_feedback.size());
zhihuang24366392017-03-08 17:15:06 -0800573 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
574 codec.rtcp_feedback[0]);
Elad Alonfadb1812019-05-24 13:40:02 +0200575 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
zhihuang24366392017-03-08 17:15:06 -0800576 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
Elad Alonfadb1812019-05-24 13:40:02 +0200577 codec.rtcp_feedback[2]);
zhihuang24366392017-03-08 17:15:06 -0800578}
579
deadbeefe814a0d2017-02-25 18:15:09 -0800580// An unknown feedback param should just be ignored.
581TEST(RtpParametersConversionTest, ToRtpCodecCapabilityUnknownFeedbackParam) {
582 cricket::AudioCodec cricket_codec;
583 cricket_codec.name = "foo";
584 cricket_codec.id = 50;
585 cricket_codec.clockrate = 22222;
586 cricket_codec.channels = 4;
587 cricket_codec.params["foo"] = "bar";
588 cricket_codec.feedback_params.Add({"unknown", "param"});
589 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
590 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
591
592 ASSERT_EQ(1u, codec.rtcp_feedback.size());
593 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
594 codec.rtcp_feedback[0]);
595}
596
597// Most of ToRtpCapabilities is tested by ToRtpCodecCapability, but we need to
598// test that the result of ToRtpCodecCapability ends up in the result, and that
599// the "fec" list is assembled correctly.
600TEST(RtpParametersConversionTest, ToRtpCapabilities) {
601 cricket::VideoCodec vp8;
602 vp8.name = "VP8";
603 vp8.id = 101;
604 vp8.clockrate = 90000;
605
606 cricket::VideoCodec red;
607 red.name = "red";
608 red.id = 102;
609 red.clockrate = 90000;
610
611 cricket::VideoCodec ulpfec;
612 ulpfec.name = "ulpfec";
613 ulpfec.id = 103;
614 ulpfec.clockrate = 90000;
615
616 cricket::VideoCodec flexfec;
617 flexfec.name = "flexfec-03";
618 flexfec.id = 102;
619 flexfec.clockrate = 90000;
620
Florent Castelli5473a452018-11-06 17:27:21 +0100621 cricket::VideoCodec rtx;
622 rtx.name = "rtx";
623 rtx.id = 104;
624 rtx.params.insert({"apt", "101"});
625
626 cricket::VideoCodec rtx2;
627 rtx2.name = "rtx";
628 rtx2.id = 105;
629 rtx2.params.insert({"apt", "109"});
630
deadbeefe814a0d2017-02-25 18:15:09 -0800631 RtpCapabilities capabilities = ToRtpCapabilities<cricket::VideoCodec>(
Florent Castelli5473a452018-11-06 17:27:21 +0100632 {vp8, ulpfec, rtx, rtx2}, {{"uri", 1}, {"uri2", 3}});
633 ASSERT_EQ(3u, capabilities.codecs.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800634 EXPECT_EQ("VP8", capabilities.codecs[0].name);
635 EXPECT_EQ("ulpfec", capabilities.codecs[1].name);
Florent Castelli5473a452018-11-06 17:27:21 +0100636 EXPECT_EQ("rtx", capabilities.codecs[2].name);
637 EXPECT_EQ(0u, capabilities.codecs[2].parameters.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800638 ASSERT_EQ(2u, capabilities.header_extensions.size());
639 EXPECT_EQ("uri", capabilities.header_extensions[0].uri);
640 EXPECT_EQ(1, capabilities.header_extensions[0].preferred_id);
641 EXPECT_EQ("uri2", capabilities.header_extensions[1].uri);
642 EXPECT_EQ(3, capabilities.header_extensions[1].preferred_id);
643 EXPECT_EQ(0u, capabilities.fec.size());
644
645 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
Florent Castelli5473a452018-11-06 17:27:21 +0100646 {vp8, red, ulpfec, rtx}, cricket::RtpHeaderExtensions());
647 EXPECT_EQ(4u, capabilities.codecs.size());
Steve Anton64b626b2019-01-28 17:25:26 -0800648 EXPECT_THAT(
649 capabilities.fec,
650 UnorderedElementsAre(FecMechanism::RED, FecMechanism::RED_AND_ULPFEC));
deadbeefe814a0d2017-02-25 18:15:09 -0800651
652 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
653 {vp8, red, flexfec}, cricket::RtpHeaderExtensions());
654 EXPECT_EQ(3u, capabilities.codecs.size());
Steve Anton64b626b2019-01-28 17:25:26 -0800655 EXPECT_THAT(capabilities.fec,
656 UnorderedElementsAre(FecMechanism::RED, FecMechanism::FLEXFEC));
deadbeefe814a0d2017-02-25 18:15:09 -0800657}
658
zhihuang24366392017-03-08 17:15:06 -0800659TEST(RtpParametersConversionTest, ToRtpParameters) {
660 cricket::VideoCodec vp8;
661 vp8.name = "VP8";
662 vp8.id = 101;
663 vp8.clockrate = 90000;
664
665 cricket::VideoCodec red;
666 red.name = "red";
667 red.id = 102;
668 red.clockrate = 90000;
669
670 cricket::VideoCodec ulpfec;
671 ulpfec.name = "ulpfec";
672 ulpfec.id = 103;
673 ulpfec.clockrate = 90000;
674
675 cricket::StreamParamsVec streams;
676 cricket::StreamParams stream;
677 stream.ssrcs.push_back(1234u);
678 streams.push_back(stream);
679
680 RtpParameters rtp_parameters = ToRtpParameters<cricket::VideoCodec>(
681 {vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
682 ASSERT_EQ(3u, rtp_parameters.codecs.size());
683 EXPECT_EQ("VP8", rtp_parameters.codecs[0].name);
684 EXPECT_EQ("red", rtp_parameters.codecs[1].name);
685 EXPECT_EQ("ulpfec", rtp_parameters.codecs[2].name);
686 ASSERT_EQ(2u, rtp_parameters.header_extensions.size());
687 EXPECT_EQ("uri", rtp_parameters.header_extensions[0].uri);
688 EXPECT_EQ(1, rtp_parameters.header_extensions[0].id);
689 EXPECT_EQ("uri2", rtp_parameters.header_extensions[1].uri);
690 EXPECT_EQ(3, rtp_parameters.header_extensions[1].id);
691 ASSERT_EQ(1u, rtp_parameters.encodings.size());
692 EXPECT_EQ(1234u, rtp_parameters.encodings[0].ssrc);
693}
694
deadbeefe814a0d2017-02-25 18:15:09 -0800695} // namespace webrtc