1 /*
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
11 #include "modules/audio_coding/neteq/timestamp_scaler.h"
12
13 #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"
16 #include "test/gmock.h"
17 #include "test/gtest.h"
18
19 using ::testing::_;
20 using ::testing::Return;
21 using ::testing::ReturnNull;
22
23 namespace webrtc {
24
TEST(TimestampScaler,TestNoScaling)25 TEST(TimestampScaler, TestNoScaling) {
26 MockDecoderDatabase db;
27 auto factory = CreateBuiltinAudioDecoderFactory();
28 // Use PCMu, because it doesn't use scaled timestamps.
29 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
30 absl::nullopt, factory.get());
31 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
TEST(TimestampScaler,TestNoScalingLargeStep)47 TEST(TimestampScaler, TestNoScalingLargeStep) {
48 MockDecoderDatabase db;
49 auto factory = CreateBuiltinAudioDecoderFactory();
50 // Use PCMu, because it doesn't use scaled timestamps.
51 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
52 absl::nullopt, factory.get());
53 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;
64 timestamp += kStep) {
65 // 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
TEST(TimestampScaler,TestG722)74 TEST(TimestampScaler, TestG722) {
75 MockDecoderDatabase db;
76 auto factory = CreateBuiltinAudioDecoderFactory();
77 // Use G722, which has a factor 2 scaling.
78 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
79 absl::nullopt, factory.get());
80 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
TEST(TimestampScaler,TestG722LargeStep)100 TEST(TimestampScaler, TestG722LargeStep) {
101 MockDecoderDatabase db;
102 auto factory = CreateBuiltinAudioDecoderFactory();
103 // Use G722, which has a factor 2 scaling.
104 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
105 absl::nullopt, factory.get());
106 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
TEST(TimestampScaler,TestG722WithCng)130 TEST(TimestampScaler, TestG722WithCng) {
131 MockDecoderDatabase db;
132 auto factory = CreateBuiltinAudioDecoderFactory();
133 // Use G722, which has a factor 2 scaling.
134 const DecoderDatabase::DecoderInfo info_g722(SdpAudioFormat("g722", 8000, 1),
135 absl::nullopt, factory.get());
136 const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 16000, 1),
137 absl::nullopt, factory.get());
138 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.
TEST(TimestampScaler,TestG722Packet)174 TEST(TimestampScaler, TestG722Packet) {
175 MockDecoderDatabase db;
176 auto factory = CreateBuiltinAudioDecoderFactory();
177 // Use G722, which has a factor 2 scaling.
178 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
179 absl::nullopt, factory.get());
180 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;
189 packet.payload_type = kRtpPayloadType;
190 for (; external_timestamp != 5; ++external_timestamp) {
191 packet.timestamp = external_timestamp;
192 // Scale to internal timestamp.
193 scaler.ToInternal(&packet);
194 EXPECT_EQ(internal_timestamp, packet.timestamp);
195 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.
TEST(TimestampScaler,TestG722PacketList)204 TEST(TimestampScaler, TestG722PacketList) {
205 MockDecoderDatabase db;
206 auto factory = CreateBuiltinAudioDecoderFactory();
207 // Use G722, which has a factor 2 scaling.
208 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
209 absl::nullopt, factory.get());
210 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;
218 PacketList packet_list;
219 {
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 }
229
230 scaler.ToInternal(&packet_list);
231 EXPECT_EQ(internal_timestamp, packet_list.front().timestamp);
232 packet_list.pop_front();
233 EXPECT_EQ(internal_timestamp + 20, packet_list.front().timestamp);
234
235 EXPECT_CALL(db, Die()); // Called when database object is deleted.
236 }
237
TEST(TimestampScaler,TestG722Reset)238 TEST(TimestampScaler, TestG722Reset) {
239 MockDecoderDatabase db;
240 auto factory = CreateBuiltinAudioDecoderFactory();
241 // Use G722, which has a factor 2 scaling.
242 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
243 absl::nullopt, factory.get());
244 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
276 // 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.
TEST(TimestampScaler,TestOpusLargeStep)280 TEST(TimestampScaler, TestOpusLargeStep) {
281 MockDecoderDatabase db;
282 auto factory = CreateBuiltinAudioDecoderFactory();
283 const DecoderDatabase::DecoderInfo info(SdpAudioFormat("opus", 48000, 2),
284 absl::nullopt, factory.get());
285 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));
302 internal_timestamp += kStep;
303 }
304
305 EXPECT_CALL(db, Die()); // Called when database object is deleted.
306 }
307
TEST(TimestampScaler,Failures)308 TEST(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
325