/*
 * Copyright (c) 2017, 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 <cstdio>
#include <string>

// TODO(tomfinegan): Remove the aom_config.h include as soon as possible. At
// present it's required because w/out aom_config.h it's impossible to know how
// Obus are being written out by the library (because
// CONFIG_ADD_4BYTES_OBUSIZE).
#include "./aom_config.h"

#if !CONFIG_ADD_4BYTES_OBUSIZE || !CONFIG_OBU
#error "obu_parser.cc requires CONFIG_ADD_4BYTES_OBUSIZE and CONFIG_OBU"
#endif

#include "aom_ports/mem_ops.h"
#include "tools/obu_parser.h"

namespace {
const aom_tools::ObuExtensionHeader kEmptyObuExt = { 0, 0, 0, false };
const aom_tools::ObuHeader kEmptyObu = { 0, 0, false, kEmptyObuExt };
}  // namespace

namespace aom_tools {

// Basic OBU syntax
// 4 bytes: length
// 8 bits: Header
//   7
//     forbidden bit
//   6,5,4,3
//     type bits
//   2,1
//     reserved bits
//   0
//     extension bit
const uint32_t kObuForbiddenBitMask = 0x1;
const uint32_t kObuForbiddenBitShift = 7;
const uint32_t kObuTypeBitsMask = 0xF;
const uint32_t kObuTypeBitsShift = 3;
const uint32_t kObuReservedBitsMask = 0x3;
const uint32_t kObuReservedBitsShift = 1;
const uint32_t kObuExtensionFlagBitMask = 0x1;

// When extension bit is set:
// 8 bits: extension header
// 7,6,5
//   temporal ID
// 4,3
//   spatial ID
// 2,1
//   quality ID
// 0
//   reserved bit
const uint32_t kObuExtTemporalIdBitsMask = 0x7;
const uint32_t kObuExtTemporalIdBitsShift = 5;
const uint32_t kObuExtSpatialIdBitsMask = 0x3;
const uint32_t kObuExtSpatialIdBitsShift = 3;
const uint32_t kObuExtQualityIdBitsMask = 0x3;
const uint32_t kObuExtQualityIdBitsShift = 1;
const uint32_t kObuExtReservedFlagBit = 0x1;

bool ValidObuType(int obu_type) {
  switch (obu_type) {
    case OBU_SEQUENCE_HEADER:
    case OBU_TEMPORAL_DELIMITER:
    case OBU_FRAME_HEADER:
    case OBU_TILE_GROUP:
    case OBU_METADATA:
    case OBU_PADDING: return true;
  }
  return false;
}

bool ParseObuHeader(uint8_t obu_header_byte, ObuHeader *obu_header) {
  const int forbidden_bit =
      (obu_header_byte >> kObuForbiddenBitShift) & kObuForbiddenBitMask;
  if (forbidden_bit) {
    fprintf(stderr, "Invalid OBU, forbidden bit set.\n");
    return false;
  }

  obu_header->type = (obu_header_byte >> kObuTypeBitsShift) & kObuTypeBitsMask;
  if (!ValidObuType(obu_header->type)) {
    fprintf(stderr, "Invalid OBU type: %d.\n", obu_header->type);
    return false;
  }

  obu_header->reserved =
      (obu_header_byte >> kObuReservedBitsShift) & kObuReservedBitsMask;
  if (obu_header->reserved != 0) {
    fprintf(stderr, "Invalid OBU: reserved bit(s) set.\n");
    return false;
  }

  obu_header->has_extension = obu_header_byte & kObuExtensionFlagBitMask;
  return true;
}

bool ParseObuExtensionHeader(uint8_t ext_header_byte,
                             ObuExtensionHeader *ext_header) {
  ext_header->temporal_id = (ext_header_byte >> kObuExtTemporalIdBitsShift) &
                            kObuExtTemporalIdBitsMask;
  ext_header->spatial_id =
      (ext_header_byte >> kObuExtSpatialIdBitsShift) & kObuExtSpatialIdBitsMask;
  ext_header->quality_id =
      (ext_header_byte >> kObuExtQualityIdBitsShift) & kObuExtQualityIdBitsMask;
  ext_header->reserved_flag = ext_header_byte & kObuExtReservedFlagBit;

  if (ext_header->reserved_flag) {
    fprintf(stderr, "Invalid OBU Extension: reserved flag set.\n");
    return false;
  }

  return true;
}

std::string ObuTypeToString(int obu_type) {
  switch (obu_type) {
    case OBU_SEQUENCE_HEADER: return "OBU_SEQUENCE_HEADER";
    case OBU_TEMPORAL_DELIMITER: return "OBU_TEMPORAL_DELIMITER";
    case OBU_FRAME_HEADER: return "OBU_FRAME_HEADER";
    case OBU_TILE_GROUP: return "OBU_TILE_GROUP";
    case OBU_METADATA: return "OBU_METADATA";
    case OBU_PADDING: return "OBU_PADDING";
  }
  return "";
}

void PrintObuHeader(const ObuHeader *header) {
  printf(
      "  OBU type:        %s\n"
      "      extension:   %s\n",
      ObuTypeToString(header->type).c_str(),
      header->has_extension ? "yes" : "no");
  if (header->has_extension) {
    printf(
        "      temporal_id: %d\n"
        "      spatial_id:  %d\n"
        "      quality_id:  %d\n",
        header->ext_header.temporal_id, header->ext_header.spatial_id,
        header->ext_header.quality_id);
  }
}

bool DumpObu(const uint8_t *data, int length) {
  const int kObuLengthFieldSizeBytes = 4;  // Assumes CONFIG_ADD_4BYTES_OBUSIZE.
  const int kObuHeaderLengthSizeBytes = 1;
  const int kMinimumBytesRequired =
      kObuLengthFieldSizeBytes + kObuHeaderLengthSizeBytes;
  int consumed = 0;
  ObuHeader obu_header;
  while (consumed < length) {
    const int remaining = length - consumed;
    if (remaining < kMinimumBytesRequired) {
      if (remaining > 0) {
        fprintf(stderr,
                "OBU parse error. Did not consume all data, %d bytes "
                "remain.\n",
                remaining);
      }
      return false;
    }

    const int current_obu_length = mem_get_le32(data + consumed);
    if (current_obu_length > remaining) {
      fprintf(stderr,
              "OBU parsing failed at offset %d with bad length of %d "
              "and %d bytes left.\n",
              consumed, current_obu_length, remaining);
      return false;
    }
    consumed += kObuLengthFieldSizeBytes;

    obu_header = kEmptyObu;
    const uint8_t obu_header_byte = *(data + consumed);
    if (!ParseObuHeader(obu_header_byte, &obu_header)) {
      fprintf(stderr, "OBU parsing failed at offset %d.\n", consumed);
      return false;
    }

    if (obu_header.has_extension) {
      const uint8_t obu_ext_header_byte =
          *(data + consumed + kObuHeaderLengthSizeBytes);
      if (!ParseObuExtensionHeader(obu_ext_header_byte,
                                   &obu_header.ext_header)) {
        fprintf(stderr, "OBU extension parsing failed at offset %d.\n",
                consumed);
        return false;
      }
    }

    PrintObuHeader(&obu_header);

    // TODO(tomfinegan): Parse OBU payload. For now just consume it.
    consumed += current_obu_length;
  }

  return true;
}

}  // namespace aom_tools
