From d7c20079a67c5d44f35db5e991982a4705f1800f Mon Sep 17 00:00:00 2001 From: Yury Gitman Date: Mon, 18 Jul 2016 12:17:58 -0700 Subject: Add --alt-ref-aq= option In the future this option will activate adaptive quantization special for altref frames. Encoder will create the adaptive quantization map on the basis of lookahead buffers similarity which is the estimate of the future motion compensation performance. Change-Id: Ia0088b3babb0f9a4899c79d8d819947ba5a03df2 --- test/alt_ref_aq_segment_test.cc | 157 ++++++++++++++++++++++++++++++++++++++++ test/test.mk | 1 + vp9/encoder/vp9_encoder.h | 6 ++ vp9/vp9_cx_iface.c | 14 +++- vpx/vp8cx.h | 15 +++- vpxenc.c | 5 ++ 6 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 test/alt_ref_aq_segment_test.cc diff --git a/test/alt_ref_aq_segment_test.cc b/test/alt_ref_aq_segment_test.cc new file mode 100644 index 000000000..64a3011eb --- /dev/null +++ b/test/alt_ref_aq_segment_test.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/codec_factory.h" +#include "test/encode_test_driver.h" +#include "test/i420_video_source.h" +#include "test/util.h" + +namespace { + +class AltRefAqSegmentTest + : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params { + protected: + AltRefAqSegmentTest() : EncoderTest(GET_PARAM(0)) {} + virtual ~AltRefAqSegmentTest() {} + + virtual void SetUp() { + InitializeConfig(); + SetMode(GET_PARAM(1)); + set_cpu_used_ = GET_PARAM(2); + aq_mode_ = 0; + alt_ref_aq_mode_ = 0; + } + + virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, + ::libvpx_test::Encoder *encoder) { + if (video->frame() == 1) { + encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_); + encoder->Control(VP9E_SET_ALT_REF_AQ, alt_ref_aq_mode_); + encoder->Control(VP9E_SET_AQ_MODE, aq_mode_); + encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100); + } + } + + int set_cpu_used_; + int aq_mode_; + int alt_ref_aq_mode_; +}; + +// Validate that this ALT_REF_AQ/AQ segmentation mode +// (ALT_REF_AQ=0, AQ=0/no_aq) +// encodes and decodes without a mismatch. +TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ0) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 0; + alt_ref_aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this ALT_REF_AQ/AQ segmentation mode +// (ALT_REF_AQ=0, AQ=1/variance_aq) +// encodes and decodes without a mismatch. +TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ1) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 1; + alt_ref_aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this ALT_REF_AQ/AQ segmentation mode +// (ALT_REF_AQ=0, AQ=2/complexity_aq) +// encodes and decodes without a mismatch. +TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ2) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 2; + alt_ref_aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this ALT_REF_AQ/AQ segmentation mode +// (ALT_REF_AQ=0, AQ=3/cyclicrefresh_aq) +// encodes and decodes without a mismatch. +TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ3) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 3; + alt_ref_aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +// Validate that this ALT_REF_AQ/AQ segmentation mode +// (ALT_REF_AQ=0, AQ=4/equator360_aq) +// encodes and decodes without a mismatch. +TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ4) { + cfg_.rc_min_quantizer = 8; + cfg_.rc_max_quantizer = 56; + cfg_.rc_end_usage = VPX_VBR; + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_target_bitrate = 300; + + aq_mode_ = 4; + alt_ref_aq_mode_ = 1; + + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 100); + + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +} + +VP9_INSTANTIATE_TEST_CASE(AltRefAqSegmentTest, + ::testing::Values(::libvpx_test::kOnePassGood, + ::libvpx_test::kTwoPassGood), + ::testing::Range(2, 5)); +} // namespace diff --git a/test/test.mk b/test/test.mk index 81381e9f3..62704a904 100644 --- a/test/test.mk +++ b/test/test.mk @@ -20,6 +20,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += alt_ref_aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += datarate_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index cfbe7a784..ce31ffb98 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -116,6 +116,9 @@ typedef enum { COMPLEXITY_AQ = 2, CYCLIC_REFRESH_AQ = 3, EQUATOR360_AQ = 4, + // AQ based on lookahead temporal + // variance (only valid for altref frames) + LOOKAHEAD_AQ = 5, AQ_MODE_COUNT // This should always be the last member of the enum } AQ_MODE; @@ -178,6 +181,9 @@ typedef struct VP9EncoderConfig { int cq_level; AQ_MODE aq_mode; // Adaptive Quantization mode + // Special handling of Adaptive Quantization for AltRef frames + int alt_ref_aq; + // Internal frame size scaling. RESIZE_TYPE resize_mode; int scaled_frame_width; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 46be1d28c..01ed3e795 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -43,6 +43,7 @@ struct vp9_extracfg { unsigned int target_level; unsigned int frame_parallel_decoding_mode; AQ_MODE aq_mode; + int alt_ref_aq; unsigned int frame_periodic_boost; vpx_bit_depth_t bit_depth; vp9e_tune_content content; @@ -73,6 +74,7 @@ static struct vp9_extracfg default_extra_cfg = { 255, // target_level 1, // frame_parallel_decoding_mode NO_AQ, // aq_mode + 0, // alt_ref_aq 0, // frame_periodic_delta_q VPX_BITS_8, // Bit depth VP9E_CONTENT_DEFAULT, // content @@ -155,7 +157,8 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, RANGE_CHECK_HI(cfg, rc_max_quantizer, 63); RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer); RANGE_CHECK_BOOL(extra_cfg, lossless); - RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 1); + RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 2); + RANGE_CHECK(extra_cfg, alt_ref_aq, 0, 1); RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1); RANGE_CHECK_HI(cfg, g_threads, 64); RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS); @@ -495,6 +498,7 @@ static vpx_codec_err_t set_encoder_config( oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode; oxcf->aq_mode = extra_cfg->aq_mode; + oxcf->alt_ref_aq = extra_cfg->alt_ref_aq; oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost; @@ -756,6 +760,13 @@ static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_alt_ref_aq(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp9_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.alt_ref_aq = CAST(VP9E_SET_ALT_REF_AQ, args); + return update_extra_cfg(ctx, &extra_cfg); +} + static vpx_codec_err_t ctrl_set_min_gf_interval(vpx_codec_alg_priv_t *ctx, va_list args) { struct vp9_extracfg extra_cfg = ctx->extra_cfg; @@ -1497,6 +1508,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { { VP9E_SET_LOSSLESS, ctrl_set_lossless }, { VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode }, { VP9E_SET_AQ_MODE, ctrl_set_aq_mode }, + { VP9E_SET_ALT_REF_AQ, ctrl_set_alt_ref_aq }, { VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost }, { VP9E_SET_SVC, ctrl_set_svc }, { VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters }, diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index a28cb5e7a..8fa25e8bc 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -551,7 +551,17 @@ enum vp8e_enc_control_id { * * Supported in codecs: VP9 */ - VP9E_GET_LEVEL + VP9E_GET_LEVEL, + + /*!\brief Codec control function to enable/disable special mode for altref + * adaptive quantization. You can use it with --aq-mode concurrently. + * + * Enable special adaptive quantization for altref frames based on their + * expected prediction quality for the future frames. + * + * Supported in codecs: VP9 + */ + VP9E_SET_ALT_REF_AQ }; /*!\brief vpx 1-D scaling mode @@ -774,6 +784,9 @@ VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int) VPX_CTRL_USE_TYPE(VP9E_SET_AQ_MODE, unsigned int) #define VPX_CTRL_VP9E_SET_AQ_MODE +VPX_CTRL_USE_TYPE(VP9E_SET_ALT_REF_AQ, int) +#define VPX_CTRL_VP9E_SET_ALT_REF_AQ + VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int) #define VPX_CTRL_VP9E_SET_FRAME_PERIODIC_BOOST diff --git a/vpxenc.c b/vpxenc.c index c414ae0cd..baae87230 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -401,6 +401,9 @@ static const arg_def_t aq_mode = ARG_DEF( NULL, "aq-mode", 1, "Adaptive quantization mode (0: off (default), 1: variance 2: complexity, " "3: cyclic refresh, 4: equator360)"); +static const arg_def_t alt_ref_aq = ARG_DEF(NULL, "alt-ref-aq", 1, + "Special adaptive quantization for " + "the alternate reference frames."); static const arg_def_t frame_periodic_boost = ARG_DEF(NULL, "frame-boost", 1, "Enable frame periodic boost (0: off (default), 1: on)"); @@ -477,6 +480,7 @@ static const arg_def_t *vp9_args[] = { &cpu_used_vp9, &lossless, &frame_parallel_decoding, &aq_mode, + &alt_ref_aq, &frame_periodic_boost, &noise_sens, &tune_content, @@ -506,6 +510,7 @@ static const int vp9_arg_ctrl_map[] = { VP8E_SET_CPUUSED, VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE, + VP9E_SET_ALT_REF_AQ, VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_NOISE_SENSITIVITY, VP9E_SET_TUNE_CONTENT, -- cgit v1.2.3