// Copyright 2013 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 <memory>

#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "build/build_config.h"
#include "cobalt/media/base/media.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/base/media_tracks.h"
#include "cobalt/media/base/test_data_util.h"
#include "cobalt/media/base/timestamp_constants.h"
#include "cobalt/media/filters/ffmpeg_demuxer.h"
#include "cobalt/media/filters/file_data_source.h"
#include "starboard/types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"

namespace cobalt {
namespace media {

static const int kBenchmarkIterations = 100;

class DemuxerHostImpl : public media::DemuxerHost {
 public:
  DemuxerHostImpl() {}
  ~DemuxerHostImpl() override {}

  // DemuxerHost implementation.
  void OnBufferedTimeRangesChanged(
      const Ranges<base::TimeDelta>& ranges) override {}
  void SetDuration(base::TimeDelta duration) override {}
  void OnDemuxerError(media::PipelineStatus error) override {}
  void AddTextStream(media::DemuxerStream* text_stream,
                     const media::TextTrackConfig& config) override {}
  void RemoveTextStream(media::DemuxerStream* text_stream) override {}

 private:
  DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
};

static void QuitLoopWithStatus(base::MessageLoop* message_loop,
                               media::PipelineStatus status) {
  CHECK_EQ(status, media::PIPELINE_OK);
  message_loop->task_runner()->PostTask(
      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

static void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
                                     const std::vector<uint8_t>& init_data) {
  VLOG(0) << "File is encrypted.";
}

static void OnMediaTracksUpdated(std::unique_ptr<MediaTracks> tracks) {
  VLOG(0) << "Got media tracks info, tracks = " << tracks->tracks().size();
}

typedef std::vector<media::DemuxerStream*> Streams;

// Simulates playback reading requirements by reading from each stream
// present in |demuxer| in as-close-to-monotonically-increasing timestamp order.
class StreamReader {
 public:
  StreamReader(media::Demuxer* demuxer, bool enable_bitstream_converter);
  ~StreamReader();

  // Performs a single step read.
  void Read();

  // Returns true when all streams have reached end of stream.
  bool IsDone();

  int number_of_streams() { return static_cast<int>(streams_.size()); }
  const Streams& streams() { return streams_; }
  const std::vector<int>& counts() { return counts_; }

 private:
  void OnReadDone(base::MessageLoop* message_loop, bool* end_of_stream,
                  base::TimeDelta* timestamp,
                  media::DemuxerStream::Status status,
                  const scoped_refptr<media::DecoderBuffer>& buffer);
  int GetNextStreamIndexToRead();

  Streams streams_;
  std::vector<bool> end_of_stream_;
  std::vector<base::TimeDelta> last_read_timestamp_;
  std::vector<int> counts_;

  DISALLOW_COPY_AND_ASSIGN(StreamReader);
};

StreamReader::StreamReader(media::Demuxer* demuxer,
                           bool enable_bitstream_converter) {
  media::DemuxerStream* stream =
      demuxer->GetStream(media::DemuxerStream::AUDIO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp);
    counts_.push_back(0);
  }

  stream = demuxer->GetStream(media::DemuxerStream::VIDEO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp);
    counts_.push_back(0);

    if (enable_bitstream_converter) stream->EnableBitstreamConverter();
  }
}

StreamReader::~StreamReader() {}

void StreamReader::Read() {
  int index = GetNextStreamIndexToRead();
  bool end_of_stream = false;
  base::TimeDelta timestamp;

  streams_[index]->Read(
      base::Bind(&StreamReader::OnReadDone, base::Unretained(this),
                 base::MessageLoop::current(), &end_of_stream, &timestamp));
  base::RunLoop().Run();

  CHECK(end_of_stream || timestamp != media::kNoTimestamp);
  end_of_stream_[index] = end_of_stream;
  last_read_timestamp_[index] = timestamp;
  counts_[index]++;
}

bool StreamReader::IsDone() {
  for (size_t i = 0; i < end_of_stream_.size(); ++i) {
    if (!end_of_stream_[i]) return false;
  }
  return true;
}

void StreamReader::OnReadDone(
    base::MessageLoop* message_loop, bool* end_of_stream,
    base::TimeDelta* timestamp, media::DemuxerStream::Status status,
    const scoped_refptr<media::DecoderBuffer>& buffer) {
  CHECK_EQ(status, media::DemuxerStream::kOk);
  CHECK(buffer.get());
  *end_of_stream = buffer->end_of_stream();
  *timestamp = *end_of_stream ? media::kNoTimestamp : buffer->timestamp();
  message_loop->task_runner()->PostTask(
      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

int StreamReader::GetNextStreamIndexToRead() {
  int index = -1;
  for (int i = 0; i < number_of_streams(); ++i) {
    // Ignore streams at EOS.
    if (end_of_stream_[i]) continue;

    // Use a stream if it hasn't been read from yet.
    if (last_read_timestamp_[i] == media::kNoTimestamp) return i;

    if (index < 0 || last_read_timestamp_[i] < last_read_timestamp_[index]) {
      index = i;
    }
  }
  CHECK_GE(index, 0) << "Couldn't find a stream to read";
  return index;
}

static void RunDemuxerBenchmark(const std::string& filename) {
  base::FilePath file_path(GetTestDataFilePath(filename));
  double total_time = 0.0;
  for (int i = 0; i < kBenchmarkIterations; ++i) {
    // Setup.
    base::MessageLoop message_loop;
    DemuxerHostImpl demuxer_host;
    FileDataSource data_source;
    ASSERT_TRUE(data_source.Initialize(file_path));

    Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
        base::Bind(&OnEncryptedMediaInitData);
    Demuxer::MediaTracksUpdatedCB tracks_updated_cb =
        base::Bind(&OnMediaTracksUpdated);
    FFmpegDemuxer demuxer(message_loop.task_runner(), &data_source,
                          encrypted_media_init_data_cb, tracks_updated_cb,
                          new MediaLog());

    demuxer.Initialize(&demuxer_host,
                       base::Bind(&QuitLoopWithStatus, &message_loop), false);
    base::RunLoop().Run();
    StreamReader stream_reader(&demuxer, false);

    // Benchmark.
    base::TimeTicks start = base::TimeTicks::Now();
    while (!stream_reader.IsDone()) {
      stream_reader.Read();
    }
    base::TimeTicks end = base::TimeTicks::Now();
    total_time += (end - start).InSecondsF();
    demuxer.Stop();
    QuitLoopWithStatus(&message_loop, PIPELINE_OK);
    base::RunLoop().Run();
  }

  perf_test::PrintResult("demuxer_bench", "", filename,
                         kBenchmarkIterations / total_time, "runs/s", true);
}

#if defined(OS_WIN)
// http://crbug.com/399002
#define MAYBE_Demuxer DISABLED_Demuxer
#else
#define MAYBE_Demuxer Demuxer
#endif
TEST(DemuxerPerfTest, MAYBE_Demuxer) {
  RunDemuxerBenchmark("bear.ogv");
  RunDemuxerBenchmark("bear-640x360.webm");
  RunDemuxerBenchmark("sfx_s16le.wav");
#if defined(USE_PROPRIETARY_CODECS)
  RunDemuxerBenchmark("bear-1280x720.mp4");
  RunDemuxerBenchmark("sfx.mp3");
#endif
#if defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.flac");
#endif
#if defined(USE_PROPRIETARY_CODECS) && defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.avi");
#endif
}

}  // namespace media
}  // namespace cobalt
