blob: 83a2893af35773377a2a79a157f2d2491351935b [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
11#include <algorithm>
12
Steve Anton10542f22019-01-11 09:11:00 -080013#include "pc/rtp_parameters_conversion.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "rtc_base/gunit.h"
Steve Anton64b626b2019-01-28 17:25:26 -080015#include "test/gmock.h"
16
17using ::testing::UnorderedElementsAre;
deadbeefe814a0d2017-02-25 18:15:09 -080018
19namespace webrtc {
20
21TEST(RtpParametersConversionTest, ToCricketFeedbackParam) {
22 auto result = ToCricketFeedbackParam(
23 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR});
24 EXPECT_EQ(cricket::FeedbackParam("ccm", "fir"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020025
26 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::LNTF));
27 EXPECT_EQ(cricket::FeedbackParam("goog-lntf"), result.value());
28
deadbeefe814a0d2017-02-25 18:15:09 -080029 result = ToCricketFeedbackParam(
30 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::GENERIC_NACK});
31 EXPECT_EQ(cricket::FeedbackParam("nack"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020032
deadbeefe814a0d2017-02-25 18:15:09 -080033 result = ToCricketFeedbackParam(
34 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI});
35 EXPECT_EQ(cricket::FeedbackParam("nack", "pli"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020036
deadbeefe814a0d2017-02-25 18:15:09 -080037 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::REMB));
38 EXPECT_EQ(cricket::FeedbackParam("goog-remb"), result.value());
Elad Alonfadb1812019-05-24 13:40:02 +020039
deadbeefe814a0d2017-02-25 18:15:09 -080040 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC));
41 EXPECT_EQ(cricket::FeedbackParam("transport-cc"), result.value());
42}
43
44TEST(RtpParametersConversionTest, ToCricketFeedbackParamErrors) {
45 // CCM with missing or invalid message type.
46 auto result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::CCM));
47 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020048
deadbeefe814a0d2017-02-25 18:15:09 -080049 result = ToCricketFeedbackParam(
50 {RtcpFeedbackType::CCM, RtcpFeedbackMessageType::PLI});
51 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020052
53 // LNTF with message type (should be left empty).
54 result = ToCricketFeedbackParam(
55 {RtcpFeedbackType::LNTF, RtcpFeedbackMessageType::GENERIC_NACK});
56 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
57
deadbeefe814a0d2017-02-25 18:15:09 -080058 // NACK with missing or invalid message type.
59 result = ToCricketFeedbackParam(RtcpFeedback(RtcpFeedbackType::NACK));
60 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020061
deadbeefe814a0d2017-02-25 18:15:09 -080062 result = ToCricketFeedbackParam(
63 {RtcpFeedbackType::NACK, RtcpFeedbackMessageType::FIR});
64 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020065
deadbeefe814a0d2017-02-25 18:15:09 -080066 // REMB with message type (should be left empty).
67 result = ToCricketFeedbackParam(
68 {RtcpFeedbackType::REMB, RtcpFeedbackMessageType::GENERIC_NACK});
69 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
Elad Alonfadb1812019-05-24 13:40:02 +020070
deadbeefe814a0d2017-02-25 18:15:09 -080071 // TRANSPORT_CC with message type (should be left empty).
72 result = ToCricketFeedbackParam(
73 {RtcpFeedbackType::TRANSPORT_CC, RtcpFeedbackMessageType::FIR});
74 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
75}
76
77TEST(RtpParametersConversionTest, ToAudioCodec) {
78 RtpCodecParameters codec;
79 codec.name = "AuDiO";
80 codec.kind = cricket::MEDIA_TYPE_AUDIO;
81 codec.payload_type = 120;
82 codec.clock_rate.emplace(36000);
83 codec.num_channels.emplace(6);
84 codec.parameters["foo"] = "bar";
85 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
86 auto result = ToCricketCodec<cricket::AudioCodec>(codec);
87 ASSERT_TRUE(result.ok());
88
89 EXPECT_EQ("AuDiO", result.value().name);
90 EXPECT_EQ(120, result.value().id);
91 EXPECT_EQ(36000, result.value().clockrate);
92 EXPECT_EQ(6u, result.value().channels);
93 ASSERT_EQ(1u, result.value().params.size());
94 EXPECT_EQ("bar", result.value().params["foo"]);
95 EXPECT_EQ(1u, result.value().feedback_params.params().size());
96 EXPECT_TRUE(result.value().feedback_params.Has(
97 cricket::FeedbackParam("transport-cc")));
98}
99
100TEST(RtpParametersConversionTest, ToVideoCodec) {
101 RtpCodecParameters codec;
102 codec.name = "coolcodec";
103 codec.kind = cricket::MEDIA_TYPE_VIDEO;
104 codec.payload_type = 101;
105 codec.clock_rate.emplace(90000);
106 codec.parameters["foo"] = "bar";
107 codec.parameters["PING"] = "PONG";
Elad Alonfadb1812019-05-24 13:40:02 +0200108 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::LNTF);
deadbeefe814a0d2017-02-25 18:15:09 -0800109 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
110 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK,
111 RtcpFeedbackMessageType::PLI);
112 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
113 ASSERT_TRUE(result.ok());
114
115 EXPECT_EQ("coolcodec", result.value().name);
116 EXPECT_EQ(101, result.value().id);
117 EXPECT_EQ(90000, result.value().clockrate);
118 ASSERT_EQ(2u, result.value().params.size());
119 EXPECT_EQ("bar", result.value().params["foo"]);
120 EXPECT_EQ("PONG", result.value().params["PING"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200121 EXPECT_EQ(3u, result.value().feedback_params.params().size());
122 EXPECT_TRUE(
123 result.value().feedback_params.Has(cricket::FeedbackParam("goog-lntf")));
deadbeefe814a0d2017-02-25 18:15:09 -0800124 EXPECT_TRUE(result.value().feedback_params.Has(
125 cricket::FeedbackParam("transport-cc")));
126 EXPECT_TRUE(result.value().feedback_params.Has(
127 cricket::FeedbackParam("nack", "pli")));
128}
129
130// Trying to convert to an AudioCodec if the kind is "video" should fail.
131TEST(RtpParametersConversionTest, ToCricketCodecInvalidKind) {
132 RtpCodecParameters audio_codec;
133 audio_codec.name = "opus";
134 audio_codec.kind = cricket::MEDIA_TYPE_VIDEO;
135 audio_codec.payload_type = 111;
136 audio_codec.clock_rate.emplace(48000);
137 audio_codec.num_channels.emplace(2);
138
139 RtpCodecParameters video_codec;
140 video_codec.name = "VP8";
141 video_codec.kind = cricket::MEDIA_TYPE_AUDIO;
142 video_codec.payload_type = 102;
143 video_codec.clock_rate.emplace(90000);
144
145 auto audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
146 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, audio_result.error().type());
147
148 auto video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
149 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_result.error().type());
150
151 // Sanity check that if the kind is correct, the conversion succeeds.
152 audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
153 video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
154 audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
155 EXPECT_TRUE(audio_result.ok());
156 video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
157 EXPECT_TRUE(video_result.ok());
158}
159
160TEST(RtpParametersConversionTest, ToAudioCodecInvalidParameters) {
161 // Missing channels.
162 RtpCodecParameters codec;
163 codec.name = "opus";
164 codec.kind = cricket::MEDIA_TYPE_AUDIO;
165 codec.payload_type = 111;
166 codec.clock_rate.emplace(48000);
167 auto result = ToCricketCodec<cricket::AudioCodec>(codec);
168 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
169
170 // Negative number of channels.
171 codec.num_channels.emplace(-1);
172 result = ToCricketCodec<cricket::AudioCodec>(codec);
173 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
174
175 // Missing clock rate.
176 codec.num_channels.emplace(2);
177 codec.clock_rate.reset();
178 result = ToCricketCodec<cricket::AudioCodec>(codec);
179 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
180
181 // Negative clock rate.
182 codec.clock_rate.emplace(-48000);
183 result = ToCricketCodec<cricket::AudioCodec>(codec);
184 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
185
186 // Sanity check that conversion succeeds if these errors are fixed.
187 codec.clock_rate.emplace(48000);
188 result = ToCricketCodec<cricket::AudioCodec>(codec);
189 EXPECT_TRUE(result.ok());
190}
191
192TEST(RtpParametersConversionTest, ToVideoCodecInvalidParameters) {
193 // Missing clock rate.
194 RtpCodecParameters codec;
195 codec.name = "VP8";
196 codec.kind = cricket::MEDIA_TYPE_VIDEO;
197 codec.payload_type = 102;
198 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
199 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
200
201 // Invalid clock rate.
202 codec.clock_rate.emplace(48000);
203 result = ToCricketCodec<cricket::VideoCodec>(codec);
204 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
205
206 // Channels set (should be unset).
207 codec.clock_rate.emplace(90000);
208 codec.num_channels.emplace(2);
209 result = ToCricketCodec<cricket::VideoCodec>(codec);
210 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
211
212 // Sanity check that conversion succeeds if these errors are fixed.
213 codec.num_channels.reset();
214 result = ToCricketCodec<cricket::VideoCodec>(codec);
215 EXPECT_TRUE(result.ok());
216}
217
218TEST(RtpParametersConversionTest, ToCricketCodecInvalidPayloadType) {
219 RtpCodecParameters codec;
220 codec.name = "VP8";
221 codec.kind = cricket::MEDIA_TYPE_VIDEO;
222 codec.clock_rate.emplace(90000);
223
224 codec.payload_type = -1000;
225 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
226 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
227
228 // Max payload type is 127.
229 codec.payload_type = 128;
230 result = ToCricketCodec<cricket::VideoCodec>(codec);
231 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
232
233 // Sanity check that conversion succeeds with a valid payload type.
234 codec.payload_type = 127;
235 result = ToCricketCodec<cricket::VideoCodec>(codec);
236 EXPECT_TRUE(result.ok());
237}
238
239// There are already tests for ToCricketFeedbackParam, but ensure that those
240// errors are propagated from ToCricketCodec.
241TEST(RtpParametersConversionTest, ToCricketCodecInvalidRtcpFeedback) {
242 RtpCodecParameters codec;
243 codec.name = "VP8";
244 codec.kind = cricket::MEDIA_TYPE_VIDEO;
245 codec.clock_rate.emplace(90000);
246 codec.payload_type = 99;
247 codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM,
248 RtcpFeedbackMessageType::PLI);
249
250 auto result = ToCricketCodec<cricket::VideoCodec>(codec);
251 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
252
253 // Sanity check that conversion succeeds without invalid feedback.
254 codec.rtcp_feedback.clear();
255 result = ToCricketCodec<cricket::VideoCodec>(codec);
256 EXPECT_TRUE(result.ok());
257}
258
259TEST(RtpParametersConversionTest, ToCricketCodecs) {
260 std::vector<RtpCodecParameters> codecs;
261 RtpCodecParameters codec;
262 codec.name = "VP8";
263 codec.kind = cricket::MEDIA_TYPE_VIDEO;
264 codec.clock_rate.emplace(90000);
265 codec.payload_type = 99;
266 codecs.push_back(codec);
267
268 codec.name = "VP9";
269 codec.payload_type = 100;
270 codecs.push_back(codec);
271
272 auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
273 ASSERT_TRUE(result.ok());
274 ASSERT_EQ(2u, result.value().size());
275 EXPECT_EQ("VP8", result.value()[0].name);
276 EXPECT_EQ(99, result.value()[0].id);
277 EXPECT_EQ("VP9", result.value()[1].name);
278 EXPECT_EQ(100, result.value()[1].id);
279}
280
281TEST(RtpParametersConversionTest, ToCricketCodecsDuplicatePayloadType) {
282 std::vector<RtpCodecParameters> codecs;
283 RtpCodecParameters codec;
284 codec.name = "VP8";
285 codec.kind = cricket::MEDIA_TYPE_VIDEO;
286 codec.clock_rate.emplace(90000);
287 codec.payload_type = 99;
288 codecs.push_back(codec);
289
290 codec.name = "VP9";
291 codec.payload_type = 99;
292 codecs.push_back(codec);
293
294 auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
295 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
296
297 // Sanity check that this succeeds without the duplicate payload type.
298 codecs[1].payload_type = 120;
299 result = ToCricketCodecs<cricket::VideoCodec>(codecs);
300 EXPECT_TRUE(result.ok());
301}
302
303TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensions) {
304 std::vector<RtpHeaderExtensionParameters> extensions = {
Johannes Kron07ba2b92018-09-26 13:33:35 +0200305 {"http://example.com", 1},
306 {"urn:foo:bar", 14},
307 {"urn:first:two-byte-only:id", 15}};
deadbeefe814a0d2017-02-25 18:15:09 -0800308 auto result = ToCricketRtpHeaderExtensions(extensions);
309 ASSERT_TRUE(result.ok());
Johannes Kron07ba2b92018-09-26 13:33:35 +0200310 ASSERT_EQ(3u, result.value().size());
deadbeefe814a0d2017-02-25 18:15:09 -0800311 EXPECT_EQ("http://example.com", result.value()[0].uri);
312 EXPECT_EQ(1, result.value()[0].id);
313 EXPECT_EQ("urn:foo:bar", result.value()[1].uri);
314 EXPECT_EQ(14, result.value()[1].id);
Johannes Kron07ba2b92018-09-26 13:33:35 +0200315 EXPECT_EQ("urn:first:two-byte-only:id", result.value()[2].uri);
316 EXPECT_EQ(15, result.value()[2].id);
deadbeefe814a0d2017-02-25 18:15:09 -0800317}
318
319TEST(RtpParametersConversionTest, ToCricketRtpHeaderExtensionsErrors) {
Johannes Kron07ba2b92018-09-26 13:33:35 +0200320 // First, IDs outside the range 1-255.
deadbeefe814a0d2017-02-25 18:15:09 -0800321 std::vector<RtpHeaderExtensionParameters> extensions = {
322 {"http://example.com", 0}};
323 auto result = ToCricketRtpHeaderExtensions(extensions);
324 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
325
Johannes Kron07ba2b92018-09-26 13:33:35 +0200326 extensions[0].id = 256;
deadbeefe814a0d2017-02-25 18:15:09 -0800327 result = ToCricketRtpHeaderExtensions(extensions);
328 EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
329
330 // Duplicate IDs.
331 extensions = {{"http://example.com", 1}, {"urn:foo:bar", 1}};
332 result = ToCricketRtpHeaderExtensions(extensions);
333 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
334}
335
336TEST(RtpParametersConversionTest, ToCricketStreamParamsVecSimple) {
337 std::vector<RtpEncodingParameters> encodings;
338 RtpEncodingParameters encoding;
339 encoding.ssrc.emplace(0xbaadf00d);
340 encodings.push_back(encoding);
341 auto result = ToCricketStreamParamsVec(encodings);
342 ASSERT_TRUE(result.ok());
343 ASSERT_EQ(1u, result.value().size());
344 EXPECT_EQ(1u, result.value()[0].ssrcs.size());
345 EXPECT_EQ(0xbaadf00d, result.value()[0].first_ssrc());
346}
347
348TEST(RtpParametersConversionTest, ToCricketStreamParamsVecWithRtx) {
349 std::vector<RtpEncodingParameters> encodings;
350 RtpEncodingParameters encoding;
351 // Test a corner case SSRC of 0.
352 encoding.ssrc.emplace(0u);
353 encoding.rtx.emplace(0xdeadbeef);
354 encodings.push_back(encoding);
355 auto result = ToCricketStreamParamsVec(encodings);
356 ASSERT_TRUE(result.ok());
357 ASSERT_EQ(1u, result.value().size());
358 EXPECT_EQ(2u, result.value()[0].ssrcs.size());
359 EXPECT_EQ(0u, result.value()[0].first_ssrc());
360 uint32_t rtx_ssrc = 0;
361 EXPECT_TRUE(result.value()[0].GetFidSsrc(0u, &rtx_ssrc));
362 EXPECT_EQ(0xdeadbeef, rtx_ssrc);
363}
364
365// No encodings should be accepted; an endpoint may want to prepare a
366// decoder/encoder without having something to receive/send yet.
367TEST(RtpParametersConversionTest, ToCricketStreamParamsVecNoEncodings) {
368 std::vector<RtpEncodingParameters> encodings;
369 auto result = ToCricketStreamParamsVec(encodings);
370 ASSERT_TRUE(result.ok());
371 EXPECT_EQ(0u, result.value().size());
372}
373
374// An encoding without SSRCs should be accepted. This could be the case when
375// SSRCs aren't signaled and payload-type based demuxing is used.
376TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMissingSsrcs) {
377 std::vector<RtpEncodingParameters> encodings = {{}};
378 // Creates RtxParameters with empty SSRC.
379 encodings[0].rtx.emplace();
380 auto result = ToCricketStreamParamsVec(encodings);
381 ASSERT_TRUE(result.ok());
382 EXPECT_EQ(0u, result.value().size());
383}
384
385// The media engine doesn't have a way of receiving an RTX SSRC that's known
386// with a primary SSRC that's unknown, so this should produce an error.
387TEST(RtpParametersConversionTest, ToStreamParamsWithPrimarySsrcSetAndRtxUnset) {
388 std::vector<RtpEncodingParameters> encodings = {{}};
389 encodings[0].rtx.emplace(0xdeadbeef);
390 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER,
391 ToCricketStreamParamsVec(encodings).error().type());
392}
393
394// TODO(deadbeef): Update this test when we support multiple encodings.
395TEST(RtpParametersConversionTest, ToCricketStreamParamsVecMultipleEncodings) {
396 std::vector<RtpEncodingParameters> encodings = {{}, {}};
397 auto result = ToCricketStreamParamsVec(encodings);
398 EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, result.error().type());
399}
400
401TEST(RtpParametersConversionTest, ToRtcpFeedback) {
Danil Chapovalov00c71832018-06-15 15:58:38 +0200402 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "fir"});
deadbeefe814a0d2017-02-25 18:15:09 -0800403 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::CCM, RtcpFeedbackMessageType::FIR),
404 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200405
406 result = ToRtcpFeedback(cricket::FeedbackParam("goog-lntf"));
407 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), *result);
408
deadbeefe814a0d2017-02-25 18:15:09 -0800409 result = ToRtcpFeedback(cricket::FeedbackParam("nack"));
410 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK,
411 RtcpFeedbackMessageType::GENERIC_NACK),
412 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200413
deadbeefe814a0d2017-02-25 18:15:09 -0800414 result = ToRtcpFeedback({"nack", "pli"});
415 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
416 *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200417
deadbeefe814a0d2017-02-25 18:15:09 -0800418 result = ToRtcpFeedback(cricket::FeedbackParam("goog-remb"));
419 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::REMB), *result);
Elad Alonfadb1812019-05-24 13:40:02 +0200420
deadbeefe814a0d2017-02-25 18:15:09 -0800421 result = ToRtcpFeedback(cricket::FeedbackParam("transport-cc"));
422 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC), *result);
423}
424
425TEST(RtpParametersConversionTest, ToRtcpFeedbackErrors) {
426 // CCM with missing or invalid message type.
Danil Chapovalov00c71832018-06-15 15:58:38 +0200427 absl::optional<RtcpFeedback> result = ToRtcpFeedback({"ccm", "pli"});
deadbeefe814a0d2017-02-25 18:15:09 -0800428 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200429
deadbeefe814a0d2017-02-25 18:15:09 -0800430 result = ToRtcpFeedback(cricket::FeedbackParam("ccm"));
431 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200432
433 // LNTF with message type (should be left empty).
434 result = ToRtcpFeedback({"goog-lntf", "pli"});
435 EXPECT_FALSE(result);
436
deadbeefe814a0d2017-02-25 18:15:09 -0800437 // NACK with missing or invalid message type.
438 result = ToRtcpFeedback({"nack", "fir"});
439 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200440
deadbeefe814a0d2017-02-25 18:15:09 -0800441 // REMB with message type (should be left empty).
442 result = ToRtcpFeedback({"goog-remb", "pli"});
443 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200444
deadbeefe814a0d2017-02-25 18:15:09 -0800445 // TRANSPORT_CC with message type (should be left empty).
446 result = ToRtcpFeedback({"transport-cc", "fir"});
447 EXPECT_FALSE(result);
Elad Alonfadb1812019-05-24 13:40:02 +0200448
deadbeefe814a0d2017-02-25 18:15:09 -0800449 // Unknown message type.
450 result = ToRtcpFeedback(cricket::FeedbackParam("foo"));
451 EXPECT_FALSE(result);
452}
453
454TEST(RtpParametersConversionTest, ToAudioRtpCodecCapability) {
455 cricket::AudioCodec cricket_codec;
456 cricket_codec.name = "foo";
457 cricket_codec.id = 50;
458 cricket_codec.clockrate = 22222;
459 cricket_codec.channels = 4;
460 cricket_codec.params["foo"] = "bar";
461 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
462 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
463
464 EXPECT_EQ("foo", codec.name);
465 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100466 EXPECT_EQ(50, codec.preferred_payload_type);
467 EXPECT_EQ(22222, codec.clock_rate);
468 EXPECT_EQ(4, codec.num_channels);
deadbeefe814a0d2017-02-25 18:15:09 -0800469 ASSERT_EQ(1u, codec.parameters.size());
470 EXPECT_EQ("bar", codec.parameters["foo"]);
471 EXPECT_EQ(1u, codec.rtcp_feedback.size());
472 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
473 codec.rtcp_feedback[0]);
474}
475
476TEST(RtpParametersConversionTest, ToVideoRtpCodecCapability) {
477 cricket::VideoCodec cricket_codec;
478 cricket_codec.name = "VID";
479 cricket_codec.id = 101;
480 cricket_codec.clockrate = 80000;
481 cricket_codec.params["foo"] = "bar";
482 cricket_codec.params["ANOTHER"] = "param";
483 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
Elad Alonfadb1812019-05-24 13:40:02 +0200484 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
deadbeefe814a0d2017-02-25 18:15:09 -0800485 cricket_codec.feedback_params.Add({"nack", "pli"});
486 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
487
488 EXPECT_EQ("VID", codec.name);
489 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100490 EXPECT_EQ(101, codec.preferred_payload_type);
491 EXPECT_EQ(80000, codec.clock_rate);
deadbeefe814a0d2017-02-25 18:15:09 -0800492 ASSERT_EQ(2u, codec.parameters.size());
493 EXPECT_EQ("bar", codec.parameters["foo"]);
494 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200495 EXPECT_EQ(3u, codec.rtcp_feedback.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800496 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
497 codec.rtcp_feedback[0]);
Elad Alonfadb1812019-05-24 13:40:02 +0200498 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
deadbeefe814a0d2017-02-25 18:15:09 -0800499 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
Elad Alonfadb1812019-05-24 13:40:02 +0200500 codec.rtcp_feedback[2]);
deadbeefe814a0d2017-02-25 18:15:09 -0800501}
502
zhihuang24366392017-03-08 17:15:06 -0800503TEST(RtpParametersConversionTest, ToRtpEncodingsWithEmptyStreamParamsVec) {
504 cricket::StreamParamsVec streams;
505 auto rtp_encodings = ToRtpEncodings(streams);
506 ASSERT_EQ(0u, rtp_encodings.size());
507}
508
509TEST(RtpParametersConversionTest, ToRtpEncodingsWithMultipleStreamParams) {
510 cricket::StreamParamsVec streams;
511 cricket::StreamParams stream1;
512 stream1.ssrcs.push_back(1111u);
513 stream1.AddFidSsrc(1111u, 0xaaaaaaaa);
514
515 cricket::StreamParams stream2;
516 stream2.ssrcs.push_back(2222u);
517 stream2.AddFidSsrc(2222u, 0xaaaaaaab);
518
519 streams.push_back(stream1);
520 streams.push_back(stream2);
521
522 auto rtp_encodings = ToRtpEncodings(streams);
523 ASSERT_EQ(2u, rtp_encodings.size());
524 EXPECT_EQ(1111u, rtp_encodings[0].ssrc);
525 EXPECT_EQ(0xaaaaaaaa, rtp_encodings[0].rtx->ssrc);
526 EXPECT_EQ(2222u, rtp_encodings[1].ssrc);
527 EXPECT_EQ(0xaaaaaaab, rtp_encodings[1].rtx->ssrc);
528}
529
530TEST(RtpParametersConversionTest, ToAudioRtpCodecParameters) {
531 cricket::AudioCodec cricket_codec;
532 cricket_codec.name = "foo";
533 cricket_codec.id = 50;
534 cricket_codec.clockrate = 22222;
535 cricket_codec.channels = 4;
536 cricket_codec.params["foo"] = "bar";
537 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
538 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
539
540 EXPECT_EQ("foo", codec.name);
541 EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, codec.kind);
542 EXPECT_EQ(50, codec.payload_type);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100543 EXPECT_EQ(22222, codec.clock_rate);
544 EXPECT_EQ(4, codec.num_channels);
zhihuang24366392017-03-08 17:15:06 -0800545 ASSERT_EQ(1u, codec.parameters.size());
546 EXPECT_EQ("bar", codec.parameters["foo"]);
547 EXPECT_EQ(1u, codec.rtcp_feedback.size());
548 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
549 codec.rtcp_feedback[0]);
550}
551
552TEST(RtpParametersConversionTest, ToVideoRtpCodecParameters) {
553 cricket::VideoCodec cricket_codec;
554 cricket_codec.name = "VID";
555 cricket_codec.id = 101;
556 cricket_codec.clockrate = 80000;
557 cricket_codec.params["foo"] = "bar";
558 cricket_codec.params["ANOTHER"] = "param";
559 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
Elad Alonfadb1812019-05-24 13:40:02 +0200560 cricket_codec.feedback_params.Add(cricket::FeedbackParam("goog-lntf"));
zhihuang24366392017-03-08 17:15:06 -0800561 cricket_codec.feedback_params.Add({"nack", "pli"});
562 RtpCodecParameters codec = ToRtpCodecParameters(cricket_codec);
563
564 EXPECT_EQ("VID", codec.name);
565 EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, codec.kind);
566 EXPECT_EQ(101, codec.payload_type);
Oskar Sundbomff610bd2017-11-16 10:57:44 +0100567 EXPECT_EQ(80000, codec.clock_rate);
zhihuang24366392017-03-08 17:15:06 -0800568 ASSERT_EQ(2u, codec.parameters.size());
569 EXPECT_EQ("bar", codec.parameters["foo"]);
570 EXPECT_EQ("param", codec.parameters["ANOTHER"]);
Elad Alonfadb1812019-05-24 13:40:02 +0200571 EXPECT_EQ(3u, codec.rtcp_feedback.size());
zhihuang24366392017-03-08 17:15:06 -0800572 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
573 codec.rtcp_feedback[0]);
Elad Alonfadb1812019-05-24 13:40:02 +0200574 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::LNTF), codec.rtcp_feedback[1]);
zhihuang24366392017-03-08 17:15:06 -0800575 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::NACK, RtcpFeedbackMessageType::PLI),
Elad Alonfadb1812019-05-24 13:40:02 +0200576 codec.rtcp_feedback[2]);
zhihuang24366392017-03-08 17:15:06 -0800577}
578
deadbeefe814a0d2017-02-25 18:15:09 -0800579// An unknown feedback param should just be ignored.
580TEST(RtpParametersConversionTest, ToRtpCodecCapabilityUnknownFeedbackParam) {
581 cricket::AudioCodec cricket_codec;
582 cricket_codec.name = "foo";
583 cricket_codec.id = 50;
584 cricket_codec.clockrate = 22222;
585 cricket_codec.channels = 4;
586 cricket_codec.params["foo"] = "bar";
587 cricket_codec.feedback_params.Add({"unknown", "param"});
588 cricket_codec.feedback_params.Add(cricket::FeedbackParam("transport-cc"));
589 RtpCodecCapability codec = ToRtpCodecCapability(cricket_codec);
590
591 ASSERT_EQ(1u, codec.rtcp_feedback.size());
592 EXPECT_EQ(RtcpFeedback(RtcpFeedbackType::TRANSPORT_CC),
593 codec.rtcp_feedback[0]);
594}
595
596// Most of ToRtpCapabilities is tested by ToRtpCodecCapability, but we need to
597// test that the result of ToRtpCodecCapability ends up in the result, and that
598// the "fec" list is assembled correctly.
599TEST(RtpParametersConversionTest, ToRtpCapabilities) {
600 cricket::VideoCodec vp8;
601 vp8.name = "VP8";
602 vp8.id = 101;
603 vp8.clockrate = 90000;
604
605 cricket::VideoCodec red;
606 red.name = "red";
607 red.id = 102;
608 red.clockrate = 90000;
609
610 cricket::VideoCodec ulpfec;
611 ulpfec.name = "ulpfec";
612 ulpfec.id = 103;
613 ulpfec.clockrate = 90000;
614
615 cricket::VideoCodec flexfec;
616 flexfec.name = "flexfec-03";
617 flexfec.id = 102;
618 flexfec.clockrate = 90000;
619
Florent Castelli5473a452018-11-06 17:27:21 +0100620 cricket::VideoCodec rtx;
621 rtx.name = "rtx";
622 rtx.id = 104;
623 rtx.params.insert({"apt", "101"});
624
625 cricket::VideoCodec rtx2;
626 rtx2.name = "rtx";
627 rtx2.id = 105;
628 rtx2.params.insert({"apt", "109"});
629
deadbeefe814a0d2017-02-25 18:15:09 -0800630 RtpCapabilities capabilities = ToRtpCapabilities<cricket::VideoCodec>(
Florent Castelli5473a452018-11-06 17:27:21 +0100631 {vp8, ulpfec, rtx, rtx2}, {{"uri", 1}, {"uri2", 3}});
632 ASSERT_EQ(3u, capabilities.codecs.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800633 EXPECT_EQ("VP8", capabilities.codecs[0].name);
634 EXPECT_EQ("ulpfec", capabilities.codecs[1].name);
Florent Castelli5473a452018-11-06 17:27:21 +0100635 EXPECT_EQ("rtx", capabilities.codecs[2].name);
636 EXPECT_EQ(0u, capabilities.codecs[2].parameters.size());
deadbeefe814a0d2017-02-25 18:15:09 -0800637 ASSERT_EQ(2u, capabilities.header_extensions.size());
638 EXPECT_EQ("uri", capabilities.header_extensions[0].uri);
639 EXPECT_EQ(1, capabilities.header_extensions[0].preferred_id);
640 EXPECT_EQ("uri2", capabilities.header_extensions[1].uri);
641 EXPECT_EQ(3, capabilities.header_extensions[1].preferred_id);
642 EXPECT_EQ(0u, capabilities.fec.size());
643
644 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
Florent Castelli5473a452018-11-06 17:27:21 +0100645 {vp8, red, ulpfec, rtx}, cricket::RtpHeaderExtensions());
646 EXPECT_EQ(4u, capabilities.codecs.size());
Steve Anton64b626b2019-01-28 17:25:26 -0800647 EXPECT_THAT(
648 capabilities.fec,
649 UnorderedElementsAre(FecMechanism::RED, FecMechanism::RED_AND_ULPFEC));
deadbeefe814a0d2017-02-25 18:15:09 -0800650
651 capabilities = ToRtpCapabilities<cricket::VideoCodec>(
652 {vp8, red, flexfec}, cricket::RtpHeaderExtensions());
653 EXPECT_EQ(3u, capabilities.codecs.size());
Steve Anton64b626b2019-01-28 17:25:26 -0800654 EXPECT_THAT(capabilities.fec,
655 UnorderedElementsAre(FecMechanism::RED, FecMechanism::FLEXFEC));
deadbeefe814a0d2017-02-25 18:15:09 -0800656}
657
zhihuang24366392017-03-08 17:15:06 -0800658TEST(RtpParametersConversionTest, ToRtpParameters) {
659 cricket::VideoCodec vp8;
660 vp8.name = "VP8";
661 vp8.id = 101;
662 vp8.clockrate = 90000;
663
664 cricket::VideoCodec red;
665 red.name = "red";
666 red.id = 102;
667 red.clockrate = 90000;
668
669 cricket::VideoCodec ulpfec;
670 ulpfec.name = "ulpfec";
671 ulpfec.id = 103;
672 ulpfec.clockrate = 90000;
673
674 cricket::StreamParamsVec streams;
675 cricket::StreamParams stream;
676 stream.ssrcs.push_back(1234u);
677 streams.push_back(stream);
678
679 RtpParameters rtp_parameters = ToRtpParameters<cricket::VideoCodec>(
680 {vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
681 ASSERT_EQ(3u, rtp_parameters.codecs.size());
682 EXPECT_EQ("VP8", rtp_parameters.codecs[0].name);
683 EXPECT_EQ("red", rtp_parameters.codecs[1].name);
684 EXPECT_EQ("ulpfec", rtp_parameters.codecs[2].name);
685 ASSERT_EQ(2u, rtp_parameters.header_extensions.size());
686 EXPECT_EQ("uri", rtp_parameters.header_extensions[0].uri);
687 EXPECT_EQ(1, rtp_parameters.header_extensions[0].id);
688 EXPECT_EQ("uri2", rtp_parameters.header_extensions[1].uri);
689 EXPECT_EQ(3, rtp_parameters.header_extensions[1].id);
690 ASSERT_EQ(1u, rtp_parameters.encodings.size());
691 EXPECT_EQ(1234u, rtp_parameters.encodings[0].ssrc);
692}
693
deadbeefe814a0d2017-02-25 18:15:09 -0800694} // namespace webrtc