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

namespace starboard {
namespace nplb {

namespace {

SbMediaAudioSampleType GetAnySupportedSampleType() {
  if (SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeInt16)) {
    return kSbMediaAudioSampleTypeInt16;
  }
  return kSbMediaAudioSampleTypeFloat32;
}

SbMediaAudioFrameStorageType GetAnySupportedFrameStorageType() {
  if (SbAudioSinkIsAudioFrameStorageTypeSupported(
          kSbMediaAudioFrameStorageTypeInterleaved)) {
    return kSbMediaAudioFrameStorageTypeInterleaved;
  }
  return kSbMediaAudioFrameStorageTypePlanar;
}

}  // namespace

AudioSinkTestFrameBuffers::AudioSinkTestFrameBuffers(int channels)
    : channels_(channels),
      sample_type_(GetAnySupportedSampleType()),
      storage_type_(GetAnySupportedFrameStorageType()) {
  Init();
}

AudioSinkTestFrameBuffers::AudioSinkTestFrameBuffers(
    int channels,
    SbMediaAudioSampleType sample_type)
    : channels_(channels),
      sample_type_(sample_type),
      storage_type_(GetAnySupportedFrameStorageType()) {
  Init();
}

AudioSinkTestFrameBuffers::AudioSinkTestFrameBuffers(
    int channels,
    SbMediaAudioFrameStorageType storage_type)
    : channels_(channels),
      sample_type_(GetAnySupportedSampleType()),
      storage_type_(storage_type) {
  Init();
}

AudioSinkTestFrameBuffers::AudioSinkTestFrameBuffers(
    int channels,
    SbMediaAudioSampleType sample_type,
    SbMediaAudioFrameStorageType storage_type)
    : channels_(channels),
      sample_type_(sample_type),
      storage_type_(storage_type) {
  Init();
}

void AudioSinkTestFrameBuffers::Init() {
  if (storage_type_ == kSbMediaAudioFrameStorageTypeInterleaved) {
    frame_buffer_.resize(bytes_per_frame() * channels_ * kFramesPerChannel);
    frame_buffers_.resize(1);
    frame_buffers_[0] = &frame_buffer_[0];
  } else {
    // We make all planar audio channels share the same frame buffer.
    frame_buffer_.resize(bytes_per_frame() * frames_per_channel());
    frame_buffers_.resize(channels_, &frame_buffer_[0]);
  }
}

AudioSinkTestEnvironment::AudioSinkTestEnvironment(
    const AudioSinkTestFrameBuffers& frame_buffers)
    : frame_buffers_(frame_buffers),
      condition_variable_(mutex_),
      update_source_status_call_count_(0),
      frames_appended_(0),
      frames_consumed_(0),
      is_playing_(true) {
  sink_ = SbAudioSinkCreate(
      frame_buffers_.channels(), sample_rate(), frame_buffers_.sample_type(),
      frame_buffers_.storage_type(), frame_buffers_.frame_buffers(),
      frame_buffers_.frames_per_channel(), UpdateSourceStatusFunc,
      ConsumeFramesFunc, this);
}

AudioSinkTestEnvironment::~AudioSinkTestEnvironment() {
  SbAudioSinkDestroy(sink_);
}

void AudioSinkTestEnvironment::SetIsPlaying(bool is_playing) {
  ScopedLock lock(mutex_);
  is_playing_ = is_playing;
}

void AudioSinkTestEnvironment::AppendFrame(int frames_to_append) {
  ScopedLock lock(mutex_);
  frames_appended_ += frames_to_append;
}

int AudioSinkTestEnvironment::GetFrameBufferFreeSpaceAmount() const {
  ScopedLock lock(mutex_);
  int frames_in_buffer = frames_appended_ - frames_consumed_;
  return frame_buffers_.frames_per_channel() - frames_in_buffer;
}

bool AudioSinkTestEnvironment::WaitUntilUpdateStatusCalled() {
  ScopedLock lock(mutex_);
  int update_source_status_call_count = update_source_status_call_count_;
  SbTimeMonotonic start = SbTimeGetMonotonicNow();
  while (update_source_status_call_count == update_source_status_call_count_) {
    SbTime time_elapsed = SbTimeGetMonotonicNow() - start;
    if (time_elapsed >= kTimeToTry) {
      return false;
    }
    SbTime time_to_wait = kTimeToTry - time_elapsed;
    condition_variable_.WaitTimed(time_to_wait);
  }
  return true;
}

bool AudioSinkTestEnvironment::WaitUntilSomeFramesAreConsumed() {
  ScopedLock lock(mutex_);
  int frames_consumed = frames_consumed_;
  SbTimeMonotonic start = SbTimeGetMonotonicNow();
  while (frames_consumed == frames_consumed_) {
    SbTime time_elapsed = SbTimeGetMonotonicNow() - start;
    if (time_elapsed >= kTimeToTry) {
      return false;
    }
    SbTime time_to_wait = kTimeToTry - time_elapsed;
    condition_variable_.WaitTimed(time_to_wait);
  }
  return true;
}

bool AudioSinkTestEnvironment::WaitUntilAllFramesAreConsumed() {
  ScopedLock lock(mutex_);
  SbTimeMonotonic start = SbTimeGetMonotonicNow();
  while (frames_appended_ == frames_consumed_) {
    SbTime time_elapsed = SbTimeGetMonotonicNow() - start;
    if (time_elapsed >= kTimeToTry) {
      return false;
    }
    SbTime time_to_wait = kTimeToTry - time_elapsed;
    condition_variable_.WaitTimed(time_to_wait);
  }
  return true;
}

void AudioSinkTestEnvironment::OnUpdateSourceStatus(int* frames_in_buffer,
                                                    int* offset_in_frames,
                                                    bool* is_playing,
                                                    bool* is_eos_reached) {
  ScopedLock lock(mutex_);
  *frames_in_buffer = frames_appended_ - frames_consumed_;
  *offset_in_frames = frames_appended_ % frame_buffers_.frames_per_channel();
  *is_playing = is_playing_;
  *is_eos_reached = false;
  ++update_source_status_call_count_;
  condition_variable_.Signal();
}

void AudioSinkTestEnvironment::OnConsumeFrames(int frames_consumed) {
  ScopedLock lock(mutex_);
  frames_consumed_ += frames_consumed;
  condition_variable_.Signal();
}

// static
void AudioSinkTestEnvironment::UpdateSourceStatusFunc(int* frames_in_buffer,
                                                      int* offset_in_frames,
                                                      bool* is_playing,
                                                      bool* is_eos_reached,
                                                      void* context) {
  AudioSinkTestEnvironment* environment =
      reinterpret_cast<AudioSinkTestEnvironment*>(context);
  environment->OnUpdateSourceStatus(frames_in_buffer, offset_in_frames,
                                    is_playing, is_eos_reached);
}

// static
void AudioSinkTestEnvironment::ConsumeFramesFunc(int frames_consumed,
                                                 void* context) {
  AudioSinkTestEnvironment* environment =
      reinterpret_cast<AudioSinkTestEnvironment*>(context);
  environment->OnConsumeFrames(frames_consumed);
}

}  // namespace nplb
}  // namespace starboard
