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 "webrtc/modules/audio_coding/neteq/timestamp_scaler.h" 12 13 #include "testing/gmock/include/gmock/gmock.h" 14 #include "testing/gtest/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" 17 18 using ::testing::Return; 19 using ::testing::ReturnNull; 20 using ::testing::_; 21 22 namespace webrtc { 23 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)); 31 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)); 37 // Scale back. 38 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp)); 39 } 40 41 EXPECT_CALL(db, Die()); // Called when database object is deleted. 42 } 43 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)); 51 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; 59 timestamp += kStep) { 60 // Scale to internal timestamp. 61 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType)); 62 // Scale back. 63 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp)); 64 } 65 66 EXPECT_CALL(db, Die()); // Called when database object is deleted. 67 } 68 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)); 76 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)); 85 // Scale back. 86 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 87 internal_timestamp += 2; 88 } 89 90 EXPECT_CALL(db, Die()); // Called when database object is deleted. 91 } 92 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)); 100 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)); 112 // Scale back. 113 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 114 // Internal timestamp should be incremented with twice the step. 115 internal_timestamp += 2 * kStep; 116 } 117 118 EXPECT_CALL(db, Die()); // Called when database object is deleted. 119 } 120 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)); 132 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. 140 if (next_is_cng) { 141 // Scale to internal timestamp. 142 EXPECT_EQ(internal_timestamp, 143 scaler.ToInternal(external_timestamp, kRtpPayloadTypeCng)); 144 next_is_cng = false; 145 } else { 146 // Scale to internal timestamp. 147 EXPECT_EQ(internal_timestamp, 148 scaler.ToInternal(external_timestamp, kRtpPayloadTypeG722)); 149 next_is_cng = true; 150 } 151 // Scale back. 152 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 153 internal_timestamp += 2; 154 } 155 156 EXPECT_CALL(db, Die()); // Called when database object is deleted. 157 } 158 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)); 169 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; 174 Packet packet; 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; 182 } 183 184 EXPECT_CALL(db, Die()); // Called when database object is deleted. 185 } 186 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)); 197 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; 202 Packet packet1; 203 packet1.header.payloadType = kRtpPayloadType; 204 packet1.header.timestamp = external_timestamp; 205 Packet packet2; 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); 211 212 scaler.ToInternal(&packet_list); 213 EXPECT_EQ(internal_timestamp, packet1.header.timestamp); 214 EXPECT_EQ(internal_timestamp + 20, packet2.header.timestamp); 215 216 EXPECT_CALL(db, Die()); // Called when database object is deleted. 217 } 218 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)); 226 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)); 235 // Scale back. 236 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 237 internal_timestamp += 2; 238 } 239 // Reset the scaler. After this, we expect the internal and external to start 240 // over at the same value again. 241 scaler.Reset(); 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)); 247 // Scale back. 248 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 249 internal_timestamp += 2; 250 } 251 252 EXPECT_CALL(db, Die()); // Called when database object is deleted. 253 } 254 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 258 // timestamp scaler. 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)); 266 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)); 278 // Scale back. 279 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 280 internal_timestamp += kStep; 281 } 282 283 EXPECT_CALL(db, Die()); // Called when database object is deleted. 284 } 285 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)); 293 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)); 305 // Scale back. 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; 309 } 310 311 EXPECT_CALL(db, Die()); // Called when database object is deleted. 312 } 313 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. 319 320 TimestampScaler scaler(db); 321 uint32_t timestamp = 4711; // Some number. 322 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType)); 323 324 Packet* packet = NULL; 325 scaler.ToInternal(packet); // Should not crash. That's all we can test. 326 327 EXPECT_CALL(db, Die()); // Called when database object is deleted. 328 } 329 330 } // namespace webrtc 331