diff options
Diffstat (limited to 'third_party/aom/common/obudec.c')
-rw-r--r-- | third_party/aom/common/obudec.c | 448 |
1 files changed, 0 insertions, 448 deletions
diff --git a/third_party/aom/common/obudec.c b/third_party/aom/common/obudec.c deleted file mode 100644 index acbd12e0c..000000000 --- a/third_party/aom/common/obudec.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * 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 <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "common/obudec.h" - -#include "aom_ports/mem_ops.h" -#include "av1/common/common.h" -#include "av1/common/obu_util.h" - -#define OBU_BUFFER_SIZE (500 * 1024) - -#define OBU_HEADER_SIZE 1 -#define OBU_EXTENSION_SIZE 1 -#define OBU_MAX_LENGTH_FIELD_SIZE 8 -#define OBU_DETECTION_SIZE \ - (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + 3 * OBU_MAX_LENGTH_FIELD_SIZE) - -// Reads unsigned LEB128 integer and returns 0 upon successful read and decode. -// Stores raw bytes in 'value_buffer', length of the number in 'value_length', -// and decoded value in 'value'. -static int obudec_read_leb128(FILE *f, uint8_t *value_buffer, - size_t *value_length, uint64_t *value) { - if (!f || !value_buffer || !value_length || !value) return -1; - size_t len; - for (len = 0; len < OBU_MAX_LENGTH_FIELD_SIZE; ++len) { - const size_t num_read = fread(&value_buffer[len], 1, 1, f); - if (num_read == 0) { - if (len == 0 && feof(f)) { - *value_length = 0; - return 0; - } - // Ran out of data before completing read of value. - return -1; - } - if ((value_buffer[len] >> 7) == 0) { - ++len; - *value_length = len; - break; - } - } - - return aom_uleb_decode(value_buffer, len, value, NULL); -} - -// Reads OBU header from 'f'. The 'buffer_capacity' passed in must be large -// enough to store an OBU header with extension (2 bytes). Raw OBU data is -// written to 'obu_data', parsed OBU header values are written to 'obu_header', -// and total bytes read from file are written to 'bytes_read'. Returns 0 for -// success, and non-zero on failure. When end of file is reached, the return -// value is 0 and the 'bytes_read' value is set to 0. -static int obudec_read_obu_header(FILE *f, size_t buffer_capacity, - int is_annexb, uint8_t *obu_data, - ObuHeader *obu_header, size_t *bytes_read) { - if (!f || buffer_capacity < (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE) || - !obu_data || !obu_header || !bytes_read) { - return -1; - } - *bytes_read = fread(obu_data, 1, 1, f); - - if (feof(f) && *bytes_read == 0) { - return 0; - } else if (*bytes_read != 1) { - fprintf(stderr, "obudec: Failure reading OBU header.\n"); - return -1; - } - - const int has_extension = (obu_data[0] >> 2) & 0x1; - if (has_extension) { - if (fread(&obu_data[1], 1, 1, f) != 1) { - fprintf(stderr, "obudec: Failure reading OBU extension."); - return -1; - } - ++*bytes_read; - } - - size_t obu_bytes_parsed = 0; - const aom_codec_err_t parse_result = aom_read_obu_header( - obu_data, *bytes_read, &obu_bytes_parsed, obu_header, is_annexb); - if (parse_result != AOM_CODEC_OK || *bytes_read != obu_bytes_parsed) { - fprintf(stderr, "obudec: Error parsing OBU header.\n"); - return -1; - } - - return 0; -} - -// Reads OBU payload from 'f' and returns 0 for success when all payload bytes -// are read from the file. Payload data is written to 'obu_data', and actual -// bytes read added to 'bytes_read'. -static int obudec_read_obu_payload(FILE *f, size_t payload_length, - uint8_t *obu_data, size_t *bytes_read) { - if (!f || payload_length == 0 || !obu_data || !bytes_read) return -1; - - if (fread(obu_data, 1, payload_length, f) != payload_length) { - fprintf(stderr, "obudec: Failure reading OBU payload.\n"); - return -1; - } - - *bytes_read += payload_length; - return 0; -} - -static int obudec_read_obu_header_and_size(FILE *f, size_t buffer_capacity, - int is_annexb, uint8_t *buffer, - size_t *bytes_read, - size_t *payload_length, - ObuHeader *obu_header) { - const size_t kMinimumBufferSize = - (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + OBU_MAX_LENGTH_FIELD_SIZE); - if (!f || !buffer || !bytes_read || !payload_length || !obu_header || - buffer_capacity < kMinimumBufferSize) { - return -1; - } - - size_t leb128_length = 0; - uint64_t obu_size = 0; - if (is_annexb) { - if (obudec_read_leb128(f, &buffer[0], &leb128_length, &obu_size) != 0) { - fprintf(stderr, "obudec: Failure reading OBU size length.\n"); - return -1; - } else if (leb128_length == 0) { - *payload_length = 0; - return 0; - } - if (obu_size > UINT32_MAX) { - fprintf(stderr, "obudec: OBU payload length too large.\n"); - return -1; - } - } - - size_t header_size = 0; - if (obudec_read_obu_header(f, buffer_capacity - leb128_length, is_annexb, - buffer + leb128_length, obu_header, - &header_size) != 0) { - return -1; - } else if (header_size == 0) { - *payload_length = 0; - return 0; - } - - if (is_annexb) { - if (obu_size < header_size) { - fprintf(stderr, "obudec: OBU size is too small.\n"); - return -1; - } - *payload_length = (size_t)obu_size - header_size; - } else { - uint64_t u64_payload_length = 0; - if (obudec_read_leb128(f, &buffer[header_size], &leb128_length, - &u64_payload_length) != 0) { - fprintf(stderr, "obudec: Failure reading OBU payload length.\n"); - return -1; - } - if (u64_payload_length > UINT32_MAX) { - fprintf(stderr, "obudec: OBU payload length too large.\n"); - return -1; - } - - *payload_length = (size_t)u64_payload_length; - } - - *bytes_read = leb128_length + header_size; - return 0; -} - -static int obudec_read_one_obu(FILE *f, uint8_t **obu_buffer, - size_t obu_bytes_buffered, - size_t *obu_buffer_capacity, size_t *obu_length, - ObuHeader *obu_header, int is_annexb) { - size_t available_buffer_capacity = *obu_buffer_capacity - obu_bytes_buffered; - - if (!(*obu_buffer)) return -1; - - size_t bytes_read = 0; - size_t obu_payload_length = 0; - const int status = obudec_read_obu_header_and_size( - f, available_buffer_capacity, is_annexb, *obu_buffer + obu_bytes_buffered, - &bytes_read, &obu_payload_length, obu_header); - if (status < 0) return status; - - if (obu_payload_length > SIZE_MAX - bytes_read) return -1; - - if (obu_payload_length > 256 * 1024 * 1024) { - fprintf(stderr, "obudec: Read invalid OBU size (%u)\n", - (unsigned int)obu_payload_length); - *obu_length = bytes_read + obu_payload_length; - return -1; - } - - if (bytes_read + obu_payload_length > available_buffer_capacity) { - // TODO(tomfinegan): Add overflow check. - const size_t new_capacity = - obu_bytes_buffered + bytes_read + 2 * obu_payload_length; - -#if defined AOM_MAX_ALLOCABLE_MEMORY - if (new_capacity > AOM_MAX_ALLOCABLE_MEMORY) { - fprintf(stderr, "obudec: OBU size exceeds max alloc size.\n"); - return -1; - } -#endif - - uint8_t *new_buffer = (uint8_t *)realloc(*obu_buffer, new_capacity); - - if (new_buffer) { - *obu_buffer = new_buffer; - *obu_buffer_capacity = new_capacity; - } else { - fprintf(stderr, "obudec: Failed to allocate compressed data buffer\n"); - *obu_length = bytes_read + obu_payload_length; - return -1; - } - } - - if (obu_payload_length > 0 && - obudec_read_obu_payload(f, obu_payload_length, - *obu_buffer + obu_bytes_buffered + bytes_read, - &bytes_read) != 0) { - return -1; - } - - *obu_length = bytes_read; - return 0; -} - -int file_is_obu(struct ObuDecInputContext *obu_ctx) { - if (!obu_ctx || !obu_ctx->avx_ctx) return 0; - - struct AvxInputContext *avx_ctx = obu_ctx->avx_ctx; - uint8_t detect_buf[OBU_DETECTION_SIZE] = { 0 }; - const int is_annexb = obu_ctx->is_annexb; - FILE *f = avx_ctx->file; - size_t payload_length = 0; - ObuHeader obu_header; - memset(&obu_header, 0, sizeof(obu_header)); - size_t length_of_unit_size = 0; - size_t annexb_header_length = 0; - uint64_t unit_size = 0; - - if (is_annexb) { - // read the size of first temporal unit - if (obudec_read_leb128(f, &detect_buf[0], &length_of_unit_size, - &unit_size) != 0) { - fprintf(stderr, "obudec: Failure reading temporal unit header\n"); - return 0; - } - - // read the size of first frame unit - if (obudec_read_leb128(f, &detect_buf[length_of_unit_size], - &annexb_header_length, &unit_size) != 0) { - fprintf(stderr, "obudec: Failure reading frame unit header\n"); - return 0; - } - annexb_header_length += length_of_unit_size; - } - - size_t bytes_read = 0; - if (obudec_read_obu_header_and_size( - f, OBU_DETECTION_SIZE - annexb_header_length, is_annexb, - &detect_buf[annexb_header_length], &bytes_read, &payload_length, - &obu_header) != 0) { - fprintf(stderr, "obudec: Failure reading first OBU.\n"); - rewind(f); - return 0; - } - - if (is_annexb) { - bytes_read += annexb_header_length; - } - - if (obu_header.type != OBU_TEMPORAL_DELIMITER && - obu_header.type != OBU_SEQUENCE_HEADER) { - return 0; - } - - if (obu_header.has_size_field) { - if (obu_header.type == OBU_TEMPORAL_DELIMITER && payload_length != 0) { - fprintf( - stderr, - "obudec: Invalid OBU_TEMPORAL_DELIMITER payload length (non-zero)."); - rewind(f); - return 0; - } - } else if (!is_annexb) { - fprintf(stderr, "obudec: OBU size fields required, cannot decode input.\n"); - rewind(f); - return 0; - } - - // Appears that input is valid Section 5 AV1 stream. - obu_ctx->buffer = (uint8_t *)malloc(OBU_BUFFER_SIZE); - if (!obu_ctx->buffer) { - fprintf(stderr, "Out of memory.\n"); - rewind(f); - return 0; - } - obu_ctx->buffer_capacity = OBU_BUFFER_SIZE; - - memcpy(obu_ctx->buffer, &detect_buf[0], bytes_read); - obu_ctx->bytes_buffered = bytes_read; - // If the first OBU is a SEQUENCE_HEADER, then it will have a payload. - // We need to read this in so that our buffer only contains complete OBUs. - if (payload_length > 0) { - if (payload_length > (obu_ctx->buffer_capacity - bytes_read)) { - fprintf(stderr, "obudec: First OBU's payload is too large\n"); - rewind(f); - return 0; - } - - size_t payload_bytes = 0; - const int status = obudec_read_obu_payload( - f, payload_length, &obu_ctx->buffer[bytes_read], &payload_bytes); - if (status < 0) { - rewind(f); - return 0; - } - obu_ctx->bytes_buffered += payload_bytes; - } - return 1; -} - -int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx, - uint8_t **buffer, size_t *bytes_read, - size_t *buffer_size) { - FILE *f = obu_ctx->avx_ctx->file; - if (!f) return -1; - - *buffer_size = 0; - *bytes_read = 0; - - if (feof(f)) { - return 1; - } - - size_t tu_size; - size_t obu_size = 0; - size_t length_of_temporal_unit_size = 0; - uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 }; - - if (obu_ctx->is_annexb) { - uint64_t size = 0; - - if (obu_ctx->bytes_buffered == 0) { - if (obudec_read_leb128(f, &tuheader[0], &length_of_temporal_unit_size, - &size) != 0) { - fprintf(stderr, "obudec: Failure reading temporal unit header\n"); - return -1; - } - if (size == 0 && feof(f)) { - return 1; - } - } else { - // temporal unit size was already stored in buffer - if (aom_uleb_decode(obu_ctx->buffer, obu_ctx->bytes_buffered, &size, - &length_of_temporal_unit_size) != 0) { - fprintf(stderr, "obudec: Failure reading temporal unit header\n"); - return -1; - } - } - - if (size > UINT32_MAX || size + length_of_temporal_unit_size > UINT32_MAX) { - fprintf(stderr, "obudec: TU too large.\n"); - return -1; - } - - size += length_of_temporal_unit_size; - tu_size = (size_t)size; - } else { - while (1) { - ObuHeader obu_header; - memset(&obu_header, 0, sizeof(obu_header)); - - if (obudec_read_one_obu(f, &obu_ctx->buffer, obu_ctx->bytes_buffered, - &obu_ctx->buffer_capacity, &obu_size, &obu_header, - 0) != 0) { - fprintf(stderr, "obudec: read_one_obu failed in TU loop\n"); - return -1; - } - - if (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0) { - tu_size = obu_ctx->bytes_buffered; - break; - } else { - obu_ctx->bytes_buffered += obu_size; - } - } - } - -#if defined AOM_MAX_ALLOCABLE_MEMORY - if (tu_size > AOM_MAX_ALLOCABLE_MEMORY) { - fprintf(stderr, "obudec: Temporal Unit size exceeds max alloc size.\n"); - return -1; - } -#endif - uint8_t *new_buffer = (uint8_t *)realloc(*buffer, tu_size); - if (!new_buffer) { - free(*buffer); - fprintf(stderr, "obudec: Out of memory.\n"); - return -1; - } - *buffer = new_buffer; - *bytes_read = tu_size; - *buffer_size = tu_size; - - if (!obu_ctx->is_annexb) { - memcpy(*buffer, obu_ctx->buffer, tu_size); - - // At this point, (obu_ctx->buffer + obu_ctx->bytes_buffered + obu_size) - // points to the end of the buffer. - memmove(obu_ctx->buffer, obu_ctx->buffer + obu_ctx->bytes_buffered, - obu_size); - obu_ctx->bytes_buffered = obu_size; - } else { - if (!feof(f)) { - size_t data_size; - size_t offset; - if (!obu_ctx->bytes_buffered) { - data_size = tu_size - length_of_temporal_unit_size; - memcpy(*buffer, &tuheader[0], length_of_temporal_unit_size); - offset = length_of_temporal_unit_size; - } else { - memcpy(*buffer, obu_ctx->buffer, obu_ctx->bytes_buffered); - offset = obu_ctx->bytes_buffered; - data_size = tu_size - obu_ctx->bytes_buffered; - obu_ctx->bytes_buffered = 0; - } - - if (fread(*buffer + offset, 1, data_size, f) != data_size) { - fprintf(stderr, "obudec: Failed to read full temporal unit\n"); - return -1; - } - } - } - return 0; -} - -void obudec_free(struct ObuDecInputContext *obu_ctx) { free(obu_ctx->buffer); } |