/*
 * Copyright 2013 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/audio/shell_audio_sink.h"

#include <limits>

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/aligned_memory.h"
#include "base/memory/scoped_ptr.h"
#include "media/base/audio_bus.h"
#include "media/base/shell_media_statistics.h"
#include "media/filters/shell_audio_renderer.h"
#include "media/mp4/aac.h"

#if defined(OS_STARBOARD)
#include "starboard/configuration.h"
#endif  // defined(OS_STARBOARD)

namespace {

scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> s_audio_sink_buffer;
size_t s_audio_sink_buffer_size_in_float;

}  // namespace

namespace media {

void AudioSinkSettings::Reset(const ShellAudioStreamer::Config& config,
                              const AudioParameters& audio_parameters) {
  config_ = config;
  audio_parameters_ = audio_parameters;
}

const ShellAudioStreamer::Config& AudioSinkSettings::config() const {
  return config_;
}

const AudioParameters& AudioSinkSettings::audio_parameters() const {
  return audio_parameters_;
}

int AudioSinkSettings::channels() const {
  return audio_parameters_.channels();
}

int AudioSinkSettings::per_channel_frames(AudioBus* audio_bus) const {
  return audio_bus->frames() * sizeof(float) /
         (config_.interleaved() ? channels() : 1) /
         (audio_parameters_.bits_per_sample() / 8);
}

// static
ShellAudioSink* ShellAudioSink::Create(ShellAudioStreamer* audio_streamer) {
  return new ShellAudioSink(audio_streamer);
}

ShellAudioSink::ShellAudioSink(ShellAudioStreamer* audio_streamer)
    : render_callback_(NULL),
      pause_requested_(true),
      rebuffering_(true),
      rebuffer_num_frames_(0),
      render_frame_cursor_(0),
      output_frame_cursor_(0),
      audio_streamer_(audio_streamer) {
  buffer_factory_ = ShellBufferFactory::Instance();
}

ShellAudioSink::~ShellAudioSink() {
  if (render_callback_) {
    DCHECK(!audio_streamer_->HasStream(this));
  }
}

void ShellAudioSink::Initialize(const AudioParameters& params,
                                RenderCallback* callback) {
  TRACE_EVENT0("media_stack", "ShellAudioSink::Initialize()");
  DCHECK(!render_callback_);
  DCHECK(params.bits_per_sample() == 16 || params.bits_per_sample() == 32);

  render_callback_ = callback;
  audio_parameters_ = params;

  streamer_config_ = audio_streamer_->GetConfig();
  settings_.Reset(streamer_config_, params);

  // Creating the audio bus
  size_t per_channel_size_in_float =
      streamer_config_.sink_buffer_size_in_frames_per_channel() *
      audio_parameters_.bits_per_sample() / (8 * sizeof(float));
  size_t audio_bus_buffer_size_in_float =
      settings_.channels() * per_channel_size_in_float;
  if (audio_bus_buffer_size_in_float > s_audio_sink_buffer_size_in_float) {
    s_audio_sink_buffer_size_in_float = audio_bus_buffer_size_in_float;
    // free the existing memory first so we have more free memory for the
    // allocation following.
    s_audio_sink_buffer.reset(NULL);
    s_audio_sink_buffer.reset(static_cast<float*>(
        base::AlignedAlloc(s_audio_sink_buffer_size_in_float * sizeof(float),
                           AudioBus::kChannelAlignment)));
    if (!s_audio_sink_buffer) {
      DLOG(ERROR) << "couldn't reallocate sink buffer";
      render_callback_->OnRenderError();
      return;
    }
  }

  if (streamer_config_.interleaved()) {
    audio_bus_ = AudioBus::WrapMemory(
        1, settings_.channels() * per_channel_size_in_float,
        s_audio_sink_buffer.get());
  } else {
    audio_bus_ =
        AudioBus::WrapMemory(settings_.channels(), per_channel_size_in_float,
                             s_audio_sink_buffer.get());
  }

  if (!audio_bus_) {
    NOTREACHED() << "couldn't create sink buffer";
    render_callback_->OnRenderError();
    return;
  }

  rebuffer_num_frames_ =
      streamer_config_.initial_rebuffering_frames_per_channel();
  renderer_audio_bus_ = AudioBus::CreateWrapper(audio_bus_->channels());
}

void ShellAudioSink::Start() {
  TRACE_EVENT0("media_stack", "ShellAudioSink::Start()");
  DCHECK(render_callback_);

  if (!audio_streamer_->HasStream(this)) {
    pause_requested_ = true;
    rebuffering_ = true;
    audio_streamer_->StopBackgroundMusic();
    audio_streamer_->AddStream(this);
    DCHECK(audio_streamer_->HasStream(this));
  }
}

void ShellAudioSink::Stop() {
  TRACE_EVENT0("media_stack", "ShellAudioSink::Stop()");
  // It is possible that Stop() is called before Initialize() is called. In
  // this case the audio_streamer_ will not be able to check if it has the
  // stream as audio_parameters_ hasn't been initialized.
  if (render_callback_ && audio_streamer_->HasStream(this)) {
    audio_streamer_->RemoveStream(this);
    pause_requested_ = true;
    rebuffering_ = true;
    render_frame_cursor_ = 0;
    output_frame_cursor_ = 0;
  }
}

void ShellAudioSink::Pause(bool flush) {
  TRACE_EVENT0("media_stack", "ShellAudioSink::Pause()");
  // clear consumption of data on the mixer.
  pause_requested_ = true;
  if (flush) {
    TRACE_EVENT0("media_stack", "ShellAudioSink::Pause() flushing.");
    // remove and re-add the stream to flush
    audio_streamer_->RemoveStream(this);
    rebuffering_ = true;
    render_frame_cursor_ = 0;
    output_frame_cursor_ = 0;
    audio_streamer_->AddStream(this);
  }
}

void ShellAudioSink::Play() {
  TRACE_EVENT0("media_stack", "ShellAudioSink::Play()");
  // clear flag on mixer callback, will start to consume more data
  pause_requested_ = false;
}

bool ShellAudioSink::SetVolume(double volume) {
  return audio_streamer_->SetVolume(this, volume);
}

void ShellAudioSink::ResumeAfterUnderflow(bool buffer_more_audio) {
  // only rebuffer when paused, we access state variables non atomically
  DCHECK(pause_requested_);
  DCHECK(rebuffering_);

  if (!buffer_more_audio)
    return;

  rebuffer_num_frames_ = std::min<int>(
      rebuffer_num_frames_ * 2, settings_.per_channel_frames(audio_bus_.get()));
}

bool ShellAudioSink::PauseRequested() const {
  return pause_requested_ || rebuffering_;
}

bool ShellAudioSink::PullFrames(uint32_t* offset_in_frame,
                                uint32_t* total_frames) {
  TRACE_EVENT0("media_stack", "ShellAudioSink::PullFrames()");
  // with a valid render callback
  DCHECK(render_callback_);

  uint32_t dummy_offset_in_frame, dummy_total_frames;
  if (!offset_in_frame)
    offset_in_frame = &dummy_offset_in_frame;
  if (!total_frames)
    total_frames = &dummy_total_frames;

  *total_frames = render_frame_cursor_ - output_frame_cursor_;
  uint32 free_frames =
      settings_.per_channel_frames(audio_bus_.get()) - *total_frames;
  // Number of ms of buffered playback remaining
  uint32_t buffered_time =
      (*total_frames * 1000 / audio_parameters_.sample_rate());
  if (free_frames >= mp4::AAC::kFramesPerAccessUnit) {
    SetupRenderAudioBus();

    int frames_rendered =
        render_callback_->Render(renderer_audio_bus_.get(), buffered_time);
    // 0 indicates the read is still pending. Positive number is # of frames
    // rendered, negative number indicates an error.
    if (frames_rendered > 0) {
      // +ve value indicates number of samples in a successful read
      // TODO: We cannot guarantee this on platforms that use a resampler. Check
      // if it is possible to move the resample into the streamer.
      // DCHECK_EQ(frames_rendered, mp4::AAC::kFramesPerAccessUnit);
      render_frame_cursor_ += frames_rendered;
      *total_frames += frames_rendered;
      free_frames -= frames_rendered;
    }
  } else {
    render_callback_->Render(NULL, buffered_time);
  }

  bool buffer_full = free_frames < mp4::AAC::kFramesPerAccessUnit;
  DCHECK_LE(*total_frames,
            static_cast<uint32>(std::numeric_limits<int32>::max()));
  bool rebuffer_threshold_reached =
      static_cast<int>(*total_frames) >= rebuffer_num_frames_;
  if (rebuffering_ && (buffer_full || rebuffer_threshold_reached)) {
    render_callback_->SinkFull();
    rebuffering_ = false;
  }

#if defined(OS_STARBOARD)
#if SB_IS(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)

#define MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK 1

#endif  // SB_IS(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)
#endif  // #if defined(OS_STARBOARD)

#if defined(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)
  const size_t kUnderflowThreshold = mp4::AAC::kFramesPerAccessUnit / 2;
  if (*total_frames < kUnderflowThreshold) {
    if (!rebuffering_) {
      rebuffering_ = true;
      render_callback_->SinkUnderflow();
      UPDATE_MEDIA_STATISTICS(STAT_TYPE_AUDIO_UNDERFLOW, 0);
    }
  }
  *offset_in_frame =
      output_frame_cursor_ % settings_.per_channel_frames(audio_bus_.get());
  return !PauseRequested();
#else   // defined(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)
  rebuffering_ = true;
  *offset_in_frame =
      output_frame_cursor_ % settings_.per_channel_frames(audio_bus_.get());
  if (pause_requested_) {
    return false;
  }
  return true;
#endif  // defined(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)
}

void ShellAudioSink::ConsumeFrames(uint32_t frame_played) {
  TRACE_EVENT1("media_stack", "ShellAudioSink::ConsumeFrames()", "audio_clock",
               (output_frame_cursor_ * 1000) / audio_parameters_.sample_rate());
  // Called by the Streamer thread to indicate where the hardware renderer
  // is in playback
  if (frame_played > 0) {
    // advance our output cursor by the number of frames we're returning
    // update audio clock, used for jitter calculations
    output_frame_cursor_ += frame_played;
    DCHECK_LE(output_frame_cursor_, render_frame_cursor_);
  }
}

AudioBus* ShellAudioSink::GetAudioBus() {
  return audio_bus_.get();
}

const AudioParameters& ShellAudioSink::GetAudioParameters() const {
  return audio_parameters_;
}

void ShellAudioSink::SetupRenderAudioBus() {
  // check for buffer wraparound, hopefully rare
  int render_frame_position =
      render_frame_cursor_ % settings_.per_channel_frames(audio_bus_.get());
  int requested_frames = mp4::AAC::kFramesPerAccessUnit;
  if (render_frame_position + requested_frames >
      settings_.per_channel_frames(audio_bus_.get())) {
    requested_frames =
        settings_.per_channel_frames(audio_bus_.get()) - render_frame_position;
  }
  // calculate the offset into the buffer where we'd like to store these data
  if (streamer_config_.interleaved()) {
    uint8* channel_data = reinterpret_cast<uint8*>(audio_bus_->channel(0));
    uint8* channel_offset = channel_data +
                            render_frame_position *
                                audio_parameters_.bits_per_sample() / 8 *
                                settings_.channels();
    // setup the AudioBus to pass to the renderer
    renderer_audio_bus_->SetChannelData(
        0, reinterpret_cast<float*>(channel_offset));
    renderer_audio_bus_->set_frames(requested_frames *
                                    audio_parameters_.bits_per_sample() / 8 /
                                    sizeof(float) * settings_.channels());
  } else {
    for (int i = 0; i < audio_bus_->channels(); ++i) {
      uint8* channel_data = reinterpret_cast<uint8*>(audio_bus_->channel(i));
      uint8* channel_offset =
          channel_data +
          render_frame_position * audio_parameters_.bits_per_sample() / 8;
      renderer_audio_bus_->SetChannelData(
          i, reinterpret_cast<float*>(channel_offset));
    }
    renderer_audio_bus_->set_frames(requested_frames *
                                    audio_parameters_.bits_per_sample() / 8 /
                                    sizeof(float));
  }
}

}  // namespace media
