/*
 * Copyright (c) 2018, 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.
 */

// Scalable Decoder
// ==============
//
// This is an example of a scalable decoder loop. It takes a 2-spatial-layer
// input file
// containing the compressed data (in OBU format), passes it through the
// decoder, and writes the decompressed frames to disk. The base layer and
// enhancement layers are stored as separate files, lyr0.yuv and lyr1.yuv,
// respectively.
//
// Standard Includes
// -----------------
// For decoders, you only have to include `aom_decoder.h` and then any
// header files for the specific codecs you use. In this case, we're using
// av1.
//
// Initializing The Codec
// ----------------------
// The libaom decoder is initialized by the call to aom_codec_dec_init().
// Determining the codec interface to use is handled by AvxVideoReader and the
// functions prefixed with aom_video_reader_. Discussion of those functions is
// beyond the scope of this example, but the main gist is to open the input file
// and parse just enough of it to determine if it's a AVx file and which AVx
// codec is contained within the file.
// Note the NULL pointer passed to aom_codec_dec_init(). We do that in this
// example because we want the algorithm to determine the stream configuration
// (width/height) and allocate memory automatically.
//
// Decoding A Frame
// ----------------
// Once the frame has been read into memory, it is decoded using the
// `aom_codec_decode` function. The call takes a pointer to the data
// (`frame`) and the length of the data (`frame_size`). No application data
// is associated with the frame in this example, so the `user_priv`
// parameter is NULL. The `deadline` parameter is left at zero for this
// example. This parameter is generally only used when doing adaptive post
// processing.
//
// Codecs may produce a variable number of output frames for every call to
// `aom_codec_decode`. These frames are retrieved by the
// `aom_codec_get_frame` iterator function. The iterator variable `iter` is
// initialized to NULL each time `aom_codec_decode` is called.
// `aom_codec_get_frame` is called in a loop, returning a pointer to a
// decoded image or NULL to indicate the end of list.
//
// Processing The Decoded Data
// ---------------------------
// In this example, we simply write the encoded data to disk. It is
// important to honor the image's `stride` values.
//
// Cleanup
// -------
// The `aom_codec_destroy` call frees any memory allocated by the codec.
//
// Error Handling
// --------------
// This example does not special case any error return codes. If there was
// an error, a descriptive message is printed and the program exits. With
// few exceptions, aom_codec functions return an enumerated error status,
// with the value `0` indicating success.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "aom/aom_decoder.h"

#include "../tools_common.h"
#include "../video_reader.h"
#include "./aom_config.h"
#include "./obudec.h"

static const char *exec_name;

#define MAX_LAYERS 5

void usage_exit(void) {
  fprintf(stderr, "Usage: %s <infile>\n", exec_name);
  exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
  int frame_cnt = 0;
  FILE *outfile[MAX_LAYERS];
  char filename[80];
  aom_codec_ctx_t codec;
  const AvxInterface *decoder = NULL;
  FILE *inputfile = NULL;
  uint8_t *buf = NULL;
  size_t bytes_in_buffer = 0;
  size_t buffer_size = 0;
  struct AvxInputContext aom_input_ctx;
  struct ObuDecInputContext obu_ctx = { &aom_input_ctx, NULL, 0, 0, 0, 0 };
  aom_codec_stream_info_t si;
  uint8_t tmpbuf[32];
  unsigned int i;

  exec_name = argv[0];

  if (argc != 2) die("Invalid number of arguments.");

  if (!(inputfile = fopen(argv[1], "rb")))
    die("Failed to open %s for read.", argv[1]);
  obu_ctx.avx_ctx->file = inputfile;
  obu_ctx.avx_ctx->filename = argv[1];

  decoder = get_aom_decoder_by_index(0);
  printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));

  if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
    die_codec(&codec, "Failed to initialize decoder.");

  // peak sequence header OBU to get number of spatial layers
  const size_t ret = fread(tmpbuf, 1, 32, inputfile);
  if (ret != 32) die_codec(&codec, "Input is not a valid obu file");
  si.is_annexb = 0;
  if (aom_codec_peek_stream_info(decoder->codec_interface(), tmpbuf, 32, &si)) {
    die_codec(&codec, "Input is not a valid obu file");
  }
  fseek(inputfile, -32, SEEK_CUR);

  if (!file_is_obu(&obu_ctx))
    die_codec(&codec, "Input is not a valid obu file");

  // open base layer output yuv file
  snprintf(filename, sizeof(filename), "out_lyr%d.yuv", 0);
  if (!(outfile[0] = fopen(filename, "wb")))
    die("Failed top open output for writing.");

  // open any enhancement layer output yuv files
  for (i = 1; i < si.number_spatial_layers; i++) {
    snprintf(filename, sizeof(filename), "out_lyr%d.yuv", i);
    if (!(outfile[i] = fopen(filename, "wb")))
      die("Failed to open output for writing.");
  }

  while (!obudec_read_temporal_unit(&obu_ctx, &buf, &bytes_in_buffer,
                                    &buffer_size)) {
    aom_codec_iter_t iter = NULL;
    aom_image_t *img = NULL;
    if (aom_codec_decode(&codec, buf, (unsigned int)bytes_in_buffer, NULL))
      die_codec(&codec, "Failed to decode frame.");

    while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
      aom_image_t *img_shifted =
          aom_img_alloc(NULL, AOM_IMG_FMT_I420, img->d_w, img->d_h, 16);
      img_shifted->bit_depth = 8;
      aom_img_downshift(img_shifted, img,
                        img->bit_depth - img_shifted->bit_depth);
      if (img->spatial_id == 0) {
        printf("Writing       base layer 0 %d\n", frame_cnt);
        aom_img_write(img_shifted, outfile[0]);
        obu_ctx.last_layer_id++;
      } else if (img->spatial_id <= (int)(si.number_spatial_layers - 1)) {
        printf("Writing enhancemnt layer %d %d\n", img->spatial_id, frame_cnt);
        aom_img_write(img_shifted, outfile[img->spatial_id]);
        if (img->spatial_id == (int)(si.number_spatial_layers - 1))
          obu_ctx.last_layer_id = 0;
        else
          obu_ctx.last_layer_id++;
      } else {
        die_codec(&codec, "Invalid bitstream.  Layer id exceeds layer count");
      }
      if (img->spatial_id == (int)(si.number_spatial_layers - 1)) ++frame_cnt;
    }
  }

  printf("Processed %d frames.\n", frame_cnt);
  if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");

  for (i = 0; i < si.number_spatial_layers; i++) fclose(outfile[i]);

  fclose(inputfile);

  return EXIT_SUCCESS;
}
