/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
#include "webrtc/rtc_base/arraysize.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/mock_audio_encoder.h"

namespace webrtc {
namespace acm2 {

using ::testing::Return;

namespace {

const int kDataLengthSamples = 80;
const int kPacketSizeSamples = 2 * kDataLengthSamples;
const int16_t kZeroData[kDataLengthSamples] = {0};
const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples,
                                     1, 64000};
const int kCngPt = 13;

class Marker final {
 public:
  MOCK_METHOD1(Mark, void(std::string desc));
};

}  // namespace

class RentACodecTestF : public ::testing::Test {
 protected:
  void CreateCodec() {
    auto speech_encoder = rent_a_codec_.RentEncoder(kDefaultCodecInst);
    ASSERT_TRUE(speech_encoder);
    RentACodec::StackParameters param;
    param.use_cng = true;
    param.speech_encoder = std::move(speech_encoder);
    encoder_ = rent_a_codec_.RentEncoderStack(&param);
  }

  void EncodeAndVerify(size_t expected_out_length,
                       uint32_t expected_timestamp,
                       int expected_payload_type,
                       int expected_send_even_if_empty) {
    rtc::Buffer out;
    AudioEncoder::EncodedInfo encoded_info;
    encoded_info =
        encoder_->Encode(timestamp_, kZeroData, &out);
    timestamp_ += kDataLengthSamples;
    EXPECT_TRUE(encoded_info.redundant.empty());
    EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
    EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
    if (expected_payload_type >= 0)
      EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
    if (expected_send_even_if_empty >= 0)
      EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty),
                encoded_info.send_even_if_empty);
  }

  RentACodec rent_a_codec_;
  std::unique_ptr<AudioEncoder> encoder_;
  uint32_t timestamp_ = 0;
};

// This test verifies that CNG frames are delivered as expected. Since the frame
// size is set to 20 ms, we expect the first encode call to produce no output
// (which is signaled as 0 bytes output of type kNoEncoding). The next encode
// call should produce one SID frame of 9 bytes. The third call should not
// result in any output (just like the first one). The fourth and final encode
// call should produce an "empty frame", which is like no output, but with
// AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to
// produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP
// module.)
TEST_F(RentACodecTestF, VerifyCngFrames) {
  CreateCodec();
  uint32_t expected_timestamp = timestamp_;
  // Verify no frame.
  {
    SCOPED_TRACE("First encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify SID frame delivered.
  {
    SCOPED_TRACE("Second encoding");
    EncodeAndVerify(9, expected_timestamp, kCngPt, 1);
  }

  // Verify no frame.
  {
    SCOPED_TRACE("Third encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify NoEncoding.
  expected_timestamp += 2 * kDataLengthSamples;
  {
    SCOPED_TRACE("Fourth encoding");
    EncodeAndVerify(0, expected_timestamp, kCngPt, 1);
  }
}

TEST(RentACodecTest, ExternalEncoder) {
  const int kSampleRateHz = 8000;
  auto* external_encoder = new MockAudioEncoder;
  EXPECT_CALL(*external_encoder, SampleRateHz())
      .WillRepeatedly(Return(kSampleRateHz));
  EXPECT_CALL(*external_encoder, NumChannels()).WillRepeatedly(Return(1));
  EXPECT_CALL(*external_encoder, SetFec(false)).WillRepeatedly(Return(true));

  RentACodec rac;
  RentACodec::StackParameters param;
  param.speech_encoder = std::unique_ptr<AudioEncoder>(external_encoder);
  std::unique_ptr<AudioEncoder> encoder_stack = rac.RentEncoderStack(&param);
  EXPECT_EQ(external_encoder, encoder_stack.get());
  const int kPacketSizeSamples = kSampleRateHz / 100;
  int16_t audio[kPacketSizeSamples] = {0};
  rtc::Buffer encoded;
  AudioEncoder::EncodedInfo info;

  Marker marker;
  {
    ::testing::InSequence s;
    info.encoded_timestamp = 0;
    EXPECT_CALL(
        *external_encoder,
        EncodeImpl(0, rtc::ArrayView<const int16_t>(audio), &encoded))
        .WillOnce(Return(info));
    EXPECT_CALL(marker, Mark("A"));
    EXPECT_CALL(marker, Mark("B"));
    EXPECT_CALL(*external_encoder, Die());
    EXPECT_CALL(marker, Mark("C"));
  }

  info = encoder_stack->Encode(0, audio, &encoded);
  EXPECT_EQ(0u, info.encoded_timestamp);
  marker.Mark("A");

  // Change to internal encoder.
  CodecInst codec_inst = kDefaultCodecInst;
  codec_inst.pacsize = kPacketSizeSamples;
  param.speech_encoder = rac.RentEncoder(codec_inst);
  ASSERT_TRUE(param.speech_encoder);
  AudioEncoder* enc = param.speech_encoder.get();
  std::unique_ptr<AudioEncoder> stack = rac.RentEncoderStack(&param);
  EXPECT_EQ(enc, stack.get());

  // Don't expect any more calls to the external encoder.
  info = stack->Encode(1, audio, &encoded);
  marker.Mark("B");
  encoder_stack.reset();
  marker.Mark("C");
}

// Verify that the speech encoder's Reset method is called when CNG or RED
// (or both) are switched on, but not when they're switched off.
void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) {
  auto make_enc = [] {
    auto speech_encoder =
        std::unique_ptr<MockAudioEncoder>(new MockAudioEncoder);
    EXPECT_CALL(*speech_encoder, NumChannels()).WillRepeatedly(Return(1));
    EXPECT_CALL(*speech_encoder, Max10MsFramesInAPacket())
        .WillRepeatedly(Return(2));
    EXPECT_CALL(*speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000));
    EXPECT_CALL(*speech_encoder, SetFec(false)).WillRepeatedly(Return(true));
    return speech_encoder;
  };
  auto speech_encoder1 = make_enc();
  auto speech_encoder2 = make_enc();
  Marker marker;
  {
    ::testing::InSequence s;
    EXPECT_CALL(marker, Mark("disabled"));
    EXPECT_CALL(*speech_encoder1, Die());
    EXPECT_CALL(marker, Mark("enabled"));
    if (use_cng || use_red)
      EXPECT_CALL(*speech_encoder2, Reset());
    EXPECT_CALL(*speech_encoder2, Die());
  }

  RentACodec::StackParameters param1, param2;
  param1.speech_encoder = std::move(speech_encoder1);
  param2.speech_encoder = std::move(speech_encoder2);
  param2.use_cng = use_cng;
  param2.use_red = use_red;
  marker.Mark("disabled");
  RentACodec rac;
  rac.RentEncoderStack(&param1);
  marker.Mark("enabled");
  rac.RentEncoderStack(&param2);
}

TEST(RentACodecTest, CngResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(true, false);
}

TEST(RentACodecTest, RedResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(false, true);
}

TEST(RentACodecTest, CngAndRedResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(true, true);
}

TEST(RentACodecTest, NoCngAndRedNoSpeechEncoderReset) {
  TestCngAndRedResetSpeechEncoder(false, false);
}

TEST(RentACodecTest, RentEncoderError) {
  const CodecInst codec_inst = {
      0, "Robert'); DROP TABLE Students;", 8000, 160, 1, 64000};
  RentACodec rent_a_codec;
  EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst));
}

TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) {
  RentACodec::StackParameters sp;
  EXPECT_EQ(nullptr, sp.speech_encoder);
  EXPECT_EQ(nullptr, RentACodec().RentEncoderStack(&sp));
}

}  // namespace acm2
}  // namespace webrtc
