shithub: libvpx

Download patch

ref: d7c20079a67c5d44f35db5e991982a4705f1800f
parent: 5260a6675e0de8f071d9e10ca86b96c02a5cd9f1
author: Yury Gitman <yuryg@google.com>
date: Mon Jul 18 08:17:58 EDT 2016

Add --alt-ref-aq=<int> 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

--- /dev/null
+++ b/test/alt_ref_aq_segment_test.cc
@@ -1,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<libvpx_test::TestMode, int> {
+ 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
--- a/test/test.mk
+++ b/test/test.mk
@@ -20,6 +20,7 @@
 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
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -116,6 +116,9 @@
   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;
 
@@ -177,6 +180,9 @@
   int best_allowed_q;
   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;
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -43,6 +43,7 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   { 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 },
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -551,7 +551,17 @@
    *
    * 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
@@ -773,6 +783,9 @@
 
 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
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -401,6 +401,9 @@
     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 @@
                                        &lossless,
                                        &frame_parallel_decoding,
                                        &aq_mode,
+                                       &alt_ref_aq,
                                        &frame_periodic_boost,
                                        &noise_sens,
                                        &tune_content,
@@ -506,6 +510,7 @@
                                         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,