// Copyright 2022 Google LLC. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#include "avifincrtest_helpers.h"

#include <algorithm>
#include <cstring>
#include <vector>

#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"

namespace libavif {
namespace testutil {
namespace {

//------------------------------------------------------------------------------

// Verifies that the first (top) row_count rows of image1 and image2 are
// identical.
void ComparePartialYuva(const avifImage& image1, const avifImage& image2,
                        uint32_t row_count) {
  if (row_count == 0) {
    return;
  }
  ASSERT_EQ(image1.width, image2.width);
  ASSERT_GE(image1.height, row_count);
  ASSERT_GE(image2.height, row_count);
  ASSERT_EQ(image1.depth, image2.depth);
  ASSERT_EQ(image1.yuvFormat, image2.yuvFormat);
  ASSERT_EQ(image1.yuvRange, image2.yuvRange);

  avifPixelFormatInfo info;
  avifGetPixelFormatInfo(image1.yuvFormat, &info);
  const uint32_t uv_width =
      (image1.width + info.chromaShiftX) >> info.chromaShiftX;
  const uint32_t uv_height =
      (row_count + info.chromaShiftY) >> info.chromaShiftY;
  const uint32_t pixel_byte_count =
      (image1.depth > 8) ? sizeof(uint16_t) : sizeof(uint8_t);

  for (int plane = 0; plane < (info.monochrome ? 1 : AVIF_PLANE_COUNT_YUV);
       ++plane) {
    const uint32_t width = (plane == AVIF_CHAN_Y) ? image1.width : uv_width;
    const uint32_t width_byte_count = width * pixel_byte_count;
    const uint32_t height = (plane == AVIF_CHAN_Y) ? row_count : uv_height;
    const uint8_t* data1 = image1.yuvPlanes[plane];
    const uint8_t* data2 = image2.yuvPlanes[plane];
    for (uint32_t y = 0; y < height; ++y) {
      ASSERT_EQ(std::memcmp(data1, data2, width_byte_count), 0);
      data1 += image1.yuvRowBytes[plane];
      data2 += image2.yuvRowBytes[plane];
    }
  }

  if (image1.alphaPlane) {
    ASSERT_NE(image2.alphaPlane, nullptr);
    ASSERT_EQ(image1.alphaPremultiplied, image2.alphaPremultiplied);
    const uint32_t width_byte_count = image1.width * pixel_byte_count;
    const uint8_t* data1 = image1.alphaPlane;
    const uint8_t* data2 = image2.alphaPlane;
    for (uint32_t y = 0; y < row_count; ++y) {
      ASSERT_EQ(std::memcmp(data1, data2, width_byte_count), 0);
      data1 += image1.alphaRowBytes;
      data2 += image2.alphaRowBytes;
    }
  }
}

// Returns the expected number of decoded rows when available_byte_count out of
// byte_count were given to the decoder, for an image of height rows, split into
// cells of cell_height rows.
uint32_t GetMinDecodedRowCount(uint32_t height, uint32_t cell_height,
                               bool has_alpha, size_t available_byte_count,
                               size_t byte_count) {
  // The whole image should be available when the full input is.
  if (available_byte_count >= byte_count) {
    return height;
  }
  // All but one cell should be decoded if at most 10 bytes are missing.
  if ((available_byte_count + 10) >= byte_count) {
    return height - cell_height;
  }

  // Subtract the header because decoding it does not output any pixel.
  // Most AVIF headers are below 500 bytes.
  if (available_byte_count <= 500) {
    return 0;
  }
  available_byte_count -= 500;
  byte_count -= 500;
  // Alpha, if any, is assumed to be located before the other planes and to
  // represent at most 50% of the payload.
  if (has_alpha) {
    if (available_byte_count <= (byte_count / 2)) {
      return 0;
    }
    available_byte_count -= byte_count / 2;
    byte_count -= byte_count / 2;
  }
  // Linearly map the input availability ratio to the decoded row ratio.
  const uint32_t min_decoded_cell_row_count = static_cast<uint32_t>(
      (height / cell_height) * available_byte_count / byte_count);
  const uint32_t min_decoded_px_row_count =
      min_decoded_cell_row_count * cell_height;
  // One cell is the incremental decoding granularity.
  // It is unlikely that bytes are evenly distributed among cells. Offset two of
  // them.
  if (min_decoded_px_row_count <= (2 * cell_height)) {
    return 0;
  }
  return min_decoded_px_row_count - 2 * cell_height;
}

//------------------------------------------------------------------------------

struct PartialData {
  avifROData available;
  size_t full_size;

  // Only used as nonpersistent input.
  std::unique_ptr<uint8_t[]> nonpersistent_bytes;
  size_t num_nonpersistent_bytes;
};

// Implementation of avifIOReadFunc simulating a stream from an array. See
// avifIOReadFunc documentation. io->data is expected to point to PartialData.
avifResult PartialRead(struct avifIO* io, uint32_t read_flags,
                       uint64_t offset64, size_t size, avifROData* out) {
  PartialData* data = reinterpret_cast<PartialData*>(io->data);
  if ((read_flags != 0) || !data || (data->full_size < offset64)) {
    return AVIF_RESULT_IO_ERROR;
  }
  const size_t offset = static_cast<size_t>(offset64);
  // Use |offset| instead of |offset64| from this point on.
  if (size > (data->full_size - offset)) {
    size = data->full_size - offset;
  }
  if (data->available.size < (offset + size)) {
    return AVIF_RESULT_WAITING_ON_IO;
  }
  if (io->persistent) {
    out->data = data->available.data + offset;
  } else {
    // Dedicated buffer containing just the available bytes and nothing more.
    std::unique_ptr<uint8_t[]> bytes(new uint8_t[size]);
    std::copy(data->available.data + offset,
              data->available.data + offset + size, bytes.get());
    out->data = bytes.get();
    // Flip the previously returned bytes to make sure the values changed.
    for (size_t i = 0; i < data->num_nonpersistent_bytes; ++i) {
      data->nonpersistent_bytes[i] = ~data->nonpersistent_bytes[i];
    }
    // Free the memory to invalidate the old pointer. Only do that after
    // allocating the new bytes to make sure to have a different pointer.
    data->nonpersistent_bytes = std::move(bytes);
    data->num_nonpersistent_bytes = size;
  }
  out->size = size;
  return AVIF_RESULT_OK;
}

//------------------------------------------------------------------------------

// Encodes the image as a grid of at most grid_cols*grid_rows cells.
// The cell count is reduced to fit libavif or AVIF format constraints. If
// impossible, the encoded output is returned empty. The final cell_width and
// cell_height are output.
void EncodeAsGrid(const avifImage& image, uint32_t grid_cols,
                  uint32_t grid_rows, avifRWData* output, uint32_t* cell_width,
                  uint32_t* cell_height) {
  // Chroma subsampling requires even dimensions. See ISO 23000-22 - 7.3.11.4.2
  const bool need_even_widths =
      ((image.yuvFormat == AVIF_PIXEL_FORMAT_YUV420) ||
       (image.yuvFormat == AVIF_PIXEL_FORMAT_YUV422));
  const bool need_even_heights = (image.yuvFormat == AVIF_PIXEL_FORMAT_YUV420);

  ASSERT_GT(grid_cols * grid_rows, 0u);
  *cell_width = image.width / grid_cols;
  *cell_height = image.height / grid_rows;

  // avifEncoderAddImageGrid() only accepts grids that evenly split the image
  // into cells at least 64 pixels wide and tall.
  while ((grid_cols > 1) &&
         (((*cell_width * grid_cols) != image.width) || (*cell_width < 64) ||
          (need_even_widths && ((*cell_width & 1) != 0)))) {
    --grid_cols;
    *cell_width = image.width / grid_cols;
  }
  while ((grid_rows > 1) &&
         (((*cell_height * grid_rows) != image.height) || (*cell_height < 64) ||
          (need_even_heights && ((*cell_height & 1) != 0)))) {
    --grid_rows;
    *cell_height = image.height / grid_rows;
  }

  std::vector<testutil::AvifImagePtr> cell_images;
  cell_images.reserve(grid_cols * grid_rows);
  for (uint32_t row = 0, i_cell = 0; row < grid_rows; ++row) {
    for (uint32_t col = 0; col < grid_cols; ++col, ++i_cell) {
      avifCropRect cell;
      cell.x = col * *cell_width;
      cell.y = row * *cell_height;
      cell.width = ((cell.x + *cell_width) <= image.width)
                       ? *cell_width
                       : (image.width - cell.x);
      cell.height = ((cell.y + *cell_height) <= image.height)
                        ? *cell_height
                        : (image.height - cell.y);
      cell_images.emplace_back(avifImageCreateEmpty(), avifImageDestroy);
      ASSERT_NE(cell_images.back(), nullptr);
      ASSERT_EQ(avifImageSetViewRect(cell_images.back().get(), &image, &cell),
                AVIF_RESULT_OK);
    }
  }

  testutil::AvifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
  ASSERT_NE(encoder, nullptr);
  encoder->speed = AVIF_SPEED_FASTEST;
  // Just here to match libavif API.
  std::vector<avifImage*> cell_image_ptrs(cell_images.size());
  for (size_t i = 0; i < cell_images.size(); ++i) {
    cell_image_ptrs[i] = cell_images[i].get();
  }
  ASSERT_EQ(avifEncoderAddImageGrid(encoder.get(), grid_cols, grid_rows,
                                    cell_image_ptrs.data(),
                                    AVIF_ADD_IMAGE_FLAG_SINGLE),
            AVIF_RESULT_OK);
  ASSERT_EQ(avifEncoderFinish(encoder.get(), output), AVIF_RESULT_OK);
}

// Encodes the image to be decoded incrementally.
void EncodeAsIncremental(const avifImage& image, bool flat_cells,
                         avifRWData* output, uint32_t* cell_width,
                         uint32_t* cell_height) {
  const uint32_t grid_cols = image.width / 64;  // 64px is the min cell width.
  const uint32_t grid_rows = flat_cells ? 1 : (image.height / 64);
  EncodeAsGrid(image, (grid_cols > 1) ? grid_cols : 1,
               (grid_rows > 1) ? grid_rows : 1, output, cell_width,
               cell_height);
}

}  // namespace

void EncodeRectAsIncremental(const avifImage& image, uint32_t width,
                             uint32_t height, bool create_alpha_if_none,
                             bool flat_cells, avifRWData* output,
                             uint32_t* cell_width, uint32_t* cell_height) {
  AvifImagePtr sub_image(avifImageCreateEmpty(), avifImageDestroy);
  ASSERT_NE(sub_image, nullptr);
  ASSERT_LE(width, image.width);
  ASSERT_LE(height, image.height);
  avifPixelFormatInfo info;
  avifGetPixelFormatInfo(image.yuvFormat, &info);
  const avifCropRect rect{
      /*x=*/((image.width - width) / 2) & ~info.chromaShiftX,
      /*y=*/((image.height - height) / 2) & ~info.chromaShiftX, width, height};
  ASSERT_EQ(avifImageSetViewRect(sub_image.get(), &image, &rect),
            AVIF_RESULT_OK);
  if (create_alpha_if_none && !sub_image->alphaPlane) {
    ASSERT_NE(image.yuvPlanes[AVIF_CHAN_Y], nullptr)
        << "No luma plane to simulate an alpha plane";
    sub_image->alphaPlane = image.yuvPlanes[AVIF_CHAN_Y];
    sub_image->alphaRowBytes = image.yuvRowBytes[AVIF_CHAN_Y];
    sub_image->alphaPremultiplied = AVIF_FALSE;
    sub_image->imageOwnsAlphaPlane = AVIF_FALSE;
  }
  EncodeAsIncremental(*sub_image, flat_cells, output, cell_width, cell_height);
}

//------------------------------------------------------------------------------

void DecodeIncrementally(const avifRWData& encoded_avif, bool is_persistent,
                         bool give_size_hint, bool use_nth_image_api,
                         const avifImage& reference, uint32_t cell_height) {
  // AVIF cells are at least 64 pixels tall.
  if (cell_height != reference.height) {
    ASSERT_GE(cell_height, 64u);
  }

  // Emulate a byte-by-byte stream.
  PartialData data = {
      /*available=*/{encoded_avif.data, 0}, /*fullSize=*/encoded_avif.size,
      /*nonpersistent_bytes=*/nullptr, /*num_nonpersistent_bytes=*/0};
  avifIO io = {
      /*destroy=*/nullptr, PartialRead,
      /*write=*/nullptr,   give_size_hint ? encoded_avif.size : 0,
      is_persistent,       &data};

  testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
  ASSERT_NE(decoder, nullptr);
  avifDecoderSetIO(decoder.get(), &io);
  decoder->allowIncremental = AVIF_TRUE;
  const size_t step = std::max<size_t>(1, data.full_size / 10000);

  // Parsing is not incremental.
  avifResult parse_result = avifDecoderParse(decoder.get());
  while (parse_result == AVIF_RESULT_WAITING_ON_IO) {
    ASSERT_LT(data.available.size, data.full_size)
        << "avifDecoderParse() returned WAITING_ON_IO instead of OK";
    data.available.size = std::min(data.available.size + step, data.full_size);
    parse_result = avifDecoderParse(decoder.get());
  }
  ASSERT_EQ(parse_result, AVIF_RESULT_OK);

  // Decoding is incremental.
  uint32_t previously_decoded_row_count = 0;
  avifResult next_image_result = use_nth_image_api
                                     ? avifDecoderNthImage(decoder.get(), 0)
                                     : avifDecoderNextImage(decoder.get());
  while (next_image_result == AVIF_RESULT_WAITING_ON_IO) {
    ASSERT_LT(data.available.size, data.full_size)
        << (use_nth_image_api ? "avifDecoderNthImage(0)"
                              : "avifDecoderNextImage()")
        << " returned WAITING_ON_IO instead of OK";
    const uint32_t decoded_row_count =
        avifDecoderDecodedRowCount(decoder.get());
    ASSERT_GE(decoded_row_count, previously_decoded_row_count);
    const uint32_t min_decoded_row_count = GetMinDecodedRowCount(
        reference.height, cell_height, reference.alphaPlane != nullptr,
        data.available.size, data.full_size);
    ASSERT_GE(decoded_row_count, min_decoded_row_count);
    ComparePartialYuva(reference, *decoder->image, decoded_row_count);

    previously_decoded_row_count = decoded_row_count;
    data.available.size = std::min(data.available.size + step, data.full_size);
    next_image_result = use_nth_image_api
                            ? avifDecoderNthImage(decoder.get(), 0)
                            : avifDecoderNextImage(decoder.get());
  }
  ASSERT_EQ(next_image_result, AVIF_RESULT_OK);
  ASSERT_EQ(data.available.size, data.full_size);
  ASSERT_EQ(avifDecoderDecodedRowCount(decoder.get()), decoder->image->height);

  ComparePartialYuva(reference, *decoder->image, reference.height);
}

void DecodeNonIncrementallyAndIncrementally(const avifRWData& encoded_avif,
                                            bool is_persistent,
                                            bool give_size_hint,
                                            bool use_nth_image_api,
                                            uint32_t cell_height) {
  AvifImagePtr reference(avifImageCreateEmpty(), avifImageDestroy);
  ASSERT_NE(reference, nullptr);
  testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
  ASSERT_NE(decoder, nullptr);
  ASSERT_EQ(avifDecoderReadMemory(decoder.get(), reference.get(),
                                  encoded_avif.data, encoded_avif.size),
            AVIF_RESULT_OK);

  DecodeIncrementally(encoded_avif, is_persistent, give_size_hint,
                      use_nth_image_api, *reference, cell_height);
}

//------------------------------------------------------------------------------

}  // namespace testutil
}  // namespace libavif
