// Copyright 2016 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 "starboard/shared/starboard/player/filter/audio_renderer_internal.h"

#include <algorithm>

#include "starboard/memory.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {

namespace {
// TODO: This should be retrieved from the decoder.
// TODO: Make it not dependent on the frame size of AAC and HE-AAC.
const int kMaxFramesPerAccessUnit = 1024 * 2;
}  // namespace

AudioRenderer::AudioRenderer(scoped_ptr<AudioDecoder> decoder,
                             const SbMediaAudioHeader& audio_header)
    : channels_(audio_header.number_of_channels),
      paused_(true),
      seeking_(false),
      seeking_to_pts_(0),
      frame_buffer_(kMaxCachedFrames * audio_header.number_of_channels),
      frames_in_buffer_(0),
      offset_in_frames_(0),
      frames_consumed_(0),
      end_of_stream_reached_(false),
      decoder_(decoder.Pass()),
      audio_sink_(kSbAudioSinkInvalid) {
  SB_DCHECK(decoder_ != NULL);
  frame_buffers_[0] = &frame_buffer_[0];
}

AudioRenderer::~AudioRenderer() {
  if (audio_sink_ != kSbAudioSinkInvalid) {
    SbAudioSinkDestroy(audio_sink_);
  }
}

void AudioRenderer::WriteSample(const InputBuffer& input_buffer) {
  if (end_of_stream_reached_) {
    SB_LOG(ERROR) << "Appending audio sample at " << input_buffer.pts()
                  << " after EOS reached.";
    return;
  }

  SbMediaTime input_pts = input_buffer.pts();
  std::vector<float> decoded_audio;
  decoder_->Decode(input_buffer, &decoded_audio);
  if (decoded_audio.empty()) {
    SB_DLOG(ERROR) << "decoded_audio contains no frames.";
    return;
  }

  {
    ScopedLock lock(mutex_);
    if (seeking_) {
      if (input_pts < seeking_to_pts_) {
        return;
      }
    }

    AppendFrames(&decoded_audio[0], decoded_audio.size() / channels_);

    if (seeking_ && frame_buffer_.size() > kPrerollFrames * channels_) {
      seeking_ = false;
    }
  }

  // Create the audio sink if it is the first incoming AU after seeking.
  if (audio_sink_ == kSbAudioSinkInvalid) {
    int sample_rate = decoder_->GetSamplesPerSecond();
    // TODO: Implement resampler.
    SB_DCHECK(sample_rate ==
              SbAudioSinkGetNearestSupportedSampleFrequency(sample_rate));
    // TODO: Handle sink creation failure.
    audio_sink_ = SbAudioSinkCreate(
        channels_, sample_rate, kSbMediaAudioSampleTypeFloat32,
        kSbMediaAudioFrameStorageTypeInterleaved,
        reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
        kMaxCachedFrames, &AudioRenderer::UpdateSourceStatusFunc,
        &AudioRenderer::ConsumeFramesFunc, this);
  }
}

void AudioRenderer::WriteEndOfStream() {
  SB_LOG_IF(WARNING, end_of_stream_reached_)
      << "Try to write EOS after EOS is reached";
  if (end_of_stream_reached_) {
    return;
  }
  end_of_stream_reached_ = true;
  decoder_->WriteEndOfStream();

  ScopedLock lock(mutex_);
  // If we are seeking, we consider the seek is finished if end of stream is
  // reached as there won't be any audio data in future.
  if (seeking_) {
    seeking_ = false;
  }
}

void AudioRenderer::Play() {
  ScopedLock lock(mutex_);
  paused_ = false;
}

void AudioRenderer::Pause() {
  ScopedLock lock(mutex_);
  paused_ = true;
}

void AudioRenderer::Seek(SbMediaTime seek_to_pts) {
  SB_DCHECK(seek_to_pts >= 0);

  SbAudioSinkDestroy(audio_sink_);
  audio_sink_ = kSbAudioSinkInvalid;

  seeking_to_pts_ = std::max<SbMediaTime>(seek_to_pts, 0);
  seeking_ = true;
  frames_in_buffer_ = 0;
  offset_in_frames_ = 0;
  frames_consumed_ = 0;
  end_of_stream_reached_ = false;

  decoder_->Reset();
  return;
}

bool AudioRenderer::IsEndOfStreamPlayed() const {
  return end_of_stream_reached_ && frames_in_buffer_ == 0;
}

bool AudioRenderer::CanAcceptMoreData() const {
  ScopedLock lock(mutex_);
  return frames_in_buffer_ <= kMaxCachedFrames - kMaxFramesPerAccessUnit &&
         !end_of_stream_reached_;
}

bool AudioRenderer::IsSeekingInProgress() const {
  return seeking_;
}

SbMediaTime AudioRenderer::GetCurrentTime() {
  if (seeking_) {
    return seeking_to_pts_;
  }
  return seeking_to_pts_ +
         frames_consumed_ * kSbMediaTimeSecond /
             decoder_->GetSamplesPerSecond();
}

// static
void AudioRenderer::UpdateSourceStatusFunc(int* frames_in_buffer,
                                           int* offset_in_frames,
                                           bool* is_playing,
                                           bool* is_eos_reached,
                                           void* context) {
  AudioRenderer* audio_renderer = reinterpret_cast<AudioRenderer*>(context);
  SB_DCHECK(audio_renderer);
  SB_DCHECK(frames_in_buffer);
  SB_DCHECK(offset_in_frames);
  SB_DCHECK(is_playing);
  SB_DCHECK(is_eos_reached);

  audio_renderer->UpdateSourceStatus(frames_in_buffer, offset_in_frames,
                                     is_playing, is_eos_reached);
}

// static
void AudioRenderer::ConsumeFramesFunc(int frames_consumed, void* context) {
  AudioRenderer* audio_renderer = reinterpret_cast<AudioRenderer*>(context);
  SB_DCHECK(audio_renderer);

  audio_renderer->ConsumeFrames(frames_consumed);
}

void AudioRenderer::UpdateSourceStatus(int* frames_in_buffer,
                                       int* offset_in_frames,
                                       bool* is_playing,
                                       bool* is_eos_reached) {
  ScopedLock lock(mutex_);

  *is_eos_reached = end_of_stream_reached_;

  if (paused_ || seeking_) {
    *is_playing = false;
    *frames_in_buffer = *offset_in_frames = 0;
    return;
  }

  *is_playing = true;
  *frames_in_buffer = frames_in_buffer_;
  *offset_in_frames = offset_in_frames_;
}

void AudioRenderer::ConsumeFrames(int frames_consumed) {
  ScopedLock lock(mutex_);

  SB_DCHECK(frames_consumed <= frames_in_buffer_);
  offset_in_frames_ += frames_consumed;
  offset_in_frames_ %= kMaxCachedFrames;
  frames_in_buffer_ -= frames_consumed;
  frames_consumed_ += frames_consumed;
}

void AudioRenderer::AppendFrames(const float* source_buffer,
                                 int frames_to_append) {
  SB_DCHECK(frames_in_buffer_ + frames_to_append <= kMaxCachedFrames);

  int offset_to_append =
      (offset_in_frames_ + frames_in_buffer_) % kMaxCachedFrames;
  if (frames_to_append > kMaxCachedFrames - offset_to_append) {
    SbMemoryCopy(
        &frame_buffer_[offset_to_append * channels_], source_buffer,
        (kMaxCachedFrames - offset_to_append) * sizeof(float) * channels_);
    source_buffer += (kMaxCachedFrames - offset_to_append) * channels_;
    frames_to_append -= kMaxCachedFrames - offset_to_append;
    frames_in_buffer_ += kMaxCachedFrames - offset_to_append;
    offset_to_append = 0;
  }
  SbMemoryCopy(&frame_buffer_[offset_to_append * channels_], source_buffer,
               frames_to_append * sizeof(float) * channels_);
  frames_in_buffer_ += frames_to_append;
}

}  // namespace filter
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
