19a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org/*
29a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
39a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *
49a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
59a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
69a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
79a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
89a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
99a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org */
109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// Test to verify correct operation for externally created decoders.
129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <string>
149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <list>
159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1649d62206ededc5905d6121d42fdcce8ed665b2c0kjellander@webrtc.org#include "testing/gmock/include/gmock/gmock.h"
1749d62206ededc5905d6121d42fdcce8ed665b2c0kjellander@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
18e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
19e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h"
20e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
21e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
229f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org#include "webrtc/system_wrappers/interface/compile_assert.h"
239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include "webrtc/test/testsupport/fileutils.h"
257537dde7698d151f5c50b5f160e4ed28347b0c90henrike@webrtc.org#include "webrtc/test/testsupport/gtest_disable.h"
269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgnamespace webrtc {
289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgusing ::testing::_;
309f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgusing ::testing::Return;
319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// This test encodes a few packets of PCM16b 32 kHz data and inserts it into two
339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// different NetEq instances. The first instance uses the internal version of
349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// the decoder object, while the second one uses an externally created decoder
359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// object (ExternalPcm16B wrapped in MockExternalPcm16B, both defined above).
369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org// The test verifies that the output from both instances match.
379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgclass NetEqExternalDecoderTest : public ::testing::Test {
389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org protected:
399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  static const int kTimeStepMs = 10;
409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  static const int kMaxBlockSize = 480;  // 10 ms @ 48 kHz.
419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  static const uint8_t kPayloadType = 95;
429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  static const int kSampleRateHz = 32000;
439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  NetEqExternalDecoderTest()
459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      : sample_rate_hz_(kSampleRateHz),
469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        samples_per_ms_(sample_rate_hz_ / 1000),
479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        frame_size_ms_(10),
489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        frame_size_samples_(frame_size_ms_ * samples_per_ms_),
499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        output_size_samples_(frame_size_ms_ * samples_per_ms_),
509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        external_decoder_(new MockExternalPcm16B(kDecoderPCM16Bswb32kHz)),
514d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        payload_size_bytes_(0),
539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        last_send_time_(0),
549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        last_arrival_time_(0) {
559f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    config_.sample_rate_hz = sample_rate_hz_;
569f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    neteq_external_ = NetEq::Create(config_);
579f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    neteq_ = NetEq::Create(config_);
589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    input_ = new int16_t[frame_size_samples_];
599a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    encoded_ = new uint8_t[2 * frame_size_samples_];
609a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  ~NetEqExternalDecoderTest() {
639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    delete neteq_external_;
649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    delete neteq_;
659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    // We will now delete the decoder ourselves, so expecting Die to be called.
669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Die()).Times(1);
679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    delete [] input_;
689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    delete [] encoded_;
699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  virtual void SetUp() {
729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    const std::string file_name =
739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    input_file_.reset(new test::InputAudioFile(file_name));
759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    assert(sample_rate_hz_ == 32000);
769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    NetEqDecoder decoder = kDecoderPCM16Bswb32kHz;
779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Init());
789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    // NetEq is not allowed to delete the external decoder (hence Times(0)).
799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Die()).Times(0);
809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK,
814d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org              neteq_external_->RegisterExternalDecoder(
824d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                  external_decoder_.get(), decoder, kPayloadType));
839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK,
849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org              neteq_->RegisterPayloadType(decoder, kPayloadType));
859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  virtual void TearDown() {}
889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int GetNewPackets() {
909a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    if (!input_file_->Read(frame_size_samples_, input_)) {
919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      return -1;
929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    }
939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    payload_size_bytes_ = WebRtcPcm16b_Encode(input_, frame_size_samples_,
949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org                                             encoded_);
959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    if (frame_size_samples_ * 2 != payload_size_bytes_) {
969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      return -1;
979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    }
984d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    int next_send_time = rtp_generator_->GetRtpHeader(
994d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        kPayloadType, frame_size_samples_, &rtp_header_);
1009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    return next_send_time;
1019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
1029a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1034d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  virtual void VerifyOutput(size_t num_samples) const {
1049a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    for (size_t i = 0; i < num_samples; ++i) {
1059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      ASSERT_EQ(output_[i], output_external_[i]) <<
1069a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org          "Diff in sample " << i << ".";
1079a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    }
1089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
1099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  virtual int GetArrivalTime(int send_time) {
1119a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    int arrival_time = last_arrival_time_ + (send_time - last_send_time_);
1129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    last_send_time_ = send_time;
1139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    last_arrival_time_ = arrival_time;
1149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    return arrival_time;
1159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
1169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  virtual bool Lost() { return false; }
1189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1194d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  virtual void InsertPackets(int next_arrival_time) {
1204d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    // Insert packet in regular instance.
1214d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    ASSERT_EQ(
1224d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        NetEq::kOK,
1234d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        neteq_->InsertPacket(
1244d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org            rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
1254d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    // Insert packet in external decoder instance.
1264d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_,
1274d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                IncomingPacket(_,
1284d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               payload_size_bytes_,
1294d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               rtp_header_.header.sequenceNumber,
1304d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               rtp_header_.header.timestamp,
1314d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               next_arrival_time));
1324d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    ASSERT_EQ(
1334d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        NetEq::kOK,
1344d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        neteq_external_->InsertPacket(
1354d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org            rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
1364d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  }
1374d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org
1384d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  virtual void GetOutputAudio() {
1394d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    NetEqOutputType output_type;
1404d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    // Get audio from regular instance.
1414d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    int samples_per_channel;
1424d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    int num_channels;
1434d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_EQ(NetEq::kOK,
1444d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org              neteq_->GetAudio(kMaxBlockSize,
1454d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               output_,
1464d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               &samples_per_channel,
1474d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               &num_channels,
1484d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                               &output_type));
1494d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_EQ(1, num_channels);
1504d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_EQ(output_size_samples_, samples_per_channel);
1514d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    // Get audio from external decoder instance.
1524d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK,
1534d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org              neteq_external_->GetAudio(kMaxBlockSize,
1544d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                                        output_external_,
1554d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                                        &samples_per_channel,
1564d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                                        &num_channels,
1574d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org                                        &output_type));
1584d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_EQ(1, num_channels);
1594d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org    EXPECT_EQ(output_size_samples_, samples_per_channel);
1604d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  }
1614d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org
1629f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  virtual int NumExpectedDecodeCalls(int num_loops) const { return num_loops; }
1639f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
1649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  void RunTest(int num_loops) {
1659a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    // Get next input packets (mono and multi-channel).
1669a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    int next_send_time;
1679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    int next_arrival_time;
1689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    do {
1699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      next_send_time = GetNewPackets();
1709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      ASSERT_NE(-1, next_send_time);
1719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      next_arrival_time = GetArrivalTime(next_send_time);
1729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    } while (Lost());  // If lost, immediately read the next packet.
1739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Decode(_, payload_size_bytes_, _, _))
1759f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        .Times(NumExpectedDecodeCalls(num_loops));
1769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    int time_now = 0;
1789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    for (int k = 0; k < num_loops; ++k) {
1799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      while (time_now >= next_arrival_time) {
1804d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org        InsertPackets(next_arrival_time);
1814d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org
1829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        // Get next input packet.
1839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        do {
1849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org          next_send_time = GetNewPackets();
1859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org          ASSERT_NE(-1, next_send_time);
1869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org          next_arrival_time = GetArrivalTime(next_send_time);
1879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org        } while (Lost());  // If lost, immediately read the next packet.
1889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      }
1894d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org
1904d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org      GetOutputAudio();
1914d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org
1929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      std::ostringstream ss;
1939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      ss << "Lap number " << k << ".";
1949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      SCOPED_TRACE(ss.str());  // Print out the parameter values on failure.
1959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      // Compare mono and multi-channel.
1969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      ASSERT_NO_FATAL_FAILURE(VerifyOutput(output_size_samples_));
1979a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
1989a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org      time_now += kTimeStepMs;
1999a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org    }
2009a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  }
2019a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
2029f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  NetEq::Config config_;
2039f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int sample_rate_hz_;
2049f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int samples_per_ms_;
2059a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  const int frame_size_ms_;
2069f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int frame_size_samples_;
2079f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int output_size_samples_;
2089a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  NetEq* neteq_external_;
2099a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  NetEq* neteq_;
2104d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  scoped_ptr<MockExternalPcm16B> external_decoder_;
2114d57d89f3ac5c952e0938cc31cbb174959107f7dhenrik.lundin@webrtc.org  scoped_ptr<test::RtpGenerator> rtp_generator_;
2129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int16_t* input_;
2139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  uint8_t* encoded_;
2149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int16_t output_[kMaxBlockSize];
2159a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int16_t output_external_[kMaxBlockSize];
2169a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  WebRtcRTPHeader rtp_header_;
2179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int payload_size_bytes_;
2189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int last_send_time_;
2199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  int last_arrival_time_;
2209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  scoped_ptr<test::InputAudioFile> input_file_;
2219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org};
2229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
22354c9b21d0c8e401c9351c1f03296fadc659825e6henrik.lundin@webrtc.orgTEST_F(NetEqExternalDecoderTest, RunTest) {
2249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org  RunTest(100);  // Run 100 laps @ 10 ms each in the test loop.
2259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org}
2269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org
2279f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgclass LargeTimestampJumpTest : public NetEqExternalDecoderTest {
2289f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org protected:
2299f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  enum TestStates {
2309f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    kInitialPhase,
2319f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    kNormalPhase,
2329f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    kExpandPhase,
2339f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    kFadedExpandPhase,
2349f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    kRecovered
2359f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  };
2369f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
2379f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  LargeTimestampJumpTest()
2389f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      : NetEqExternalDecoderTest(), test_state_(kInitialPhase) {
2399f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    sample_rate_hz_ = 8000;
2409f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    samples_per_ms_ = sample_rate_hz_ / 1000;
2419f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    frame_size_samples_ = frame_size_ms_ * samples_per_ms_;
2429f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    output_size_samples_ = frame_size_ms_ * samples_per_ms_;
2439f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Die()).Times(1);
2449f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    external_decoder_.reset(new MockExternalPcm16B(kDecoderPCM16B));
2459f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
2469f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
2479f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  void SetUp() OVERRIDE {
2489f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    const std::string file_name =
2499f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
2509f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    input_file_.reset(new test::InputAudioFile(file_name));
2519f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    assert(sample_rate_hz_ == 8000);
2529f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    NetEqDecoder decoder = kDecoderPCM16B;
2539f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Init());
2549f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, HasDecodePlc())
2559f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        .WillRepeatedly(Return(false));
2569f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // NetEq is not allowed to delete the external decoder (hence Times(0)).
2579f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_, Die()).Times(0);
2589f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK,
2599f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org              neteq_external_->RegisterExternalDecoder(
2609f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                  external_decoder_.get(), decoder, kPayloadType));
2619f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(decoder, kPayloadType));
2629f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
2639f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
2649f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  void InsertPackets(int next_arrival_time) OVERRIDE {
2659f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // Insert packet in external decoder instance.
2669f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_CALL(*external_decoder_,
2679f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                IncomingPacket(_,
2689f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                               payload_size_bytes_,
2699f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                               rtp_header_.header.sequenceNumber,
2709f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                               rtp_header_.header.timestamp,
2719f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                               next_arrival_time));
2729f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    ASSERT_EQ(
2739f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        NetEq::kOK,
2749f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        neteq_external_->InsertPacket(
2759f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org            rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
2769f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
2779f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
2789f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  void GetOutputAudio() OVERRIDE {
2799f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    NetEqOutputType output_type;
2809f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    int samples_per_channel;
2819f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    int num_channels;
2829f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // Get audio from external decoder instance.
2839f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    ASSERT_EQ(NetEq::kOK,
2849f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org              neteq_external_->GetAudio(kMaxBlockSize,
2859f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                        output_external_,
2869f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                        &samples_per_channel,
2879f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                        &num_channels,
2889f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                        &output_type));
2899f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_EQ(1, num_channels);
2909f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_EQ(output_size_samples_, samples_per_channel);
2919f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    UpdateState(output_type);
2929f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
2939f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
2949f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  virtual void UpdateState(NetEqOutputType output_type) {
2959f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    switch (test_state_) {
2969f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kInitialPhase: {
2979f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputNormal) {
2989f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kNormalPhase;
2999f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
3009f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
3019f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
3029f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kNormalPhase: {
3039f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputPLC) {
3049f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kExpandPhase;
3059f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
3069f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
3079f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
3089f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kExpandPhase: {
3099f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputPLCtoCNG) {
3109f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kFadedExpandPhase;
3119f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
3129f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
3139f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
3149f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kFadedExpandPhase: {
3159f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputNormal) {
3169f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kRecovered;
3179f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
3189f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
3199f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
3209f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kRecovered: {
3219f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
3229f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
3239f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    }
3249f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
3259f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3269f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  void VerifyOutput(size_t num_samples) const OVERRIDE {
3279f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    if (test_state_ == kExpandPhase || test_state_ == kFadedExpandPhase) {
3289f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      // Don't verify the output in this phase of the test.
3299f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      return;
3309f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    }
3319f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    for (size_t i = 0; i < num_samples; ++i) {
3329f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      if (output_external_[i] != 0)
3339f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        return;
3349f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    }
3359f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    EXPECT_TRUE(false)
3369f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        << "Expected at least one non-zero sample in each output block.";
3379f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
3389f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3399f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int NumExpectedDecodeCalls(int num_loops) const OVERRIDE {
3409f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // Some packets won't be decoded because of the buffer being flushed after
3419f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // the timestamp jump.
3429f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    return num_loops - (config_.max_packets_in_buffer + 1);
3439f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
3449f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3459f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  TestStates test_state_;
3469f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org};
3479f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3489f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgTEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRange) {
3499f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Set the timestamp series to start at 2880, increase to 7200, then jump to
3509f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // 2869342376. The sequence numbers start at 42076 and increase by 1 for each
3519f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // packet, also when the timestamp jumps.
3529f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint16_t kStartSeqeunceNumber = 42076;
3539f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kStartTimestamp = 2880;
3549f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpFromTimestamp = 7200;
3559f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpToTimestamp = 2869342376;
3569f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(kJumpFromTimestamp < kJumpToTimestamp,
3579f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                 timestamp_jump_should_not_result_in_wrap);
3589f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(
3599f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) > 0x7FFFFFFF,
3609f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      jump_should_be_larger_than_half_range);
3619f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Replace the default RTP generator with one that jumps in timestamp.
3629f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
3639f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartSeqeunceNumber,
3649f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartTimestamp,
3659f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpFromTimestamp,
3669f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpToTimestamp));
3679f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3689f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
3699f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  EXPECT_EQ(kRecovered, test_state_);
3709f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org}
3719f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3729f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgTEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRangeAndWrap) {
3739f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Make a jump larger than half the 32-bit timestamp range. Set the start
3749f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // timestamp such that the jump will result in a wrap around.
3759f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint16_t kStartSeqeunceNumber = 42076;
3769f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Set the jump length slightly larger than 2^31.
3779f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kStartTimestamp = 3221223116;
3789f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpFromTimestamp = 3221223216;
3799f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpToTimestamp = 1073744278;
3809f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(kJumpToTimestamp < kJumpFromTimestamp,
3819f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                 timestamp_jump_should_result_in_wrap);
3829f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(
3839f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) > 0x7FFFFFFF,
3849f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      jump_should_be_larger_than_half_range);
3859f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Replace the default RTP generator with one that jumps in timestamp.
3869f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
3879f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartSeqeunceNumber,
3889f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartTimestamp,
3899f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpFromTimestamp,
3909f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpToTimestamp));
3919f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3929f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
3939f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  EXPECT_EQ(kRecovered, test_state_);
3949f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org}
3959f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
3969f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgclass ShortTimestampJumpTest : public LargeTimestampJumpTest {
3979f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org protected:
3989f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  void UpdateState(NetEqOutputType output_type) OVERRIDE {
3999f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    switch (test_state_) {
4009f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kInitialPhase: {
4019f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputNormal) {
4029f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kNormalPhase;
4039f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
4049f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
4059f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
4069f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kNormalPhase: {
4079f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputPLC) {
4089f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kExpandPhase;
4099f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
4109f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
4119f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
4129f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kExpandPhase: {
4139f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        if (output_type == kOutputNormal) {
4149f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org          test_state_ = kRecovered;
4159f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        }
4169f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
4179f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
4189f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      case kRecovered: {
4199f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org        break;
4209f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      }
4219f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      default: { FAIL(); }
4229f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    }
4239f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
4249f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4259f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  int NumExpectedDecodeCalls(int num_loops) const OVERRIDE {
4269f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    // Some packets won't be decoded because of the timestamp jump.
4279f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org    return num_loops - 2;
4289f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  }
4299f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org};
4309f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4319f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgTEST_F(ShortTimestampJumpTest, JumpShorterThanHalfRange) {
4329f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Make a jump shorter than half the 32-bit timestamp range. Set the start
4339f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // timestamp such that the jump will not result in a wrap around.
4349f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint16_t kStartSeqeunceNumber = 42076;
4359f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Set the jump length slightly smaller than 2^31.
4369f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kStartTimestamp = 4711;
4379f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpFromTimestamp = 4811;
4389f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpToTimestamp = 2147483747;
4399f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(kJumpFromTimestamp < kJumpToTimestamp,
4409f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                 timestamp_jump_should_not_result_in_wrap);
4419f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(
4429f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) < 0x7FFFFFFF,
4439f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      jump_should_be_smaller_than_half_range);
4449f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Replace the default RTP generator with one that jumps in timestamp.
4459f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
4469f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartSeqeunceNumber,
4479f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartTimestamp,
4489f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpFromTimestamp,
4499f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpToTimestamp));
4509f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4519f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
4529f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  EXPECT_EQ(kRecovered, test_state_);
4539f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org}
4549f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4559f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.orgTEST_F(ShortTimestampJumpTest, JumpShorterThanHalfRangeAndWrap) {
4569f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Make a jump shorter than half the 32-bit timestamp range. Set the start
4579f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // timestamp such that the jump will result in a wrap around.
4589f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint16_t kStartSeqeunceNumber = 42076;
4599f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Set the jump length slightly smaller than 2^31.
4609f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kStartTimestamp = 3221227827;
4619f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpFromTimestamp = 3221227927;
4629f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  static const uint32_t kJumpToTimestamp = 1073739567;
4639f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(kJumpToTimestamp < kJumpFromTimestamp,
4649f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                 timestamp_jump_should_result_in_wrap);
4659f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  COMPILE_ASSERT(
4669f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) < 0x7FFFFFFF,
4679f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org      jump_should_be_smaller_than_half_range);
4689f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  // Replace the default RTP generator with one that jumps in timestamp.
4699f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
4709f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartSeqeunceNumber,
4719f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kStartTimestamp,
4729f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpFromTimestamp,
4739f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org                                                           kJumpToTimestamp));
4749f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4759f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
4769f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org  EXPECT_EQ(kRecovered, test_state_);
4779f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org}
4789f91a3099fb22e818eeed3d37f376430c7aa22c1henrik.lundin@webrtc.org
4799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org}  // namespace webrtc
480