2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/audio_coding/neteq/timestamp_scaler.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 #include "webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h"
16 #include "webrtc/modules/audio_coding/neteq/packet.h"
18 using ::testing::Return;
19 using ::testing::ReturnNull;
24 TEST(TimestampScaler, TestNoScaling) {
25 MockDecoderDatabase db;
26 DecoderDatabase::DecoderInfo info;
27 info.codec_type = kDecoderPCMu; // Does not use scaled timestamps.
28 static const uint8_t kRtpPayloadType = 0;
29 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
30 .WillRepeatedly(Return(&info));
32 TimestampScaler scaler(db);
33 // Test both sides of the timestamp wrap-around.
34 for (uint32_t timestamp = 0xFFFFFFFF - 5; timestamp != 5; ++timestamp) {
35 // Scale to internal timestamp.
36 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
38 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp));
41 EXPECT_CALL(db, Die()); // Called when database object is deleted.
44 TEST(TimestampScaler, TestNoScalingLargeStep) {
45 MockDecoderDatabase db;
46 DecoderDatabase::DecoderInfo info;
47 info.codec_type = kDecoderPCMu; // Does not use scaled timestamps.
48 static const uint8_t kRtpPayloadType = 0;
49 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
50 .WillRepeatedly(Return(&info));
52 TimestampScaler scaler(db);
53 // Test both sides of the timestamp wrap-around.
54 static const uint32_t kStep = 160;
55 uint32_t start_timestamp = 0;
56 // |external_timestamp| will be a large positive value.
57 start_timestamp = start_timestamp - 5 * kStep;
58 for (uint32_t timestamp = start_timestamp; timestamp != 5 * kStep;
60 // Scale to internal timestamp.
61 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
63 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp));
66 EXPECT_CALL(db, Die()); // Called when database object is deleted.
69 TEST(TimestampScaler, TestG722) {
70 MockDecoderDatabase db;
71 DecoderDatabase::DecoderInfo info;
72 info.codec_type = kDecoderG722; // Uses a factor 2 scaling.
73 static const uint8_t kRtpPayloadType = 17;
74 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
75 .WillRepeatedly(Return(&info));
77 TimestampScaler scaler(db);
78 // Test both sides of the timestamp wrap-around.
79 uint32_t external_timestamp = 0xFFFFFFFF - 5;
80 uint32_t internal_timestamp = external_timestamp;
81 for (; external_timestamp != 5; ++external_timestamp) {
82 // Scale to internal timestamp.
83 EXPECT_EQ(internal_timestamp,
84 scaler.ToInternal(external_timestamp, kRtpPayloadType));
86 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
87 internal_timestamp += 2;
90 EXPECT_CALL(db, Die()); // Called when database object is deleted.
93 TEST(TimestampScaler, TestG722LargeStep) {
94 MockDecoderDatabase db;
95 DecoderDatabase::DecoderInfo info;
96 info.codec_type = kDecoderG722; // Uses a factor 2 scaling.
97 static const uint8_t kRtpPayloadType = 17;
98 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
99 .WillRepeatedly(Return(&info));
101 TimestampScaler scaler(db);
102 // Test both sides of the timestamp wrap-around.
103 static const uint32_t kStep = 320;
104 uint32_t external_timestamp = 0;
105 // |external_timestamp| will be a large positive value.
106 external_timestamp = external_timestamp - 5 * kStep;
107 uint32_t internal_timestamp = external_timestamp;
108 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) {
109 // Scale to internal timestamp.
110 EXPECT_EQ(internal_timestamp,
111 scaler.ToInternal(external_timestamp, kRtpPayloadType));
113 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
114 // Internal timestamp should be incremented with twice the step.
115 internal_timestamp += 2 * kStep;
118 EXPECT_CALL(db, Die()); // Called when database object is deleted.
121 TEST(TimestampScaler, TestG722WithCng) {
122 MockDecoderDatabase db;
123 DecoderDatabase::DecoderInfo info_g722, info_cng;
124 info_g722.codec_type = kDecoderG722; // Uses a factor 2 scaling.
125 info_cng.codec_type = kDecoderCNGwb;
126 static const uint8_t kRtpPayloadTypeG722 = 17;
127 static const uint8_t kRtpPayloadTypeCng = 13;
128 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeG722))
129 .WillRepeatedly(Return(&info_g722));
130 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeCng))
131 .WillRepeatedly(Return(&info_cng));
133 TimestampScaler scaler(db);
134 // Test both sides of the timestamp wrap-around.
135 uint32_t external_timestamp = 0xFFFFFFFF - 5;
136 uint32_t internal_timestamp = external_timestamp;
137 bool next_is_cng = false;
138 for (; external_timestamp != 5; ++external_timestamp) {
139 // Alternate between G.722 and CNG every other packet.
141 // Scale to internal timestamp.
142 EXPECT_EQ(internal_timestamp,
143 scaler.ToInternal(external_timestamp, kRtpPayloadTypeCng));
146 // Scale to internal timestamp.
147 EXPECT_EQ(internal_timestamp,
148 scaler.ToInternal(external_timestamp, kRtpPayloadTypeG722));
152 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
153 internal_timestamp += 2;
156 EXPECT_CALL(db, Die()); // Called when database object is deleted.
159 // Make sure that the method ToInternal(Packet* packet) is wired up correctly.
160 // Since it is simply calling the other ToInternal method, we are not doing
161 // as many tests here.
162 TEST(TimestampScaler, TestG722Packet) {
163 MockDecoderDatabase db;
164 DecoderDatabase::DecoderInfo info;
165 info.codec_type = kDecoderG722; // Does uses a factor 2 scaling.
166 static const uint8_t kRtpPayloadType = 17;
167 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
168 .WillRepeatedly(Return(&info));
170 TimestampScaler scaler(db);
171 // Test both sides of the timestamp wrap-around.
172 uint32_t external_timestamp = 0xFFFFFFFF - 5;
173 uint32_t internal_timestamp = external_timestamp;
175 packet.header.payloadType = kRtpPayloadType;
176 for (; external_timestamp != 5; ++external_timestamp) {
177 packet.header.timestamp = external_timestamp;
178 // Scale to internal timestamp.
179 scaler.ToInternal(&packet);
180 EXPECT_EQ(internal_timestamp, packet.header.timestamp);
181 internal_timestamp += 2;
184 EXPECT_CALL(db, Die()); // Called when database object is deleted.
187 // Make sure that the method ToInternal(PacketList* packet_list) is wired up
188 // correctly. Since it is simply calling the ToInternal(Packet* packet) method,
189 // we are not doing as many tests here.
190 TEST(TimestampScaler, TestG722PacketList) {
191 MockDecoderDatabase db;
192 DecoderDatabase::DecoderInfo info;
193 info.codec_type = kDecoderG722; // Uses a factor 2 scaling.
194 static const uint8_t kRtpPayloadType = 17;
195 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
196 .WillRepeatedly(Return(&info));
198 TimestampScaler scaler(db);
199 // Test both sides of the timestamp wrap-around.
200 uint32_t external_timestamp = 0xFFFFFFFF - 5;
201 uint32_t internal_timestamp = external_timestamp;
203 packet1.header.payloadType = kRtpPayloadType;
204 packet1.header.timestamp = external_timestamp;
206 packet2.header.payloadType = kRtpPayloadType;
207 packet2.header.timestamp = external_timestamp + 10;
208 PacketList packet_list;
209 packet_list.push_back(&packet1);
210 packet_list.push_back(&packet2);
212 scaler.ToInternal(&packet_list);
213 EXPECT_EQ(internal_timestamp, packet1.header.timestamp);
214 EXPECT_EQ(internal_timestamp + 20, packet2.header.timestamp);
216 EXPECT_CALL(db, Die()); // Called when database object is deleted.
219 TEST(TimestampScaler, TestG722Reset) {
220 MockDecoderDatabase db;
221 DecoderDatabase::DecoderInfo info;
222 info.codec_type = kDecoderG722; // Uses a factor 2 scaling.
223 static const uint8_t kRtpPayloadType = 17;
224 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
225 .WillRepeatedly(Return(&info));
227 TimestampScaler scaler(db);
228 // Test both sides of the timestamp wrap-around.
229 uint32_t external_timestamp = 0xFFFFFFFF - 5;
230 uint32_t internal_timestamp = external_timestamp;
231 for (; external_timestamp != 5; ++external_timestamp) {
232 // Scale to internal timestamp.
233 EXPECT_EQ(internal_timestamp,
234 scaler.ToInternal(external_timestamp, kRtpPayloadType));
236 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
237 internal_timestamp += 2;
239 // Reset the scaler. After this, we expect the internal and external to start
240 // over at the same value again.
242 internal_timestamp = external_timestamp;
243 for (; external_timestamp != 15; ++external_timestamp) {
244 // Scale to internal timestamp.
245 EXPECT_EQ(internal_timestamp,
246 scaler.ToInternal(external_timestamp, kRtpPayloadType));
248 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
249 internal_timestamp += 2;
252 EXPECT_CALL(db, Die()); // Called when database object is deleted.
255 // TODO(minyue): This test becomes trivial since Opus does not need a timestamp
256 // scaler. Therefore, this test may be removed in future. There is no harm to
257 // keep it, since it can be taken as a test case for the situation of a trivial
259 TEST(TimestampScaler, TestOpusLargeStep) {
260 MockDecoderDatabase db;
261 DecoderDatabase::DecoderInfo info;
262 info.codec_type = kDecoderOpus;
263 static const uint8_t kRtpPayloadType = 17;
264 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
265 .WillRepeatedly(Return(&info));
267 TimestampScaler scaler(db);
268 // Test both sides of the timestamp wrap-around.
269 static const uint32_t kStep = 960;
270 uint32_t external_timestamp = 0;
271 // |external_timestamp| will be a large positive value.
272 external_timestamp = external_timestamp - 5 * kStep;
273 uint32_t internal_timestamp = external_timestamp;
274 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) {
275 // Scale to internal timestamp.
276 EXPECT_EQ(internal_timestamp,
277 scaler.ToInternal(external_timestamp, kRtpPayloadType));
279 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
280 internal_timestamp += kStep;
283 EXPECT_CALL(db, Die()); // Called when database object is deleted.
286 TEST(TimestampScaler, TestIsacFbLargeStep) {
287 MockDecoderDatabase db;
288 DecoderDatabase::DecoderInfo info;
289 info.codec_type = kDecoderISACfb;
290 static const uint8_t kRtpPayloadType = 17;
291 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
292 .WillRepeatedly(Return(&info));
294 TimestampScaler scaler(db);
295 // Test both sides of the timestamp wrap-around.
296 static const uint32_t kStep = 960;
297 uint32_t external_timestamp = 0;
298 // |external_timestamp| will be a large positive value.
299 external_timestamp = external_timestamp - 5 * kStep;
300 uint32_t internal_timestamp = external_timestamp;
301 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) {
302 // Scale to internal timestamp.
303 EXPECT_EQ(internal_timestamp,
304 scaler.ToInternal(external_timestamp, kRtpPayloadType));
306 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp));
307 // Internal timestamp should be incremented with two-thirds the step.
308 internal_timestamp += 2 * kStep / 3;
311 EXPECT_CALL(db, Die()); // Called when database object is deleted.
314 TEST(TimestampScaler, Failures) {
315 static const uint8_t kRtpPayloadType = 17;
316 MockDecoderDatabase db;
317 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
318 .WillOnce(ReturnNull()); // Return NULL to indicate unknown payload type.
320 TimestampScaler scaler(db);
321 uint32_t timestamp = 4711; // Some number.
322 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType));
324 Packet* packet = NULL;
325 scaler.ToInternal(packet); // Should not crash. That's all we can test.
327 EXPECT_CALL(db, Die()); // Called when database object is deleted.
330 } // namespace webrtc