Commit 4beef21b authored by Imdad Sardharwalla's avatar Imdad Sardharwalla

Dynamically-sized buffer in obudec.c

The buffer used to read data from .obu files is set to be
OBU_BUFFER_SIZE = 500 KiB. Because of this, prior to this patch
a temporal unit of > 500KiB resulted in an error (when reading a
non-annex_b stream), causing decoding to halt.

This patch dynamically increases the size of the buffer as it is
needed.

BUG=aomedia:1812

Change-Id: Ie2f4a85efea37d37b9d41f182cdf31913a82e5cb
parent eede8351
...@@ -162,28 +162,50 @@ static int obudec_read_obu_header_and_size(FILE *f, size_t buffer_capacity, ...@@ -162,28 +162,50 @@ static int obudec_read_obu_header_and_size(FILE *f, size_t buffer_capacity,
return 0; return 0;
} }
static int obudec_read_one_obu(FILE *f, size_t buffer_capacity, int is_annexb, static int obudec_read_one_obu(FILE *f, uint8_t **obu_buffer,
uint8_t *obu_data, uint64_t *obu_length, size_t obu_bytes_buffered,
ObuHeader *obu_header) { size_t *obu_buffer_capacity,
if (!obu_data) { uint64_t *obu_length, ObuHeader *obu_header,
return -1; int is_annexb) {
} uint64_t available_buffer_capacity =
*obu_buffer_capacity - obu_bytes_buffered;
if (!(*obu_buffer)) return -1;
uint64_t obu_payload_length = 0; uint64_t obu_payload_length = 0;
uint64_t bytes_read = 0; uint64_t bytes_read = 0;
const int status = obudec_read_obu_header_and_size( const int status = obudec_read_obu_header_and_size(
f, buffer_capacity, is_annexb, obu_data, &bytes_read, &obu_payload_length, f, available_buffer_capacity, is_annexb, *obu_buffer + obu_bytes_buffered,
obu_header); &bytes_read, &obu_payload_length, obu_header);
if (status < 0) return status; if (status < 0) return status;
if (UINT64_MAX - bytes_read < obu_payload_length) return -1; if (obu_payload_length > UINT64_MAX - bytes_read) return -1;
if (bytes_read + obu_payload_length > buffer_capacity) {
if (obu_payload_length > 256 * 1024 * 1024) {
warn("obudec: Read invalid OBU size (%u)\n",
(unsigned int)obu_payload_length);
*obu_length = bytes_read + obu_payload_length; *obu_length = bytes_read + obu_payload_length;
return -1; return -1;
} }
if (bytes_read + obu_payload_length > available_buffer_capacity) {
uint64_t new_capacity =
obu_bytes_buffered + bytes_read + 2 * obu_payload_length;
uint8_t *new_buffer = (uint8_t *)realloc(*obu_buffer, new_capacity);
if (new_buffer) {
*obu_buffer = new_buffer;
*obu_buffer_capacity = new_capacity;
} else {
warn("obudec: Failed to allocate compressed data buffer\n");
*obu_length = bytes_read + obu_payload_length;
return -1;
}
}
if (obu_payload_length > 0 && if (obu_payload_length > 0 &&
obudec_read_obu_payload(f, obu_payload_length, &obu_data[bytes_read], obudec_read_obu_payload(f, obu_payload_length,
*obu_buffer + obu_bytes_buffered + bytes_read,
&bytes_read) != 0) { &bytes_read) != 0) {
return -1; return -1;
} }
...@@ -302,7 +324,6 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx, ...@@ -302,7 +324,6 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx,
uint64_t tu_size; uint64_t tu_size;
uint64_t obu_size = 0; uint64_t obu_size = 0;
uint8_t *data = obu_ctx->buffer;
uint64_t length_of_temporal_unit_size = 0; uint64_t length_of_temporal_unit_size = 0;
uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 }; uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 };
...@@ -336,12 +357,9 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx, ...@@ -336,12 +357,9 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx,
ObuHeader obu_header; ObuHeader obu_header;
memset(&obu_header, 0, sizeof(obu_header)); memset(&obu_header, 0, sizeof(obu_header));
data = obu_ctx->buffer + obu_ctx->bytes_buffered; if (obudec_read_one_obu(f, &obu_ctx->buffer, obu_ctx->bytes_buffered,
const size_t capacity = &obu_ctx->buffer_capacity, &obu_size, &obu_header,
obu_ctx->buffer_capacity - obu_ctx->bytes_buffered; 0) != 0) {
if (obudec_read_one_obu(f, capacity, 0, data, &obu_size, &obu_header) !=
0) {
fprintf(stderr, "obudec: read_one_obu failed in TU loop\n"); fprintf(stderr, "obudec: read_one_obu failed in TU loop\n");
return -1; return -1;
} }
...@@ -375,7 +393,12 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx, ...@@ -375,7 +393,12 @@ int obudec_read_temporal_unit(struct ObuDecInputContext *obu_ctx,
if (!obu_ctx->is_annexb) { if (!obu_ctx->is_annexb) {
memcpy(*buffer, obu_ctx->buffer, (size_t)tu_size); memcpy(*buffer, obu_ctx->buffer, (size_t)tu_size);
memmove(obu_ctx->buffer, data, (size_t)obu_size);
// At this point, (obu_ctx->buffer + obu_ctx->bytes_buffered) points to the
// end of the buffer.
memmove(obu_ctx->buffer,
obu_ctx->buffer + obu_ctx->bytes_buffered - obu_size,
(size_t)obu_size);
obu_ctx->bytes_buffered = (size_t)obu_size; obu_ctx->bytes_buffered = (size_t)obu_size;
} else { } else {
if (!feof(f)) { if (!feof(f)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment