// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/filters/decrypting_audio_decoder.h"

#include <cstdlib>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/bind_to_loop.h"
#include "media/base/buffers.h"
#include "media/base/data_buffer.h"
#include "media/base/decryptor.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
#include "media/base/decoder_buffer.h"

namespace media {

#define BIND_TO_LOOP(function) \
    media::BindToLoop(message_loop_, base::Bind(function, this))

static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1,
                               const base::TimeDelta& timestamp_2) {
  // Out of sync of 100ms would be pretty noticeable and we should keep any
  // drift below that.
  const int64 kOutOfSyncThresholdInMicroseconds = 100000;
  return std::abs(timestamp_1.InMicroseconds() - timestamp_2.InMicroseconds()) >
         kOutOfSyncThresholdInMicroseconds;
}

DecryptingAudioDecoder::DecryptingAudioDecoder(
    const scoped_refptr<base::MessageLoopProxy>& message_loop,
    const SetDecryptorReadyCB& set_decryptor_ready_cb)
    : message_loop_(message_loop),
      state_(kUninitialized),
      set_decryptor_ready_cb_(set_decryptor_ready_cb),
      decryptor_(NULL),
      key_added_while_decode_pending_(false),
      bits_per_channel_(0),
      channel_layout_(CHANNEL_LAYOUT_NONE),
      samples_per_second_(0),
      bytes_per_sample_(0),
      output_timestamp_base_(kNoTimestamp()),
      total_samples_decoded_(0) {
}

void DecryptingAudioDecoder::Initialize(
    const scoped_refptr<DemuxerStream>& stream,
    const PipelineStatusCB& status_cb,
    const StatisticsCB& statistics_cb) {
  if (!message_loop_->BelongsToCurrentThread()) {
    message_loop_->PostTask(FROM_HERE, base::Bind(
        &DecryptingAudioDecoder::DoInitialize, this,
        stream, status_cb, statistics_cb));
    return;
  }
  DoInitialize(stream, status_cb, statistics_cb);
}

void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
  // Complete operation asynchronously on different stack of execution as per
  // the API contract of AudioDecoder::Read()
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &DecryptingAudioDecoder::DoRead, this, read_cb));
}

void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
  if (!message_loop_->BelongsToCurrentThread()) {
    message_loop_->PostTask(FROM_HERE, base::Bind(
        &DecryptingAudioDecoder::Reset, this, closure));
    return;
  }

  DVLOG(2) << "Reset() - state: " << state_;
  DCHECK(state_ == kIdle ||
         state_ == kPendingConfigChange ||
         state_ == kPendingDemuxerRead ||
         state_ == kPendingDecode ||
         state_ == kWaitingForKey ||
         state_ == kDecodeFinished) << state_;
  DCHECK(init_cb_.is_null());  // No Reset() during pending initialization.
  DCHECK(reset_cb_.is_null());

  reset_cb_ = closure;

  decryptor_->ResetDecoder(Decryptor::kAudio);

  // Reset() cannot complete if the read callback is still pending.
  // Defer the resetting process in this case. The |reset_cb_| will be fired
  // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
  // DoDeliverFrame().
  if (state_ == kPendingConfigChange ||
      state_ == kPendingDemuxerRead ||
      state_ == kPendingDecode) {
    DCHECK(!read_cb_.is_null());
    return;
  }

  if (state_ == kWaitingForKey) {
    DCHECK(!read_cb_.is_null());
    pending_buffer_to_decode_ = NULL;
    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
  }

  DCHECK(read_cb_.is_null());
  DoReset();
}

int DecryptingAudioDecoder::bits_per_channel() {
  return bits_per_channel_;
}

ChannelLayout DecryptingAudioDecoder::channel_layout() {
  return channel_layout_;
}

int DecryptingAudioDecoder::samples_per_second() {
  return samples_per_second_;
}

DecryptingAudioDecoder::~DecryptingAudioDecoder() {
}

void DecryptingAudioDecoder::DoInitialize(
    const scoped_refptr<DemuxerStream>& stream,
    const PipelineStatusCB& status_cb,
    const StatisticsCB& statistics_cb) {
  DVLOG(2) << "DoInitialize()";
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kUninitialized) << state_;
  DCHECK(stream);

  const AudioDecoderConfig& config = stream->audio_decoder_config();
  if (!config.IsValidConfig()) {
    DLOG(ERROR) << "Invalid audio stream config.";
    status_cb.Run(PIPELINE_ERROR_DECODE);
    return;
  }

  // DecryptingAudioDecoder only accepts potentially encrypted stream.
  if (!config.is_encrypted()) {
    status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
    return;
  }

  DCHECK(!demuxer_stream_);
  demuxer_stream_ = stream;
  statistics_cb_ = statistics_cb;

  init_cb_ = status_cb;

  state_ = kDecryptorRequested;
  set_decryptor_ready_cb_.Run(
      BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor));
}

void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
  DVLOG(2) << "SetDecryptor()";
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kDecryptorRequested) << state_;
  DCHECK(!init_cb_.is_null());
  DCHECK(!set_decryptor_ready_cb_.is_null());

  set_decryptor_ready_cb_.Reset();

  if (!decryptor) {
    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
    // TODO(xhwang): Add kError state. See http://crbug.com/251503
    state_ = kDecodeFinished;
    return;
  }

  decryptor_ = decryptor;

  scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
  scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());

  state_ = kPendingDecoderInit;
  decryptor_->InitializeAudioDecoder(
      scoped_config.Pass(),
      BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization));
}

void DecryptingAudioDecoder::FinishInitialization(bool success) {
  DVLOG(2) << "FinishInitialization()";
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kPendingDecoderInit) << state_;
  DCHECK(!init_cb_.is_null());
  DCHECK(reset_cb_.is_null());  // No Reset() before initialization finished.
  DCHECK(read_cb_.is_null());  // No Read() before initialization finished.

  if (!success) {
    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
    state_ = kDecodeFinished;
    return;
  }

  // Success!
  const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
  bits_per_channel_ = config.bits_per_channel();
  channel_layout_ = config.channel_layout();
  samples_per_second_ = config.samples_per_second();
  const int kBitsPerByte = 8;
  bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) *
      bits_per_channel_ / kBitsPerByte;

  decryptor_->RegisterKeyAddedCB(
      Decryptor::kAudio, BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded));

  state_ = kIdle;
  base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
}

void DecryptingAudioDecoder::FinishConfigChange(bool success) {
  DVLOG(2) << "FinishConfigChange()";
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kPendingConfigChange) << state_;
  DCHECK(!read_cb_.is_null());

  if (!success) {
    base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
    state_ = kDecodeFinished;
    if (!reset_cb_.is_null())
      base::ResetAndReturn(&reset_cb_).Run();
    return;
  }

  // Config change succeeded.
  if (!reset_cb_.is_null()) {
    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
    DoReset();
    return;
  }

  state_ = kPendingDemuxerRead;
  ReadFromDemuxerStream();
}

void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) {
  DVLOG(3) << "DoRead()";
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
  DCHECK(!read_cb.is_null());
  CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";

  // Return empty (end-of-stream) frames if decoding has finished.
  if (state_ == kDecodeFinished) {
    read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
    return;
  }

  if (!queued_audio_frames_.empty()) {
    read_cb.Run(kOk, queued_audio_frames_.front());
    queued_audio_frames_.pop_front();
    return;
  }

  read_cb_ = read_cb;
  state_ = kPendingDemuxerRead;
  ReadFromDemuxerStream();
}

void DecryptingAudioDecoder::ReadFromDemuxerStream() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
  DCHECK(!read_cb_.is_null());

  demuxer_stream_->Read(
      base::Bind(&DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this));
}

void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer(
    DemuxerStream::Status status,
    const scoped_refptr<DecoderBuffer>& buffer) {
  if (!message_loop_->BelongsToCurrentThread()) {
    message_loop_->PostTask(FROM_HERE, base::Bind(
        &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this,
        status, buffer));
    return;
  }

  DVLOG(3) << "DoDecryptAndDecodeBuffer()";
  DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
  DCHECK(!read_cb_.is_null());
  DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;

  if (status == DemuxerStream::kConfigChanged) {
    DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";

    scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
    scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());

    state_ = kPendingConfigChange;
    decryptor_->DeinitializeDecoder(Decryptor::kAudio);
    decryptor_->InitializeAudioDecoder(
        scoped_config.Pass(), BindToCurrentLoop(base::Bind(
            &DecryptingAudioDecoder::FinishConfigChange, this)));
    return;
  }

  if (!reset_cb_.is_null()) {
    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
    DoReset();
    return;
  }

  if (status == DemuxerStream::kAborted) {
    DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
    state_ = kIdle;
    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
    return;
  }

  DCHECK_EQ(status, DemuxerStream::kOk);

  // Initialize the |next_output_timestamp_| to be the timestamp of the first
  // non-EOS buffer.
  if (output_timestamp_base_ == kNoTimestamp() && !buffer->IsEndOfStream()) {
    DCHECK_EQ(total_samples_decoded_, 0);
    output_timestamp_base_ = buffer->GetTimestamp();
  }

  pending_buffer_to_decode_ = buffer;
  state_ = kPendingDecode;
  DecodePendingBuffer();
}

void DecryptingAudioDecoder::DecodePendingBuffer() {
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kPendingDecode) << state_;
  decryptor_->DecryptAndDecodeAudio(
      pending_buffer_to_decode_,
      base::Bind(&DecryptingAudioDecoder::DeliverFrame, this,
                 pending_buffer_to_decode_->GetDataSize()));
}

void DecryptingAudioDecoder::DeliverFrame(
    int buffer_size,
    Decryptor::Status status,
    const Decryptor::AudioBuffers& frames) {
  // We need to force task post here because the AudioDecodeCB can be executed
  // synchronously in Reset(). Instead of using more complicated logic in
  // those function to fix it, why not force task post here to make everything
  // simple and clear?
  message_loop_->PostTask(FROM_HERE, base::Bind(
      &DecryptingAudioDecoder::DoDeliverFrame, this,
      buffer_size, status, frames));
}

void DecryptingAudioDecoder::DoDeliverFrame(
    int buffer_size,
    Decryptor::Status status,
    const Decryptor::AudioBuffers& frames) {
  DVLOG(3) << "DoDeliverFrame() - status: " << status;
  DCHECK(message_loop_->BelongsToCurrentThread());
  DCHECK_EQ(state_, kPendingDecode) << state_;
  DCHECK(!read_cb_.is_null());
  DCHECK(pending_buffer_to_decode_);
  DCHECK(queued_audio_frames_.empty());

  bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
  key_added_while_decode_pending_ = false;

  scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
      pending_buffer_to_decode_;

  pending_buffer_to_decode_ = NULL;

  if (!reset_cb_.is_null()) {
    base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
    DoReset();
    return;
  }

  DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());

  if (status == Decryptor::kError) {
    DVLOG(2) << "DoDeliverFrame() - kError";
    state_ = kDecodeFinished;
    base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
    return;
  }

  if (status == Decryptor::kNoKey) {
    DVLOG(2) << "DoDeliverFrame() - kNoKey";
    // Set |pending_buffer_to_decode_| back as we need to try decoding the
    // pending buffer again when new key is added to the decryptor.
    pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;

    if (need_to_try_again_if_nokey_is_returned) {
      // The |state_| is still kPendingDecode.
      DecodePendingBuffer();
      return;
    }

    state_ = kWaitingForKey;
    return;
  }

  // The buffer has been accepted by the decoder, let's report statistics.
  if (buffer_size) {
    PipelineStatistics statistics;
    statistics.audio_bytes_decoded = buffer_size;
    statistics_cb_.Run(statistics);
  }

  if (status == Decryptor::kNeedMoreData) {
    DVLOG(2) << "DoDeliverFrame() - kNeedMoreData";
    if (scoped_pending_buffer_to_decode->IsEndOfStream()) {
      state_ = kDecodeFinished;
      base::ResetAndReturn(&read_cb_).Run(
          kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
      return;
    }

    state_ = kPendingDemuxerRead;
    ReadFromDemuxerStream();
    return;
  }

  DCHECK_EQ(status, Decryptor::kSuccess);
  DCHECK(!frames.empty());
  EnqueueFrames(frames);

  state_ = kIdle;
  base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front());
  queued_audio_frames_.pop_front();
}

void DecryptingAudioDecoder::OnKeyAdded() {
  DCHECK(message_loop_->BelongsToCurrentThread());

  if (state_ == kPendingDecode) {
    key_added_while_decode_pending_ = true;
    return;
  }

  if (state_ == kWaitingForKey) {
    state_ = kPendingDecode;
    DecodePendingBuffer();
  }
}

void DecryptingAudioDecoder::DoReset() {
  DCHECK(init_cb_.is_null());
  DCHECK(read_cb_.is_null());
  output_timestamp_base_ = kNoTimestamp();
  total_samples_decoded_ = 0;
  state_ = kIdle;
  base::ResetAndReturn(&reset_cb_).Run();
}

void DecryptingAudioDecoder::EnqueueFrames(
    const Decryptor::AudioBuffers& frames) {
  queued_audio_frames_ = frames;

  for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
      iter != queued_audio_frames_.end();
      ++iter) {
    scoped_refptr<Buffer>& frame = *iter;

    DCHECK(!frame->IsEndOfStream()) << "EOS frame returned.";
    DCHECK_GT(frame->GetDataSize(), 0) << "Empty frame returned.";

    base::TimeDelta cur_timestamp = output_timestamp_base_ +
        NumberOfSamplesToDuration(total_samples_decoded_);
    if (IsOutOfSync(cur_timestamp, frame->GetTimestamp())) {
      DVLOG(1)  << "Timestamp returned by the decoder ("
                << frame->GetTimestamp().InMilliseconds() << " ms)"
                << " does not match the input timestamp and number of samples"
                << " decoded (" << cur_timestamp.InMilliseconds() << " ms).";
    }
    frame->SetTimestamp(cur_timestamp);

    int frame_size = frame->GetDataSize();
    DCHECK_EQ(frame_size % bytes_per_sample_, 0) <<
        "Decoder didn't output full samples";
    int samples_decoded = frame_size / bytes_per_sample_;
    total_samples_decoded_ += samples_decoded;

    base::TimeDelta next_timestamp = output_timestamp_base_ +
        NumberOfSamplesToDuration(total_samples_decoded_);
    base::TimeDelta duration = next_timestamp - cur_timestamp;
    frame->SetDuration(duration);
  }
}

base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration(
    int number_of_samples) const {
  DCHECK(samples_per_second_);
  return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
                                           number_of_samples /
                                           samples_per_second_);
}

}  // namespace media
