Commit 28e9ce29 authored by Andrey Norkin's avatar Andrey Norkin

Adding timing info to sequence headers

Change-Id: I0fdb09499196e02709e067f690dff71146ee5114
parent 9d234571
......@@ -683,6 +683,12 @@ enum aome_enc_control_id {
* 0 : off, 1 : MAX_EXTREME_MV, 2 : MIN_EXTREME_MV
*/
AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST,
/*!\brief Codec control function to signal picture timing info in the
* bitstream. \note Valid ranges: 0..1, default is "UNKNOWN". 0 = UNKNOWN, 1 =
* EQUAL
*/
AV1E_SET_TIMING_INFO,
};
/*!\brief aom 1-D scaling mode
......@@ -753,6 +759,9 @@ typedef enum {
AOM_CONTENT_INVALID
} aom_tune_content;
/*!brief AV1 encoder timing info signaling */
typedef enum { AOM_TIMING_UNSPECIFIED, AOM_TIMING_EQUAL } aom_timing_info_t;
/*!\brief Model tuning parameters
*
* Changes the encoder to tune for certain types of input material.
......@@ -857,6 +866,9 @@ AOM_CTRL_USE_TYPE(AV1E_SET_NUM_TG, unsigned int)
AOM_CTRL_USE_TYPE(AV1E_SET_MTU, unsigned int)
#define AOM_CTRL_AV1E_SET_MTU
AOM_CTRL_USE_TYPE(AV1E_SET_TIMING_INFO, aom_timing_info_t)
#define AOM_CTRL_AV1E_SET_TIMING_INFO
AOM_CTRL_USE_TYPE(AV1E_SET_DISABLE_TEMPMV, unsigned int)
#define AOM_CTRL_AV1E_SET_DISABLE_TEMPMV
......
......@@ -143,3 +143,16 @@ int16_t aom_rb_read_signed_primitive_refsubexpfin(
const uint16_t scaled_n = (n << 1) - 1;
return aom_rb_read_primitive_refsubexpfin(rb, scaled_n, k, ref) - n + 1;
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
uint32_t aom_rb_read_uvlc(struct aom_read_bit_buffer *rb) {
int leading_zeros = 0;
while (!aom_rb_read_bit(rb)) ++leading_zeros;
uint32_t value = aom_rb_read_literal(rb, leading_zeros);
value += (1 << leading_zeros) - 1;
return value;
}
#endif
......@@ -46,6 +46,11 @@ int16_t aom_read_signed_primitive_refsubexpfin_(aom_reader *r, uint16_t n,
int16_t aom_rb_read_signed_primitive_refsubexpfin(
struct aom_read_bit_buffer *rb, uint16_t n, uint16_t k, int16_t ref);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
uint32_t aom_rb_read_uvlc(struct aom_read_bit_buffer *rb);
#endif
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -208,3 +208,17 @@ int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
const uint16_t scaled_n = (n << 1) - 1;
return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void aom_wb_write_uvlc(struct aom_write_bit_buffer *wb, uint32_t v) {
int64_t shift_val = ++v;
int leading_zeroes = 1;
assert(shift_val > 0);
while (shift_val >>= 1) leading_zeroes += 2;
aom_wb_write_literal(wb, 0, leading_zeroes >> 1);
aom_wb_write_unsigned_literal(wb, v, (leading_zeroes + 1) >> 1);
}
#endif
......@@ -60,6 +60,9 @@ int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
uint16_t v);
int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
int16_t v);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void aom_wb_write_uvlc(struct aom_write_bit_buffer *wb, uint32_t v);
#endif
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -35,6 +35,16 @@ int aom_rb_read_literal(struct aom_read_bit_buffer *rb, int bits) {
return value;
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
uint32_t aom_rb_read_unsigned_literal(struct aom_read_bit_buffer *rb,
int bits) {
uint32_t value = 0;
int bit;
for (bit = bits - 1; bit >= 0; bit--) value |= aom_rb_read_bit(rb) << bit;
return value;
}
#endif
int aom_rb_read_inv_signed_literal(struct aom_read_bit_buffer *rb, int bits) {
const int nbits = sizeof(unsigned) * 8 - bits - 1;
const unsigned value = (unsigned)aom_rb_read_literal(rb, bits + 1) << nbits;
......
......@@ -37,6 +37,10 @@ int aom_rb_read_bit(struct aom_read_bit_buffer *rb);
int aom_rb_read_literal(struct aom_read_bit_buffer *rb, int bits);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
uint32_t aom_rb_read_unsigned_literal(struct aom_read_bit_buffer *rb, int bits);
#endif
int aom_rb_read_inv_signed_literal(struct aom_read_bit_buffer *rb, int bits);
#ifdef __cplusplus
......
......@@ -48,6 +48,14 @@ void aom_wb_write_literal(struct aom_write_bit_buffer *wb, int data, int bits) {
for (bit = bits - 1; bit >= 0; bit--) aom_wb_write_bit(wb, (data >> bit) & 1);
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void aom_wb_write_unsigned_literal(struct aom_write_bit_buffer *wb,
uint32_t data, int bits) {
int bit;
for (bit = bits - 1; bit >= 0; bit--) aom_wb_write_bit(wb, (data >> bit) & 1);
}
#endif
void aom_wb_overwrite_literal(struct aom_write_bit_buffer *wb, int data,
int bits) {
int bit;
......
......@@ -31,6 +31,11 @@ void aom_wb_overwrite_bit(struct aom_write_bit_buffer *wb, int bit);
void aom_wb_write_literal(struct aom_write_bit_buffer *wb, int data, int bits);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void aom_wb_write_unsigned_literal(struct aom_write_bit_buffer *wb,
uint32_t data, int bits);
#endif
void aom_wb_overwrite_literal(struct aom_write_bit_buffer *wb, int data,
int bits);
......
......@@ -467,6 +467,16 @@ static const arg_def_t mtu_size =
ARG_DEF(NULL, "mtu-size", 1,
"MTU size for a tile group, default is 0 (no MTU targeting), "
"overrides maximum number of tile groups");
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
static const struct arg_enum_list timing_info_enum[] = {
{ "unspecified", AOM_TIMING_UNSPECIFIED },
{ "constant", AOM_TIMING_EQUAL },
{ NULL, 0 }
};
static const arg_def_t timing_info =
ARG_DEF_ENUM(NULL, "timing-info", 1,
"Signal timing info in the bitstream:", timing_info_enum);
#endif
#if CONFIG_TEMPMV_SIGNALING
static const arg_def_t disable_tempmv = ARG_DEF(
NULL, "disable-tempmv", 1, "Disable temporal mv prediction (default is 0)");
......@@ -696,6 +706,9 @@ static const arg_def_t *av1_args[] = { &cpu_used_av1,
#endif // CONFIG_EXT_PARTITION
&num_tg,
&mtu_size,
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
&timing_info,
#endif
#if CONFIG_TEMPMV_SIGNALING
&disable_tempmv,
#endif
......@@ -764,6 +777,9 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED,
#endif // CONFIG_EXT_PARTITION
AV1E_SET_NUM_TG,
AV1E_SET_MTU,
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
AV1E_SET_TIMING_INFO,
#endif
#if CONFIG_TEMPMV_SIGNALING
AV1E_SET_DISABLE_TEMPMV,
#endif
......@@ -2125,9 +2141,19 @@ int main(int argc, const char **argv_) {
}
#endif
/* Use the frame rate from the file only if none was specified
* on the command-line.
*/
/* Use the frame rate from the file only if none was specified
* on the command-line.
*/
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
if (!global.have_framerate) {
global.framerate.num = input.framerate.numerator;
global.framerate.den = input.framerate.denominator;
}
FOREACH_STREAM(stream, streams) {
stream->config.cfg.g_timebase.den = global.framerate.num;
stream->config.cfg.g_timebase.num = global.framerate.den;
}
#else
if (!global.have_framerate) {
global.framerate.num = input.framerate.numerator;
global.framerate.den = input.framerate.denominator;
......@@ -2136,7 +2162,7 @@ int main(int argc, const char **argv_) {
stream->config.cfg.g_timebase.num = global.framerate.den;
}
}
#endif
/* Show configuration */
if (global.verbose && pass == 0) {
FOREACH_STREAM(stream, streams) {
......
......@@ -71,6 +71,9 @@ struct av1_extracfg {
#endif
unsigned int num_tg;
unsigned int mtu_size;
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
aom_timing_info_t timing_info;
#endif
#if CONFIG_TEMPMV_SIGNALING
unsigned int disable_tempmv;
#endif
......@@ -144,6 +147,9 @@ static struct av1_extracfg default_extra_cfg = {
#endif
1, // max number of tile groups
0, // mtu_size
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
AOM_TIMING_UNSPECIFIED, // No picture timing signaling in bitstream
#endif
#if CONFIG_TEMPMV_SIGNALING
0, // disable temporal mv prediction
#endif
......@@ -424,6 +430,10 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK(extra_cfg, tuning, AOM_TUNE_PSNR, AOM_TUNE_SSIM);
#endif
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
RANGE_CHECK(extra_cfg, timing_info, AOM_TIMING_UNSPECIFIED, AOM_TIMING_EQUAL);
#endif
if (extra_cfg->lossless) {
if (extra_cfg->aq_mode != 0)
ERROR("Only --aq_mode=0 can be used with --lossless=1.");
......@@ -497,8 +507,24 @@ static aom_codec_err_t set_encoder_config(
oxcf->input_bit_depth = cfg->g_input_bit_depth;
// guess a frame rate if out of whack, use 30
oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
if (extra_cfg->timing_info == AOM_TIMING_EQUAL) {
oxcf->timing_info_present = 1;
oxcf->num_units_in_tick = cfg->g_timebase.num;
oxcf->time_scale = cfg->g_timebase.den;
oxcf->equal_picture_interval = 1;
oxcf->num_ticks_per_picture = 1;
} else {
oxcf->timing_info_present = 0;
}
if (oxcf->init_framerate > 180) {
oxcf->init_framerate = 30;
oxcf->timing_info_present = 0;
}
#else
if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
#endif
oxcf->mode = GOOD;
switch (cfg->g_pass) {
......@@ -983,6 +1009,14 @@ static aom_codec_err_t ctrl_set_mtu(aom_codec_alg_priv_t *ctx, va_list args) {
extra_cfg.mtu_size = CAST(AV1E_SET_MTU, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
static aom_codec_err_t ctrl_set_timing_info(aom_codec_alg_priv_t *ctx,
va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.timing_info = CAST(AV1E_SET_TIMING_INFO, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#endif
#if CONFIG_TEMPMV_SIGNALING
static aom_codec_err_t ctrl_set_disable_tempmv(aom_codec_alg_priv_t *ctx,
va_list args) {
......@@ -1682,6 +1716,9 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
#endif
{ AV1E_SET_NUM_TG, ctrl_set_num_tg },
{ AV1E_SET_MTU, ctrl_set_mtu },
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
{ AV1E_SET_TIMING_INFO, ctrl_set_timing_info },
#endif
#if CONFIG_TEMPMV_SIGNALING
{ AV1E_SET_DISABLE_TEMPMV, ctrl_set_disable_tempmv },
#endif
......
......@@ -167,6 +167,26 @@ static aom_bit_depth_t parse_bitdepth(BITSTREAM_PROFILE profile,
return bit_depth;
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
static void parse_timing_info_header(struct aom_read_bit_buffer *rb) {
int timing_info_present;
int equal_picture_interval;
uint32_t num_ticks_per_picture;
timing_info_present = aom_rb_read_bit(rb); // timing info present flag
if (timing_info_present) {
rb->bit_offset += 32; // Number of units in tick
rb->bit_offset += 32; // Time scale
equal_picture_interval = aom_rb_read_bit(rb); // Equal picture interval bit
if (equal_picture_interval) {
num_ticks_per_picture = aom_rb_read_uvlc(rb) - 1; // ticks per picture
}
}
}
#endif // CONFIG_TIMING_INFO_IN_SEQ_HEADERS
static int parse_bitdepth_colorspace_sampling(BITSTREAM_PROFILE profile,
struct aom_read_bit_buffer *rb) {
#if CONFIG_CICP
......@@ -259,6 +279,9 @@ static int parse_bitdepth_colorspace_sampling(BITSTREAM_PROFILE profile,
#if CONFIG_EXT_QM
rb->bit_offset += 1; // separate_uv_delta_q
#endif // CONFIG_EXT_QM
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
parse_timing_info_header(rb);
#endif
return 1;
}
#endif
......
......@@ -242,6 +242,13 @@ typedef struct AV1Common {
int render_height;
int last_width;
int last_height;
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
int timing_info_present;
uint32_t num_units_in_tick;
uint32_t time_scale;
int equal_picture_interval;
uint32_t num_ticks_per_picture;
#endif
// TODO(jkoleszar): this implies chroma ss right now, but could vary per
// plane. Revisit as part of the future change to YV12_BUFFER_CONFIG to
......
......@@ -2269,6 +2269,25 @@ void av1_read_bitdepth_colorspace_sampling(AV1_COMMON *cm,
#endif // CONFIG_EXT_QM
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void av1_read_timing_info_header(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb) {
cm->timing_info_present = aom_rb_read_bit(rb); // timing info present flag
if (cm->timing_info_present) {
cm->num_units_in_tick =
aom_rb_read_unsigned_literal(rb, 32); // Number of units in tick
cm->time_scale = aom_rb_read_unsigned_literal(rb, 32); // Time scale
cm->equal_picture_interval =
aom_rb_read_bit(rb); // Equal picture interval bit
if (cm->equal_picture_interval) {
cm->num_ticks_per_picture =
aom_rb_read_uvlc(rb) + 1; // ticks per picture
}
}
}
#endif
#if CONFIG_REFERENCE_BUFFER || CONFIG_OBU
void read_sequence_header(SequenceHeader *seq_params,
struct aom_read_bit_buffer *rb) {
......@@ -2668,6 +2687,9 @@ static int read_uncompressed_header(AV1Decoder *pbi,
cm->current_video_frame = 0;
#if !CONFIG_OBU
av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
av1_read_time_info_header(cm, rb);
#endif
#endif
pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
......@@ -2735,6 +2757,9 @@ static int read_uncompressed_header(AV1Decoder *pbi,
if (cm->intra_only) {
#if !CONFIG_OBU
av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
av1_read_timing_info_header(cm, rb);
#endif
#endif
pbi->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
......
......@@ -50,6 +50,11 @@ void av1_decode_tg_tiles_and_wrapup(struct AV1Decoder *pbi, const uint8_t *data,
void av1_read_bitdepth_colorspace_sampling(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb,
int allow_lowbitdepth);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
void av1_read_timing_info_header(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb);
#endif
struct aom_read_bit_buffer *av1_init_read_bit_buffer(
struct AV1Decoder *pbi, struct aom_read_bit_buffer *rb, const uint8_t *data,
const uint8_t *data_end);
......
......@@ -56,6 +56,10 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
av1_read_timing_info_header(cm, rb);
#endif
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
......
......@@ -3289,6 +3289,25 @@ static void write_bitdepth_colorspace_sampling(
#endif
}
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
static void write_timing_info_header(AV1_COMMON *const cm,
struct aom_write_bit_buffer *wb) {
aom_wb_write_bit(wb, cm->timing_info_present); // timing info present flag
if (cm->timing_info_present) {
aom_wb_write_unsigned_literal(wb, cm->num_units_in_tick,
32); // Number of units in tick
aom_wb_write_unsigned_literal(wb, cm->time_scale, 32); // Time scale
aom_wb_write_bit(wb,
cm->equal_picture_interval); // Equal picture interval bit
if (cm->equal_picture_interval) {
aom_wb_write_uvlc(wb,
cm->num_ticks_per_picture - 1); // ticks per picture
}
}
}
#endif // CONFIG_TIMING_INFO_IN_SEQ_HEADERS
#if CONFIG_REFERENCE_BUFFER || CONFIG_OBU
void write_sequence_header(AV1_COMP *cpi, struct aom_write_bit_buffer *wb) {
AV1_COMMON *const cm = &cpi->common;
......@@ -3547,6 +3566,10 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
if (cm->frame_type == KEY_FRAME) {
write_bitdepth_colorspace_sampling(cm, wb);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
// timing_info
write_timing_info_header(cm, wb);
#endif
#if CONFIG_FRAME_SIZE
write_frame_size(cm, frame_size_override_flag, wb);
#else
......@@ -3587,6 +3610,9 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
if (cm->intra_only) {
write_bitdepth_colorspace_sampling(cm, wb);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
write_timing_info_header(cm, wb);
#endif
aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
#if CONFIG_FRAME_SIZE
......@@ -4352,6 +4378,11 @@ static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) {
// color_config
write_bitdepth_colorspace_sampling(cm, &wb);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
// timing_info
write_timing_info_header(cm, &wb);
#endif
size = aom_wb_bytes_written(&wb);
return size;
}
......
......@@ -1067,6 +1067,13 @@ static void init_config(struct AV1_COMP *cpi, AV1EncoderConfig *oxcf) {
cm->chroma_sample_position = oxcf->chroma_sample_position;
#endif
cm->color_range = oxcf->color_range;
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
cm->timing_info_present = oxcf->timing_info_present;
cm->num_units_in_tick = oxcf->num_units_in_tick;
cm->time_scale = oxcf->time_scale;
cm->equal_picture_interval = oxcf->equal_picture_interval;
cm->num_ticks_per_picture = oxcf->num_ticks_per_picture;
#endif
cm->width = oxcf->width;
cm->height = oxcf->height;
......@@ -3102,6 +3109,14 @@ void av1_change_config(struct AV1_COMP *cpi, const AV1EncoderConfig *oxcf) {
assert(IMPLIES(cm->profile <= PROFILE_1, cm->bit_depth <= AOM_BITS_10));
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
cm->timing_info_present = oxcf->timing_info_present;
cm->num_units_in_tick = oxcf->num_units_in_tick;
cm->time_scale = oxcf->time_scale;
cm->equal_picture_interval = oxcf->equal_picture_interval;
cm->num_ticks_per_picture = oxcf->num_ticks_per_picture;
#endif
cpi->oxcf = *oxcf;
x->e_mbd.bd = (int)cm->bit_depth;
x->e_mbd.global_motion = cm->global_motion;
......
......@@ -294,6 +294,14 @@ typedef struct AV1EncoderConfig {
int color_range;
int render_width;
int render_height;
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
aom_timing_info_t timing_info;
int timing_info_present;
uint32_t num_units_in_tick;
uint32_t time_scale;
int equal_picture_interval;
uint32_t num_ticks_per_picture;
#endif
#if CONFIG_EXT_PARTITION
aom_superblock_size_t superblock_size;
......
......@@ -163,6 +163,7 @@ set(CONFIG_SPATIAL_SEGMENTATION 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_STRIPED_LOOP_RESTORATION 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TEMPMV_SIGNALING 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TILE_INFO_FIRST 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TIMING_INFO_IN_SEQ_HEADERS 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TMV 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TX64X64 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_TXK_SEL 0 CACHE NUMBER "AV1 experiment flag.")
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