From 49aa77c61fc1d2dc369594fb19c3165f9c56bd18 Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Thu, 16 Jan 2020 23:17:26 -0800 Subject: [PATCH] vp9: add delta q for uv channel. add tests. Add control for delta q for uv. 0 by default. Change-Id: Ib8ed160b1a5c9a61ba15985076f6c6f121477103 --- test/vp9_datarate_test.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++ vp9/encoder/vp9_encoder.c | 8 +++---- vp9/encoder/vp9_encoder.h | 1 + vp9/encoder/vp9_firstpass.c | 2 +- vp9/encoder/vp9_quantize.c | 7 +++++- vp9/encoder/vp9_quantize.h | 2 +- vp9/vp9_cx_iface.c | 12 ++++++++++ vpx/vp8cx.h | 11 +++++++++ 8 files changed, 92 insertions(+), 7 deletions(-) diff --git a/test/vp9_datarate_test.cc b/test/vp9_datarate_test.cc index b8be275..f9f2aaa 100644 --- a/test/vp9_datarate_test.cc +++ b/test/vp9_datarate_test.cc @@ -46,6 +46,7 @@ class DatarateTestVP9 : public ::libvpx_test::EncoderTest { denoiser_offon_test_ = 0; denoiser_offon_period_ = -1; frame_parallel_decoding_mode_ = 1; + delta_q_uv_ = 0; use_roi_ = false; } @@ -138,6 +139,10 @@ class DatarateTestVP9 : public ::libvpx_test::EncoderTest { encoder->Control(VP9E_SET_AQ_MODE, 0); } + if (delta_q_uv_ != 0) { + encoder->Control(VP9E_SET_DELTA_Q_UV, delta_q_uv_); + } + if (cfg_.ts_number_layers > 1) { if (video->frame() == 0) { encoder->Control(VP9E_SET_SVC, 1); @@ -222,6 +227,7 @@ class DatarateTestVP9 : public ::libvpx_test::EncoderTest { int denoiser_offon_test_; int denoiser_offon_period_; int frame_parallel_decoding_mode_; + int delta_q_uv_; bool use_roi_; vpx_roi_map_t roi_; }; @@ -716,6 +722,52 @@ TEST_P(DatarateTestVP9RealTime, RegionOfInterest) { free(roi_.roi_map); } +// Params: speed setting, delta q UV. +class DatarateTestVP9RealTimeDeltaQUV + : public DatarateTestVP9, + public ::libvpx_test::CodecTestWith2Params { + public: + DatarateTestVP9RealTimeDeltaQUV() : DatarateTestVP9(GET_PARAM(0)) {} + virtual ~DatarateTestVP9RealTimeDeltaQUV() {} + + protected: + virtual void SetUp() { + InitializeConfig(); + SetMode(::libvpx_test::kRealTime); + set_cpu_used_ = GET_PARAM(1); + ResetModel(); + } +}; + +TEST_P(DatarateTestVP9RealTimeDeltaQUV, DeltaQUV) { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 0; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = VPX_CBR; + cfg_.g_lag_in_frames = 0; + + ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, + 0, 400); + + cfg_.rc_target_bitrate = 450; + cfg_.g_w = 640; + cfg_.g_h = 480; + + ResetModel(); + + delta_q_uv_ = GET_PARAM(2); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_[0] * 0.90) + << " The datarate for the file exceeds the target!"; + + ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_[0] * 1.4) + << " The datarate for the file missed the target!"; +} + // Params: test mode, speed setting and index for bitrate array. class DatarateTestVP9PostEncodeDrop : public DatarateTestVP9, @@ -891,6 +943,10 @@ VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9LargeVBR, ::testing::Range(5, 9), VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9RealTime, ::testing::Range(5, 10)); +VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9RealTimeDeltaQUV, + ::testing::Range(5, 10), + ::testing::Values(-5, -10, -15)); + VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9PostEncodeDrop, ::testing::Range(5, 6)); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 9b03b20..182064c 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -4065,7 +4065,7 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, cpi->oxcf.rc_mode == VPX_CBR && cm->frame_type != KEY_FRAME; - vp9_set_quantizer(cm, q); + vp9_set_quantizer(cpi, q); vp9_set_variance_partition_thresholds(cpi, q, 0); setup_frame(cpi); @@ -4094,7 +4094,7 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, (cpi->rc.high_source_sad || (cpi->use_svc && svc->high_source_sad_superframe))) { if (vp9_encodedframe_overshoot(cpi, -1, &q)) { - vp9_set_quantizer(cm, q); + vp9_set_quantizer(cpi, q); vp9_set_variance_partition_thresholds(cpi, q, 0); } } @@ -4144,7 +4144,7 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, // adjust some rate control parameters, and return to re-encode the frame. if (vp9_encodedframe_overshoot(cpi, frame_size, &q)) { vpx_clear_system_state(); - vp9_set_quantizer(cm, q); + vp9_set_quantizer(cpi, q); vp9_set_variance_partition_thresholds(cpi, q, 0); suppress_active_map(cpi); // Turn-off cyclic refresh for re-encoded frame. @@ -4294,7 +4294,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, } #endif - vp9_set_quantizer(cm, q); + vp9_set_quantizer(cpi, q); if (loop_count == 0) setup_frame(cpi); diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index c2bdebb..388653d 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -282,6 +282,7 @@ typedef struct VP9EncoderConfig { int row_mt; unsigned int motion_vector_unit_test; + int delta_q_uv; } VP9EncoderConfig; static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) { diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index cfaa68c..ba35e6b 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -1366,7 +1366,7 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { #endif set_first_pass_params(cpi); - vp9_set_quantizer(cm, find_fp_qindex(cm->bit_depth)); + vp9_set_quantizer(cpi, find_fp_qindex(cm->bit_depth)); vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y); diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c index 26d1434..c996b75 100644 --- a/vp9/encoder/vp9_quantize.c +++ b/vp9/encoder/vp9_quantize.c @@ -323,13 +323,18 @@ void vp9_frame_init_quantizer(VP9_COMP *cpi) { vp9_init_plane_quantizers(cpi, &cpi->td.mb); } -void vp9_set_quantizer(VP9_COMMON *cm, int q) { +void vp9_set_quantizer(VP9_COMP *cpi, int q) { + VP9_COMMON *cm = &cpi->common; // quantizer has to be reinitialized with vp9_init_quantizer() if any // delta_q changes. cm->base_qindex = q; cm->y_dc_delta_q = 0; cm->uv_dc_delta_q = 0; cm->uv_ac_delta_q = 0; + if (cpi->oxcf.delta_q_uv != 0) { + cm->uv_dc_delta_q = cm->uv_ac_delta_q = cpi->oxcf.delta_q_uv; + vp9_init_quantizer(cpi); + } } // Table that converts 0-63 Q-range values passed in outside to the Qindex diff --git a/vp9/encoder/vp9_quantize.h b/vp9/encoder/vp9_quantize.h index ed9b849..2e6d7da 100644 --- a/vp9/encoder/vp9_quantize.h +++ b/vp9/encoder/vp9_quantize.h @@ -49,7 +49,7 @@ void vp9_init_plane_quantizers(struct VP9_COMP *cpi, MACROBLOCK *x); void vp9_init_quantizer(struct VP9_COMP *cpi); -void vp9_set_quantizer(struct VP9Common *cm, int q); +void vp9_set_quantizer(struct VP9_COMP *cm, int q); int vp9_quantizer_to_qindex(int quantizer); diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index f415e50..baea0ec 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -581,6 +581,8 @@ static vpx_codec_err_t set_encoder_config( oxcf->min_gf_interval = extra_cfg->min_gf_interval; oxcf->max_gf_interval = extra_cfg->max_gf_interval; + oxcf->delta_q_uv = 0; + oxcf->tuning = extra_cfg->tuning; oxcf->content = extra_cfg->content; @@ -1655,6 +1657,15 @@ static vpx_codec_err_t ctrl_set_svc_spatial_layer_sync( return VPX_CODEC_OK; } +static vpx_codec_err_t ctrl_set_delta_q_uv(vpx_codec_alg_priv_t *ctx, + va_list args) { + int data = va_arg(args, int); + VP9_COMP *const cpi = ctx->cpi; + data = VPXMIN(VPXMAX(data, -20), 20); + cpi->oxcf.delta_q_uv = data; + return VPX_CODEC_OK; +} + static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx, va_list args) { vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp = @@ -1752,6 +1763,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { { VP9E_SET_SVC_FRAME_DROP_LAYER, ctrl_set_svc_frame_drop_layer }, { VP9E_SET_SVC_GF_TEMPORAL_REF, ctrl_set_svc_gf_temporal_ref }, { VP9E_SET_SVC_SPATIAL_LAYER_SYNC, ctrl_set_svc_spatial_layer_sync }, + { VP9E_SET_DELTA_Q_UV, ctrl_set_delta_q_uv }, // Getters { VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer }, diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index 95e2493..d8b769b 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -676,6 +676,14 @@ enum vp8e_enc_control_id { * Supported in codecs: VP9 */ VP9E_SET_POSTENCODE_DROP, + + /*!\brief Codec control function to set delta q for uv. + * + * Cap it at +/-20 for now. + * + * Supported in codecs: VP9 + */ + VP9E_SET_DELTA_Q_UV, }; /*!\brief vpx 1-D scaling mode @@ -1023,6 +1031,9 @@ VPX_CTRL_USE_TYPE(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, VPX_CTRL_USE_TYPE(VP9E_SET_POSTENCODE_DROP, unsigned int) #define VPX_CTRL_VP9E_SET_POSTENCODE_DROP +VPX_CTRL_USE_TYPE(VP9E_SET_DELTA_Q_UV, int) +#define VPX_CTRL_VP9E_SET_DELTA_Q_UV + /*!\endcond */ /*! @} - end defgroup vp8_encoder */ #ifdef __cplusplus -- 2.7.4