/*
 * 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.
 */

#include <vector>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"

#include "config/aom_config.h"

#include "aom/aomcx.h"
#include "aom/aomdx.h"
#include "aom/aom_encoder.h"
#include "aom/aom_decoder.h"

#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))

using libaom_test::ACMRandom;
namespace {

class CompressedSource {
 public:
  explicit CompressedSource(int seed) : rnd_(seed), frame_count_(0) {
    aom_codec_iface_t *algo = aom_codec_av1_cx();

    aom_codec_enc_cfg_t cfg;
#if CONFIG_REALTIME_ONLY
    aom_codec_enc_config_default(algo, &cfg, 1);
#else
    aom_codec_enc_config_default(algo, &cfg, 0);
#endif

    // force the quantizer, to reduce the sensitivity on encoding choices.
    // e.g, we don't want this test to break when the rate control is modified.
    {
      const int max_q = cfg.rc_max_quantizer;
      const int min_q = cfg.rc_min_quantizer;
      const int q = rnd_.PseudoUniform(max_q - min_q + 1) + min_q;

      cfg.rc_end_usage = AOM_Q;
      cfg.rc_max_quantizer = q;
      cfg.rc_min_quantizer = q;
    }

    // choose the picture size
    {
      width_ = rnd_.PseudoUniform(kWidth - 8) + 8;
      height_ = rnd_.PseudoUniform(kHeight - 8) + 8;
    }

    // choose the chroma subsampling
    {
      const aom_img_fmt_t fmts[] = {
        AOM_IMG_FMT_I420,
        AOM_IMG_FMT_I422,
        AOM_IMG_FMT_I444,
      };

      format_ = fmts[rnd_.PseudoUniform(NELEMENTS(fmts))];
    }

    cfg.g_w = width_;
    cfg.g_h = height_;
    cfg.g_lag_in_frames = 0;
    if (format_ == AOM_IMG_FMT_I420)
      cfg.g_profile = 0;
    else if (format_ == AOM_IMG_FMT_I444)
      cfg.g_profile = 1;
    else if (format_ == AOM_IMG_FMT_I422)
      cfg.g_profile = 2;

    aom_codec_enc_init(&enc_, algo, &cfg, 0);
  }

  ~CompressedSource() { aom_codec_destroy(&enc_); }

  const aom_codec_cx_pkt_t *ReadFrame() {
    uint8_t buf[kWidth * kHeight * 3] = { 0 };

    // render regular pattern
    const int period = rnd_.Rand8() % 32 + 1;
    const int phase = rnd_.Rand8() % period;

    const int val_a = rnd_.Rand8();
    const int val_b = rnd_.Rand8();

    for (int i = 0; i < (int)sizeof buf; ++i)
      buf[i] = (i + phase) % period < period / 2 ? val_a : val_b;

    aom_image_t img;
    aom_img_wrap(&img, format_, width_, height_, 0, buf);
    aom_codec_encode(&enc_, &img, frame_count_++, 1, 0);

    aom_codec_iter_t iter = nullptr;

    const aom_codec_cx_pkt_t *pkt = nullptr;

    do {
      pkt = aom_codec_get_cx_data(&enc_, &iter);
    } while (pkt && pkt->kind != AOM_CODEC_CX_FRAME_PKT);

    return pkt;
  }

 private:
  static const int kWidth = 128;
  static const int kHeight = 128;

  ACMRandom rnd_;
  aom_img_fmt_t format_;
  aom_codec_ctx_t enc_;
  int frame_count_;
  int width_, height_;
};

// lowers an aom_image_t to an easily comparable/printable form
std::vector<uint16_t> Serialize(const aom_image_t *img) {
  std::vector<uint16_t> bytes;
  bytes.reserve(img->d_w * img->d_h * 3);
  for (int plane = 0; plane < 3; ++plane) {
    const int w = aom_img_plane_width(img, plane);
    const int h = aom_img_plane_height(img, plane);

    for (int r = 0; r < h; ++r) {
      for (int c = 0; c < w; ++c) {
        const unsigned char *row = img->planes[plane] + r * img->stride[plane];
        if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
          const uint16_t *row16 = reinterpret_cast<const uint16_t *>(row);
          bytes.push_back(row16[c]);
        } else {
          bytes.push_back(row[c]);
        }
      }
    }
  }

  return bytes;
}

class Decoder {
 public:
  explicit Decoder(int allowLowbitdepth) {
    aom_codec_iface_t *algo = aom_codec_av1_dx();

    aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
    cfg.allow_lowbitdepth = allowLowbitdepth;

    aom_codec_dec_init(&dec_, algo, &cfg, 0);
  }

  ~Decoder() { aom_codec_destroy(&dec_); }

  std::vector<uint16_t> decode(const aom_codec_cx_pkt_t *pkt) {
    aom_codec_decode(&dec_, static_cast<uint8_t *>(pkt->data.frame.buf),
                     pkt->data.frame.sz, nullptr);

    aom_codec_iter_t iter = nullptr;
    return Serialize(aom_codec_get_frame(&dec_, &iter));
  }

 private:
  aom_codec_ctx_t dec_;
};

// Try to reveal a mismatch between LBD and HBD coding paths.
TEST(CodingPathSync, SearchForHbdLbdMismatch) {
  const int count_tests = 10;
  for (int i = 0; i < count_tests; ++i) {
    Decoder dec_hbd(0);
    Decoder dec_lbd(1);

    CompressedSource enc(i);

    for (int k = 0; k < 3; ++k) {
      const aom_codec_cx_pkt_t *frame = enc.ReadFrame();

      std::vector<uint16_t> lbd_yuv = dec_lbd.decode(frame);
      std::vector<uint16_t> hbd_yuv = dec_hbd.decode(frame);

      ASSERT_EQ(lbd_yuv, hbd_yuv);
    }
  }
}

TEST(CodingPathSyncLarge, SearchForHbdLbdMismatchLarge) {
  const int count_tests = 100;
  const int seed = 1234;
  for (int i = 0; i < count_tests; ++i) {
    Decoder dec_hbd(0);
    Decoder dec_lbd(1);

    CompressedSource enc(seed + i);

    for (int k = 0; k < 5; ++k) {
      const aom_codec_cx_pkt_t *frame = enc.ReadFrame();

      std::vector<uint16_t> lbd_yuv = dec_lbd.decode(frame);
      std::vector<uint16_t> hbd_yuv = dec_hbd.decode(frame);

      ASSERT_EQ(lbd_yuv, hbd_yuv);
    }
  }
}

}  // namespace
