/*
 *  Copyright (c) 2012 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/test/EncodeDecodeTest.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sstream>
#include <string>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
#include "webrtc/modules/audio_coding/main/test/utility.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/test/testsupport/fileutils.h"

namespace webrtc {

TestPacketization::TestPacketization(RTPStream *rtpStream,
                                     uint16_t frequency)
    : _rtpStream(rtpStream),
      _frequency(frequency),
      _seqNo(0) {
}

TestPacketization::~TestPacketization() { }

int32_t TestPacketization::SendData(
    const FrameType /* frameType */,
    const uint8_t payloadType,
    const uint32_t timeStamp,
    const uint8_t* payloadData,
    const uint16_t payloadSize,
    const RTPFragmentationHeader* /* fragmentation */) {
  _rtpStream->Write(payloadType, timeStamp, _seqNo++, payloadData, payloadSize,
                    _frequency);
  return 1;
}

Sender::Sender()
    : _acm(NULL),
      _pcmFile(),
      _audioFrame(),
      _packetization(NULL) {
}

void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
  acm->InitializeSender();
  struct CodecInst sendCodec;
  int noOfCodecs = acm->NumberOfCodecs();
  int codecNo;

  // Open input file
  const std::string file_name =
      webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
  _pcmFile.Open(file_name, 32000, "rb");

  // Set the codec for the current test.
  if ((testMode == 0) || (testMode == 1)) {
    // Set the codec id.
    codecNo = codeId;
  } else {
    // Choose codec on command line.
    printf("List of supported codec.\n");
    for (int n = 0; n < noOfCodecs; n++) {
      acm->Codec(n, &sendCodec);
      printf("%d %s\n", n, sendCodec.plname);
    }
    printf("Choose your codec:");
    ASSERT_GT(scanf("%d", &codecNo), 0);
  }

  acm->Codec(codecNo, &sendCodec);
  if (!strcmp(sendCodec.plname, "CELT")) {
    sendCodec.channels = 1;
  }
  acm->RegisterSendCodec(sendCodec);
  _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
  if (acm->RegisterTransportCallback(_packetization) < 0) {
    printf("Registering Transport Callback failed, for run: codecId: %d: --\n",
           codeId);
  }

  _acm = acm;
}

void Sender::Teardown() {
  _pcmFile.Close();
  delete _packetization;
}

bool Sender::Add10MsData() {
  if (!_pcmFile.EndOfFile()) {
    _pcmFile.Read10MsData(_audioFrame);
    int32_t ok = _acm->Add10MsData(_audioFrame);
    if (ok != 0) {
      printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
      exit(1);
    }
    return true;
  }
  return false;
}

bool Sender::Process() {
  int32_t ok = _acm->Process();
  if (ok < 0) {
    printf("Error calling Add10MsData: for run: codecId: %d\n", codeId);
    exit(1);
  }
  return true;
}

void Sender::Run() {
  while (true) {
    if (!Add10MsData()) {
      break;
    }
    if (!Process()) { // This could be done in a processing thread
      break;
    }
  }
}

Receiver::Receiver()
    : _playoutLengthSmpls(WEBRTC_10MS_PCM_AUDIO),
      _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
}

void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
  struct CodecInst recvCodec;
  int noOfCodecs;
  acm->InitializeReceiver();

  noOfCodecs = acm->NumberOfCodecs();
  for (int i = 0; i < noOfCodecs; i++) {
    acm->Codec((uint8_t) i, &recvCodec);
    if (acm->RegisterReceiveCodec(recvCodec) != 0) {
      printf("Unable to register codec: for run: codecId: %d\n", codeId);
      exit(1);
    }
  }

  int playSampFreq;
  std::string file_name;
  std::stringstream file_stream;
  file_stream << webrtc::test::OutputPath() << "encodeDecode_out" <<
      static_cast<int>(codeId) << ".pcm";
  file_name = file_stream.str();
  _rtpStream = rtpStream;

  if (testMode == 1) {
    playSampFreq=recvCodec.plfreq;
    _pcmFile.Open(file_name, recvCodec.plfreq, "wb+");
  } else if (testMode == 0) {
    playSampFreq=32000;
    _pcmFile.Open(file_name, 32000, "wb+");
  } else {
    printf("\nValid output frequencies:\n");
    printf("8000\n16000\n32000\n-1,");
    printf("which means output frequency equal to received signal frequency");
    printf("\n\nChoose output sampling frequency: ");
    ASSERT_GT(scanf("%d", &playSampFreq), 0);
    file_name =  webrtc::test::OutputPath() + "encodeDecode_out.pcm";
    _pcmFile.Open(file_name, playSampFreq, "wb+");
  }

  _realPayloadSizeBytes = 0;
  _playoutBuffer = new int16_t[WEBRTC_10MS_PCM_AUDIO];
  _frequency = playSampFreq;
  _acm = acm;
  _firstTime = true;
}

void Receiver::Teardown() {
  delete [] _playoutBuffer;
  _pcmFile.Close();
  if (testMode > 1)
    Trace::ReturnTrace();
}

bool Receiver::IncomingPacket() {
  if (!_rtpStream->EndOfFile()) {
    if (_firstTime) {
      _firstTime = false;
      _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
                                               _payloadSizeBytes, &_nextTime);
      if (_realPayloadSizeBytes == 0) {
        if (_rtpStream->EndOfFile()) {
          _firstTime = true;
          return true;
        } else {
          printf("Error in reading incoming payload.\n");
          return false;
        }
      }
   }

   int32_t ok = _acm->IncomingPacket(_incomingPayload,
                                           _realPayloadSizeBytes, _rtpInfo);
   if (ok != 0) {
     printf("Error when inserting packet to ACM, for run: codecId: %d\n",
            codeId);
   }
   _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
                                            _payloadSizeBytes, &_nextTime);
    if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
      _firstTime = true;
    }
  }
  return true;
}

bool Receiver::PlayoutData() {
  AudioFrame audioFrame;

  if (_acm->PlayoutData10Ms(_frequency, &audioFrame) != 0) {
    printf("Error when calling PlayoutData10Ms, for run: codecId: %d\n",
           codeId);
    exit(1);
  }
  if (_playoutLengthSmpls == 0) {
    return false;
  }
  _pcmFile.Write10MsData(audioFrame.data_,
                         audioFrame.samples_per_channel_);
  return true;
}

void Receiver::Run() {
  uint8_t counter500Ms = 50;
  uint32_t clock = 0;

  while (counter500Ms > 0) {
    if (clock == 0 || clock >= _nextTime) {
      IncomingPacket();
      if (clock == 0) {
        clock = _nextTime;
      }
    }
    if ((clock % 10) == 0) {
      if (!PlayoutData()) {
        clock++;
        continue;
      }
    }
    if (_rtpStream->EndOfFile()) {
      counter500Ms--;
    }
    clock++;
  }
}

EncodeDecodeTest::EncodeDecodeTest() {
  _testMode = 2;
  Trace::CreateTrace();
  Trace::SetTraceFile((webrtc::test::OutputPath() +
      "acm_encdec_trace.txt").c_str());
}

EncodeDecodeTest::EncodeDecodeTest(int testMode) {
  //testMode == 0 for autotest
  //testMode == 1 for testing all codecs/parameters
  //testMode > 1 for specific user-input test (as it was used before)
 _testMode = testMode;
 if(_testMode != 0) {
   Trace::CreateTrace();
   Trace::SetTraceFile((webrtc::test::OutputPath() +
       "acm_encdec_trace.txt").c_str());
 }
}

void EncodeDecodeTest::Perform() {
  if (_testMode == 0) {
    printf("Running Encode/Decode Test");
    WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
                 "---------- EncodeDecodeTest ----------");
  }

  int numCodecs = 1;
  int codePars[3]; // Frequency, packet size, rate.
  int numPars[52]; // Number of codec parameters sets (freq, pacsize, rate)
                   // to test, for a given codec.

  codePars[0] = 0;
  codePars[1] = 0;
  codePars[2] = 0;

  AudioCodingModule* acm = AudioCodingModule::Create(0);
  struct CodecInst sendCodecTmp;
  numCodecs = acm->NumberOfCodecs();

  if (_testMode == 1) {
    printf("List of supported codec.\n");
  }
  if (_testMode != 2) {
    for (int n = 0; n < numCodecs; n++) {
      acm->Codec(n, &sendCodecTmp);
      if (STR_CASE_CMP(sendCodecTmp.plname, "telephone-event") == 0) {
        numPars[n] = 0;
      } else if (STR_CASE_CMP(sendCodecTmp.plname, "cn") == 0) {
        numPars[n] = 0;
      } else if (STR_CASE_CMP(sendCodecTmp.plname, "red") == 0) {
        numPars[n] = 0;
      } else if (sendCodecTmp.channels == 2) {
        numPars[n] = 0;
      } else {
        numPars[n] = 1;
        if (_testMode == 1) {
          printf("%d %s\n", n, sendCodecTmp.plname);
        }
      }
    }
  } else {
    numCodecs = 1;
    numPars[0] = 1;
  }

  _receiver.testMode = _testMode;

  // Loop over all mono codecs:
  for (int codeId = 0; codeId < numCodecs; codeId++) {
    // Only encode using real mono encoders, not telephone-event and cng.
    for (int loopPars = 1; loopPars <= numPars[codeId]; loopPars++) {
      if (_testMode == 1) {
        printf("\n");
        printf("***FOR RUN: codeId: %d\n", codeId);
        printf("\n");
      } else if (_testMode == 0) {
        printf(".");
      }

      EncodeToFile(1, codeId, codePars, _testMode);

      RTPFile rtpFile;
      std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
      rtpFile.Open(fileName.c_str(), "rb");

      _receiver.codeId = codeId;

      rtpFile.ReadHeader();
      _receiver.Setup(acm, &rtpFile);
      _receiver.Run();
      _receiver.Teardown();
      rtpFile.Close();

      if (_testMode == 1) {
        printf("***COMPLETED RUN FOR: codecID: %d ***\n", codeId);
      }
    }
  }
  AudioCodingModule::Destroy(acm);
  if (_testMode == 0) {
    printf("Done!\n");
  }
  if (_testMode == 1)
    Trace::ReturnTrace();
}

void EncodeDecodeTest::EncodeToFile(int fileType, int codeId, int* codePars,
                                    int testMode) {
  AudioCodingModule* acm = AudioCodingModule::Create(1);
  RTPFile rtpFile;
  std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
  rtpFile.Open(fileName.c_str(), "wb+");
  rtpFile.WriteHeader();

  //for auto_test and logging
  _sender.testMode = testMode;
  _sender.codeId = codeId;

  _sender.Setup(acm, &rtpFile);
  struct CodecInst sendCodecInst;
  if (acm->SendCodec(&sendCodecInst) >= 0) {
    _sender.Run();
  }
  _sender.Teardown();
  rtpFile.Close();
  AudioCodingModule::Destroy(acm);
}

} // namespace webrtc
