/*
 *  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 "webrtc/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h"

#include <assert.h>
#include <stdio.h>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/main/include/audio_coding_module.h"
#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h"

namespace webrtc {
namespace test {

namespace {
// Returns true if the codec should be registered, otherwise false. Changes
// the number of channels for the Opus codec to always be 1.
bool ModifyAndUseThisCodec(CodecInst* codec_param) {
  if (STR_CASE_CMP(codec_param->plname, "CN") == 0 &&
      codec_param->plfreq == 48000)
    return false;  // Skip 48 kHz comfort noise.

  if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0)
    return false;  // Skip DTFM.

  return true;
}

// Remaps payload types from ACM's default to those used in the resource file
// neteq_universal_new.rtp. Returns true if the codec should be registered,
// otherwise false. The payload types are set as follows (all are mono codecs):
// PCMu = 0;
// PCMa = 8;
// Comfort noise 8 kHz = 13
// Comfort noise 16 kHz = 98
// Comfort noise 32 kHz = 99
// iLBC = 102
// iSAC wideband = 103
// iSAC super-wideband = 104
// AVT/DTMF = 106
// RED = 117
// PCM16b 8 kHz = 93
// PCM16b 16 kHz = 94
// PCM16b 32 kHz = 95
// G.722 = 94
bool RemapPltypeAndUseThisCodec(const char* plname,
                                int plfreq,
                                int channels,
                                int* pltype) {
  if (channels != 1)
    return false;  // Don't use non-mono codecs.

  // Re-map pltypes to those used in the NetEq test files.
  if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) {
    *pltype = 0;
  } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) {
    *pltype = 8;
  } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) {
    *pltype = 13;
  } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) {
    *pltype = 98;
  } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) {
    *pltype = 99;
  } else if (STR_CASE_CMP(plname, "ILBC") == 0) {
    *pltype = 102;
  } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) {
    *pltype = 103;
  } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) {
    *pltype = 104;
  } else if (STR_CASE_CMP(plname, "telephone-event") == 0) {
    *pltype = 106;
  } else if (STR_CASE_CMP(plname, "red") == 0) {
    *pltype = 117;
  } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) {
    *pltype = 93;
  } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) {
    *pltype = 94;
  } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) {
    *pltype = 95;
  } else if (STR_CASE_CMP(plname, "G722") == 0) {
    *pltype = 9;
  } else {
    // Don't use any other codecs.
    return false;
  }
  return true;
}
}  // namespace

AcmReceiveTestOldApi::AcmReceiveTestOldApi(
    PacketSource* packet_source,
    AudioSink* audio_sink,
    int output_freq_hz,
    NumOutputChannels exptected_output_channels)
    : clock_(0),
      acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
      packet_source_(packet_source),
      audio_sink_(audio_sink),
      output_freq_hz_(output_freq_hz),
      exptected_output_channels_(exptected_output_channels) {
}

void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
  CodecInst my_codec_param;
  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    if (ModifyAndUseThisCodec(&my_codec_param)) {
      ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
          << "Couldn't register receive codec.\n";
    }
  }
}

void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
  CodecInst my_codec_param;
  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    if (!ModifyAndUseThisCodec(&my_codec_param)) {
      // Skip this codec.
      continue;
    }

    if (RemapPltypeAndUseThisCodec(my_codec_param.plname,
                                   my_codec_param.plfreq,
                                   my_codec_param.channels,
                                   &my_codec_param.pltype)) {
      ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
          << "Couldn't register receive codec.\n";
    }
  }
}

int AcmReceiveTestOldApi::RegisterExternalReceiveCodec(
    int rtp_payload_type,
    AudioDecoder* external_decoder,
    int sample_rate_hz,
    int num_channels) {
  return acm_->RegisterExternalReceiveCodec(rtp_payload_type, external_decoder,
                                            sample_rate_hz, num_channels);
}

void AcmReceiveTestOldApi::Run() {
  for (rtc::scoped_ptr<Packet> packet(packet_source_->NextPacket()); packet;
       packet.reset(packet_source_->NextPacket())) {
    // Pull audio until time to insert packet.
    while (clock_.TimeInMilliseconds() < packet->time_ms()) {
      AudioFrame output_frame;
      EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame));
      EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
      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();
    }

    // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
    WebRtcRTPHeader header;
    header.header = packet->header();
    header.frameType = kAudioFrameSpeech;
    memset(&header.type.Audio, 0, sizeof(RTPAudioHeader));
    EXPECT_EQ(0,
              acm_->IncomingPacket(
                  packet->payload(),
                  static_cast<int32_t>(packet->payload_length_bytes()),
                  header))
        << "Failure when inserting packet:" << std::endl
        << "  PT = " << static_cast<int>(header.header.payloadType) << std::endl
        << "  TS = " << header.header.timestamp << std::endl
        << "  SN = " << header.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),
      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
