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
31using cricket::AudioCodec;
32using cricket::Codec;
33using cricket::DataCodec;
34using cricket::FeedbackParam;
35using cricket::VideoCodec;
36using cricket::VideoEncoderConfig;
37using cricket::kCodecParamAssociatedPayloadType;
38using cricket::kCodecParamMaxBitrate;
39using cricket::kCodecParamMinBitrate;
40
41class CodecTest : public testing::Test {
42 public:
43  CodecTest() {}
44};
45
46TEST_F(CodecTest, TestCodecOperators) {
47  Codec c0(96, "D", 1000, 0);
48  c0.SetParam("a", 1);
49
50  Codec c1 = c0;
51  EXPECT_TRUE(c1 == c0);
52
53  int param_value0;
54  int param_value1;
55  EXPECT_TRUE(c0.GetParam("a", &param_value0));
56  EXPECT_TRUE(c1.GetParam("a", &param_value1));
57  EXPECT_EQ(param_value0, param_value1);
58
59  c1.id = 86;
60  EXPECT_TRUE(c0 != c1);
61
62  c1 = c0;
63  c1.name = "x";
64  EXPECT_TRUE(c0 != c1);
65
66  c1 = c0;
67  c1.clockrate = 2000;
68  EXPECT_TRUE(c0 != c1);
69
70  c1 = c0;
71  c1.preference = 1;
72  EXPECT_TRUE(c0 != c1);
73
74  c1 = c0;
75  c1.SetParam("a", 2);
76  EXPECT_TRUE(c0 != c1);
77
78  Codec c5;
79  Codec c6(0, "", 0, 0);
80  EXPECT_TRUE(c5 == c6);
81}
82
83TEST_F(CodecTest, TestAudioCodecOperators) {
84  AudioCodec c0(96, "A", 44100, 20000, 2, 3);
85  AudioCodec c1(95, "A", 44100, 20000, 2, 3);
86  AudioCodec c2(96, "x", 44100, 20000, 2, 3);
87  AudioCodec c3(96, "A", 48000, 20000, 2, 3);
88  AudioCodec c4(96, "A", 44100, 10000, 2, 3);
89  AudioCodec c5(96, "A", 44100, 20000, 1, 3);
90  AudioCodec c6(96, "A", 44100, 20000, 2, 1);
91  EXPECT_TRUE(c0 != c1);
92  EXPECT_TRUE(c0 != c2);
93  EXPECT_TRUE(c0 != c3);
94  EXPECT_TRUE(c0 != c4);
95  EXPECT_TRUE(c0 != c5);
96  EXPECT_TRUE(c0 != c6);
97
98  AudioCodec c7;
99  AudioCodec c8(0, "", 0, 0, 0, 0);
100  AudioCodec c9 = c0;
101  EXPECT_TRUE(c8 == c7);
102  EXPECT_TRUE(c9 != c7);
103  EXPECT_TRUE(c9 == c0);
104
105  AudioCodec c10(c0);
106  AudioCodec c11(c0);
107  AudioCodec c12(c0);
108  AudioCodec c13(c0);
109  c10.params["x"] = "abc";
110  c11.params["x"] = "def";
111  c12.params["y"] = "abc";
112  c13.params["x"] = "abc";
113  EXPECT_TRUE(c10 != c0);
114  EXPECT_TRUE(c11 != c0);
115  EXPECT_TRUE(c11 != c10);
116  EXPECT_TRUE(c12 != c0);
117  EXPECT_TRUE(c12 != c10);
118  EXPECT_TRUE(c12 != c11);
119  EXPECT_TRUE(c13 == c10);
120}
121
122TEST_F(CodecTest, TestAudioCodecMatches) {
123  // Test a codec with a static payload type.
124  AudioCodec c0(95, "A", 44100, 20000, 1, 3);
125  EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 20000, 1, 0)));
126  EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 20000, 0, 0)));
127  EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 44100, 0, 0, 0)));
128  EXPECT_TRUE(c0.Matches(AudioCodec(95, "", 0, 0, 0, 0)));
129  EXPECT_FALSE(c0.Matches(AudioCodec(96, "", 44100, 20000, 1, 0)));
130  EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 55100, 20000, 1, 0)));
131  EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 44100, 30000, 1, 0)));
132  EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 44100, 20000, 2, 0)));
133  EXPECT_FALSE(c0.Matches(AudioCodec(95, "", 55100, 30000, 2, 0)));
134
135  // Test a codec with a dynamic payload type.
136  AudioCodec c1(96, "A", 44100, 20000, 1, 3);
137  EXPECT_TRUE(c1.Matches(AudioCodec(96, "A", 0, 0, 0, 0)));
138  EXPECT_TRUE(c1.Matches(AudioCodec(97, "A", 0, 0, 0, 0)));
139  EXPECT_TRUE(c1.Matches(AudioCodec(96, "a", 0, 0, 0, 0)));
140  EXPECT_TRUE(c1.Matches(AudioCodec(97, "a", 0, 0, 0, 0)));
141  EXPECT_FALSE(c1.Matches(AudioCodec(95, "A", 0, 0, 0, 0)));
142  EXPECT_FALSE(c1.Matches(AudioCodec(96, "", 44100, 20000, 2, 0)));
143  EXPECT_FALSE(c1.Matches(AudioCodec(96, "A", 55100, 30000, 1, 0)));
144
145  // Test a codec with a dynamic payload type, and auto bitrate.
146  AudioCodec c2(97, "A", 16000, 0, 1, 3);
147  // Use default bitrate.
148  EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 0, 1, 0)));
149  EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 0, 0, 0)));
150  // Use explicit bitrate.
151  EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, 32000, 1, 0)));
152  // Backward compatibility with clients that might send "-1" (for default).
153  EXPECT_TRUE(c2.Matches(AudioCodec(97, "A", 16000, -1, 1, 0)));
154
155  // Stereo doesn't match channels = 0.
156  AudioCodec c3(96, "A", 44100, 20000, 2, 3);
157  EXPECT_TRUE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 2, 3)));
158  EXPECT_FALSE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 1, 3)));
159  EXPECT_FALSE(c3.Matches(AudioCodec(96, "A", 44100, 20000, 0, 3)));
160}
161
162TEST_F(CodecTest, TestVideoCodecOperators) {
163  VideoCodec c0(96, "V", 320, 200, 30, 3);
164  VideoCodec c1(95, "V", 320, 200, 30, 3);
165  VideoCodec c2(96, "x", 320, 200, 30, 3);
166  VideoCodec c3(96, "V", 120, 200, 30, 3);
167  VideoCodec c4(96, "V", 320, 100, 30, 3);
168  VideoCodec c5(96, "V", 320, 200, 10, 3);
169  VideoCodec c6(96, "V", 320, 200, 30, 1);
170  EXPECT_TRUE(c0 != c1);
171  EXPECT_TRUE(c0 != c2);
172  EXPECT_TRUE(c0 != c3);
173  EXPECT_TRUE(c0 != c4);
174  EXPECT_TRUE(c0 != c5);
175  EXPECT_TRUE(c0 != c6);
176
177  VideoCodec c7;
178  VideoCodec c8(0, "", 0, 0, 0, 0);
179  VideoCodec c9 = c0;
180  EXPECT_TRUE(c8 == c7);
181  EXPECT_TRUE(c9 != c7);
182  EXPECT_TRUE(c9 == c0);
183
184  VideoCodec c10(c0);
185  VideoCodec c11(c0);
186  VideoCodec c12(c0);
187  VideoCodec c13(c0);
188  c10.params["x"] = "abc";
189  c11.params["x"] = "def";
190  c12.params["y"] = "abc";
191  c13.params["x"] = "abc";
192  EXPECT_TRUE(c10 != c0);
193  EXPECT_TRUE(c11 != c0);
194  EXPECT_TRUE(c11 != c10);
195  EXPECT_TRUE(c12 != c0);
196  EXPECT_TRUE(c12 != c10);
197  EXPECT_TRUE(c12 != c11);
198  EXPECT_TRUE(c13 == c10);
199}
200
201TEST_F(CodecTest, TestVideoCodecMatches) {
202  // Test a codec with a static payload type.
203  VideoCodec c0(95, "V", 320, 200, 30, 3);
204  EXPECT_TRUE(c0.Matches(VideoCodec(95, "", 640, 400, 15, 0)));
205  EXPECT_FALSE(c0.Matches(VideoCodec(96, "", 320, 200, 30, 0)));
206
207  // Test a codec with a dynamic payload type.
208  VideoCodec c1(96, "V", 320, 200, 30, 3);
209  EXPECT_TRUE(c1.Matches(VideoCodec(96, "V", 640, 400, 15, 0)));
210  EXPECT_TRUE(c1.Matches(VideoCodec(97, "V", 640, 400, 15, 0)));
211  EXPECT_TRUE(c1.Matches(VideoCodec(96, "v", 640, 400, 15, 0)));
212  EXPECT_TRUE(c1.Matches(VideoCodec(97, "v", 640, 400, 15, 0)));
213  EXPECT_FALSE(c1.Matches(VideoCodec(96, "", 320, 200, 30, 0)));
214  EXPECT_FALSE(c1.Matches(VideoCodec(95, "V", 640, 400, 15, 0)));
215}
216
217TEST_F(CodecTest, TestVideoEncoderConfigOperators) {
218  VideoEncoderConfig c1(VideoCodec(
219      96, "SVC", 320, 200, 30, 3), 1, 2);
220  VideoEncoderConfig c2(VideoCodec(
221      95, "SVC", 320, 200, 30, 3), 1, 2);
222  VideoEncoderConfig c3(VideoCodec(
223      96, "xxx", 320, 200, 30, 3), 1, 2);
224  VideoEncoderConfig c4(VideoCodec(
225      96, "SVC", 120, 200, 30, 3), 1, 2);
226  VideoEncoderConfig c5(VideoCodec(
227      96, "SVC", 320, 100, 30, 3), 1, 2);
228  VideoEncoderConfig c6(VideoCodec(
229      96, "SVC", 320, 200, 10, 3), 1, 2);
230  VideoEncoderConfig c7(VideoCodec(
231      96, "SVC", 320, 200, 30, 1), 1, 2);
232  VideoEncoderConfig c8(VideoCodec(
233      96, "SVC", 320, 200, 30, 3), 0, 2);
234  VideoEncoderConfig c9(VideoCodec(
235      96, "SVC", 320, 200, 30, 3), 1, 1);
236  EXPECT_TRUE(c1 != c2);
237  EXPECT_TRUE(c1 != c2);
238  EXPECT_TRUE(c1 != c3);
239  EXPECT_TRUE(c1 != c4);
240  EXPECT_TRUE(c1 != c5);
241  EXPECT_TRUE(c1 != c6);
242  EXPECT_TRUE(c1 != c7);
243  EXPECT_TRUE(c1 != c8);
244  EXPECT_TRUE(c1 != c9);
245
246  VideoEncoderConfig c10;
247  VideoEncoderConfig c11(VideoCodec(
248      0, "", 0, 0, 0, 0));
249  VideoEncoderConfig c12(VideoCodec(
250      0, "", 0, 0, 0, 0),
251      VideoEncoderConfig::kDefaultMaxThreads,
252      VideoEncoderConfig::kDefaultCpuProfile);
253  VideoEncoderConfig c13 = c1;
254  VideoEncoderConfig c14(VideoCodec(
255      0, "", 0, 0, 0, 0), 0, 0);
256
257  EXPECT_TRUE(c11 == c10);
258  EXPECT_TRUE(c12 == c10);
259  EXPECT_TRUE(c13 != c10);
260  EXPECT_TRUE(c13 == c1);
261  EXPECT_TRUE(c14 != c11);
262  EXPECT_TRUE(c14 != c12);
263}
264
265TEST_F(CodecTest, TestDataCodecMatches) {
266  // Test a codec with a static payload type.
267  DataCodec c0(95, "D", 0);
268  EXPECT_TRUE(c0.Matches(DataCodec(95, "", 0)));
269  EXPECT_FALSE(c0.Matches(DataCodec(96, "", 0)));
270
271  // Test a codec with a dynamic payload type.
272  DataCodec c1(96, "D", 3);
273  EXPECT_TRUE(c1.Matches(DataCodec(96, "D", 0)));
274  EXPECT_TRUE(c1.Matches(DataCodec(97, "D", 0)));
275  EXPECT_TRUE(c1.Matches(DataCodec(96, "d", 0)));
276  EXPECT_TRUE(c1.Matches(DataCodec(97, "d", 0)));
277  EXPECT_FALSE(c1.Matches(DataCodec(96, "", 0)));
278  EXPECT_FALSE(c1.Matches(DataCodec(95, "D", 0)));
279}
280
281TEST_F(CodecTest, TestSetParamGetParamAndRemoveParam) {
282  AudioCodec codec;
283  codec.SetParam("a", "1");
284  codec.SetParam("b", "x");
285
286  int int_value = 0;
287  EXPECT_TRUE(codec.GetParam("a", &int_value));
288  EXPECT_EQ(1, int_value);
289  EXPECT_FALSE(codec.GetParam("b", &int_value));
290  EXPECT_FALSE(codec.GetParam("c", &int_value));
291
292  std::string str_value;
293  EXPECT_TRUE(codec.GetParam("a", &str_value));
294  EXPECT_EQ("1", str_value);
295  EXPECT_TRUE(codec.GetParam("b", &str_value));
296  EXPECT_EQ("x", str_value);
297  EXPECT_FALSE(codec.GetParam("c", &str_value));
298  EXPECT_TRUE(codec.RemoveParam("a"));
299  EXPECT_FALSE(codec.RemoveParam("c"));
300}
301
302TEST_F(CodecTest, TestIntersectFeedbackParams) {
303  const FeedbackParam a1("a", "1");
304  const FeedbackParam b2("b", "2");
305  const FeedbackParam b3("b", "3");
306  const FeedbackParam c3("c", "3");
307  Codec c1;
308  c1.AddFeedbackParam(a1); // Only match with c2.
309  c1.AddFeedbackParam(b2); // Same param different values.
310  c1.AddFeedbackParam(c3); // Not in c2.
311  Codec c2;
312  c2.AddFeedbackParam(a1);
313  c2.AddFeedbackParam(b3);
314
315  c1.IntersectFeedbackParams(c2);
316  EXPECT_TRUE(c1.HasFeedbackParam(a1));
317  EXPECT_FALSE(c1.HasFeedbackParam(b2));
318  EXPECT_FALSE(c1.HasFeedbackParam(c3));
319}
320
321TEST_F(CodecTest, TestGetCodecType) {
322  // Codec type comparison should be case insenstive on names.
323  const VideoCodec codec(96, "V", 320, 200, 30, 3);
324  const VideoCodec rtx_codec(96, "rTx", 320, 200, 30, 3);
325  const VideoCodec ulpfec_codec(96, "ulpFeC", 320, 200, 30, 3);
326  const VideoCodec red_codec(96, "ReD", 320, 200, 30, 3);
327  EXPECT_EQ(VideoCodec::CODEC_VIDEO, codec.GetCodecType());
328  EXPECT_EQ(VideoCodec::CODEC_RTX, rtx_codec.GetCodecType());
329  EXPECT_EQ(VideoCodec::CODEC_ULPFEC, ulpfec_codec.GetCodecType());
330  EXPECT_EQ(VideoCodec::CODEC_RED, red_codec.GetCodecType());
331}
332
333TEST_F(CodecTest, TestCreateRtxCodec) {
334  VideoCodec rtx_codec = VideoCodec::CreateRtxCodec(96, 120);
335  EXPECT_EQ(96, rtx_codec.id);
336  EXPECT_EQ(VideoCodec::CODEC_RTX, rtx_codec.GetCodecType());
337  int associated_payload_type;
338  ASSERT_TRUE(rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
339                                 &associated_payload_type));
340  EXPECT_EQ(120, associated_payload_type);
341}
342
343TEST_F(CodecTest, TestValidateCodecFormat) {
344  const VideoCodec codec(96, "V", 320, 200, 30, 3);
345  ASSERT_TRUE(codec.ValidateCodecFormat());
346
347  // Accept 0-127 as payload types.
348  VideoCodec low_payload_type = codec;
349  low_payload_type.id = 0;
350  VideoCodec high_payload_type = codec;
351  high_payload_type.id = 127;
352  ASSERT_TRUE(low_payload_type.ValidateCodecFormat());
353  EXPECT_TRUE(high_payload_type.ValidateCodecFormat());
354
355  // Reject negative payloads.
356  VideoCodec negative_payload_type = codec;
357  negative_payload_type.id = -1;
358  EXPECT_FALSE(negative_payload_type.ValidateCodecFormat());
359
360  // Reject too-high payloads.
361  VideoCodec too_high_payload_type = codec;
362  too_high_payload_type.id = 128;
363  EXPECT_FALSE(too_high_payload_type.ValidateCodecFormat());
364
365  // Reject zero-width codecs.
366  VideoCodec zero_width = codec;
367  zero_width.width = 0;
368  EXPECT_FALSE(zero_width.ValidateCodecFormat());
369
370  // Reject zero-height codecs.
371  VideoCodec zero_height = codec;
372  zero_height.height = 0;
373  EXPECT_FALSE(zero_height.ValidateCodecFormat());
374
375  // Accept non-video codecs with zero dimensions.
376  VideoCodec zero_width_rtx_codec = VideoCodec::CreateRtxCodec(96, 120);
377  zero_width_rtx_codec.width = 0;
378  EXPECT_TRUE(zero_width_rtx_codec.ValidateCodecFormat());
379
380  // Reject codecs with min bitrate > max bitrate.
381  VideoCodec incorrect_bitrates = codec;
382  incorrect_bitrates.params[kCodecParamMinBitrate] = "100";
383  incorrect_bitrates.params[kCodecParamMaxBitrate] = "80";
384  EXPECT_FALSE(incorrect_bitrates.ValidateCodecFormat());
385
386  // Accept min bitrate == max bitrate.
387  VideoCodec equal_bitrates = codec;
388  equal_bitrates.params[kCodecParamMinBitrate] = "100";
389  equal_bitrates.params[kCodecParamMaxBitrate] = "100";
390  EXPECT_TRUE(equal_bitrates.ValidateCodecFormat());
391
392  // Accept min bitrate < max bitrate.
393  VideoCodec different_bitrates = codec;
394  different_bitrates.params[kCodecParamMinBitrate] = "99";
395  different_bitrates.params[kCodecParamMaxBitrate] = "100";
396  EXPECT_TRUE(different_bitrates.ValidateCodecFormat());
397}
398