// Copyright 2022 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/ffmpeg/ffmpeg_demuxer.h"

#include <sys/stat.h>

#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <memory>
#include <string>
#include <vector>

#include "starboard/configuration_constants.h"
#include "starboard/log.h"
#include "starboard/system.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace starboard {
namespace shared {
namespace ffmpeg {
namespace {

using ::testing::_;
using ::testing::AtLeast;
using ::testing::ElementsAreArray;
using ::testing::ExplainMatchResult;
using ::testing::Ge;
using ::testing::Invoke;
using ::testing::IsNull;
using ::testing::MockFunction;
using ::testing::NotNull;
using ::testing::SizeIs;

// Streaming is not supported.
constexpr bool kIsStreaming = false;
constexpr char kInputWebm[] = "bear-320x240.webm";

std::string ResolveTestFilename(const char* filename) {
  std::vector<char> content_path(kSbFileMaxPath);
  SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
                           kSbFileMaxPath));
  const std::string directory_path =
      std::string(content_path.data()) + kSbFileSepChar + "third_party" +
      kSbFileSepChar + "chromium" + kSbFileSepChar + "media" + kSbFileSepChar +
      "test" + kSbFileSepChar + "data";
  struct stat info;
  SB_CHECK(stat(directory_path.c_str(), &info) == 0 && S_ISDIR(info.st_mode))
      << "Cannot open directory " << directory_path;
  return directory_path + kSbFileSepChar + filename;
}

// Used to convert a MockFn to a pure C function.
template <typename T, typename U>
void CallMockCB(U* u, void* user_data) {
  static_cast<T*>(user_data)->AsStdFunction()(u);
}

// These functions forward calls to a FstreamDataSource.
int FstreamBlockingRead(uint8_t* data, int bytes_requested, void* user_data) {
  auto* input = static_cast<std::ifstream*>(user_data);
  input->read(reinterpret_cast<char*>(data), bytes_requested);
  return input->gcount();
}

void FstreamSeekTo(int position, void* user_data) {
  auto* input = static_cast<std::ifstream*>(user_data);
  input->seekg(position, input->beg);
}

int64_t FstreamGetPosition(void* user_data) {
  return static_cast<std::ifstream*>(user_data)->tellg();
}

int64_t FstreamGetSize(void* user_data) {
  // Seek to the end of the file to get the size, then seek back to the current
  // position.
  auto* input = static_cast<std::ifstream*>(user_data);
  const auto current_pos = input->tellg();
  input->seekg(0, input->end);
  const int64_t filesize = input->tellg();
  input->seekg(current_pos);
  return filesize;
}

TEST(FFmpegDemuxerTest, InitializeSucceeds) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, ReadsAudioData) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);

  const std::vector<uint8_t> expected_audio = {
      0xbc, 0xd6, 0xf2, 0xda, 0x7b, 0xad, 0xe5, 0xb5,
      0x87, 0x29, 0x05, 0x50, 0x6b, 0xfc, 0x6f, 0xd6,
  };

  MockFunction<void(CobaltExtensionDemuxerBuffer*)> read_cb;
  std::vector<uint8_t> actual_audio;
  bool read_eos = false;

  EXPECT_CALL(read_cb, Call(_))
      .Times(AtLeast(1))
      .WillRepeatedly(Invoke([&](CobaltExtensionDemuxerBuffer* buffer) {
        SB_CHECK(buffer);
        if (buffer->end_of_stream || buffer->data_size <= 0) {
          read_eos = buffer->end_of_stream;
          return;
        }
        actual_audio.insert(actual_audio.end(), buffer->data,
                            buffer->data + buffer->data_size);
      }));

  // Calling Read may return less -- or more -- data than we need. Keep reading
  // until we have at least as much data as the amount we're checking.
  while (!read_eos && actual_audio.size() < expected_audio.size()) {
    demuxer->Read(kCobaltExtensionDemuxerStreamTypeAudio,
                  &CallMockCB<decltype(read_cb), CobaltExtensionDemuxerBuffer>,
                  &read_cb, demuxer->user_data);
  }

  ASSERT_THAT(actual_audio, SizeIs(Ge(expected_audio.size())));
  actual_audio.resize(expected_audio.size());
  EXPECT_THAT(actual_audio, ElementsAreArray(expected_audio));

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, ReadsVideoData) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);

  const std::vector<uint8_t> expected_video = {
      0x50, 0x04, 0x01, 0x9d, 0x01, 0x2a, 0x40, 0x01,
      0xf0, 0x00, 0x00, 0x47, 0x08, 0x85, 0x85, 0x88,
  };

  MockFunction<void(CobaltExtensionDemuxerBuffer*)> read_cb;
  std::vector<uint8_t> actual_video;
  bool read_eos = false;

  EXPECT_CALL(read_cb, Call(_))
      .Times(AtLeast(1))
      .WillRepeatedly(Invoke([&](CobaltExtensionDemuxerBuffer* buffer) {
        SB_CHECK(buffer);
        if (buffer->end_of_stream || buffer->data_size <= 0) {
          read_eos = buffer->end_of_stream;
          return;
        }
        actual_video.insert(actual_video.end(), buffer->data,
                            buffer->data + buffer->data_size);
      }));

  // Calling Read may return less -- or more -- data than we need. Keep reading
  // until we have at least as much data as the amount we're checking.
  while (!read_eos && actual_video.size() < expected_video.size()) {
    demuxer->Read(kCobaltExtensionDemuxerStreamTypeVideo,
                  &CallMockCB<decltype(read_cb), CobaltExtensionDemuxerBuffer>,
                  &read_cb, demuxer->user_data);
  }

  ASSERT_THAT(actual_video, SizeIs(Ge(expected_video.size())));
  actual_video.resize(expected_video.size());
  EXPECT_THAT(actual_video, ElementsAreArray(expected_video));

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, PopulatesAudioConfig) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);

  CobaltExtensionDemuxerAudioDecoderConfig actual_config = {};
  demuxer->GetAudioConfig(&actual_config, demuxer->user_data);

  EXPECT_EQ(actual_config.codec, kCobaltExtensionDemuxerCodecVorbis);
  EXPECT_EQ(actual_config.sample_format,
            kCobaltExtensionDemuxerSampleFormatPlanarF32);
  EXPECT_EQ(actual_config.channel_layout,
            kCobaltExtensionDemuxerChannelLayoutStereo);
  EXPECT_EQ(actual_config.encryption_scheme,
            kCobaltExtensionDemuxerEncryptionSchemeUnencrypted);
  EXPECT_EQ(actual_config.samples_per_second, 44100);

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, PopulatesVideoConfig) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);

  CobaltExtensionDemuxerVideoDecoderConfig actual_config = {};
  demuxer->GetVideoConfig(&actual_config, demuxer->user_data);

  EXPECT_EQ(actual_config.codec, kCobaltExtensionDemuxerCodecVP8);
  EXPECT_EQ(actual_config.profile, kCobaltExtensionDemuxerVp8ProfileMin);
  EXPECT_EQ(actual_config.color_space_primaries, 2);
  EXPECT_EQ(actual_config.color_space_transfer, 2);
  EXPECT_EQ(actual_config.color_space_matrix, 2);
  EXPECT_EQ(actual_config.color_space_range_id,
            kCobaltExtensionDemuxerColorSpaceRangeIdLimited);
  EXPECT_EQ(actual_config.alpha_mode, kCobaltExtensionDemuxerHasAlpha);
  EXPECT_EQ(actual_config.coded_width, 320);
  EXPECT_EQ(actual_config.coded_height, 240);
  EXPECT_EQ(actual_config.visible_rect_x, 0);
  EXPECT_EQ(actual_config.visible_rect_y, 0);
  EXPECT_EQ(actual_config.visible_rect_width, 320);
  EXPECT_EQ(actual_config.visible_rect_height, 240);
  EXPECT_EQ(actual_config.natural_width, 320);
  EXPECT_EQ(actual_config.natural_height, 240);
  EXPECT_EQ(actual_config.encryption_scheme,
            kCobaltExtensionDemuxerEncryptionSchemeUnencrypted);
  EXPECT_THAT(actual_config.extra_data, IsNull());
  EXPECT_EQ(actual_config.extra_data_size, 0);

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, ReturnsVideoDuration) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);
  EXPECT_EQ(demuxer->GetDuration(demuxer->user_data), 2744000);

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, TimelineOffsetReturnsZero) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);
  EXPECT_EQ(demuxer->GetTimelineOffset(demuxer->user_data), 0);

  api->DestroyDemuxer(demuxer);
}

TEST(FFmpegDemuxerTest, StartTimeReturnsZero) {
  const std::string filename = ResolveTestFilename(kInputWebm);
  std::ifstream input(filename, std::ios_base::binary);
  SB_CHECK(input.good()) << "Unable to load file " << filename;

  const CobaltExtensionDemuxerApi* api = GetFFmpegDemuxerApi();
  ASSERT_THAT(api, NotNull());
  CobaltExtensionDemuxerDataSource c_data_source{
      &FstreamBlockingRead, &FstreamSeekTo, &FstreamGetPosition,
      &FstreamGetSize,      kIsStreaming,   &input};
  std::vector<CobaltExtensionDemuxerAudioCodec> supported_audio_codecs;
  std::vector<CobaltExtensionDemuxerVideoCodec> supported_video_codecs;

  CobaltExtensionDemuxer* demuxer = api->CreateDemuxer(
      &c_data_source, supported_audio_codecs.data(),
      supported_audio_codecs.size(), supported_video_codecs.data(),
      supported_video_codecs.size());

  ASSERT_THAT(demuxer, NotNull());
  EXPECT_EQ(demuxer->Initialize(demuxer->user_data), kCobaltExtensionDemuxerOk);
  EXPECT_EQ(demuxer->GetStartTime(demuxer->user_data), 0);

  api->DestroyDemuxer(demuxer);
}

}  // namespace
}  // namespace ffmpeg
}  // namespace shared
}  // namespace starboard
