/*
 * 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
#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() {}

  // 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();
  }

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

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

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

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

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

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

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

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

  virtual unsigned int limit() const { 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) & ~31) * 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) {}

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

  // 15 frames of noise, followed by 15 static frames. Reset to 0 rather
  // than holding previous frames to encourage keyframes to be thrown.
  virtual void FillFrame() {
    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() {}

  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_
