// Copyright 2020 The libgav1 Authors
//
// 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 <cstddef>
#include <cstdint>
#include <deque>
#include <memory>
#include <vector>

#include "examples/file_reader.h"
#include "examples/file_reader_constants.h"
#include "examples/file_reader_interface.h"
#include "src/gav1/decoder.h"
#include "src/gav1/status_code.h"
#include "tests/fuzzer/fuzzer_temp_file.h"

namespace {

#if defined(LIBGAV1_EXHAUSTIVE_FUZZING)
// Set a large upper bound to give more coverage of a single input; this value
// should be larger than most of the frame counts in the corpus.
constexpr size_t kMaxDataSize = 400 * 1024;
#else
constexpr size_t kMaxDataSize = 200 * 1024;
#endif

using InputBuffer = std::vector<uint8_t>;

struct InputBuffers {
  ~InputBuffers() {
    for (auto& buffer : free_buffers) {
      delete buffer;
    }
  }
  std::deque<InputBuffer*> free_buffers;
};

void ReleaseInputBuffer(void* callback_private_data,
                        void* buffer_private_data) {
  auto* const test = static_cast<InputBuffers*>(callback_private_data);
  test->free_buffers.push_back(static_cast<InputBuffer*>(buffer_private_data));
}

}  // namespace

// Always returns 0. Nonzero return values are reserved by libFuzzer for future
// use.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  // Reject large chunks of data to improve fuzzer throughput.
  if (size > kMaxDataSize) return 0;

  // Note that |input_buffers| has to outlive the |decoder| object since the
  // |release_input_buffer| callback could be called on the |decoder|'s
  // destructor.
  InputBuffers input_buffers;

  libgav1::Decoder decoder;
  libgav1::DecoderSettings settings = {};
  // Use the 33 + low byte of the width to seed the number of threads. This
  // ensures that we will trigger the frame parallel path in most cases.
  // We use both nibbles of the lower byte as this results in values != 1 much
  // more quickly than using the lower nibble alone.
  settings.threads =
      33 + ((size >= 13) ? ((data[12] >> 4 | data[12]) & 0xF) + 1 : 1);

  settings.frame_parallel = true;
  settings.blocking_dequeue = true;
  settings.callback_private_data = &input_buffers;
  settings.release_input_buffer = ReleaseInputBuffer;
  if (decoder.Init(&settings) != libgav1::kStatusOk) return 0;

  FuzzerTemporaryFile tempfile(data, size);
  auto file_reader =
      libgav1::FileReader::Open(tempfile.filename(), /*error_tolerant=*/true);
  if (file_reader == nullptr) return 0;

  InputBuffer* input_buffer = nullptr;
  bool dequeue_finished = false;

  do {
    if (input_buffer == nullptr && !file_reader->IsEndOfFile()) {
      if (input_buffers.free_buffers.empty()) {
        auto* const buffer = new (std::nothrow) InputBuffer();
        if (buffer == nullptr) {
          break;
        }
        input_buffers.free_buffers.push_back(buffer);
      }
      input_buffer = input_buffers.free_buffers.front();
      input_buffers.free_buffers.pop_front();
      if (!file_reader->ReadTemporalUnit(input_buffer, nullptr)) {
        break;
      }
    }

    if (input_buffer != nullptr) {
      libgav1::StatusCode status =
          decoder.EnqueueFrame(input_buffer->data(), input_buffer->size(),
                               /*user_private_data=*/0,
                               /*buffer_private_data=*/input_buffer);
      if (status == libgav1::kStatusOk) {
        input_buffer = nullptr;
        // Continue to enqueue frames until we get a kStatusTryAgain status.
        continue;
      }
      if (status != libgav1::kStatusTryAgain) {
        break;
      }
    }

    const libgav1::DecoderBuffer* buffer;
    libgav1::StatusCode status = decoder.DequeueFrame(&buffer);
    if (status != libgav1::kStatusOk &&
        status != libgav1::kStatusNothingToDequeue) {
      break;
    }
    if (buffer == nullptr) {
      dequeue_finished = status == libgav1::kStatusNothingToDequeue;
    } else {
      dequeue_finished = false;
    }
  } while (input_buffer != nullptr || !file_reader->IsEndOfFile() ||
           !dequeue_finished);

  if (input_buffer != nullptr) {
    input_buffers.free_buffers.push_back(input_buffer);
  }

  return 0;
}
