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 = 28 NetEqDecoder::kDecoderPCMu; // Does not use scaled timestamps. 29 static const uint8_t kRtpPayloadType = 0; 30 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 31 .WillRepeatedly(Return(&info)); 32 33 TimestampScaler scaler(db); 34 // Test both sides of the timestamp wrap-around. 35 for (uint32_t timestamp = 0xFFFFFFFF - 5; timestamp != 5; ++timestamp) { 36 // Scale to internal timestamp. 37 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType)); 38 // Scale back. 39 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp)); 40 } 41 42 EXPECT_CALL(db, Die()); // Called when database object is deleted. 43 } 44 45 TEST(TimestampScaler, TestNoScalingLargeStep) { 46 MockDecoderDatabase db; 47 DecoderDatabase::DecoderInfo info; 48 info.codec_type = 49 NetEqDecoder::kDecoderPCMu; // Does not use scaled timestamps. 50 static const uint8_t kRtpPayloadType = 0; 51 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 52 .WillRepeatedly(Return(&info)); 53 54 TimestampScaler scaler(db); 55 // Test both sides of the timestamp wrap-around. 56 static const uint32_t kStep = 160; 57 uint32_t start_timestamp = 0; 58 // |external_timestamp| will be a large positive value. 59 start_timestamp = start_timestamp - 5 * kStep; 60 for (uint32_t timestamp = start_timestamp; timestamp != 5 * kStep; 61 timestamp += kStep) { 62 // Scale to internal timestamp. 63 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType)); 64 // Scale back. 65 EXPECT_EQ(timestamp, scaler.ToExternal(timestamp)); 66 } 67 68 EXPECT_CALL(db, Die()); // Called when database object is deleted. 69 } 70 71 TEST(TimestampScaler, TestG722) { 72 MockDecoderDatabase db; 73 DecoderDatabase::DecoderInfo info; 74 info.codec_type = NetEqDecoder::kDecoderG722; // Uses a factor 2 scaling. 75 static const uint8_t kRtpPayloadType = 17; 76 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 77 .WillRepeatedly(Return(&info)); 78 79 TimestampScaler scaler(db); 80 // Test both sides of the timestamp wrap-around. 81 uint32_t external_timestamp = 0xFFFFFFFF - 5; 82 uint32_t internal_timestamp = external_timestamp; 83 for (; external_timestamp != 5; ++external_timestamp) { 84 // Scale to internal timestamp. 85 EXPECT_EQ(internal_timestamp, 86 scaler.ToInternal(external_timestamp, kRtpPayloadType)); 87 // Scale back. 88 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 89 internal_timestamp += 2; 90 } 91 92 EXPECT_CALL(db, Die()); // Called when database object is deleted. 93 } 94 95 TEST(TimestampScaler, TestG722LargeStep) { 96 MockDecoderDatabase db; 97 DecoderDatabase::DecoderInfo info; 98 info.codec_type = NetEqDecoder::kDecoderG722; // Uses a factor 2 scaling. 99 static const uint8_t kRtpPayloadType = 17; 100 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 101 .WillRepeatedly(Return(&info)); 102 103 TimestampScaler scaler(db); 104 // Test both sides of the timestamp wrap-around. 105 static const uint32_t kStep = 320; 106 uint32_t external_timestamp = 0; 107 // |external_timestamp| will be a large positive value. 108 external_timestamp = external_timestamp - 5 * kStep; 109 uint32_t internal_timestamp = external_timestamp; 110 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) { 111 // Scale to internal timestamp. 112 EXPECT_EQ(internal_timestamp, 113 scaler.ToInternal(external_timestamp, kRtpPayloadType)); 114 // Scale back. 115 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 116 // Internal timestamp should be incremented with twice the step. 117 internal_timestamp += 2 * kStep; 118 } 119 120 EXPECT_CALL(db, Die()); // Called when database object is deleted. 121 } 122 123 TEST(TimestampScaler, TestG722WithCng) { 124 MockDecoderDatabase db; 125 DecoderDatabase::DecoderInfo info_g722, info_cng; 126 info_g722.codec_type = 127 NetEqDecoder::kDecoderG722; // Uses a factor 2 scaling. 128 info_cng.codec_type = NetEqDecoder::kDecoderCNGwb; 129 static const uint8_t kRtpPayloadTypeG722 = 17; 130 static const uint8_t kRtpPayloadTypeCng = 13; 131 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeG722)) 132 .WillRepeatedly(Return(&info_g722)); 133 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadTypeCng)) 134 .WillRepeatedly(Return(&info_cng)); 135 136 TimestampScaler scaler(db); 137 // Test both sides of the timestamp wrap-around. 138 uint32_t external_timestamp = 0xFFFFFFFF - 5; 139 uint32_t internal_timestamp = external_timestamp; 140 bool next_is_cng = false; 141 for (; external_timestamp != 5; ++external_timestamp) { 142 // Alternate between G.722 and CNG every other packet. 143 if (next_is_cng) { 144 // Scale to internal timestamp. 145 EXPECT_EQ(internal_timestamp, 146 scaler.ToInternal(external_timestamp, kRtpPayloadTypeCng)); 147 next_is_cng = false; 148 } else { 149 // Scale to internal timestamp. 150 EXPECT_EQ(internal_timestamp, 151 scaler.ToInternal(external_timestamp, kRtpPayloadTypeG722)); 152 next_is_cng = true; 153 } 154 // Scale back. 155 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 156 internal_timestamp += 2; 157 } 158 159 EXPECT_CALL(db, Die()); // Called when database object is deleted. 160 } 161 162 // Make sure that the method ToInternal(Packet* packet) is wired up correctly. 163 // Since it is simply calling the other ToInternal method, we are not doing 164 // as many tests here. 165 TEST(TimestampScaler, TestG722Packet) { 166 MockDecoderDatabase db; 167 DecoderDatabase::DecoderInfo info; 168 info.codec_type = 169 NetEqDecoder::kDecoderG722; // Does uses a factor 2 scaling. 170 static const uint8_t kRtpPayloadType = 17; 171 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 172 .WillRepeatedly(Return(&info)); 173 174 TimestampScaler scaler(db); 175 // Test both sides of the timestamp wrap-around. 176 uint32_t external_timestamp = 0xFFFFFFFF - 5; 177 uint32_t internal_timestamp = external_timestamp; 178 Packet packet; 179 packet.header.payloadType = kRtpPayloadType; 180 for (; external_timestamp != 5; ++external_timestamp) { 181 packet.header.timestamp = external_timestamp; 182 // Scale to internal timestamp. 183 scaler.ToInternal(&packet); 184 EXPECT_EQ(internal_timestamp, packet.header.timestamp); 185 internal_timestamp += 2; 186 } 187 188 EXPECT_CALL(db, Die()); // Called when database object is deleted. 189 } 190 191 // Make sure that the method ToInternal(PacketList* packet_list) is wired up 192 // correctly. Since it is simply calling the ToInternal(Packet* packet) method, 193 // we are not doing as many tests here. 194 TEST(TimestampScaler, TestG722PacketList) { 195 MockDecoderDatabase db; 196 DecoderDatabase::DecoderInfo info; 197 info.codec_type = NetEqDecoder::kDecoderG722; // Uses a factor 2 scaling. 198 static const uint8_t kRtpPayloadType = 17; 199 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 200 .WillRepeatedly(Return(&info)); 201 202 TimestampScaler scaler(db); 203 // Test both sides of the timestamp wrap-around. 204 uint32_t external_timestamp = 0xFFFFFFFF - 5; 205 uint32_t internal_timestamp = external_timestamp; 206 Packet packet1; 207 packet1.header.payloadType = kRtpPayloadType; 208 packet1.header.timestamp = external_timestamp; 209 Packet packet2; 210 packet2.header.payloadType = kRtpPayloadType; 211 packet2.header.timestamp = external_timestamp + 10; 212 PacketList packet_list; 213 packet_list.push_back(&packet1); 214 packet_list.push_back(&packet2); 215 216 scaler.ToInternal(&packet_list); 217 EXPECT_EQ(internal_timestamp, packet1.header.timestamp); 218 EXPECT_EQ(internal_timestamp + 20, packet2.header.timestamp); 219 220 EXPECT_CALL(db, Die()); // Called when database object is deleted. 221 } 222 223 TEST(TimestampScaler, TestG722Reset) { 224 MockDecoderDatabase db; 225 DecoderDatabase::DecoderInfo info; 226 info.codec_type = NetEqDecoder::kDecoderG722; // Uses a factor 2 scaling. 227 static const uint8_t kRtpPayloadType = 17; 228 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 229 .WillRepeatedly(Return(&info)); 230 231 TimestampScaler scaler(db); 232 // Test both sides of the timestamp wrap-around. 233 uint32_t external_timestamp = 0xFFFFFFFF - 5; 234 uint32_t internal_timestamp = external_timestamp; 235 for (; external_timestamp != 5; ++external_timestamp) { 236 // Scale to internal timestamp. 237 EXPECT_EQ(internal_timestamp, 238 scaler.ToInternal(external_timestamp, kRtpPayloadType)); 239 // Scale back. 240 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 241 internal_timestamp += 2; 242 } 243 // Reset the scaler. After this, we expect the internal and external to start 244 // over at the same value again. 245 scaler.Reset(); 246 internal_timestamp = external_timestamp; 247 for (; external_timestamp != 15; ++external_timestamp) { 248 // Scale to internal timestamp. 249 EXPECT_EQ(internal_timestamp, 250 scaler.ToInternal(external_timestamp, kRtpPayloadType)); 251 // Scale back. 252 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 253 internal_timestamp += 2; 254 } 255 256 EXPECT_CALL(db, Die()); // Called when database object is deleted. 257 } 258 259 // TODO(minyue): This test becomes trivial since Opus does not need a timestamp 260 // scaler. Therefore, this test may be removed in future. There is no harm to 261 // keep it, since it can be taken as a test case for the situation of a trivial 262 // timestamp scaler. 263 TEST(TimestampScaler, TestOpusLargeStep) { 264 MockDecoderDatabase db; 265 DecoderDatabase::DecoderInfo info; 266 info.codec_type = NetEqDecoder::kDecoderOpus; 267 static const uint8_t kRtpPayloadType = 17; 268 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 269 .WillRepeatedly(Return(&info)); 270 271 TimestampScaler scaler(db); 272 // Test both sides of the timestamp wrap-around. 273 static const uint32_t kStep = 960; 274 uint32_t external_timestamp = 0; 275 // |external_timestamp| will be a large positive value. 276 external_timestamp = external_timestamp - 5 * kStep; 277 uint32_t internal_timestamp = external_timestamp; 278 for (; external_timestamp != 5 * kStep; external_timestamp += kStep) { 279 // Scale to internal timestamp. 280 EXPECT_EQ(internal_timestamp, 281 scaler.ToInternal(external_timestamp, kRtpPayloadType)); 282 // Scale back. 283 EXPECT_EQ(external_timestamp, scaler.ToExternal(internal_timestamp)); 284 internal_timestamp += kStep; 285 } 286 287 EXPECT_CALL(db, Die()); // Called when database object is deleted. 288 } 289 290 TEST(TimestampScaler, Failures) { 291 static const uint8_t kRtpPayloadType = 17; 292 MockDecoderDatabase db; 293 EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType)) 294 .WillOnce(ReturnNull()); // Return NULL to indicate unknown payload type. 295 296 TimestampScaler scaler(db); 297 uint32_t timestamp = 4711; // Some number. 298 EXPECT_EQ(timestamp, scaler.ToInternal(timestamp, kRtpPayloadType)); 299 300 Packet* packet = NULL; 301 scaler.ToInternal(packet); // Should not crash. That's all we can test. 302 303 EXPECT_CALL(db, Die()); // Called when database object is deleted. 304 } 305 306 } // namespace webrtc 307