/*
 * Copyright 2014 Google Inc. 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 "media/filters/shell_raw_audio_decoder_linux.h"

#include <memory.h>

#include <list>

#include "base/bind.h"
#include "base/logging.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/base/decoder_buffer_pool.h"
#include "media/filters/shell_ffmpeg.h"
#include "media/mp4/aac.h"

namespace media {

namespace {

const size_t kSampleSizeInBytes = sizeof(float);

struct QueuedAudioBuffer {
  //  AudioDecoder::Status status;  // status is used to represent decode errors
  scoped_refptr<DecoderBuffer> buffer;
};

bool IsEndOfStream(int result,
                   int decoded_size,
                   scoped_refptr<DecoderBuffer> buffer) {
  return result == 0 && decoded_size == 0 && buffer->IsEndOfStream();
}

void ResampleToInterleavedFloat(int source_sample_format,
                                int channel_layout,
                                int sample_rate,
                                int samples_per_channel,
                                uint8** input_buffer,
                                uint8* output_buffer) {
  AVAudioResampleContext* context = avresample_alloc_context();
  DCHECK(context);

  av_opt_set_int(context, "in_channel_layout", channel_layout, 0);
  av_opt_set_int(context, "out_channel_layout", channel_layout, 0);
  av_opt_set_int(context, "in_sample_rate", sample_rate, 0);
  av_opt_set_int(context, "out_sample_rate", sample_rate, 0);
  av_opt_set_int(context, "in_sample_fmt", source_sample_format, 0);
  av_opt_set_int(context, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
  av_opt_set_int(context, "internal_sample_fmt", source_sample_format, 0);

  int result = avresample_open(context);
  DCHECK(!result);

  int samples_resampled =
      avresample_convert(context, &output_buffer, 1024, samples_per_channel,
                         input_buffer, 0, samples_per_channel);
  DCHECK_EQ(samples_resampled, samples_per_channel);

  avresample_close(context);
  av_free(context);
}

class ShellRawAudioDecoderLinux : public ShellRawAudioDecoder {
 public:
  ShellRawAudioDecoderLinux();
  ~ShellRawAudioDecoderLinux() OVERRIDE;

  int GetBytesPerSample() const OVERRIDE { return kSampleSizeInBytes; }
  // When the input buffer is not NULL, it can be a normal buffer or an EOS
  // buffer. In this case the function will return the decoded buffer if there
  // is any.
  // The input buffer can be NULL, in this case the function will return a
  // queued buffer if there is any or return NULL if there is no queued buffer.
  void Decode(const scoped_refptr<DecoderBuffer>& buffer,
              const DecodeCB& decoder_cb) OVERRIDE;
  bool Flush() OVERRIDE;
  bool UpdateConfig(const AudioDecoderConfig& config) OVERRIDE;

 private:
  void ReleaseResource();
  void ResetTimestampState();
  void RunDecodeLoop(const scoped_refptr<DecoderBuffer>& input,
                     bool skip_eos_append);

  DecoderBufferPool decoder_buffer_pool_;

  AVCodecContext* codec_context_;
  AVFrame* av_frame_;

  // Decoded audio format.
  int bits_per_channel_;
  ChannelLayout channel_layout_;
  int samples_per_second_;

  // Used for computing output timestamps.
  scoped_ptr<AudioTimestampHelper> output_timestamp_helper_;
  int bytes_per_frame_;
  base::TimeDelta last_input_timestamp_;

  // Since multiple frames may be decoded from the same packet we need to
  // queue them up and hand them out as we receive Read() calls.
  std::list<QueuedAudioBuffer> queued_audio_;

  DISALLOW_COPY_AND_ASSIGN(ShellRawAudioDecoderLinux);
};

ShellRawAudioDecoderLinux::ShellRawAudioDecoderLinux()
    : decoder_buffer_pool_(GetBytesPerSample()),
      codec_context_(NULL),
      av_frame_(NULL),
      bits_per_channel_(0),
      channel_layout_(CHANNEL_LAYOUT_NONE),
      samples_per_second_(0),
      bytes_per_frame_(0),
      last_input_timestamp_(kNoTimestamp()) {
  EnsureFfmpegInitialized();
}

ShellRawAudioDecoderLinux::~ShellRawAudioDecoderLinux() {
  ReleaseResource();
}

void ShellRawAudioDecoderLinux::Decode(
    const scoped_refptr<DecoderBuffer>& buffer,
    const DecodeCB& decoder_cb) {
  if (buffer && !buffer->IsEndOfStream()) {
    if (last_input_timestamp_ == kNoTimestamp()) {
      last_input_timestamp_ = buffer->GetTimestamp();
    } else if (buffer->GetTimestamp() != kNoTimestamp()) {
      DCHECK_GE(buffer->GetTimestamp().ToInternalValue(),
                last_input_timestamp_.ToInternalValue());
      last_input_timestamp_ = buffer->GetTimestamp();
    }
  }

  if (buffer && queued_audio_.empty())
    RunDecodeLoop(buffer, false);

  if (queued_audio_.empty()) {
    decoder_cb.Run(NEED_MORE_DATA, NULL);
    return;
  }
  scoped_refptr<DecoderBuffer> result = queued_audio_.front().buffer;
  queued_audio_.pop_front();
  decoder_cb.Run(BUFFER_DECODED, result);
}

bool ShellRawAudioDecoderLinux::Flush() {
  avcodec_flush_buffers(codec_context_);
  ResetTimestampState();
  queued_audio_.clear();

  return true;
}

bool ShellRawAudioDecoderLinux::UpdateConfig(const AudioDecoderConfig& config) {
  if (!config.IsValidConfig()) {
    DLOG(ERROR) << "Invalid audio stream -"
                << " codec: " << config.codec()
                << " channel layout: " << config.channel_layout()
                << " bits per channel: " << config.bits_per_channel()
                << " samples per second: " << config.samples_per_second();
    return false;
  }

  if (codec_context_ && (bits_per_channel_ != config.bits_per_channel() ||
                         channel_layout_ != config.channel_layout() ||
                         samples_per_second_ != config.samples_per_second())) {
    DVLOG(1) << "Unsupported config change :";
    DVLOG(1) << "\tbits_per_channel : " << bits_per_channel_ << " -> "
             << config.bits_per_channel();
    DVLOG(1) << "\tchannel_layout : " << channel_layout_ << " -> "
             << config.channel_layout();
    DVLOG(1) << "\tsample_rate : " << samples_per_second_ << " -> "
             << config.samples_per_second();
    return false;
  }

  ReleaseResource();

  codec_context_ = avcodec_alloc_context3(NULL);
  DCHECK(codec_context_);
  codec_context_->codec_type = AVMEDIA_TYPE_AUDIO;
  codec_context_->codec_id = CODEC_ID_AAC;
  // request_sample_fmt is set by us, but sample_fmt is set by the decoder.
  codec_context_->request_sample_fmt = AV_SAMPLE_FMT_FLT;  // interleaved float

  codec_context_->channels =
      ChannelLayoutToChannelCount(config.channel_layout());
  codec_context_->sample_rate = config.samples_per_second();

  if (config.extra_data()) {
    codec_context_->extradata_size = config.extra_data_size();
    codec_context_->extradata = reinterpret_cast<uint8_t*>(
        av_malloc(config.extra_data_size() + FF_INPUT_BUFFER_PADDING_SIZE));
    memcpy(codec_context_->extradata, config.extra_data(),
           config.extra_data_size());
    memset(codec_context_->extradata + config.extra_data_size(), '\0',
           FF_INPUT_BUFFER_PADDING_SIZE);
  } else {
    codec_context_->extradata = NULL;
    codec_context_->extradata_size = 0;
  }

  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
  DCHECK(codec);

  int rv = avcodec_open2(codec_context_, codec, NULL);
  DCHECK_GE(rv, 0);
  if (rv < 0) {
    DLOG(ERROR) << "Unable to open codec, result = " << rv;
    return false;
  }

  // Ensure avcodec_open2() respected our format request.
  if (codec_context_->sample_fmt != codec_context_->request_sample_fmt) {
    DLOG(INFO) << "Unable to configure a supported sample format,"
               << " sample_fmt = " << codec_context_->sample_fmt
               << " instead of " << codec_context_->request_sample_fmt
               << ". Use libavresample to resample the decoded result to FLT";
    DLOG(INFO) << "Supported formats:";
    const AVSampleFormat* fmt;
    for (fmt = codec_context_->codec->sample_fmts; *fmt != -1; ++fmt) {
      DLOG(INFO) << "  " << *fmt << " (" << av_get_sample_fmt_name(*fmt) << ")";
    }
  }

  av_frame_ = avcodec_alloc_frame();
  DCHECK(av_frame_);

  bits_per_channel_ = config.bits_per_channel();
  channel_layout_ = config.channel_layout();
  samples_per_second_ = config.samples_per_second();
  output_timestamp_helper_.reset(new AudioTimestampHelper(
      kSampleSizeInBytes, config.samples_per_second()));

  ResetTimestampState();

  return true;
}

void ShellRawAudioDecoderLinux::ReleaseResource() {
  if (codec_context_) {
    av_free(codec_context_->extradata);
    avcodec_close(codec_context_);
    av_free(codec_context_);
    codec_context_ = NULL;
  }
  if (av_frame_) {
    av_free(av_frame_);
    av_frame_ = NULL;
  }
}

void ShellRawAudioDecoderLinux::ResetTimestampState() {
  output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
  last_input_timestamp_ = kNoTimestamp();
}

void ShellRawAudioDecoderLinux::RunDecodeLoop(
    const scoped_refptr<DecoderBuffer>& input,
    bool skip_eos_append) {
  AVPacket packet;
  av_init_packet(&packet);
  packet.data = input->GetWritableData();
  packet.size = input->GetDataSize();

  do {
    avcodec_get_frame_defaults(av_frame_);
    int frame_decoded = 0;
    int result = avcodec_decode_audio4(codec_context_, av_frame_,
                                       &frame_decoded, &packet);
    DCHECK_GE(result, 0);

    // Update packet size and data pointer in case we need to call the decoder
    // with the remaining bytes from this packet.
    packet.size -= result;
    packet.data += result;

    if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
        !input->IsEndOfStream()) {
      DCHECK_NE(input->GetTimestamp().ToInternalValue(),
                kNoTimestamp().ToInternalValue());
      output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp());
    }

    const uint8* decoded_audio_data = NULL;
    int decoded_audio_size = 0;
    if (frame_decoded) {
      decoded_audio_data = av_frame_->data[0];
      decoded_audio_size = av_samples_get_buffer_size(
          NULL, codec_context_->channels, av_frame_->nb_samples,
          codec_context_->sample_fmt, 1);
    }

    scoped_refptr<DecoderBuffer> output;

    if (decoded_audio_size > 0) {
      // Copy the audio samples into an output buffer.
      int buffer_size = kSampleSizeInBytes * mp4::AAC::kFramesPerAccessUnit *
                        codec_context_->channels;
      output = decoder_buffer_pool_.Allocate(buffer_size);
      DCHECK(output);
      // Interleave the planar samples to conform to the general decoder
      // requirement. This should eventually be lifted.
      ResampleToInterleavedFloat(
          codec_context_->sample_fmt, codec_context_->channel_layout,
          samples_per_second_, mp4::AAC::kFramesPerAccessUnit,
          av_frame_->extended_data,
          reinterpret_cast<uint8*>(output->GetWritableData()));
      output->SetTimestamp(output_timestamp_helper_->GetTimestamp());
      output->SetDuration(
          output_timestamp_helper_->GetDuration(decoded_audio_size));
      output_timestamp_helper_->AddBytes(decoded_audio_size /
                                         codec_context_->channels);
    } else if (IsEndOfStream(result, decoded_audio_size, input) &&
               !skip_eos_append) {
      DCHECK_EQ(packet.size, 0);
      // Create an end of stream output buffer.
      output = DecoderBuffer::CreateEOSBuffer(kNoTimestamp());
    }

    if (output) {
      QueuedAudioBuffer queue_entry = {output};
      queued_audio_.push_back(queue_entry);
    }

    // TODO: update statistics.
  } while (packet.size > 0);
}

}  // namespace

scoped_ptr<ShellRawAudioDecoder> CreateShellRawAudioDecoderLinux(
    const AudioDecoderConfig& config) {
  scoped_ptr<ShellRawAudioDecoder> decoder(new ShellRawAudioDecoderLinux);
  if (!decoder->UpdateConfig(config)) {
    decoder.reset();
  }
  return decoder.Pass();
}

}  // namespace media
