Home | History | Annotate | Download | only in neteq
      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