Commit f2d40f6b authored by Tom Finegan's avatar Tom Finegan

Write LEB128 OBU size fields.

Removes padding bytes.

BUG=aomedia:1125

Change-Id: Ib9bce81a86aa218abeeba8e027387634aaa89b92
parent e11fe10f
......@@ -28,6 +28,7 @@ void aom_uleb_decode(const uint8_t *buffer, size_t available, uint32_t *value) {
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;
}
}
}
......
......@@ -1267,10 +1267,6 @@ static aom_codec_frame_flags_t get_frame_pkt_flags(const AV1_COMP *cpi,
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 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
// 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 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
#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
......
......@@ -54,8 +54,13 @@ static INLINE int get_unsigned_bits(unsigned int num_values) {
#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"
......
......@@ -148,7 +148,6 @@ static uint32_t read_one_tile_group_obu(AV1Decoder *pbi,
// 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 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
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 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
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 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
break;
default: break;
}
data += obu_payload_size;
if (data_end < data) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
......
......@@ -4509,13 +4509,8 @@ uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
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_tile_group_header(uint8_t *const dst, int startTile,
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 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
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 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
} 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 @@ int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
#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 @@ int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
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 @@ int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
#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 @@ int av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
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.
......
......@@ -30,6 +30,10 @@ TEST(AomLeb128, DecodeTest) {
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) {
......
......@@ -153,10 +153,8 @@ void PrintObuHeader(const ObuHeader *header) {
}
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 @@ bool DumpObu(const uint8_t *data, int length) {
#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 @@ bool DumpObu(const uint8_t *data, int length) {
consumed, current_obu_length, remaining);
return false;
}
consumed += kObuLengthFieldSizeBytes;
consumed += length_field_size;
obu_header = kEmptyObu;
const uint8_t obu_header_byte = *(data + consumed);
......
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