/*
 *  Copyright (c) 2014 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 "modules/audio_coding/acm2/acm_receive_test.h"

#include <stdio.h>

#include <memory>

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/environment/environment_factory.h"
#include "api/neteq/default_neteq_factory.h"
#include "modules/audio_coding/include/audio_coding_module.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/packet.h"
#include "modules/audio_coding/neteq/tools/packet_source.h"
#include "test/gtest.h"

namespace webrtc {
namespace test {

AcmReceiveTestOldApi::AcmReceiveTestOldApi(
    PacketSource* packet_source,
    AudioSink* audio_sink,
    int output_freq_hz,
    NumOutputChannels exptected_output_channels,
    rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
    : clock_(0),
      neteq_(DefaultNetEqFactory().Create(CreateEnvironment(&clock_),
                                          NetEq::Config(),
                                          std::move(decoder_factory))),
      packet_source_(packet_source),
      audio_sink_(audio_sink),
      output_freq_hz_(output_freq_hz),
      exptected_output_channels_(exptected_output_channels) {}

AcmReceiveTestOldApi::~AcmReceiveTestOldApi() = default;

void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
  neteq_->SetCodecs({{103, {"ISAC", 16000, 1}},
                     {104, {"ISAC", 32000, 1}},
                     {107, {"L16", 8000, 1}},
                     {108, {"L16", 16000, 1}},
                     {109, {"L16", 32000, 1}},
                     {111, {"L16", 8000, 2}},
                     {112, {"L16", 16000, 2}},
                     {113, {"L16", 32000, 2}},
                     {0, {"PCMU", 8000, 1}},
                     {110, {"PCMU", 8000, 2}},
                     {8, {"PCMA", 8000, 1}},
                     {118, {"PCMA", 8000, 2}},
                     {9, {"G722", 8000, 1}},
                     {119, {"G722", 8000, 2}},
                     {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}},
                     {13, {"CN", 8000, 1}},
                     {98, {"CN", 16000, 1}},
                     {99, {"CN", 32000, 1}}});
}

// Remaps payload types from ACM's default to those used in the resource file
// neteq_universal_new.rtp.
void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
  neteq_->SetCodecs({{103, {"ISAC", 16000, 1}},
                     {104, {"ISAC", 32000, 1}},
                     {93, {"L16", 8000, 1}},
                     {94, {"L16", 16000, 1}},
                     {95, {"L16", 32000, 1}},
                     {0, {"PCMU", 8000, 1}},
                     {8, {"PCMA", 8000, 1}},
                     {102, {"ILBC", 8000, 1}},
                     {9, {"G722", 8000, 1}},
                     {120, {"OPUS", 48000, 2}},
                     {13, {"CN", 8000, 1}},
                     {98, {"CN", 16000, 1}},
                     {99, {"CN", 32000, 1}}});
}

void AcmReceiveTestOldApi::Run() {
  for (std::unique_ptr<Packet> packet(packet_source_->NextPacket()); packet;
       packet = packet_source_->NextPacket()) {
    // Pull audio until time to insert packet.
    while (clock_.TimeInMilliseconds() < packet->time_ms()) {
      AudioFrame output_frame;
      bool muted;
      EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_frame, &muted));
      EXPECT_TRUE(
          resampler_helper_.MaybeResample(output_freq_hz_, &output_frame));
      ASSERT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
      ASSERT_FALSE(muted);
      const size_t samples_per_block =
          static_cast<size_t>(output_freq_hz_ * 10 / 1000);
      EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
      if (exptected_output_channels_ != kArbitraryChannels) {
        if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) {
          // Don't check number of channels for PLC output, since each test run
          // usually starts with a short period of mono PLC before decoding the
          // first packet.
        } else {
          EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_);
        }
      }
      ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
      clock_.AdvanceTimeMilliseconds(10);
      AfterGetAudio();
    }

    EXPECT_EQ(0, neteq_->InsertPacket(
                     packet->header(),
                     rtc::ArrayView<const uint8_t>(
                         packet->payload(), packet->payload_length_bytes()),
                     clock_.CurrentTime()))
        << "Failure when inserting packet:" << std::endl
        << "  PT = " << static_cast<int>(packet->header().payloadType)
        << std::endl
        << "  TS = " << packet->header().timestamp << std::endl
        << "  SN = " << packet->header().sequenceNumber;
  }
}

AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi(
    PacketSource* packet_source,
    AudioSink* audio_sink,
    int output_freq_hz_1,
    int output_freq_hz_2,
    int toggle_period_ms,
    NumOutputChannels exptected_output_channels)
    : AcmReceiveTestOldApi(packet_source,
                           audio_sink,
                           output_freq_hz_1,
                           exptected_output_channels,
                           CreateBuiltinAudioDecoderFactory()),
      output_freq_hz_1_(output_freq_hz_1),
      output_freq_hz_2_(output_freq_hz_2),
      toggle_period_ms_(toggle_period_ms),
      last_toggle_time_ms_(clock_.TimeInMilliseconds()) {}

void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() {
  if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) {
    output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_)
                          ? output_freq_hz_2_
                          : output_freq_hz_1_;
    last_toggle_time_ms_ = clock_.TimeInMilliseconds();
  }
}

}  // namespace test
}  // namespace webrtc
