/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */
#ifndef AOM_TEST_VIDEO_SOURCE_H_
#define AOM_TEST_VIDEO_SOURCE_H_

#if defined(_WIN32)
#undef NOMINMAX
#define NOMINMAX
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <string>

#include "aom/aom_encoder.h"
#include "test/acm_random.h"
#if !defined(_WIN32)
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#endif

namespace libaom_test {

// Helper macros to ensure LIBAOM_TEST_DATA_PATH is a quoted string.
// These are undefined right below GetDataPath
// NOTE: LIBAOM_TEST_DATA_PATH MUST NOT be a quoted string before
// Stringification or the GetDataPath will fail at runtime
#define TO_STRING(S) #S
#define STRINGIFY(S) TO_STRING(S)

// A simple function to encapsulate cross platform retrieval of test data path
static std::string GetDataPath() {
  const char *const data_path = getenv("LIBAOM_TEST_DATA_PATH");
  if (data_path == nullptr) {
#ifdef LIBAOM_TEST_DATA_PATH
    // In some environments, we cannot set environment variables
    // Instead, we set the data path by using a preprocessor symbol
    // which can be set from make files
    return STRINGIFY(LIBAOM_TEST_DATA_PATH);
#else
    return ".";
#endif
  }
  return data_path;
}

// Undefining stringification macros because they are not used elsewhere
#undef TO_STRING
#undef STRINGIFY

inline FILE *OpenTestDataFile(const std::string &file_name) {
  const std::string path_to_source = GetDataPath() + "/" + file_name;
  return fopen(path_to_source.c_str(), "rb");
}

static FILE *GetTempOutFile(std::string *file_name) {
  file_name->clear();
#if defined(_WIN32)
  char fname[MAX_PATH];
  char tmppath[MAX_PATH];
  if (GetTempPathA(MAX_PATH, tmppath)) {
    // Assume for now that the filename generated is unique per process
    if (GetTempFileNameA(tmppath, "lvx", 0, fname)) {
      file_name->assign(fname);
      return fopen(fname, "wb+");
    }
  }
  return nullptr;
#else
  std::string temp_dir = testing::TempDir();
  if (temp_dir.empty()) return nullptr;
  // Versions of testing::TempDir() prior to release-1.11.0-214-g5e6a5336 may
  // use the value of an environment variable without checking for a trailing
  // path delimiter.
  if (temp_dir[temp_dir.size() - 1] != '/') temp_dir += '/';
  const char name_template[] = "libaomtest.XXXXXX";
  std::unique_ptr<char[]> temp_file_name(
      new char[temp_dir.size() + sizeof(name_template)]);
  if (temp_file_name == nullptr) return nullptr;
  memcpy(temp_file_name.get(), temp_dir.data(), temp_dir.size());
  memcpy(temp_file_name.get() + temp_dir.size(), name_template,
         sizeof(name_template));
  const int fd = mkstemp(temp_file_name.get());
  if (fd == -1) return nullptr;
  *file_name = temp_file_name.get();
  return fdopen(fd, "wb+");
#endif
}

class TempOutFile {
 public:
  TempOutFile() { file_ = GetTempOutFile(&file_name_); }
  ~TempOutFile() {
    CloseFile();
    if (!file_name_.empty()) {
      EXPECT_EQ(0, remove(file_name_.c_str()));
    }
  }
  FILE *file() { return file_; }
  const std::string &file_name() { return file_name_; }

 protected:
  void CloseFile() {
    if (file_) {
      fclose(file_);
      file_ = nullptr;
    }
  }
  FILE *file_;
  std::string file_name_;
};

// Abstract base class for test video sources, which provide a stream of
// aom_image_t images with associated timestamps and duration.
class VideoSource {
 public:
  virtual ~VideoSource() = default;

  // Prepare the stream for reading, rewind/open as necessary.
  virtual void Begin() = 0;

  // Advance the cursor to the next frame
  virtual void Next() = 0;

  // Get the current video frame, or nullptr on End-Of-Stream.
  virtual aom_image_t *img() const = 0;

  // Get the presentation timestamp of the current frame.
  virtual aom_codec_pts_t pts() const = 0;

  // Get the current frame's duration
  virtual unsigned long duration() const = 0;

  // Get the timebase for the stream
  virtual aom_rational_t timebase() const = 0;

  // Get the current frame counter, starting at 0.
  virtual unsigned int frame() const = 0;

  // Get the current file limit.
  virtual unsigned int limit() const = 0;
};

class DummyVideoSource : public VideoSource {
 public:
  DummyVideoSource()
      : img_(nullptr), limit_(100), width_(80), height_(64),
        format_(AOM_IMG_FMT_I420) {
    ReallocImage();
  }

  ~DummyVideoSource() override { aom_img_free(img_); }

  void Begin() override {
    frame_ = 0;
    FillFrame();
  }

  void Next() override {
    ++frame_;
    FillFrame();
  }

  aom_image_t *img() const override {
    return (frame_ < limit_) ? img_ : nullptr;
  }

  // Models a stream where Timebase = 1/FPS, so pts == frame.
  aom_codec_pts_t pts() const override { return frame_; }

  unsigned long duration() const override { return 1; }

  aom_rational_t timebase() const override {
    const aom_rational_t t = { 1, 30 };
    return t;
  }

  unsigned int frame() const override { return frame_; }

  unsigned int limit() const override { return limit_; }

  void set_limit(unsigned int limit) { limit_ = limit; }

  void SetSize(unsigned int width, unsigned int height) {
    if (width != width_ || height != height_) {
      width_ = width;
      height_ = height;
      ReallocImage();
    }
  }

  void SetImageFormat(aom_img_fmt_t format) {
    if (format_ != format) {
      format_ = format;
      ReallocImage();
    }
  }

 protected:
  virtual void FillFrame() {
    if (img_) memset(img_->img_data, 0, raw_sz_);
  }

  void ReallocImage() {
    aom_img_free(img_);
    img_ = aom_img_alloc(nullptr, format_, width_, height_, 32);
    ASSERT_NE(img_, nullptr);
    raw_sz_ = ((img_->w + 31) & ~31u) * img_->h * img_->bps / 8;
  }

  aom_image_t *img_;
  size_t raw_sz_;
  unsigned int limit_;
  unsigned int frame_;
  unsigned int width_;
  unsigned int height_;
  aom_img_fmt_t format_;
};

class RandomVideoSource : public DummyVideoSource {
 public:
  RandomVideoSource(int seed = ACMRandom::DeterministicSeed())
      : rnd_(seed), seed_(seed) {}

  // Reset the RNG to get a matching stream for the second pass
  void Begin() override {
    frame_ = 0;
    rnd_.Reset(seed_);
    FillFrame();
  }

 protected:
  // 15 frames of noise, followed by 15 static frames. Reset to 0 rather
  // than holding previous frames to encourage keyframes to be thrown.
  void FillFrame() override {
    if (img_) {
      if (frame_ % 30 < 15)
        for (size_t i = 0; i < raw_sz_; ++i) img_->img_data[i] = rnd_.Rand8();
      else
        memset(img_->img_data, 0, raw_sz_);
    }
  }

  ACMRandom rnd_;
  int seed_;
};

// Abstract base class for test video sources, which provide a stream of
// decompressed images to the decoder.
class CompressedVideoSource {
 public:
  virtual ~CompressedVideoSource() = default;

  virtual void Init() = 0;

  // Prepare the stream for reading, rewind/open as necessary.
  virtual void Begin() = 0;

  // Advance the cursor to the next frame
  virtual void Next() = 0;

  virtual const uint8_t *cxdata() const = 0;

  virtual size_t frame_size() const = 0;

  virtual unsigned int frame_number() const = 0;
};

}  // namespace libaom_test

#endif  // AOM_TEST_VIDEO_SOURCE_H_
