Commit 38427e8e authored by Soo-Chul Han's avatar Soo-Chul Han

remove writing/parsing superframe index with new HLS

* add build-time option to add/read 4-byte size of every OBU
* update to R19 by adding forbidden bit to obu header
* add metadata OBU decoding

Change-Id: I525264f53a8666b7bc29493fb29ae661841eba50
parent 28fcbfe5
......@@ -21,6 +21,10 @@
#include "aom/aomcx.h"
#include "av1/encoder/firstpass.h"
#include "av1/av1_iface_common.h"
#if CONFIG_OBU
#include "av1/encoder/bitstream.h"
#include "aom_ports/mem_ops.h"
#endif
#define MAG_SIZE (4)
#define MAX_INDEX_SIZE (256)
......@@ -1047,6 +1051,7 @@ static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx,
// Turn on to test if supplemental superframe data breaks decoding
#define TEST_SUPPLEMENTAL_SUPERFRAME_DATA 0
#if !CONFIG_OBU
static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
uint8_t marker = 0xc0;
size_t max_frame_sz = 0;
......@@ -1111,6 +1116,7 @@ static int write_superframe_index(aom_codec_alg_priv_t *ctx) {
return (int)index_sz;
}
#endif
// av1 uses 10,000,000 ticks/second as time stamp
#define TICKS_PER_SEC 10000000LL
......@@ -1137,6 +1143,10 @@ 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,
......@@ -1274,6 +1284,7 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
}
}
if (is_frame_visible) {
#if !CONFIG_OBU
// insert superframe index if needed
if (ctx->pending_frame_count > 1) {
#if CONFIG_DEBUG
......@@ -1282,7 +1293,7 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
write_superframe_index(ctx);
#endif
}
#endif
// Add the frame packet to the list of returned packets.
aom_codec_cx_pkt_t pkt;
......@@ -1292,6 +1303,21 @@ static aom_codec_err_t encoder_encode(aom_codec_alg_priv_t *ctx,
pkt.data.frame.sz = ctx->pending_cx_data_sz;
pkt.data.frame.partition_id = -1;
#if CONFIG_OBU
// move data PRE_OBU_SIZE_BYTES + 1 bytes and insert OBU_TD preceded by
// 4-byte size
uint32_t obu_size = 1;
memmove(ctx->pending_cx_data + PRE_OBU_SIZE_BYTES + 1,
ctx->pending_cx_data, ctx->pending_cx_data_sz);
obu_size = write_obu_header(
OBU_TD, 0, (uint8_t *)(ctx->pending_cx_data + PRE_OBU_SIZE_BYTES));
obu_size += write_temporal_delimiter_obu();
#if CONFIG_ADD_4BYTES_OBUSIZE
mem_put_le32(ctx->pending_cx_data, obu_size);
#endif
pkt.data.frame.sz += (obu_size + PRE_OBU_SIZE_BYTES);
#endif
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(
......
......@@ -682,7 +682,7 @@ static aom_codec_err_t decoder_decode(aom_codec_alg_priv_t *ctx,
const uint8_t *const data_end = data + data_sz;
aom_codec_err_t res;
uint32_t frame_sizes[8];
int frame_count;
int frame_count = 0;
if (data == NULL && data_sz == 0) {
ctx->flushed = 1;
......@@ -697,7 +697,7 @@ static aom_codec_err_t decoder_decode(aom_codec_alg_priv_t *ctx,
res = init_decoder(ctx);
if (res != AOM_CODEC_OK) return res;
}
#if !CONFIG_OBU
int index_size = 0;
res = av1_parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
&index_size, ctx->decrypt_cb,
......@@ -705,7 +705,7 @@ static aom_codec_err_t decoder_decode(aom_codec_alg_priv_t *ctx,
if (res != AOM_CODEC_OK) return res;
data_start += index_size;
#endif
if (ctx->frame_parallel_decode) {
// Decode in frame parallel mode. When decoding in this mode, the frame
// passed to the decoder must be either a normal frame or a superframe with
......
......@@ -20,6 +20,7 @@
#include "aom_mem/aom_mem.h"
#include "aom/aom_integer.h"
#include "aom_ports/bitops.h"
#include "./aom_config.h"
#ifdef __cplusplus
extern "C" {
......@@ -53,6 +54,12 @@ static INLINE int get_unsigned_bits(unsigned int num_values) {
#define AOM_FRAME_MARKER 0x2
#if CONFIG_ADD_4BYTES_OBUSIZE
#define PRE_OBU_SIZE_BYTES 4
#else
#define PRE_OBU_SIZE_BYTES 0
#endif
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -769,6 +769,12 @@ typedef enum ATTRIBUTE_PACKED {
OBU_METADATA = 5,
OBU_PADDING = 15,
} OBU_TYPE;
typedef enum {
METADATA_TYPE_PRIVATE_DATA = 0,
METADATA_TYPE_HDR_CLL = 1,
METADATA_TYPE_HDR_MDCV = 2,
} METADATA_TYPE;
#endif
#if CONFIG_LGT_FROM_PRED
......
......@@ -2128,7 +2128,12 @@ static void get_tile_buffer(const uint8_t *const data_end,
aom_internal_error(error_info, AOM_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt tile size");
} else {
#if !CONFIG_OBU || CONFIG_ADD_4BYTES_OBUSIZE
size = data_end - *data;
#else
size = mem_get_varsize(*data, tile_size_bytes);
*data += tile_size_bytes;
#endif
}
buf->data = *data;
......@@ -3928,7 +3933,10 @@ static OBU_TYPE read_obu_header(struct aom_read_bit_buffer *rb,
*header_size = 1;
obu_type = (OBU_TYPE)aom_rb_read_literal(rb, 5);
// first bit is obu_forbidden_bit (0) according to R19
aom_rb_read_bit(rb);
obu_type = (OBU_TYPE)aom_rb_read_literal(rb, 4);
aom_rb_read_literal(rb, 2); // reserved
obu_extension_flag = aom_rb_read_bit(rb);
if (obu_extension_flag) {
......@@ -4024,6 +4032,55 @@ static uint32_t read_one_tile_group_obu(AV1Decoder *pbi,
return header_size + tg_payload_size;
}
static void read_metadata_private_data(const uint8_t *data, uint32_t sz) {
int i;
for (i = 0; i < (int)sz; i++) {
mem_get_le16(data);
data += 2;
}
}
static void read_metadata_hdr_cll(const uint8_t *data) {
mem_get_le16(data);
mem_get_le16(data + 2);
}
static void read_metadata_hdr_mdcv(const uint8_t *data) {
int i;
for (i = 0; i < 3; i++) {
mem_get_le16(data);
data += 2;
mem_get_le16(data);
data += 2;
}
mem_get_le16(data);
data += 2;
mem_get_le16(data);
data += 2;
mem_get_le16(data);
data += 2;
mem_get_le16(data);
}
static uint32_t read_metadata(const uint8_t *data, uint32_t sz) {
METADATA_TYPE metadata_type;
metadata_type = (METADATA_TYPE)mem_get_le16(data);
if (metadata_type == METADATA_TYPE_PRIVATE_DATA) {
read_metadata_private_data(data + 2, sz - 2);
} else if (metadata_type == METADATA_TYPE_HDR_CLL) {
read_metadata_hdr_cll(data + 2);
} else if (metadata_type == METADATA_TYPE_HDR_MDCV) {
read_metadata_hdr_mdcv(data + 2);
}
return sz;
}
void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
const uint8_t *data_end,
const uint8_t **p_data_end) {
......@@ -4040,13 +4097,19 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
uint32_t obu_size, obu_header_size, obu_payload_size = 0;
OBU_TYPE obu_type;
init_read_bit_buffer(pbi, &rb, data + 4, data_end, clear_data);
init_read_bit_buffer(pbi, &rb, data + PRE_OBU_SIZE_BYTES, data_end,
clear_data);
// every obu is preceded by 4-byte size of obu (obu header + payload size)
// The obu size is only needed for tile group OBUs
// 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
#if CONFIG_ADD_4BYTES_OBUSIZE
obu_size = mem_get_le32(data);
#else
obu_size = data_end - data;
#endif
obu_type = read_obu_header(&rb, &obu_header_size);
data += (4 + obu_header_size);
data += (PRE_OBU_SIZE_BYTES + obu_header_size);
switch (obu_type) {
case OBU_TD: obu_payload_size = read_temporal_delimiter_obu(); break;
......@@ -4070,6 +4133,9 @@ void av1_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
p_data_end, &frame_decoding_finished);
is_first_tg_obu_received = 0;
break;
case OBU_METADATA:
obu_payload_size = read_metadata(data, obu_size);
break;
default: break;
}
data += obu_payload_size;
......
......@@ -3361,7 +3361,12 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst,
}
} else {
#endif // CONFIG_EXT_TILE
#if !CONFIG_OBU
write_uncompressed_header_frame(cpi, &wb);
#else
write_uncompressed_header_obu(cpi, &wb);
#endif
if (cm->show_existing_frame) {
total_size = aom_wb_bytes_written(&wb);
......@@ -4781,12 +4786,15 @@ static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst,
#endif
#if CONFIG_OBU
static uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
uint8_t *const dst) {
uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
uint8_t *const dst) {
struct aom_write_bit_buffer wb = { dst, 0 };
uint32_t size = 0;
aom_wb_write_literal(&wb, (int)obu_type, 5);
// first bit is obu_forbidden_bit according to R19
aom_wb_write_literal(&wb, 0, 1);
aom_wb_write_literal(&wb, (int)obu_type, 4);
aom_wb_write_literal(&wb, 0, 2);
aom_wb_write_literal(&wb, obu_extension ? 1 : 0, 1);
if (obu_extension) {
......@@ -4797,8 +4805,6 @@ static uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
return size;
}
static uint32_t write_temporal_delimiter_obu() { return 0; }
static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) {
AV1_COMMON *const cm = &cpi->common;
SequenceHeader *const seq_params = &cm->seq_params;
......@@ -5036,7 +5042,8 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
if (new_tg) {
if (insert_frame_header_obu_flag && tile_idx) {
// insert a copy of frame header OBU (including 4-byte size),
// 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);
......@@ -5045,13 +5052,14 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
data = dst + total_size;
// A new tile group begins at this tile. Write the obu header and
// tile group header
curr_tg_data_size = write_obu_header(OBU_TILE_GROUP, 0, data + 4);
curr_tg_data_size =
write_obu_header(OBU_TILE_GROUP, 0, data + PRE_OBU_SIZE_BYTES);
if (n_log2_tiles)
curr_tg_data_size += write_tile_group_header(
data + curr_tg_data_size + 4, tile_idx,
data + curr_tg_data_size + PRE_OBU_SIZE_BYTES, tile_idx,
AOMMIN(tile_idx + tg_size - 1, tile_cols * tile_rows - 1),
n_log2_tiles);
total_size += curr_tg_data_size + 4;
total_size += curr_tg_data_size + PRE_OBU_SIZE_BYTES;
new_tg = 0;
tile_count = 0;
}
......@@ -5070,8 +5078,12 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
#endif
buf->data = dst + total_size;
// The last tile of the tile group does not have a header.
// The last tile of the tile group does not have a header.
#if CONFIG_ADD_4BYTES_OBUSIZE
if (!is_last_tile_in_tg) total_size += 4;
#else
total_size += 4;
#endif
// Initialise tile context from the frame context
this_tile->tctx = *cm->fc;
......@@ -5110,8 +5122,12 @@ static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst,
// size of this tile
mem_put_le32(buf->data, tile_size);
} else {
#if CONFIG_ADD_4BYTES_OBUSIZE
// write current tile group size
mem_put_le32(data, curr_tg_data_size);
#else
mem_put_le32(buf->data, tile_size);
#endif
}
total_size += tile_size;
......@@ -5154,45 +5170,51 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) {
#endif
#if CONFIG_OBU
// write temporal delimiter obu, preceded by 4-byte size
obu_size = write_obu_header(OBU_TD, 0, data + 4);
obu_size += write_temporal_delimiter_obu(/*data + 4 + obu_size*/);
mem_put_le32(data, obu_size);
data += obu_size + 4;
// The TD is now written outside the frame encode loop
// write sequence header obu if KEY_FRAME, preceded by 4-byte size
if (cm->frame_type == KEY_FRAME) {
obu_size = write_obu_header(OBU_SEQUENCE_HEADER, 0, data + 4);
obu_size += write_sequence_header_obu(cpi, data + 4 + obu_size);
obu_size =
write_obu_header(OBU_SEQUENCE_HEADER, 0, data + PRE_OBU_SIZE_BYTES);
obu_size +=
write_sequence_header_obu(cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
#if CONFIG_ADD_4BYTES_OBUSIZE
mem_put_le32(data, obu_size);
data += obu_size + 4;
#endif
data += obu_size + PRE_OBU_SIZE_BYTES;
}
// write frame header obu, preceded by 4-byte size
frame_header_location = data + 4;
frame_header_location = data + PRE_OBU_SIZE_BYTES;
obu_size = write_obu_header(OBU_FRAME_HEADER, 0, frame_header_location);
frame_header_size = write_frame_header_obu(cpi, data + 4 + obu_size);
frame_header_size =
write_frame_header_obu(cpi, data + PRE_OBU_SIZE_BYTES + obu_size);
obu_size += frame_header_size;
#if CONFIG_ADD_4BYTES_OBUSIZE
mem_put_le32(data, obu_size);
data += obu_size + 4;
#endif
data += obu_size + PRE_OBU_SIZE_BYTES;
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 - 4, obu_size + 4,
1 /* cm->error_resilient_mode */);
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, 1 /* cm->error_resilient_mode */);
}
#endif
#if CONFIG_EXT_TILE
if (cm->large_scale_tile) {
// Write the uncompressed header
#if !CONFIG_OBU
write_uncompressed_header_frame(cpi, &wb);
#else
write_uncompressed_header_obu(cpi, &wb);
#endif
if (cm->show_existing_frame) {
*size = aom_wb_bytes_written(&wb);
......
......@@ -25,6 +25,11 @@ void write_sequence_header(AV1_COMMON *const cm,
struct aom_write_bit_buffer *wb);
#endif
#if CONFIG_OBU
uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension,
uint8_t *const dst);
#endif
void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dest, size_t *size);
void av1_encode_token_init(void);
......
......@@ -106,6 +106,7 @@ set(CONFIG_SYMBOLRATE 0 CACHE NUMBER "Enables symbol rate accounting.")
# AV1 experiment flags.
set(CONFIG_ADAPT_SCAN 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_ADD_4BYTES_OBUSIZE 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_AMVR 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_ANS 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_AOM_QM 1 CACHE NUMBER "AV1 experiment flag.")
......
......@@ -333,6 +333,7 @@ EXPERIMENT_LIST="
frame_sign_bias
ext_skip
obu
add_4bytes_obusize
amvr
lpf_sb
opt_ref_mv
......
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