replace Annex-B with Annex-B-prime Annex-B-prime has been fully adopted. Replace Annex-B with Annex-B-prime for encoding/decoding BUG=aomedia:1700 Change-Id: Ib1478daf9d78fd9684911e343b407b91c969e691
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 6f6bd4f..3471886 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c
@@ -1270,6 +1270,55 @@ if (frame_size) { if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data; + const int write_temporal_delimiter = + !cpi->common.enhancement_layer_id && !ctx->pending_frame_count; + + if (write_temporal_delimiter) { + uint32_t obu_header_size = 1; + const uint32_t obu_payload_size = 0; + const size_t length_field_size = + aom_uleb_size_in_bytes(obu_payload_size); + + if (ctx->pending_cx_data) { + const size_t move_offset = length_field_size + 1; + memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data, + frame_size); + } + const uint32_t obu_header_offset = 0; + obu_header_size = write_obu_header( + OBU_TEMPORAL_DELIMITER, 0, + (uint8_t *)(ctx->pending_cx_data + obu_header_offset)); + + // OBUs are preceded/succeeded by an unsigned leb128 coded integer. + if (write_uleb_obu_size(obu_header_size, obu_payload_size, + ctx->pending_cx_data) != AOM_CODEC_OK) { + return AOM_CODEC_ERROR; + } + + frame_size += obu_header_size + obu_payload_size + length_field_size; + } + + if (ctx->oxcf.save_as_annexb) { + size_t curr_frame_size = frame_size; + if (av1_convert_sect5obus_to_annexb(cx_data, &curr_frame_size) != + AOM_CODEC_OK) { + return AOM_CODEC_ERROR; + } + frame_size = curr_frame_size; + + // B_PRIME (add frame size) + const size_t length_field_size = aom_uleb_size_in_bytes(frame_size); + if (ctx->pending_cx_data) { + const size_t move_offset = length_field_size; + memmove(cx_data + move_offset, cx_data, frame_size); + } + if (write_uleb_obu_size(0, (uint32_t)frame_size, cx_data) != + AOM_CODEC_OK) { + return AOM_CODEC_ERROR; + } + frame_size += length_field_size; + } + ctx->pending_frame_sizes[ctx->pending_frame_count++] = frame_size; ctx->pending_cx_data_sz += frame_size; @@ -1285,51 +1334,28 @@ // Add the frame packet to the list of returned packets. aom_codec_cx_pkt_t pkt; + if (ctx->oxcf.save_as_annexb) { + // B_PRIME (add TU size) + size_t tu_size = ctx->pending_cx_data_sz; + const size_t length_field_size = aom_uleb_size_in_bytes(tu_size); + if (ctx->pending_cx_data) { + const size_t move_offset = length_field_size; + memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data, + tu_size); + } + if (write_uleb_obu_size(0, (uint32_t)tu_size, ctx->pending_cx_data) != + AOM_CODEC_OK) { + return AOM_CODEC_ERROR; + } + ctx->pending_cx_data_sz += length_field_size; + } + pkt.kind = AOM_CODEC_CX_FRAME_PKT; pkt.data.frame.buf = ctx->pending_cx_data; pkt.data.frame.sz = ctx->pending_cx_data_sz; pkt.data.frame.partition_id = -1; - int write_temporal_delimiter = 1; - // only write OBU_TD if base layer - write_temporal_delimiter = !cpi->common.enhancement_layer_id; - if (write_temporal_delimiter) { - // move data and insert OBU_TD preceded by optional 4 byte size - uint32_t obu_header_size = 1; - const uint32_t obu_payload_size = 0; - const size_t length_field_size = - aom_uleb_size_in_bytes(obu_payload_size); - - if (ctx->pending_cx_data) { - const size_t move_offset = length_field_size + 1; - memmove(ctx->pending_cx_data + move_offset, ctx->pending_cx_data, - ctx->pending_cx_data_sz); - } - const uint32_t obu_header_offset = 0; - obu_header_size = write_obu_header( - OBU_TEMPORAL_DELIMITER, 0, - (uint8_t *)(ctx->pending_cx_data + obu_header_offset)); - - // OBUs are preceded/succeeded by an unsigned leb128 coded integer. - if (write_uleb_obu_size(obu_header_size, obu_payload_size, - ctx->pending_cx_data) != AOM_CODEC_OK) { - return AOM_CODEC_ERROR; - } - - pkt.data.frame.sz += - obu_header_size + obu_payload_size + length_field_size; - } - - if (ctx->oxcf.save_as_annexb) { - size_t curr_frame_size = pkt.data.frame.sz; - if (av1_convert_sect5obus_to_annexb(ctx->pending_cx_data, - &curr_frame_size) != AOM_CODEC_OK) { - return AOM_CODEC_ERROR; - } - pkt.data.frame.sz = curr_frame_size; - } - pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp); pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags); pkt.data.frame.duration = (uint32_t)ticks_to_timebase_units(
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c index f3ae661..64e3844 100644 --- a/av1/av1_dx_iface.c +++ b/av1/av1_dx_iface.c
@@ -477,6 +477,17 @@ if (res != AOM_CODEC_OK) return res; } + if (ctx->is_annexb) { + // read the size of this temporal unit + size_t length_of_size; + uint64_t size_of_unit; + if (aom_uleb_decode(data_start, data_sz, &size_of_unit, &length_of_size) != + 0) { + return AOM_CODEC_CORRUPT_FRAME; + } + data_start += length_of_size; + } + // Decode in serial mode. if (frame_count > 0) { int i; @@ -496,6 +507,17 @@ } } else { while (data_start < data_end) { + if (ctx->is_annexb) { + // read the size of this frame unit + size_t length_of_size; + uint64_t size_of_frame_unit; + if (aom_uleb_decode(data_start, (uint32_t)(data_end - data_start), + &size_of_frame_unit, &length_of_size) != 0) { + return AOM_CODEC_CORRUPT_FRAME; + } + data_start += length_of_size; + } + const uint32_t frame_size = (uint32_t)(data_end - data_start); res = decode_one(ctx, &data_start, frame_size, user_priv); if (res != AOM_CODEC_OK) return res;
diff --git a/obudec.c b/obudec.c index 0974178..988457b 100644 --- a/obudec.c +++ b/obudec.c
@@ -25,7 +25,7 @@ #define OBU_EXTENSION_SIZE 1 #define OBU_MAX_LENGTH_FIELD_SIZE 8 #define OBU_DETECTION_SIZE \ - (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + OBU_MAX_LENGTH_FIELD_SIZE) + (OBU_HEADER_SIZE + OBU_EXTENSION_SIZE + 2 * 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', @@ -209,9 +209,30 @@ uint64_t obu_length = 0; ObuHeader obu_header; memset(&obu_header, 0, sizeof(obu_header)); + size_t length_of_unit_size = 0; + uint64_t unit_size; + size_t annexb_header_length = 0; - if (obudec_read_one_obu(f, OBU_DETECTION_SIZE, is_annexb, &detect_buf[0], - &obu_length, &obu_header) != 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; + } + + if (obudec_read_one_obu(f, OBU_DETECTION_SIZE, is_annexb, + &detect_buf[annexb_header_length], &obu_length, + &obu_header) != 0) { fprintf(stderr, "obudec: Failure reading first OBU.\n"); rewind(f); return 0; @@ -250,6 +271,10 @@ return 0; } obu_ctx->buffer_capacity = OBU_BUFFER_SIZE; + + if (is_annexb) { + obu_length += annexb_header_length; + } memcpy(obu_ctx->buffer, &detect_buf[0], (size_t)obu_length); obu_ctx->bytes_buffered = (size_t)obu_length; @@ -269,51 +294,102 @@ return 1; } - const int is_annexb = obu_ctx->is_annexb; - while (1) { - ObuHeader obu_header; - memset(&obu_header, 0, sizeof(obu_header)); + size_t tu_size; + uint64_t obu_size = 0; + uint8_t *data = obu_ctx->buffer; + size_t length_of_temporal_unit_size = 0; + uint8_t tuheader[OBU_MAX_LENGTH_FIELD_SIZE] = { 0 }; - uint64_t obu_size = 0; - uint8_t *data = obu_ctx->buffer + obu_ctx->bytes_buffered; - const size_t capacity = obu_ctx->buffer_capacity - obu_ctx->bytes_buffered; + if (obu_ctx->is_annexb) { + uint64_t size = 0; - if (obudec_read_one_obu(f, capacity, is_annexb, data, &obu_size, - &obu_header) != 0) { - fprintf(stderr, "obudec: read_one_obu failed in TU loop\n"); - return -1; + 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 (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0 || - (obu_header.has_extension && - obu_header.enhancement_layer_id > obu_ctx->last_layer_id)) { - const size_t tu_size = obu_ctx->bytes_buffered; + 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 defined AOM_MAX_ALLOCABLE_MEMORY - if (tu_size > AOM_MAX_ALLOCABLE_MEMORY) { - fprintf(stderr, "obudec: Temporal Unit size exceeds max alloc size.\n"); + data = obu_ctx->buffer + obu_ctx->bytes_buffered; + const size_t capacity = + obu_ctx->buffer_capacity - obu_ctx->bytes_buffered; + + 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"); 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; - memcpy(*buffer, obu_ctx->buffer, tu_size); - memmove(obu_ctx->buffer, data, (size_t)obu_size); - obu_ctx->bytes_buffered = (size_t)obu_size; - break; - } else { - obu_ctx->bytes_buffered += (size_t)obu_size; + if (obu_header.type == OBU_TEMPORAL_DELIMITER || obu_size == 0 || + (obu_header.has_extension && + obu_header.enhancement_layer_id > obu_ctx->last_layer_id)) { + tu_size = obu_ctx->bytes_buffered; + break; + } else { + obu_ctx->bytes_buffered += (size_t)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); + memmove(obu_ctx->buffer, data, (size_t)obu_size); + obu_ctx->bytes_buffered = (size_t)obu_size; + } else { + if (!feof(f)) { + size_t data_size; + size_t offset; + if (!obu_ctx->bytes_buffered) { + data_size = (uint32_t)(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(new_buffer + offset, 1, data_size, f) != data_size) { + fprintf(stderr, "obudec: Failed to read full temporal unit\n"); + return -1; + } + } + } return 0; }