Write LEB128 OBU size fields.
Removes padding bytes.
BUG=aomedia:1125
Change-Id: Ib9bce81a86aa218abeeba8e027387634aaa89b92
diff --git a/aom/src/aom_integer.c b/aom/src/aom_integer.c
index 1fd9a84..23a0a8c 100644
--- a/aom/src/aom_integer.c
+++ b/aom/src/aom_integer.c
@@ -28,6 +28,7 @@
for (size_t i = 0; i < kMaximumLeb128Size && i < available; ++i) {
const uint8_t decoded_byte = *(buffer + i) & kLeb128ByteMask;
*value |= decoded_byte << (i * 7);
+ if ((*(buffer + i) >> 7) == 0) break;
}
}
}
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 3304634..10939f9 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1267,10 +1267,6 @@
return flags;
}
-#if CONFIG_OBU
-static uint32_t write_temporal_delimiter_obu() { return 0; }
-#endif
-
static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
const aom_image_t *img,
aom_codec_pts_t pts,
@@ -1436,15 +1432,19 @@
// move data PRE_OBU_SIZE_BYTES + 1 bytes and insert OBU_TD preceded by
// optional 4 byte size
uint32_t obu_size = 1;
+#if CONFIG_OBU_SIZING
+ const size_t length_field_size = aom_uleb_size_in_bytes(obu_size);
+#else
+ const size_t length_field_size = PRE_OBU_SIZE_BYTES;
+#endif
if (ctx->pending_cx_data) {
- const size_t index_sz = PRE_OBU_SIZE_BYTES + 1;
- memmove(ctx->pending_cx_data + index_sz, ctx->pending_cx_data,
+ const size_t obu_header_size = length_field_size + 1;
+ memmove(ctx->pending_cx_data + obu_header_size, ctx->pending_cx_data,
ctx->pending_cx_data_sz);
}
obu_size = write_obu_header(
OBU_TEMPORAL_DELIMITER, 0,
- (uint8_t *)(ctx->pending_cx_data + PRE_OBU_SIZE_BYTES));
- obu_size += write_temporal_delimiter_obu();
+ (uint8_t *)(ctx->pending_cx_data + length_field_size));
#if CONFIG_OBU_SIZING
// OBUs are preceded by an unsigned leb128 coded unsigned integer padded
// to PRE_OBU_SIZE_BYTES bytes.
@@ -1453,7 +1453,7 @@
#else
mem_put_le32(ctx->pending_cx_data, obu_size);
#endif // CONFIG_OBU_SIZING
- pkt.data.frame.sz += (obu_size + PRE_OBU_SIZE_BYTES);
+ pkt.data.frame.sz += obu_size + length_field_size;
}
#endif // CONFIG_OBU
diff --git a/av1/common/common.h b/av1/common/common.h
index 286c1f1..b051921 100644
--- a/av1/common/common.h
+++ b/av1/common/common.h
@@ -54,8 +54,13 @@
#define AOM_FRAME_MARKER 0x2
-// Size of OBU length field.
+#if CONFIG_OBU_SIZING
+// Variable size LEB128 unsigned integer length field.
+#define PRE_OBU_SIZE_BYTES 0
+#else
+// Fixed size OBU length field.
#define PRE_OBU_SIZE_BYTES 4
+#endif
#ifdef __cplusplus
} // extern "C"
diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c
index e1ed8eb..e49faae 100644
--- a/av1/decoder/obu.c
+++ b/av1/decoder/obu.c
@@ -148,7 +148,6 @@
// TODO(shan): For now, assume all tile groups received in order
*is_last_tg = endTile == cm->tile_rows * cm->tile_cols - 1;
-
return header_size + tg_payload_size;
}
@@ -273,21 +272,29 @@
while (!frame_decoding_finished && !cm->error.error_code) {
struct aom_read_bit_buffer rb;
size_t obu_header_size, obu_payload_size = 0;
- av1_init_read_bit_buffer(pbi, &rb, data + PRE_OBU_SIZE_BYTES, data_end);
+ const size_t bytes_available = data_end - data;
+
+ if (bytes_available < 1) {
+ cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
+ return;
+ }
#if CONFIG_OBU_SIZING
- // OBUs are preceded by an unsigned leb128 coded unsigned integer padded to
- // PRE_OBU_SIZE_BYTES bytes.
+ // OBUs are preceded by an unsigned leb128 coded unsigned integer.
uint32_t u_obu_size = 0;
- aom_uleb_decode(data, PRE_OBU_SIZE_BYTES, &u_obu_size);
+ aom_uleb_decode(data, bytes_available, &u_obu_size);
const size_t obu_size = (size_t)u_obu_size;
+ const size_t length_field_size = aom_uleb_size_in_bytes(u_obu_size);
#else
// every obu is preceded by PRE_OBU_SIZE_BYTES-byte size of obu (obu header
// + payload size)
// The obu size is only needed for tile group OBUs
const size_t obu_size = mem_get_le32(data);
+ const size_t length_field_size = PRE_OBU_SIZE_BYTES;
#endif // CONFIG_OBU_SIZING
+ av1_init_read_bit_buffer(pbi, &rb, data + length_field_size, data_end);
+
#if !CONFIG_SCALABILITY
const OBU_TYPE obu_type = read_obu_header(&rb, &obu_header_size, NULL);
#else
@@ -295,7 +302,7 @@
read_obu_header(&rb, &obu_header_size, &obu_extension_header);
#endif
- data += (PRE_OBU_SIZE_BYTES + obu_header_size);
+ data += length_field_size + obu_header_size;
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return;
@@ -339,6 +346,7 @@
break;
default: break;
}
+
data += obu_payload_size;
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index e7c6200..9416be5 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -4509,13 +4509,8 @@
int write_uleb_obu_size(uint32_t obu_size, uint8_t *dest) {
size_t coded_obu_size = 0;
- // Encode an unsigned leb128 coded unsigned integer padded to
- // PRE_OBU_SIZE_BYTES bytes.
- if (aom_uleb_encode_fixed_size(obu_size, PRE_OBU_SIZE_BYTES,
- PRE_OBU_SIZE_BYTES, dest, &coded_obu_size) ||
- coded_obu_size != PRE_OBU_SIZE_BYTES) {
+ if (aom_uleb_encode(obu_size, sizeof(uint32_t), dest, &coded_obu_size) != 0)
return AOM_CODEC_ERROR;
- }
return AOM_CODEC_OK;
}
@@ -4610,12 +4605,9 @@
static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
unsigned int *max_tile_size,
unsigned int *max_tile_col_size,
- uint8_t *const frame_header_obu_location,
- uint32_t frame_header_obu_size,
#if CONFIG_EXT_TILE
struct aom_write_bit_buffer *saved_wb,
#endif
- int insert_frame_header_obu_flag,
uint8_t obu_extension_header) {
AV1_COMMON *const cm = &cpi->common;
aom_writer mode_bc;
@@ -4771,14 +4763,6 @@
int is_last_tile_in_tg = 0;
if (new_tg) {
- if (insert_frame_header_obu_flag && tile_idx) {
- // insert a copy of frame header OBU (including
- // PRE_OBU_SIZE_BYTES-byte size),
- // except before the first tile group
- data = dst + total_size;
- memmove(data, frame_header_obu_location, frame_header_obu_size);
- total_size += frame_header_obu_size;
- }
data = dst + total_size;
// A new tile group begins at this tile. Write the obu header and
// tile group header
@@ -4844,8 +4828,13 @@
} else {
// write current tile group size
#if CONFIG_OBU_SIZING
+ const size_t length_field_size =
+ aom_uleb_size_in_bytes(curr_tg_data_size);
+ memmove(data + length_field_size, data, curr_tg_data_size);
if (write_uleb_obu_size(curr_tg_data_size, data) != AOM_CODEC_OK)
assert(0);
+ curr_tg_data_size += length_field_size;
+ total_size += length_field_size;
#else
mem_put_le32(data, curr_tg_data_size);
#endif // CONFIG_OBU_SIZING
@@ -4870,8 +4859,6 @@
#if CONFIG_OBU
AV1_COMMON *const cm = &cpi->common;
uint32_t obu_size;
- uint8_t *frame_header_location;
- uint32_t frame_header_size;
#if CONFIG_SCALABILITY
const uint8_t enhancement_layers_cnt = cm->enhancement_layers_cnt;
const uint8_t obu_extension_header =
@@ -4893,21 +4880,26 @@
obu_size =
write_obu_header(OBU_SEQUENCE_HEADER, 0, data + PRE_OBU_SIZE_BYTES);
- obu_size += write_sequence_header_obu(
#if CONFIG_SCALABILITY
+ obu_size += write_sequence_header_obu(
cpi, data + PRE_OBU_SIZE_BYTES + obu_size, enhancement_layers_cnt);
#else
- cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
+ obu_size +=
+ write_sequence_header_obu(cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
#endif // CONFIG_SCALABILITY
#if CONFIG_OBU_SIZING
+ const size_t length_field_size = aom_uleb_size_in_bytes(obu_size);
+ memmove(data + length_field_size, data, obu_size);
+
if (write_uleb_obu_size(obu_size, data) != AOM_CODEC_OK)
return AOM_CODEC_ERROR;
#else
+ const size_t length_field_size = PRE_OBU_SIZE_BYTES;
mem_put_le32(data, obu_size);
#endif // CONFIG_OBU_SIZING
- data += obu_size + PRE_OBU_SIZE_BYTES;
+ data += obu_size + length_field_size;
}
#if CONFIG_EXT_TILE
@@ -4915,39 +4907,37 @@
#endif
// write frame header obu, preceded by 4-byte size
- frame_header_location = data + PRE_OBU_SIZE_BYTES;
obu_size = write_obu_header(OBU_FRAME_HEADER, obu_extension_header,
- frame_header_location);
- frame_header_size =
- write_frame_header_obu(cpi,
+ data + PRE_OBU_SIZE_BYTES);
+ obu_size += write_frame_header_obu(cpi,
#if CONFIG_EXT_TILE
- &saved_wb,
+ &saved_wb,
#endif
- data + PRE_OBU_SIZE_BYTES + obu_size);
- obu_size += frame_header_size;
+ data + PRE_OBU_SIZE_BYTES + obu_size);
#if CONFIG_OBU_SIZING
+ const size_t length_field_size = aom_uleb_size_in_bytes(obu_size);
+ memmove(data + length_field_size, data, obu_size);
if (write_uleb_obu_size(obu_size, data) != AOM_CODEC_OK)
return AOM_CODEC_ERROR;
#else
+ const size_t length_field_size = PRE_OBU_SIZE_BYTES;
mem_put_le32(data, obu_size);
#endif // CONFIG_OBU_SIZING
- data += obu_size + PRE_OBU_SIZE_BYTES;
+ data += obu_size + length_field_size;
if (cm->show_existing_frame) {
data_size = 0;
} else {
// Each tile group obu will be preceded by 4-byte size of the tile group
// obu
- data_size = write_tiles_in_tg_obus(
- cpi, data, &max_tile_size, &max_tile_col_size,
- frame_header_location - PRE_OBU_SIZE_BYTES,
- obu_size + PRE_OBU_SIZE_BYTES,
+ data_size =
+ write_tiles_in_tg_obus(cpi, data, &max_tile_size, &max_tile_col_size,
#if CONFIG_EXT_TILE
- &saved_wb,
+ &saved_wb,
#endif
- 1 /* cm->error_resilient_mode */, obu_extension_header);
+ obu_extension_header);
}
#endif // CONFIG_OBU
@@ -4969,7 +4959,7 @@
if (cm->show_existing_frame) {
*size = aom_wb_bytes_written(&wb);
- return;
+ return AOM_CODEC_OK;
}
// We do not know these in advance. Output placeholder bit.
diff --git a/test/aom_integer_test.cc b/test/aom_integer_test.cc
index 7c1535b..4daa64b 100644
--- a/test/aom_integer_test.cc
+++ b/test/aom_integer_test.cc
@@ -30,6 +30,10 @@
uint32_t value = 0;
aom_uleb_decode(&leb128_bytes[0], num_leb128_bytes, &value);
ASSERT_EQ(expected_value, value);
+
+ // Make sure the decoder stops on the last marked LEB128 byte.
+ aom_uleb_decode(&leb128_bytes[0], num_leb128_bytes + 1, &value);
+ ASSERT_EQ(expected_value, value);
}
TEST(AomLeb128, EncodeTest) {
diff --git a/tools/obu_parser.cc b/tools/obu_parser.cc
index d63a484..667019a 100644
--- a/tools/obu_parser.cc
+++ b/tools/obu_parser.cc
@@ -153,10 +153,8 @@
}
bool DumpObu(const uint8_t *data, int length) {
- const int kObuLengthFieldSizeBytes = 4;
const int kObuHeaderLengthSizeBytes = 1;
- const int kMinimumBytesRequired =
- kObuLengthFieldSizeBytes + kObuHeaderLengthSizeBytes;
+ const int kMinimumBytesRequired = 1 + kObuHeaderLengthSizeBytes;
int consumed = 0;
ObuHeader obu_header;
while (consumed < length) {
@@ -173,10 +171,13 @@
#if CONFIG_OBU_SIZING
uint32_t obu_size = 0;
- aom_uleb_decode(data + consumed, kObuLengthFieldSizeBytes, &obu_size);
+ aom_uleb_decode(data + consumed, sizeof(obu_size), &obu_size);
const int current_obu_length = static_cast<int>(obu_size);
+ const size_t length_field_size = aom_uleb_size_in_bytes(obu_size);
#else
const int current_obu_length = mem_get_le32(data + consumed);
+ const int kObuLengthFieldSizeBytes = 4;
+ const size_t length_field_size = kObuLengthFieldSizeBytes;
#endif // CONFIG_OBU_SIZING
if (current_obu_length > remaining) {
@@ -186,7 +187,7 @@
consumed, current_obu_length, remaining);
return false;
}
- consumed += kObuLengthFieldSizeBytes;
+ consumed += length_field_size;
obu_header = kEmptyObu;
const uint8_t obu_header_byte = *(data + consumed);