diff --git a/aom/aomcx.h b/aom/aomcx.h index 57901452a9d890b15d7de4887e88f13d6487f243..f25701097e9bd648a40289a59490493c60db7f1f 100644 --- a/aom/aomcx.h +++ b/aom/aomcx.h @@ -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 diff --git a/aom_dsp/binary_codes_reader.c b/aom_dsp/binary_codes_reader.c index 7eba5a42e0d657c3bb1942d3801eed59929f893e..ef64b752f72ebbf6f18859ed04df1fce4136eb61 100644 --- a/aom_dsp/binary_codes_reader.c +++ b/aom_dsp/binary_codes_reader.c @@ -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 diff --git a/aom_dsp/binary_codes_reader.h b/aom_dsp/binary_codes_reader.h index f9596c23aff48a98594377f26357cda31cdd9ff0..a27709dfe51f78847eaab1201fac4ef3926edd1e 100644 --- a/aom_dsp/binary_codes_reader.h +++ b/aom_dsp/binary_codes_reader.h @@ -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 diff --git a/aom_dsp/binary_codes_writer.c b/aom_dsp/binary_codes_writer.c index 4e53b156ca80e9babbaebaad13772648ba496d23..3db9a5808ba6e1ff571cf053c63de6ff466f4b5b 100644 --- a/aom_dsp/binary_codes_writer.c +++ b/aom_dsp/binary_codes_writer.c @@ -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 diff --git a/aom_dsp/binary_codes_writer.h b/aom_dsp/binary_codes_writer.h index 6c22c4c7aefe6bce60f990c93f2f90835fd41b13..69d383efed23be4edd46738eed04069ac87801fd 100644 --- a/aom_dsp/binary_codes_writer.h +++ b/aom_dsp/binary_codes_writer.h @@ -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 diff --git a/aom_dsp/bitreader_buffer.c b/aom_dsp/bitreader_buffer.c index 1a61db1df34f40ca9d2ac05a5609b1540dddcf6f..312fa5681f274587a7ecf22911b7f3e2634d9e1e 100644 --- a/aom_dsp/bitreader_buffer.c +++ b/aom_dsp/bitreader_buffer.c @@ -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; diff --git a/aom_dsp/bitreader_buffer.h b/aom_dsp/bitreader_buffer.h index eeedc1f6f62b3814345f0788aa8362e3515af2e0..2c583a3905cba38d1277963a1df40afb6a052468 100644 --- a/aom_dsp/bitreader_buffer.h +++ b/aom_dsp/bitreader_buffer.h @@ -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 diff --git a/aom_dsp/bitwriter_buffer.c b/aom_dsp/bitwriter_buffer.c index 1b3dd2913e8c63255b94ad57769faad81e465773..6601b4cff0cfd3c9f27bccf808c1d7b027c3b640 100644 --- a/aom_dsp/bitwriter_buffer.c +++ b/aom_dsp/bitwriter_buffer.c @@ -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; diff --git a/aom_dsp/bitwriter_buffer.h b/aom_dsp/bitwriter_buffer.h index 1f23dc857b882ce2659b7e88441017b37447b059..ac328d5313d588753e272d8b07c44811272217d8 100644 --- a/aom_dsp/bitwriter_buffer.h +++ b/aom_dsp/bitwriter_buffer.h @@ -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); diff --git a/aomenc.c b/aomenc.c index 33d7199111381e69216abd7f27d155c9b768347f..e9196d89e20baf2acf11fdc88edfff097779d590 100644 --- a/aomenc.c +++ b/aomenc.c @@ -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) { diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 8af3c14ab3829dacb4d9fae839641c5be56d3b27..385111daa5b3fae2bcabefeb1941a062fc12bfb4 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c @@ -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 diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c index 35c2da366ac7deee5d44fc98dc133605177f82b9..5dfc5266cc98e9a7c4b4130307cd2543a7b9e956 100644 --- a/av1/av1_dx_iface.c +++ b/av1/av1_dx_iface.c @@ -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 diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index 7dff3ebc61026e09124683d0461c5a3f052a0be6..5c128053042b30e76ccc92faed15599ff620b811 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h @@ -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 diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 025afdf122d4450b6e6fddecca8fdef3cd44b20e..5066de1a9f76de5e166e71cfa42a11d8f9a755ae 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c @@ -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); diff --git a/av1/decoder/decodeframe.h b/av1/decoder/decodeframe.h index 9cc511d7fff43fdea6d02975b661aecf1263c6d9..8a4bed6facc73be60a420d5fdc375f1770388777 100644 --- a/av1/decoder/decodeframe.h +++ b/av1/decoder/decodeframe.h @@ -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); diff --git a/av1/decoder/obu.c b/av1/decoder/obu.c index 5f8675c5839e9e05843cfe2d6c0b5e7b6ae6eae5..2586ed54fd982d78c9b26c268386bb9337bdb0d5 100644 --- a/av1/decoder/obu.c +++ b/av1/decoder/obu.c @@ -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); } diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index 418c22e52df3c1d2babbe761e2008f23303b45cd..a0b52685eb70d97535018664aa7b11de002bb613 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c @@ -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; } diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 298ec4617ca8be0f835c5364c0d26e1d7a3eb6a7..a276fdc7837e13f68d02a6dcdd4036b99328fce0 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c @@ -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; diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 1e47e946d2320798f7b8d38efa71b42a4c64e6ae..a47aff9de89f0a03840b4516339c1fffc6498fd6 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h @@ -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; diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake index 954deb860204b945a97cdcb3815aa62d26f3982c..1ae86b9eb4c7aca73aff524a242d72ca7cbdc512 100644 --- a/build/cmake/aom_config_defaults.cmake +++ b/build/cmake/aom_config_defaults.cmake @@ -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.")