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;
}