// 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/audio_renderer_impl.h"

#include <math.h>

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "media/audio/audio_util.h"
#include "media/base/audio_splicer.h"
#include "media/base/bind_to_loop.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_switches.h"
#include "media/filters/audio_decoder_selector.h"
#include "media/filters/decrypting_demuxer_stream.h"

namespace media {

AudioRendererImpl::AudioRendererImpl(
    media::AudioRendererSink* sink,
    const SetDecryptorReadyCB& set_decryptor_ready_cb)
    : sink_(sink),
      set_decryptor_ready_cb_(set_decryptor_ready_cb),
      state_(kUninitialized),
      pending_read_(false),
      received_end_of_stream_(false),
      rendered_end_of_stream_(false),
      audio_time_buffered_(kNoTimestamp()),
      current_time_(kNoTimestamp()),
      underflow_disabled_(false),
      preroll_aborted_(false),
      actual_frames_per_buffer_(0) {
  // We're created on the render thread, but this thread checker is for another.
  pipeline_thread_checker_.DetachFromThread();
}

void AudioRendererImpl::Play(const base::Closure& callback) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());

  float playback_rate = 0;
  {
    base::AutoLock auto_lock(lock_);
    DCHECK_EQ(kPaused, state_);
    state_ = kPlaying;
    callback.Run();
    playback_rate = algorithm_->playback_rate();
  }

  if (playback_rate != 0.0f) {
    DoPlay();
  } else {
    DoPause();
  }
}

void AudioRendererImpl::DoPlay() {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(sink_);
  {
    base::AutoLock auto_lock(lock_);
    earliest_end_time_ = base::Time::Now();
  }
  sink_->Play();
}

void AudioRendererImpl::Pause(const base::Closure& callback) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());

  {
    base::AutoLock auto_lock(lock_);
    DCHECK(state_ == kPlaying || state_ == kUnderflow ||
           state_ == kRebuffering);
    pause_cb_ = callback;
    state_ = kPaused;

    // Pause only when we've completed our pending read.
    if (!pending_read_)
      base::ResetAndReturn(&pause_cb_).Run();
  }

  DoPause();
}

void AudioRendererImpl::DoPause() {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(sink_);
  sink_->Pause(false);
}

void AudioRendererImpl::Flush(const base::Closure& callback) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());

  if (decrypting_demuxer_stream_) {
    decrypting_demuxer_stream_->Reset(base::Bind(
        &AudioRendererImpl::ResetDecoder, this, callback));
    return;
  }

  decoder_->Reset(callback);
}

void AudioRendererImpl::ResetDecoder(const base::Closure& callback) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  decoder_->Reset(callback);
}

void AudioRendererImpl::Stop(const base::Closure& callback) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(!callback.is_null());

  if (sink_) {
    sink_->Stop();
    sink_ = NULL;
  }

  {
    base::AutoLock auto_lock(lock_);
    state_ = kStopped;
    algorithm_.reset(NULL);
    init_cb_.Reset();
    underflow_cb_.Reset();
    time_cb_.Reset();
  }

  callback.Run();
}

void AudioRendererImpl::Preroll(base::TimeDelta time,
                                const PipelineStatusCB& cb) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(sink_);

  {
    base::AutoLock auto_lock(lock_);
    DCHECK_EQ(kPaused, state_);
    DCHECK(!pending_read_) << "Pending read must complete before seeking";
    DCHECK(pause_cb_.is_null());
    DCHECK(preroll_cb_.is_null());
    state_ = kPrerolling;
    preroll_cb_ = cb;
    preroll_timestamp_ = time;

    // Throw away everything and schedule our reads.
    audio_time_buffered_ = kNoTimestamp();
    current_time_ = kNoTimestamp();
    received_end_of_stream_ = false;
    rendered_end_of_stream_ = false;
    preroll_aborted_ = false;

    splicer_->Reset();

    // |algorithm_| will request more reads.
    algorithm_->FlushBuffers();
    earliest_end_time_ = base::Time::Now();
  }

  // Pause and flush the stream when we preroll to a new location.
  sink_->Pause(true);
}

void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream,
                                   const AudioDecoderList& decoders,
                                   const PipelineStatusCB& init_cb,
                                   const StatisticsCB& statistics_cb,
                                   const base::Closure& underflow_cb,
                                   const TimeCB& time_cb,
                                   const base::Closure& ended_cb,
                                   const base::Closure& disabled_cb,
                                   const PipelineStatusCB& error_cb) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(stream);
  DCHECK(!decoders.empty());
  DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
  DCHECK(!init_cb.is_null());
  DCHECK(!statistics_cb.is_null());
  DCHECK(!underflow_cb.is_null());
  DCHECK(!time_cb.is_null());
  DCHECK(!ended_cb.is_null());
  DCHECK(!disabled_cb.is_null());
  DCHECK(!error_cb.is_null());
  DCHECK_EQ(kUninitialized, state_);
  DCHECK(sink_);

  init_cb_ = init_cb;
  statistics_cb_ = statistics_cb;
  underflow_cb_ = underflow_cb;
  time_cb_ = time_cb;
  ended_cb_ = ended_cb;
  disabled_cb_ = disabled_cb;
  error_cb_ = error_cb;

  scoped_ptr<AudioDecoderSelector> decoder_selector(
      new AudioDecoderSelector(base::MessageLoopProxy::current(),
                               decoders,
                               set_decryptor_ready_cb_));

  // To avoid calling |decoder_selector| methods and passing ownership of
  // |decoder_selector| in the same line.
  AudioDecoderSelector* decoder_selector_ptr = decoder_selector.get();

  decoder_selector_ptr->SelectAudioDecoder(
      stream,
      statistics_cb,
      base::Bind(&AudioRendererImpl::OnDecoderSelected, this,
                 base::Passed(&decoder_selector)));
}

void AudioRendererImpl::OnDecoderSelected(
    scoped_ptr<AudioDecoderSelector> decoder_selector,
    const scoped_refptr<AudioDecoder>& selected_decoder,
    const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());

  if (state_ == kStopped) {
    DCHECK(!sink_);
    return;
  }

  if (!selected_decoder) {
    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
    return;
  }

  decoder_ = selected_decoder;
  decrypting_demuxer_stream_ = decrypting_demuxer_stream;

  int sample_rate = decoder_->samples_per_second();
  int buffer_size = GetHighLatencyOutputBufferSize(sample_rate);
  AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR;

  // On Windows and Mac we can use the low latency pipeline because they provide
  // accurate and smooth delay information.  On other platforms like Linux there
  // are jitter issues.
  // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757
#if defined(OS_WIN) || defined(OS_MACOSX)
  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
  // Either AudioOutputResampler or renderer side mixing must be enabled to use
  // the low latency pipeline.
  if (!cmd_line->HasSwitch(switches::kDisableRendererSideMixing) ||
      !cmd_line->HasSwitch(switches::kDisableAudioOutputResampler)) {
    // There are two cases here:
    //
    // 1. Renderer side mixing is enabled and the buffer size is actually
    //    controlled by the size of the AudioBus provided to Render().  In this
    //    case the buffer size below is ignored.
    //
    // 2. Renderer side mixing is disabled and AudioOutputResampler on the
    //    browser side is rebuffering to the hardware size on the fly.
    //
    // In the second case we need to choose a a buffer size small enough that
    // the decoder can fulfill the high frequency low latency audio callbacks,
    // but not so small that it's less than the hardware buffer size (or we'll
    // run into issues since the shared memory sync is non-blocking).
    //
    // The buffer size below is arbitrarily the same size used by Pepper Flash
    // for consistency.  Since renderer side mixing is only disabled for debug
    // purposes it's okay that this buffer size might lead to jitter since it's
    // not a multiple of the hardware buffer size.
    format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
    buffer_size = 2048;
  }
#endif

  audio_parameters_ = AudioParameters(
      format, decoder_->channel_layout(), sample_rate,
      decoder_->bits_per_channel(), buffer_size);
  if (!audio_parameters_.IsValid()) {
    base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
    return;
  }

  int channels = ChannelLayoutToChannelCount(decoder_->channel_layout());
  int bytes_per_frame = channels * decoder_->bits_per_channel() / 8;
  splicer_.reset(new AudioSplicer(bytes_per_frame, sample_rate));

  // We're all good! Continue initializing the rest of the audio renderer based
  // on the decoder format.
  algorithm_.reset(new AudioRendererAlgorithm());
  algorithm_->Initialize(0, audio_parameters_, base::Bind(
      &AudioRendererImpl::ScheduleRead_Locked, this));

  state_ = kPaused;

  sink_->Initialize(audio_parameters_, this);
  sink_->Start();

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

void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  base::AutoLock auto_lock(lock_);
  if (state_ == kUnderflow) {
    // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we
    // shouldn't even reach the kUnderflow state to begin with. But for now
    // we're just making sure that the audio buffer capacity (i.e. the
    // number of bytes that need to be buffered for preroll to complete)
    // does not increase due to an aborted preroll.
    // TODO(vrk): Fix this bug correctly! (crbug.com/151352)
    if (buffer_more_audio && !preroll_aborted_)
      algorithm_->IncreaseQueueCapacity();

    state_ = kRebuffering;
  }
}

void AudioRendererImpl::SetVolume(float volume) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK(sink_);
  sink_->SetVolume(volume);
}

AudioRendererImpl::~AudioRendererImpl() {
  // Stop() should have been called and |algorithm_| should have been destroyed.
  DCHECK(state_ == kUninitialized || state_ == kStopped);
  DCHECK(!algorithm_.get());
}

void AudioRendererImpl::DecodedAudioReady(AudioDecoder::Status status,
                                          const scoped_refptr<Buffer>& buffer) {
  base::AutoLock auto_lock(lock_);
  DCHECK(state_ == kPaused || state_ == kPrerolling || state_ == kPlaying ||
         state_ == kUnderflow || state_ == kRebuffering || state_ == kStopped);

  CHECK(pending_read_);
  pending_read_ = false;

  if (status == AudioDecoder::kAborted) {
    HandleAbortedReadOrDecodeError(false);
    return;
  }

  if (status == AudioDecoder::kDecodeError) {
    HandleAbortedReadOrDecodeError(true);
    return;
  }

  DCHECK_EQ(status, AudioDecoder::kOk);
  DCHECK(buffer);

  if (!splicer_->AddInput(buffer)) {
    HandleAbortedReadOrDecodeError(true);
    return;
  }

  if (!splicer_->HasNextBuffer()) {
    ScheduleRead_Locked();
    return;
  }

  bool need_another_buffer = false;
  while (splicer_->HasNextBuffer())
    need_another_buffer = HandleSplicerBuffer(splicer_->GetNextBuffer());

  if (!need_another_buffer)
    return;

  ScheduleRead_Locked();
}

bool AudioRendererImpl::HandleSplicerBuffer(
    const scoped_refptr<Buffer>& buffer) {
  if (buffer->IsEndOfStream()) {
    received_end_of_stream_ = true;

    // Transition to kPlaying if we are currently handling an underflow since
    // no more data will be arriving.
    if (state_ == kUnderflow || state_ == kRebuffering)
      state_ = kPlaying;
  }

  switch (state_) {
    case kUninitialized:
      NOTREACHED();
      return false;
    case kPaused:
      if (!buffer->IsEndOfStream())
        algorithm_->EnqueueBuffer(buffer);
      DCHECK(!pending_read_);
      base::ResetAndReturn(&pause_cb_).Run();
      return false;
    case kPrerolling:
      if (IsBeforePrerollTime(buffer))
        return true;

      if (!buffer->IsEndOfStream()) {
        algorithm_->EnqueueBuffer(buffer);
        if (!algorithm_->IsQueueFull())
          return false;
      }
      state_ = kPaused;
      base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
      return false;
    case kPlaying:
    case kUnderflow:
    case kRebuffering:
      if (!buffer->IsEndOfStream())
        algorithm_->EnqueueBuffer(buffer);
      return false;
    case kStopped:
      return false;
  }
  return false;
}

void AudioRendererImpl::ScheduleRead_Locked() {
  lock_.AssertAcquired();
  if (pending_read_ || state_ == kPaused)
    return;
  pending_read_ = true;
  decoder_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, this));
}

void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
  DCHECK(pipeline_thread_checker_.CalledOnValidThread());
  DCHECK_LE(0.0f, playback_rate);
  DCHECK(sink_);

  // We have two cases here:
  // Play: current_playback_rate == 0.0 && playback_rate != 0.0
  // Pause: current_playback_rate != 0.0 && playback_rate == 0.0
  float current_playback_rate = algorithm_->playback_rate();
  if (current_playback_rate == 0.0f && playback_rate != 0.0f) {
    DoPlay();
  } else if (current_playback_rate != 0.0f && playback_rate == 0.0f) {
    // Pause is easy, we can always pause.
    DoPause();
  }

  base::AutoLock auto_lock(lock_);
  algorithm_->SetPlaybackRate(playback_rate);
}

bool AudioRendererImpl::IsBeforePrerollTime(
    const scoped_refptr<Buffer>& buffer) {
  return (state_ == kPrerolling) && buffer && !buffer->IsEndOfStream() &&
      (buffer->GetTimestamp() + buffer->GetDuration()) < preroll_timestamp_;
}

int AudioRendererImpl::Render(AudioBus* audio_bus,
                              int audio_delay_milliseconds) {
  if (actual_frames_per_buffer_ != audio_bus->frames()) {
    audio_buffer_.reset(
        new uint8[audio_bus->frames() * audio_parameters_.GetBytesPerFrame()]);
    actual_frames_per_buffer_ = audio_bus->frames();
  }

  int frames_filled = FillBuffer(
      audio_buffer_.get(), audio_bus->frames(), audio_delay_milliseconds);
  DCHECK_LE(frames_filled, actual_frames_per_buffer_);

  // Deinterleave audio data into the output bus.
  audio_bus->FromInterleaved(
      audio_buffer_.get(), frames_filled,
      audio_parameters_.bits_per_sample() / 8);

  return frames_filled;
}

uint32 AudioRendererImpl::FillBuffer(uint8* dest,
                                     uint32 requested_frames,
                                     int audio_delay_milliseconds) {
  base::TimeDelta current_time = kNoTimestamp();
  base::TimeDelta max_time = kNoTimestamp();

  size_t frames_written = 0;
  base::Closure underflow_cb;
  {
    base::AutoLock auto_lock(lock_);

    // Ensure Stop() hasn't destroyed our |algorithm_| on the pipeline thread.
    if (!algorithm_)
      return 0;

    float playback_rate = algorithm_->playback_rate();
    if (playback_rate == 0.0f)
      return 0;

    // Adjust the delay according to playback rate.
    base::TimeDelta playback_delay =
        base::TimeDelta::FromMilliseconds(audio_delay_milliseconds);
    if (playback_rate != 1.0f) {
      playback_delay = base::TimeDelta::FromMicroseconds(static_cast<int64>(
          ceil(playback_delay.InMicroseconds() * playback_rate)));
    }

    if (state_ == kRebuffering && algorithm_->IsQueueFull())
      state_ = kPlaying;

    // Mute audio by returning 0 when not playing.
    if (state_ != kPlaying) {
      // TODO(scherkus): To keep the audio hardware busy we write at most 8k of
      // zeros.  This gets around the tricky situation of pausing and resuming
      // the audio IPC layer in Chrome.  Ideally, we should return zero and then
      // the subclass can restart the conversation.
      //
      // This should get handled by the subclass http://crbug.com/106600
      const uint32 kZeroLength = 8192;
      size_t zeros_to_write = std::min(
          kZeroLength, requested_frames * audio_parameters_.GetBytesPerFrame());
      memset(dest, 0, zeros_to_write);
      return zeros_to_write / audio_parameters_.GetBytesPerFrame();
    }

    // We use the following conditions to determine end of playback:
    //   1) Algorithm can not fill the audio callback buffer
    //   2) We received an end of stream buffer
    //   3) We haven't already signalled that we've ended
    //   4) Our estimated earliest end time has expired
    //
    // TODO(enal): we should replace (4) with a check that the browser has no
    // more audio data or at least use a delayed callback.
    //
    // We use the following conditions to determine underflow:
    //   1) Algorithm can not fill the audio callback buffer
    //   2) We have NOT received an end of stream buffer
    //   3) We are in the kPlaying state
    //
    // Otherwise fill the buffer with whatever data we can send to the device.
    if (!algorithm_->CanFillBuffer() && received_end_of_stream_ &&
        !rendered_end_of_stream_ && base::Time::Now() >= earliest_end_time_) {
      rendered_end_of_stream_ = true;
      ended_cb_.Run();
    } else if (!algorithm_->CanFillBuffer() && !received_end_of_stream_ &&
               state_ == kPlaying && !underflow_disabled_) {
      state_ = kUnderflow;
      underflow_cb = underflow_cb_;
    } else if (algorithm_->CanFillBuffer()) {
      frames_written = algorithm_->FillBuffer(dest, requested_frames);
      DCHECK_GT(frames_written, 0u);
    } else {
      // We can't write any data this cycle. For example, we may have
      // sent all available data to the audio device while not reaching
      // |earliest_end_time_|.
    }

    // The |audio_time_buffered_| is the ending timestamp of the last frame
    // buffered at the audio device. |playback_delay| is the amount of time
    // buffered at the audio device. The current time can be computed by their
    // difference.
    if (audio_time_buffered_ != kNoTimestamp()) {
      base::TimeDelta previous_time = current_time_;
      current_time_ = audio_time_buffered_ - playback_delay;

      // Time can change in one of two ways:
      //   1) The time of the audio data at the audio device changed, or
      //   2) The playback delay value has changed
      //
      // We only want to set |current_time| (and thus execute |time_cb_|) if
      // time has progressed and we haven't signaled end of stream yet.
      //
      // Why? The current latency of the system results in getting the last call
      // to FillBuffer() later than we'd like, which delays firing the 'ended'
      // event, which delays the looping/trigging performance of short sound
      // effects.
      //
      // TODO(scherkus): revisit this and switch back to relying on playback
      // delay after we've revamped our audio IPC subsystem.
      if (current_time_ > previous_time && !rendered_end_of_stream_) {
        current_time = current_time_;
      }
    }

    // The call to FillBuffer() on |algorithm_| has increased the amount of
    // buffered audio data. Update the new amount of time buffered.
    max_time = algorithm_->GetTime();
    audio_time_buffered_ = max_time;

    UpdateEarliestEndTime_Locked(
        frames_written, playback_rate, playback_delay, base::Time::Now());
  }

  if (current_time != kNoTimestamp() && max_time != kNoTimestamp()) {
    time_cb_.Run(current_time, max_time);
  }

  if (!underflow_cb.is_null())
    underflow_cb.Run();

  return frames_written;
}

void AudioRendererImpl::UpdateEarliestEndTime_Locked(
    int frames_filled, float playback_rate, base::TimeDelta playback_delay,
    base::Time time_now) {
  if (frames_filled <= 0)
    return;

  base::TimeDelta predicted_play_time = base::TimeDelta::FromMicroseconds(
      static_cast<float>(frames_filled) * base::Time::kMicrosecondsPerSecond /
      audio_parameters_.sample_rate());

  if (playback_rate != 1.0f) {
    predicted_play_time = base::TimeDelta::FromMicroseconds(
        static_cast<int64>(ceil(predicted_play_time.InMicroseconds() *
                                playback_rate)));
  }

  lock_.AssertAcquired();
  earliest_end_time_ = std::max(
      earliest_end_time_, time_now + playback_delay + predicted_play_time);
}

void AudioRendererImpl::OnRenderError() {
  disabled_cb_.Run();
}

void AudioRendererImpl::DisableUnderflowForTesting() {
  underflow_disabled_ = true;
}

void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
  PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK;
  switch (state_) {
    case kUninitialized:
      NOTREACHED();
      return;
    case kPaused:
      if (status != PIPELINE_OK)
        error_cb_.Run(status);
      base::ResetAndReturn(&pause_cb_).Run();
      return;
    case kPrerolling:
      // This is a signal for abort if it's not an error.
      preroll_aborted_ = !is_decode_error;
      state_ = kPaused;
      base::ResetAndReturn(&preroll_cb_).Run(status);
      return;
    case kPlaying:
    case kUnderflow:
    case kRebuffering:
    case kStopped:
      if (status != PIPELINE_OK)
        error_cb_.Run(status);
      return;
  }
}

}  // namespace media
