Move mv precision decision to a separate file
STATS_CHANGED
BUG=aomedia:2534
Change-Id: Ic6a2e2b48c6b85ae870eaf91b0bc39ec210122e9
diff --git a/av1/av1.cmake b/av1/av1.cmake
index b12aca0..ad0e633 100644
--- a/av1/av1.cmake
+++ b/av1/av1.cmake
@@ -176,6 +176,8 @@
"${AOM_ROOT}/av1/encoder/ml.c"
"${AOM_ROOT}/av1/encoder/ml.h"
"${AOM_ROOT}/av1/encoder/model_rd.h"
+ "${AOM_ROOT}/av1/encoder/mv_prec.c"
+ "${AOM_ROOT}/av1/encoder/mv_prec.h"
"${AOM_ROOT}/av1/encoder/palette.c"
"${AOM_ROOT}/av1/encoder/palette.h"
"${AOM_ROOT}/av1/encoder/partition_strategy.h"
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 1948149..47e2704 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -65,6 +65,7 @@
#include "av1/encoder/firstpass.h"
#include "av1/encoder/grain_test_vectors.h"
#include "av1/encoder/hash_motion.h"
+#include "av1/encoder/mv_prec.h"
#include "av1/encoder/pass2_strategy.h"
#include "av1/encoder/picklpf.h"
#include "av1/encoder/pickrst.h"
@@ -87,9 +88,6 @@
#define AM_SEGMENT_ID_INACTIVE 7
#define AM_SEGMENT_ID_ACTIVE 0
-// Q threshold for high precision mv.
-#define HIGH_PRECISION_MV_QTHRESH 128
-
// #define OUTPUT_YUV_REC
#ifdef OUTPUT_YUV_SKINMAP
FILE *yuv_skinmap_file = NULL;
@@ -453,21 +451,6 @@
}
}
-static void set_high_precision_mv(AV1_COMP *cpi, int allow_high_precision_mv,
- int cur_frame_force_integer_mv) {
- MACROBLOCK *const x = &cpi->td.mb;
- cpi->common.allow_high_precision_mv =
- allow_high_precision_mv && cur_frame_force_integer_mv == 0;
- const int copy_hp =
- cpi->common.allow_high_precision_mv && cur_frame_force_integer_mv == 0;
- x->nmvcost[0] = &x->nmv_costs[0][MV_MAX];
- x->nmvcost[1] = &x->nmv_costs[1][MV_MAX];
- x->nmvcost_hp[0] = &x->nmv_costs_hp[0][MV_MAX];
- x->nmvcost_hp[1] = &x->nmv_costs_hp[1][MV_MAX];
- int *(*src)[2] = copy_hp ? &x->nmvcost_hp : &x->nmvcost;
- x->mv_cost_stack = *src;
-}
-
static BLOCK_SIZE select_sb_size(const AV1_COMP *const cpi) {
const AV1_COMMON *const cm = &cpi->common;
@@ -2758,7 +2741,7 @@
}
av1_reset_segment_features(cm);
- set_high_precision_mv(cpi, 1, 0);
+ av1_set_high_precision_mv(cpi, 1, 0);
set_rc_buffer_sizes(rc, &cpi->oxcf);
@@ -3990,16 +3973,6 @@
}
#endif // !CONFIG_REALTIME_ONLY
-static int determine_frame_high_precision_mv(const AV1_COMP *cpi, int qindex) {
- (void)cpi;
- if (cpi->sf.hl_sf.reduce_high_precision_mv_usage == 2)
- return 0;
- else if (cpi->sf.hl_sf.reduce_high_precision_mv_usage == 1)
- return qindex < HIGH_PRECISION_MV_QTHRESH / 2;
- else
- return qindex < HIGH_PRECISION_MV_QTHRESH;
-}
-
static void set_size_dependent_vars(AV1_COMP *cpi, int *q, int *bottom_index,
int *top_index) {
AV1_COMMON *const cm = &cpi->common;
@@ -4019,13 +3992,6 @@
*q = av1_rc_pick_q_and_bounds(cpi, &cpi->rc, cm->width, cm->height,
cpi->gf_group.index, bottom_index, top_index);
- if (!frame_is_intra_only(cm)) {
- const int use_hp = cpi->common.cur_frame_force_integer_mv
- ? 0
- : determine_frame_high_precision_mv(cpi, *q);
- set_high_precision_mv(cpi, use_hp, cpi->common.cur_frame_force_integer_mv);
- }
-
// Configure experimental use of segmentation for enhanced coding of
// static regions if indicated.
// Only allowed in the second pass of a two pass encode, as it requires
@@ -5140,6 +5106,12 @@
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_encode_frame_time);
#endif
+ // Set the motion vector precision based on mv stats from the last coded
+ // frame.
+ if (!frame_is_intra_only(cm)) {
+ av1_pick_and_set_high_precision_mv(cpi, q);
+ }
+
// transform / motion compensation build reconstruction frame
av1_encode_frame(cpi);
#if CONFIG_COLLECT_COMPONENT_TIMING
@@ -5158,8 +5130,10 @@
if (do_dummy_pack) {
finalize_encoded_frame(cpi);
int largest_tile_id = 0; // Output from bitstream: unused here
- if (av1_pack_bitstream(cpi, dest, size, &largest_tile_id) != AOM_CODEC_OK)
+ if (av1_pack_bitstream(cpi, dest, size, &largest_tile_id) !=
+ AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
+ }
rc->projected_frame_size = (int)(*size) << 3;
}
@@ -6452,7 +6426,7 @@
struct aom_usec_timer cmptimer;
aom_usec_timer_start(&cmptimer);
#endif
- set_high_precision_mv(cpi, 1, 0);
+ av1_set_high_precision_mv(cpi, 1, 0);
// Normal defaults
cm->refresh_frame_context = oxcf->frame_parallel_decoding_mode
diff --git a/av1/encoder/mv_prec.c b/av1/encoder/mv_prec.c
new file mode 100644
index 0000000..fb6d478
--- /dev/null
+++ b/av1/encoder/mv_prec.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+#include "av1/encoder/mv_prec.h"
+
+void av1_pick_and_set_high_precision_mv(AV1_COMP *cpi, int qindex) {
+ int use_hp = qindex < HIGH_PRECISION_MV_QTHRESH;
+
+ if (cpi->sf.hl_sf.high_precision_mv_usage == QTR_ONLY) {
+ use_hp = 0;
+ }
+
+ av1_set_high_precision_mv(cpi, use_hp,
+ cpi->common.cur_frame_force_integer_mv);
+}
diff --git a/av1/encoder/mv_prec.h b/av1/encoder/mv_prec.h
new file mode 100644
index 0000000..eec0016
--- /dev/null
+++ b/av1/encoder/mv_prec.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#ifndef AOM_AV1_ENCODER_MV_PREC_H_
+#define AOM_AV1_ENCODER_MV_PREC_H_
+
+#include "av1/encoder/encoder.h"
+#include "av1/encoder/speed_features.h"
+
+// Q threshold for high precision mv.
+#define HIGH_PRECISION_MV_QTHRESH 128
+
+static AOM_INLINE void av1_set_high_precision_mv(
+ AV1_COMP *cpi, int allow_high_precision_mv,
+ int cur_frame_force_integer_mv) {
+ MACROBLOCK *const x = &cpi->td.mb;
+ cpi->common.allow_high_precision_mv =
+ allow_high_precision_mv && cur_frame_force_integer_mv == 0;
+ const int copy_hp =
+ cpi->common.allow_high_precision_mv && cur_frame_force_integer_mv == 0;
+ x->nmvcost[0] = &x->nmv_costs[0][MV_MAX];
+ x->nmvcost[1] = &x->nmv_costs[1][MV_MAX];
+ x->nmvcost_hp[0] = &x->nmv_costs_hp[0][MV_MAX];
+ x->nmvcost_hp[1] = &x->nmv_costs_hp[1][MV_MAX];
+ int *(*src)[2] = copy_hp ? &x->nmvcost_hp : &x->nmvcost;
+ x->mv_cost_stack = *src;
+}
+
+void av1_pick_and_set_high_precision_mv(AV1_COMP *cpi, int qindex);
+
+#endif // AOM_AV1_ENCODER_MV_PREC_H_
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 54d29e5..33f073a 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -833,12 +833,12 @@
// best quality defaults
hl_sf->frame_parameter_update = 1;
hl_sf->recode_loop = ALLOW_RECODE;
- hl_sf->reduce_high_precision_mv_usage = 0;
hl_sf->disable_overlay_frames = 0;
// TODO(yunqing): turn it on for speed 0 if there is gain.
hl_sf->adaptive_overlay_encoding = 1;
// Recode loop tolerance %.
hl_sf->recode_tolerance = 25;
+ hl_sf->high_precision_mv_usage = CURRENT_Q;
}
static AOM_INLINE void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 7a416103..e9b5ffc 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -261,6 +261,12 @@
ADAPT_PRED
} UENUM1BYTE(MAX_PART_PRED_MODE);
+enum {
+ LAST_MV_DATA, // Not implemented yet
+ CURRENT_Q,
+ QTR_ONLY,
+} UENUM1BYTE(MV_PREC_LOGIC);
+
typedef struct HIGH_LEVEL_SPEED_FEATURES {
// Frame level coding parameter update
int frame_parameter_update;
@@ -271,11 +277,11 @@
// recode a frame. It has no meaning if recode is disabled.
int recode_tolerance;
- // Use reduced 1/8th pel mv usage, in the range 0 - 2, where
- // 0: maximizes quality and does not reduce mv precision
- // 1: more aggressive reduced usage of high precision MV
- // 2: use only quarter pel motion
- int reduce_high_precision_mv_usage;
+ // Determine how motion vector precision is chosen. The possibilities are:
+ // LAST_MV_DATA: use the mv data from the last coded frame
+ // CURRENT_Q: use the current q as a threshold
+ // QTR_ONLY: use quarter pel precision only.
+ MV_PREC_LOGIC high_precision_mv_usage;
// Whether to disable overlay frames for filtered Altref frames,
// overiding oxcf->enable_overlay flag set as 1.