1 /*
2 * libjingle
3 * Copyright 2009 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "talk/media/base/codec.h"
29 #include "webrtc/base/gunit.h"
30
31 using cricket::AudioCodec;
32 using cricket::Codec;
33 using cricket::DataCodec;
34 using cricket::FeedbackParam;
35 using cricket::VideoCodec;
36 using cricket::kCodecParamAssociatedPayloadType;
37 using cricket::kCodecParamMaxBitrate;
38 using cricket::kCodecParamMinBitrate;
39
40 class CodecTest : public testing::Test {
41 public:
CodecTest()42 CodecTest() {}
43 };
44
TEST_F(CodecTest,TestCodecOperators)45 TEST_F(CodecTest, TestCodecOperators) {
46 Codec c0(96, "D", 1000, 0);
47 c0.SetParam("a", 1);
48
49 Codec c1 = c0;
50 EXPECT_TRUE(c1 == c0);
51
52 int param_value0;
53 int param_value1;
54 EXPECT_TRUE(c0.GetParam("a", ¶m_value0));
55 EXPECT_TRUE(c1.GetParam("a", ¶m_value1));
56 EXPECT_EQ(param_value0, param_value1);
57
58 c1.id = 86;
59 EXPECT_TRUE(c0 != c1);
60
61 c1 = c0;
62 c1.name = "x";
63 EXPECT_TRUE(c0 != c1);
64
65 c1 = c0;
66 c1.clockrate = 2000;
67 EXPECT_TRUE(c0 != c1);
68
69 c1 = c0;
70 c1.preference = 1;
71 EXPECT_TRUE(c0 != c1);
72
73 c1 = c0;
74 c1.SetParam("a", 2);
75 EXPECT_TRUE(c0 != c1);
76
77 Codec c5;
78 Codec c6(0, "", 0, 0);
79 EXPECT_TRUE(c5 == c6);
80 }
81
TEST_F(CodecTest,TestAudioCodecOperators)82 TEST_F(CodecTest, TestAudioCodecOperators) {
83 AudioCodec c0(96, "A", 44100, 20000, 2, 3);
84 AudioCodec c1(95, "A", 44100, 20000, 2, 3);
85 AudioCodec c2(96, "x", 44100, 20000, 2, 3);
86 AudioCodec c3(96, "A", 48000, 20000, 2, 3);
87 AudioCodec c4(96, "A", 44100, 10000, 2, 3);
88 AudioCodec c5(96, "A", 44100, 20000, 1, 3);
89 AudioCodec c6(96, "A", 44100, 20000, 2, 1);
90 EXPECT_TRUE(c0 != c1);
91 EXPECT_TRUE(c0 != c2);
92 EXPECT_TRUE(c0 != c3);
93 EXPECT_TRUE(c0 != c4);
94 EXPECT_TRUE(c0 != c5);
95 EXPECT_TRUE(c0 != c6);
96
97 AudioCodec c7;
98 AudioCodec c8(0, "", 0, 0, 0, 0);
99 AudioCodec c9 = c0;
100 EXPECT_TRUE(c8 == c7);
101 EXPECT_TRUE(c9 != c7);
102 EXPECT_TRUE(c9 == c0);
103
104 AudioCodec c10(c0);
105 AudioCodec c11(c0);
106 AudioCodec c12(c0);
107 AudioCodec c13(c0);
108 c10.params["x"] = "abc";
109 c11.params["x"] = "def";
110 c12.params["y"] = "abc";
111 c13.params["x"] = "abc";
112 EXPECT_TRUE(c10 != c0);
113 EXPECT_TRUE(c11 != c0);
114 EXPECT_TRUE(c11 != c10);
115 EXPECT_TRUE(c12 != c0);
116 EXPECT_TRUE(c12 != c10);
117 EXPECT_TRUE(c12 != c11);
118 EXPECT_TRUE(c13 == c10);
119 }
120
TEST_F(CodecTest,TestAudioCodecMatches)121 TEST_F(CodecTest, TestAudioCodecMatches) {
122 // Test a codec with a static payload type.
123 AudioCodec c0(95, "A", 44100, 20000, 1, 3);
124 EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 20000, 1, 0)));
125 EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 20000, 0, 0)));
126 EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 0, 0, 0)));
127 EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 0, 0, 0, 0)));
128 EXPECT_FALSE(c0.Matches(AudioCodec(96, "", 44100, 20000, 1, 0)));
129 EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 55100, 20000, 1, 0)));
130 EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 44100, 30000, 1, 0)));
131 EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 44100, 20000, 2, 0)));
132 EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 55100, 30000, 2, 0)));
133
134 // Test a codec with a dynamic payload type.
135 AudioCodec c1(96, "A", 44100, 20000, 1, 3);
136 EXPECT_TRUE(c1.Matches(AudioCodec(96, "A", 0, 0, 0, 0)));
137 EXPECT_TRUE(c1.Matches(AudioCodec(97, "A", 0, 0, 0, 0)));
138 EXPECT_TRUE(c1.Matches(AudioCodec(96, "a", 0, 0, 0, 0)));
139 EXPECT_TRUE(c1.Matches(AudioCodec(97, "a", 0, 0, 0, 0)));
140 EXPECT_FALSE(c1.Matches(AudioCodec(95, "A", 0, 0, 0, 0)));
141 EXPECT_FALSE(c1.Matches(AudioCodec(96, "", 44100, 20000, 2, 0)));
142 EXPECT_FALSE(c1.Matches(AudioCodec(96, "A", 55100, 30000, 1, 0)));
143
144 // Test a codec with a dynamic payload type, and auto bitrate.
145 AudioCodec c2(97, "A", 16000, 0, 1, 3);
146 // Use default bitrate.
147 EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 0, 1, 0)));
148 EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 0, 0, 0)));
149 // Use explicit bitrate.
150 EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 32000, 1, 0)));
151 // Backward compatibility with clients that might send "-1" (for default).
152 EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, -1, 1, 0)));
153
154 // Stereo doesn't match channels = 0.
155 AudioCodec c3(96, "A", 44100, 20000, 2, 3);
156 EXPECT_TRUE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 2, 3)));
157 EXPECT_FALSE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 1, 3)));
158 EXPECT_FALSE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 0, 3)));
159 }
160
TEST_F(CodecTest,TestVideoCodecOperators)161 TEST_F(CodecTest, TestVideoCodecOperators) {
162 VideoCodec c0(96, "V", 320, 200, 30, 3);
163 VideoCodec c1(95, "V", 320, 200, 30, 3);
164 VideoCodec c2(96, "x", 320, 200, 30, 3);
165 VideoCodec c3(96, "V", 120, 200, 30, 3);
166 VideoCodec c4(96, "V", 320, 100, 30, 3);
167 VideoCodec c5(96, "V", 320, 200, 10, 3);
168 VideoCodec c6(96, "V", 320, 200, 30, 1);
169 EXPECT_TRUE(c0 != c1);
170 EXPECT_TRUE(c0 != c2);
171 EXPECT_TRUE(c0 != c3);
172 EXPECT_TRUE(c0 != c4);
173 EXPECT_TRUE(c0 != c5);
174 EXPECT_TRUE(c0 != c6);
175
176 VideoCodec c7;
177 VideoCodec c8(0, "", 0, 0, 0, 0);
178 VideoCodec c9 = c0;
179 EXPECT_TRUE(c8 == c7);
180 EXPECT_TRUE(c9 != c7);
181 EXPECT_TRUE(c9 == c0);
182
183 VideoCodec c10(c0);
184 VideoCodec c11(c0);
185 VideoCodec c12(c0);
186 VideoCodec c13(c0);
187 c10.params["x"] = "abc";
188 c11.params["x"] = "def";
189 c12.params["y"] = "abc";
190 c13.params["x"] = "abc";
191 EXPECT_TRUE(c10 != c0);
192 EXPECT_TRUE(c11 != c0);
193 EXPECT_TRUE(c11 != c10);
194 EXPECT_TRUE(c12 != c0);
195 EXPECT_TRUE(c12 != c10);
196 EXPECT_TRUE(c12 != c11);
197 EXPECT_TRUE(c13 == c10);
198 }
199
TEST_F(CodecTest,TestVideoCodecMatches)200 TEST_F(CodecTest, TestVideoCodecMatches) {
201 // Test a codec with a static payload type.
202 VideoCodec c0(95, "V", 320, 200, 30, 3);
203 EXPECT_TRUE(c0.Matches(VideoCodec(95, "", 640, 400, 15, 0)));
204 EXPECT_FALSE(c0.Matches(VideoCodec(96, "", 320, 200, 30, 0)));
205
206 // Test a codec with a dynamic payload type.
207 VideoCodec c1(96, "V", 320, 200, 30, 3);
208 EXPECT_TRUE(c1.Matches(VideoCodec(96, "V", 640, 400, 15, 0)));
209 EXPECT_TRUE(c1.Matches(VideoCodec(97, "V", 640, 400, 15, 0)));
210 EXPECT_TRUE(c1.Matches(VideoCodec(96, "v", 640, 400, 15, 0)));
211 EXPECT_TRUE(c1.Matches(VideoCodec(97, "v", 640, 400, 15, 0)));
212 EXPECT_FALSE(c1.Matches(VideoCodec(96, "", 320, 200, 30, 0)));
213 EXPECT_FALSE(c1.Matches(VideoCodec(95, "V", 640, 400, 15, 0)));
214 }
215
TEST_F(CodecTest,TestDataCodecMatches)216 TEST_F(CodecTest, TestDataCodecMatches) {
217 // Test a codec with a static payload type.
218 DataCodec c0(95, "D", 0);
219 EXPECT_TRUE(c0.Matches(DataCodec(95, "", 0)));
220 EXPECT_FALSE(c0.Matches(DataCodec(96, "", 0)));
221
222 // Test a codec with a dynamic payload type.
223 DataCodec c1(96, "D", 3);
224 EXPECT_TRUE(c1.Matches(DataCodec(96, "D", 0)));
225 EXPECT_TRUE(c1.Matches(DataCodec(97, "D", 0)));
226 EXPECT_TRUE(c1.Matches(DataCodec(96, "d", 0)));
227 EXPECT_TRUE(c1.Matches(DataCodec(97, "d", 0)));
228 EXPECT_FALSE(c1.Matches(DataCodec(96, "", 0)));
229 EXPECT_FALSE(c1.Matches(DataCodec(95, "D", 0)));
230 }
231
TEST_F(CodecTest,TestSetParamGetParamAndRemoveParam)232 TEST_F(CodecTest, TestSetParamGetParamAndRemoveParam) {
233 AudioCodec codec;
234 codec.SetParam("a", "1");
235 codec.SetParam("b", "x");
236
237 int int_value = 0;
238 EXPECT_TRUE(codec.GetParam("a", &int_value));
239 EXPECT_EQ(1, int_value);
240 EXPECT_FALSE(codec.GetParam("b", &int_value));
241 EXPECT_FALSE(codec.GetParam("c", &int_value));
242
243 std::string str_value;
244 EXPECT_TRUE(codec.GetParam("a", &str_value));
245 EXPECT_EQ("1", str_value);
246 EXPECT_TRUE(codec.GetParam("b", &str_value));
247 EXPECT_EQ("x", str_value);
248 EXPECT_FALSE(codec.GetParam("c", &str_value));
249 EXPECT_TRUE(codec.RemoveParam("a"));
250 EXPECT_FALSE(codec.RemoveParam("c"));
251 }
252
TEST_F(CodecTest,TestIntersectFeedbackParams)253 TEST_F(CodecTest, TestIntersectFeedbackParams) {
254 const FeedbackParam a1("a", "1");
255 const FeedbackParam b2("b", "2");
256 const FeedbackParam b3("b", "3");
257 const FeedbackParam c3("c", "3");
258 Codec c1;
259 c1.AddFeedbackParam(a1); // Only match with c2.
260 c1.AddFeedbackParam(b2); // Same param different values.
261 c1.AddFeedbackParam(c3); // Not in c2.
262 Codec c2;
263 c2.AddFeedbackParam(a1);
264 c2.AddFeedbackParam(b3);
265
266 c1.IntersectFeedbackParams(c2);
267 EXPECT_TRUE(c1.HasFeedbackParam(a1));
268 EXPECT_FALSE(c1.HasFeedbackParam(b2));
269 EXPECT_FALSE(c1.HasFeedbackParam(c3));
270 }
271
TEST_F(CodecTest,TestGetCodecType)272 TEST_F(CodecTest, TestGetCodecType) {
273 // Codec type comparison should be case insenstive on names.
274 const VideoCodec codec(96, "V", 320, 200, 30, 3);
275 const VideoCodec rtx_codec(96, "rTx", 320, 200, 30, 3);
276 const VideoCodec ulpfec_codec(96, "ulpFeC", 320, 200, 30, 3);
277 const VideoCodec red_codec(96, "ReD", 320, 200, 30, 3);
278 EXPECT_EQ(VideoCodec::CODEC_VIDEO, codec.GetCodecType());
279 EXPECT_EQ(VideoCodec::CODEC_RTX, rtx_codec.GetCodecType());
280 EXPECT_EQ(VideoCodec::CODEC_ULPFEC, ulpfec_codec.GetCodecType());
281 EXPECT_EQ(VideoCodec::CODEC_RED, red_codec.GetCodecType());
282 }
283
TEST_F(CodecTest,TestCreateRtxCodec)284 TEST_F(CodecTest, TestCreateRtxCodec) {
285 VideoCodec rtx_codec = VideoCodec::CreateRtxCodec(96, 120);
286 EXPECT_EQ(96, rtx_codec.id);
287 EXPECT_EQ(VideoCodec::CODEC_RTX, rtx_codec.GetCodecType());
288 int associated_payload_type;
289 ASSERT_TRUE(rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
290 &associated_payload_type));
291 EXPECT_EQ(120, associated_payload_type);
292 }
293
TEST_F(CodecTest,TestValidateCodecFormat)294 TEST_F(CodecTest, TestValidateCodecFormat) {
295 const VideoCodec codec(96, "V", 320, 200, 30, 3);
296 ASSERT_TRUE(codec.ValidateCodecFormat());
297
298 // Accept 0-127 as payload types.
299 VideoCodec low_payload_type = codec;
300 low_payload_type.id = 0;
301 VideoCodec high_payload_type = codec;
302 high_payload_type.id = 127;
303 ASSERT_TRUE(low_payload_type.ValidateCodecFormat());
304 EXPECT_TRUE(high_payload_type.ValidateCodecFormat());
305
306 // Reject negative payloads.
307 VideoCodec negative_payload_type = codec;
308 negative_payload_type.id = -1;
309 EXPECT_FALSE(negative_payload_type.ValidateCodecFormat());
310
311 // Reject too-high payloads.
312 VideoCodec too_high_payload_type = codec;
313 too_high_payload_type.id = 128;
314 EXPECT_FALSE(too_high_payload_type.ValidateCodecFormat());
315
316 // Reject zero-width codecs.
317 VideoCodec zero_width = codec;
318 zero_width.width = 0;
319 EXPECT_FALSE(zero_width.ValidateCodecFormat());
320
321 // Reject zero-height codecs.
322 VideoCodec zero_height = codec;
323 zero_height.height = 0;
324 EXPECT_FALSE(zero_height.ValidateCodecFormat());
325
326 // Accept non-video codecs with zero dimensions.
327 VideoCodec zero_width_rtx_codec = VideoCodec::CreateRtxCodec(96, 120);
328 zero_width_rtx_codec.width = 0;
329 EXPECT_TRUE(zero_width_rtx_codec.ValidateCodecFormat());
330
331 // Reject codecs with min bitrate > max bitrate.
332 VideoCodec incorrect_bitrates = codec;
333 incorrect_bitrates.params[kCodecParamMinBitrate] = "100";
334 incorrect_bitrates.params[kCodecParamMaxBitrate] = "80";
335 EXPECT_FALSE(incorrect_bitrates.ValidateCodecFormat());
336
337 // Accept min bitrate == max bitrate.
338 VideoCodec equal_bitrates = codec;
339 equal_bitrates.params[kCodecParamMinBitrate] = "100";
340 equal_bitrates.params[kCodecParamMaxBitrate] = "100";
341 EXPECT_TRUE(equal_bitrates.ValidateCodecFormat());
342
343 // Accept min bitrate < max bitrate.
344 VideoCodec different_bitrates = codec;
345 different_bitrates.params[kCodecParamMinBitrate] = "99";
346 different_bitrates.params[kCodecParamMaxBitrate] = "100";
347 EXPECT_TRUE(different_bitrates.ValidateCodecFormat());
348 }
349