blob: 9ba63e37806b4f12f5d329298a48318d5df4d52d [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2012 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
Yves Gerey665174f2018-06-19 15:03:05 +020011#include "modules/audio_coding/neteq/timestamp_scaler.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "api/audio_codecs/builtin_audio_decoder_factory.h"
14#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
15#include "modules/audio_coding/neteq/packet.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "test/gmock.h"
17#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000018
Jonas Olssona4d87372019-07-05 19:08:33 +020019using ::testing::_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000020using ::testing::Return;
21using ::testing::ReturnNull;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000022
23namespace webrtc {
24
25TEST(TimestampScaler, TestNoScaling) {
26 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -070027 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -070028 // Use PCMu, because it doesn't use scaled timestamps.
Niels Möller72899062019-01-11 09:36:13 +010029 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +020030 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000031 static const uint8_t kRtpPayloadType = 0;
32 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
33 .WillRepeatedly(Return(&info));
34
35 TimestampScaler scaler(db);
36 // Test both sides of the timestamp wrap-around.
37 for (uint32_t timestamp = 0xFFFFFFFF - 5; timestamp != 5; ++timestamp) {
38 // Scale to internal timestamp.
39 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
40 // Scale back.
41 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp));
42 }
43
44 EXPECT_CALL(db, Die()); // Called when database object is deleted.
45}
46
47TEST(TimestampScaler, TestNoScalingLargeStep) {
48 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -070049 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -070050 // Use PCMu, because it doesn't use scaled timestamps.
Niels Möller72899062019-01-11 09:36:13 +010051 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +020052 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000053 static const uint8_t kRtpPayloadType = 0;
54 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
55 .WillRepeatedly(Return(&info));
56
57 TimestampScaler scaler(db);
58 // Test both sides of the timestamp wrap-around.
59 static const uint32_t kStep = 160;
60 uint32_t start_timestamp = 0;
61 // |external_timestamp| will be a large positive value.
62 start_timestamp = start_timestamp - 5 * kStep;
63 for (uint32_t timestamp = start_timestamp; timestamp != 5 * kStep;
Yves Gerey665174f2018-06-19 15:03:05 +020064 timestamp += kStep) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000065 // Scale to internal timestamp.
66 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
67 // Scale back.
68 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp));
69 }
70
71 EXPECT_CALL(db, Die()); // Called when database object is deleted.
72}
73
74TEST(TimestampScaler, TestG722) {
75 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -070076 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -070077 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +010078 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +020079 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000080 static const uint8_t kRtpPayloadType = 17;
81 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
82 .WillRepeatedly(Return(&info));
83
84 TimestampScaler scaler(db);
85 // Test both sides of the timestamp wrap-around.
86 uint32_t external_timestamp = 0xFFFFFFFF - 5;
87 uint32_t internal_timestamp = external_timestamp;
88 for (; external_timestamp != 5; ++external_timestamp) {
89 // Scale to internal timestamp.
90 EXPECT_EQ(internal_timestamp,
91 scaler.ToInternal(external_timestamp, kRtpPayloadType));
92 // Scale back.
93 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
94 internal_timestamp += 2;
95 }
96
97 EXPECT_CALL(db, Die()); // Called when database object is deleted.
98}
99
100TEST(TimestampScaler, TestG722LargeStep) {
101 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700102 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -0700103 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +0100104 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200105 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000106 static const uint8_t kRtpPayloadType = 17;
107 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
108 .WillRepeatedly(Return(&info));
109
110 TimestampScaler scaler(db);
111 // Test both sides of the timestamp wrap-around.
112 static const uint32_t kStep = 320;
113 uint32_t external_timestamp = 0;
114 // |external_timestamp| will be a large positive value.
115 external_timestamp = external_timestamp - 5 * kStep;
116 uint32_t internal_timestamp = external_timestamp;
117 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) {
118 // Scale to internal timestamp.
119 EXPECT_EQ(internal_timestamp,
120 scaler.ToInternal(external_timestamp, kRtpPayloadType));
121 // Scale back.
122 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
123 // Internal timestamp should be incremented with twice the step.
124 internal_timestamp += 2 * kStep;
125 }
126
127 EXPECT_CALL(db, Die()); // Called when database object is deleted.
128}
129
130TEST(TimestampScaler, TestG722WithCng) {
131 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700132 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -0700133 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +0100134 const DecoderDatabase::DecoderInfo info_g722(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200135 absl::nullopt, factory);
Niels Möller72899062019-01-11 09:36:13 +0100136 const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 16000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200137 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000138 static const uint8_t kRtpPayloadTypeG722 = 17;
139 static const uint8_t kRtpPayloadTypeCng = 13;
140 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeG722))
141 .WillRepeatedly(Return(&info_g722));
142 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeCng))
143 .WillRepeatedly(Return(&info_cng));
144
145 TimestampScaler scaler(db);
146 // Test both sides of the timestamp wrap-around.
147 uint32_t external_timestamp = 0xFFFFFFFF - 5;
148 uint32_t internal_timestamp = external_timestamp;
149 bool next_is_cng = false;
150 for (; external_timestamp != 5; ++external_timestamp) {
151 // Alternate between G.722 and CNG every other packet.
152 if (next_is_cng) {
153 // Scale to internal timestamp.
154 EXPECT_EQ(internal_timestamp,
155 scaler.ToInternal(external_timestamp, kRtpPayloadTypeCng));
156 next_is_cng = false;
157 } else {
158 // Scale to internal timestamp.
159 EXPECT_EQ(internal_timestamp,
160 scaler.ToInternal(external_timestamp, kRtpPayloadTypeG722));
161 next_is_cng = true;
162 }
163 // Scale back.
164 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
165 internal_timestamp += 2;
166 }
167
168 EXPECT_CALL(db, Die()); // Called when database object is deleted.
169}
170
171// Make sure that the method ToInternal(Packet* packet) is wired up correctly.
172// Since it is simply calling the other ToInternal method, we are not doing
173// as many tests here.
174TEST(TimestampScaler, TestG722Packet) {
175 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700176 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -0700177 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +0100178 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200179 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180 static const uint8_t kRtpPayloadType = 17;
181 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
182 .WillRepeatedly(Return(&info));
183
184 TimestampScaler scaler(db);
185 // Test both sides of the timestamp wrap-around.
186 uint32_t external_timestamp = 0xFFFFFFFF - 5;
187 uint32_t internal_timestamp = external_timestamp;
188 Packet packet;
ossu7a377612016-10-18 04:06:13 -0700189 packet.payload_type = kRtpPayloadType;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000190 for (; external_timestamp != 5; ++external_timestamp) {
ossu7a377612016-10-18 04:06:13 -0700191 packet.timestamp = external_timestamp;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000192 // Scale to internal timestamp.
193 scaler.ToInternal(&packet);
ossu7a377612016-10-18 04:06:13 -0700194 EXPECT_EQ(internal_timestamp, packet.timestamp);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000195 internal_timestamp += 2;
196 }
197
198 EXPECT_CALL(db, Die()); // Called when database object is deleted.
199}
200
201// Make sure that the method ToInternal(PacketList* packet_list) is wired up
202// correctly. Since it is simply calling the ToInternal(Packet* packet) method,
203// we are not doing as many tests here.
204TEST(TimestampScaler, TestG722PacketList) {
205 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700206 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -0700207 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +0100208 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200209 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000210 static const uint8_t kRtpPayloadType = 17;
211 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
212 .WillRepeatedly(Return(&info));
213
214 TimestampScaler scaler(db);
215 // Test both sides of the timestamp wrap-around.
216 uint32_t external_timestamp = 0xFFFFFFFF - 5;
217 uint32_t internal_timestamp = external_timestamp;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000218 PacketList packet_list;
ossua73f6c92016-10-24 08:25:28 -0700219 {
220 Packet packet1;
221 packet1.payload_type = kRtpPayloadType;
222 packet1.timestamp = external_timestamp;
223 Packet packet2;
224 packet2.payload_type = kRtpPayloadType;
225 packet2.timestamp = external_timestamp + 10;
226 packet_list.push_back(std::move(packet1));
227 packet_list.push_back(std::move(packet2));
228 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229
230 scaler.ToInternal(&packet_list);
ossua73f6c92016-10-24 08:25:28 -0700231 EXPECT_EQ(internal_timestamp, packet_list.front().timestamp);
232 packet_list.pop_front();
233 EXPECT_EQ(internal_timestamp + 20, packet_list.front().timestamp);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000234
235 EXPECT_CALL(db, Die()); // Called when database object is deleted.
236}
237
238TEST(TimestampScaler, TestG722Reset) {
239 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700240 auto factory = CreateBuiltinAudioDecoderFactory();
kwiberg0fa0a972016-04-19 05:03:45 -0700241 // Use G722, which has a factor 2 scaling.
Niels Möller72899062019-01-11 09:36:13 +0100242 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200243 absl::nullopt, factory);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000244 static const uint8_t kRtpPayloadType = 17;
245 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
246 .WillRepeatedly(Return(&info));
247
248 TimestampScaler scaler(db);
249 // Test both sides of the timestamp wrap-around.
250 uint32_t external_timestamp = 0xFFFFFFFF - 5;
251 uint32_t internal_timestamp = external_timestamp;
252 for (; external_timestamp != 5; ++external_timestamp) {
253 // Scale to internal timestamp.
254 EXPECT_EQ(internal_timestamp,
255 scaler.ToInternal(external_timestamp, kRtpPayloadType));
256 // Scale back.
257 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
258 internal_timestamp += 2;
259 }
260 // Reset the scaler. After this, we expect the internal and external to start
261 // over at the same value again.
262 scaler.Reset();
263 internal_timestamp = external_timestamp;
264 for (; external_timestamp != 15; ++external_timestamp) {
265 // Scale to internal timestamp.
266 EXPECT_EQ(internal_timestamp,
267 scaler.ToInternal(external_timestamp, kRtpPayloadType));
268 // Scale back.
269 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
270 internal_timestamp += 2;
271 }
272
273 EXPECT_CALL(db, Die()); // Called when database object is deleted.
274}
275
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000276// TODO(minyue): This test becomes trivial since Opus does not need a timestamp
277// scaler. Therefore, this test may be removed in future. There is no harm to
278// keep it, since it can be taken as a test case for the situation of a trivial
279// timestamp scaler.
henrik.lundin@webrtc.orgac59dba2013-01-31 09:55:24 +0000280TEST(TimestampScaler, TestOpusLargeStep) {
281 MockDecoderDatabase db;
ossu09f15602016-08-29 03:59:05 -0700282 auto factory = CreateBuiltinAudioDecoderFactory();
Niels Möller72899062019-01-11 09:36:13 +0100283 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("opus", 48000, 2),
Danil Chapovalovb6021232018-06-19 13:26:36 +0200284 absl::nullopt, factory);
henrik.lundin@webrtc.orgac59dba2013-01-31 09:55:24 +0000285 static const uint8_t kRtpPayloadType = 17;
286 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
287 .WillRepeatedly(Return(&info));
288
289 TimestampScaler scaler(db);
290 // Test both sides of the timestamp wrap-around.
291 static const uint32_t kStep = 960;
292 uint32_t external_timestamp = 0;
293 // |external_timestamp| will be a large positive value.
294 external_timestamp = external_timestamp - 5 * kStep;
295 uint32_t internal_timestamp = external_timestamp;
296 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) {
297 // Scale to internal timestamp.
298 EXPECT_EQ(internal_timestamp,
299 scaler.ToInternal(external_timestamp, kRtpPayloadType));
300 // Scale back.
301 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000302 internal_timestamp += kStep;
henrik.lundin@webrtc.orgac59dba2013-01-31 09:55:24 +0000303 }
304
305 EXPECT_CALL(db, Die()); // Called when database object is deleted.
306}
307
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000308TEST(TimestampScaler, Failures) {
309 static const uint8_t kRtpPayloadType = 17;
310 MockDecoderDatabase db;
311 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
312 .WillOnce(ReturnNull()); // Return NULL to indicate unknown payload type.
313
314 TimestampScaler scaler(db);
315 uint32_t timestamp = 4711; // Some number.
316 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
317
318 Packet* packet = NULL;
319 scaler.ToInternal(packet); // Should not crash. That's all we can test.
320
321 EXPECT_CALL(db, Die()); // Called when database object is deleted.
322}
323
324} // namespace webrtc