// Copyright 2020 The Cobalt Authors. 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_decoder_internal.h"

#include <algorithm>

#include "starboard/common/log.h"
#include "starboard/media.h"
#include "starboard/player.h"
#include "starboard/shared/starboard/player/decoded_audio_internal.h"
#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "third_party/google_benchmark/include/benchmark/benchmark.h"

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

using video_dmp::VideoDmpReader;

const size_t kMaxNumberOfInputs = 256;

class AudioDecoderHelper {
 public:
  explicit AudioDecoderHelper(const char* filename)
      : dmp_reader_(ResolveTestFileName(filename).c_str()),
        number_of_inputs_(std::min(dmp_reader_.number_of_audio_buffers(),
                                   kMaxNumberOfInputs)) {
    const bool kUseStubDecoder = false;
    SB_CHECK(number_of_inputs_ > 0);
    SB_CHECK(CreateAudioComponents(kUseStubDecoder,
                                   dmp_reader_.audio_stream_info(),
                                   &audio_decoder_, &audio_renderer_sink_));
    SB_CHECK(audio_decoder_);
    audio_decoder_->Initialize(std::bind(&AudioDecoderHelper::OnOutput, this),
                               std::bind(&AudioDecoderHelper::OnError, this));
  }

  size_t number_of_inputs() const { return number_of_inputs_; }

  void DecodeAll() {
    SB_CHECK(current_input_buffer_index_ == 0);
    OnConsumed();  // Kick off the first Decode() call
    // Note that we deliberately don't add any time out to the loop, to ensure
    // that the benchmark is accurate.
    while (!end_of_stream_decoded_) {
      job_queue_.RunUntilIdle();
    }
  }

 private:
  scoped_refptr<InputBuffer> GetAudioInputBuffer(size_t index) {
    auto player_sample_info =
        dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, index);
    return new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
                           player_sample_info);
  }

  void OnOutput() {
    if (!job_queue_.BelongsToCurrentThread()) {
      job_queue_.Schedule(std::bind(&AudioDecoderHelper::OnOutput, this));
      return;
    }
    int decoded_sample_rate;
    auto decoded_audio = audio_decoder_->Read(&decoded_sample_rate);
    end_of_stream_decoded_ = decoded_audio->is_end_of_stream();
  }

  void OnError() { SB_NOTREACHED(); }

  void OnConsumed() {
    if (!job_queue_.BelongsToCurrentThread()) {
      job_queue_.Schedule(std::bind(&AudioDecoderHelper::OnConsumed, this));
      return;
    }
    if (current_input_buffer_index_ < number_of_inputs_) {
      audio_decoder_->Decode({GetAudioInputBuffer(current_input_buffer_index_)},
                             std::bind(&AudioDecoderHelper::OnConsumed, this));
      ++current_input_buffer_index_;
    } else {
      SB_CHECK(current_input_buffer_index_ == number_of_inputs_);
      audio_decoder_->WriteEndOfStream();
      // Increment so we can know if WriteEndOfStream() is called twice.
      ++current_input_buffer_index_;
    }
  }

  VideoDmpReader dmp_reader_;
  JobQueue job_queue_;

  const size_t number_of_inputs_;
  size_t current_input_buffer_index_ = 0;
  bool end_of_stream_decoded_ = false;

  scoped_ptr<AudioDecoder> audio_decoder_;
  scoped_ptr<AudioRendererSink> audio_renderer_sink_;
};

}  // namespace

void RunBenchmark(::benchmark::State& state, const char* filename) {
  size_t number_of_inputs = 0;
  for (auto _ : state) {
    state.PauseTiming();
    AudioDecoderHelper helper(filename);
    number_of_inputs = helper.number_of_inputs();
    state.ResumeTiming();
    helper.DecodeAll();
  }
  state.SetItemsProcessed(state.iterations() * number_of_inputs);
}

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

// This function has to reside in the global namespace for BENCHMARK_CAPTURE to
// pick it up.
void BM_AudioDecoder(::benchmark::State& state, const char* filename) {
  starboard::shared::starboard::player::filter::testing::RunBenchmark(state,
                                                                      filename);
}

BENCHMARK_CAPTURE(BM_AudioDecoder,
                  aac_stereo,
                  "beneath_the_canopy_aac_stereo.dmp");
BENCHMARK_CAPTURE(BM_AudioDecoder,
                  opus_stereo,
                  "beneath_the_canopy_opus_stereo.dmp");
