// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/opus/opus_audio_decoder.h"

#include "starboard/common/format_string.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/media/media_util.h"

namespace starboard {
namespace shared {
namespace opus {

namespace {

typedef struct {
  int nb_streams;
  int nb_coupled_streams;
  unsigned char mapping[8];
} VorbisLayout;

/* Index is nb_channel-1 */
static const VorbisLayout vorbis_mappings[8] = {
    {1, 0, {0}},                      /* 1: mono */
    {1, 1, {0, 1}},                   /* 2: stereo */
    {2, 1, {0, 2, 1}},                /* 3: 1-d surround */
    {2, 2, {0, 1, 2, 3}},             /* 4: quadraphonic surround */
    {3, 2, {0, 4, 1, 2, 3}},          /* 5: 5-channel surround */
    {4, 2, {0, 4, 1, 2, 3, 5}},       /* 6: 5.1 surround */
    {4, 3, {0, 4, 1, 2, 3, 5, 6}},    /* 7: 6.1 surround */
    {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
};

}  // namespace

OpusAudioDecoder::OpusAudioDecoder(
    const SbMediaAudioSampleInfo& audio_sample_info)
    : audio_sample_info_(audio_sample_info) {
  int error;
  int channels = audio_sample_info_.number_of_channels;
  if (channels > 8 || channels < 1) {
    SB_LOG(ERROR) << "Can't create decoder with " << channels << " channels";
    return;
  }

  decoder_ = opus_multistream_decoder_create(
      audio_sample_info_.samples_per_second, channels,
      vorbis_mappings[channels - 1].nb_streams,
      vorbis_mappings[channels - 1].nb_coupled_streams,
      vorbis_mappings[channels - 1].mapping, &error);
  if (error != OPUS_OK) {
    SB_LOG(ERROR) << "Failed to create decoder with error: "
                  << opus_strerror(error);
    decoder_ = NULL;
    return;
  }
  SB_DCHECK(decoder_ != NULL);
}

OpusAudioDecoder::~OpusAudioDecoder() {
  if (decoder_) {
    opus_multistream_decoder_destroy(decoder_);
  }
}

void OpusAudioDecoder::Initialize(const OutputCB& output_cb,
                                  const ErrorCB& error_cb) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(output_cb);
  SB_DCHECK(!output_cb_);
  SB_DCHECK(error_cb);
  SB_DCHECK(!error_cb_);

  output_cb_ = output_cb;
  error_cb_ = error_cb;
}

void OpusAudioDecoder::Decode(const scoped_refptr<InputBuffer>& input_buffer,
                              const ConsumedCB& consumed_cb) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(input_buffer);
  SB_DCHECK(output_cb_);

  if (stream_ended_) {
    SB_LOG(ERROR) << "Decode() is called after WriteEndOfStream() is called.";
    return;
  }

  scoped_refptr<DecodedAudio> decoded_audio = new DecodedAudio(
      audio_sample_info_.number_of_channels, GetSampleType(),
      kSbMediaAudioFrameStorageTypeInterleaved, input_buffer->timestamp(),
      audio_sample_info_.number_of_channels * frames_per_au_ *
          starboard::media::GetBytesPerSample(GetSampleType()));

#if SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
  const char kDecodeFunctionName[] = "opus_multistream_decode";
  int decoded_frames = opus_multistream_decode(
      decoder_, static_cast<const unsigned char*>(input_buffer->data()),
      input_buffer->size(),
      reinterpret_cast<opus_int16*>(decoded_audio->buffer()), frames_per_au_,
      0);
#else   // SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
  const char kDecodeFunctionName[] = "opus_multistream_decode_float";
  int decoded_frames = opus_multistream_decode_float(
      decoder_, static_cast<const unsigned char*>(input_buffer->data()),
      input_buffer->size(), reinterpret_cast<float*>(decoded_audio->buffer()),
      frames_per_au_, 0);
#endif  // SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
  if (decoded_frames == OPUS_BUFFER_TOO_SMALL &&
      frames_per_au_ < kMaxOpusFramesPerAU) {
    frames_per_au_ = kMaxOpusFramesPerAU;
    // Send to decode again with the new |frames_per_au_|.
    Decode(input_buffer, consumed_cb);
    return;
  }
  if (decoded_frames <= 0) {
    // When the following check fails, it indicates that |frames_per_au_| is
    // greater than or equal to |kMaxOpusFramesPerAU|, which should never happen
    // for Opus.
    SB_DCHECK(decoded_frames != OPUS_BUFFER_TOO_SMALL);

    // TODO: Consider fill it with silence.
    SB_LOG(ERROR) << kDecodeFunctionName
                  << "() failed with error code: " << decoded_frames;
    error_cb_(kSbPlayerErrorDecode,
              FormatString("%s() failed with error code: %d",
                           kDecodeFunctionName, decoded_frames));
    return;
  }

  frames_per_au_ = decoded_frames;
  decoded_audio->ShrinkTo(audio_sample_info_.number_of_channels *
                          frames_per_au_ *
                          starboard::media::GetBytesPerSample(GetSampleType()));

  decoded_audios_.push(decoded_audio);
  Schedule(consumed_cb);
  Schedule(output_cb_);
}

void OpusAudioDecoder::WriteEndOfStream() {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(output_cb_);

  // Opus has no dependent frames so we needn't flush the decoder.  Set the
  // flag to ensure that Decode() is not called when the stream is ended.
  stream_ended_ = true;
  // Put EOS into the queue.
  decoded_audios_.push(new DecodedAudio);

  Schedule(output_cb_);
}

scoped_refptr<OpusAudioDecoder::DecodedAudio> OpusAudioDecoder::Read(
    int* samples_per_second) {
  SB_DCHECK(BelongsToCurrentThread());
  SB_DCHECK(output_cb_);
  SB_DCHECK(!decoded_audios_.empty());

  scoped_refptr<DecodedAudio> result;
  if (!decoded_audios_.empty()) {
    result = decoded_audios_.front();
    decoded_audios_.pop();
  }
  *samples_per_second = audio_sample_info_.samples_per_second;
  return result;
}

void OpusAudioDecoder::Reset() {
  SB_DCHECK(BelongsToCurrentThread());

  stream_ended_ = false;
  while (!decoded_audios_.empty()) {
    decoded_audios_.pop();
  }

  CancelPendingJobs();
}

bool OpusAudioDecoder::is_valid() const {
  return decoder_ != NULL;
}

SbMediaAudioSampleType OpusAudioDecoder::GetSampleType() const {
  SB_DCHECK(BelongsToCurrentThread());
#if SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
  return kSbMediaAudioSampleTypeInt16;
#else   // SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
  return kSbMediaAudioSampleTypeFloat32;
#endif  // SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
}

}  // namespace opus
}  // namespace shared
}  // namespace starboard
