Adaptive Motion Vector Resolution Change-Id: Ic3c93a5d2e427ce1ed578389196a265245063821
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index 8910eea..4b72fb2 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -4447,6 +4447,16 @@ aom_wb_write_literal(wb, cpi->common.ans_window_size_log2 - 8, 4); #endif // CONFIG_ANS && ANS_MAX_SYMBOLS aom_wb_write_bit(wb, cm->allow_screen_content_tools); +#if CONFIG_AMVR + if (cm->allow_screen_content_tools) { + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, 1); + } else { + aom_wb_write_bit(wb, 0); + aom_wb_write_bit(wb, cm->seq_mv_precision_level == 0); + } + } +#endif } else { if (!cm->show_frame) aom_wb_write_bit(wb, cm->intra_only); if (cm->intra_only) aom_wb_write_bit(wb, cm->allow_screen_content_tools); @@ -4534,6 +4544,11 @@ write_frame_size_with_refs(cpi, wb); #endif +#if CONFIG_AMVR + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, cm->cur_frame_mv_precision_level == 0); + } +#endif aom_wb_write_bit(wb, cm->allow_high_precision_mv); fix_interp_filter(cm, cpi->td.counts);
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index c87916d..b68b662 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -4637,7 +4637,9 @@ int segment_id = get_segment_id(cm, map, cm->sb_size, mi_row, mi_col); seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP); } - +#if CONFIG_AMVR + xd->cur_frame_mv_precision_level = cm->cur_frame_mv_precision_level; +#endif #if CONFIG_DELTA_Q if (cm->delta_q_present_flag) { // Test mode for delta quantization
diff --git a/av1/encoder/encodemv.c b/av1/encoder/encodemv.c index 5225e8e..fa14964 100644 --- a/av1/encoder/encodemv.c +++ b/av1/encoder/encodemv.c
@@ -66,9 +66,9 @@ } // Fractional bits -#if CONFIG_INTRABC +#if CONFIG_INTRABC || CONFIG_AMVR if (precision > MV_SUBPEL_NONE) -#endif // CONFIG_INTRABC +#endif // CONFIG_INTRABC || CONFIG_AMVR { aom_write_symbol( w, fr, @@ -130,9 +130,9 @@ const int b = c + CLASS0_BITS - 1; /* number of bits */ for (i = 0; i < b; ++i) cost += bits_cost[i][((d >> i) & 1)]; } -#if CONFIG_INTRABC +#if CONFIG_INTRABC || CONFIG_AMVR if (precision > MV_SUBPEL_NONE) -#endif // CONFIG_INTRABC +#endif // CONFIG_INTRABC || CONFIG_AMVR { if (c == MV_CLASS_0) { cost += class0_fp_cost[d][f]; @@ -166,6 +166,11 @@ nmv_context_counts *const nmv_counts) { int i; int nmv_ctx = 0; +#if CONFIG_AMVR + if (cm->cur_frame_mv_precision_level) { + return; + } +#endif for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) { nmv_context *const mvc = &cm->fc->nmvc[nmv_ctx]; nmv_context_counts *const counts = &nmv_counts[nmv_ctx]; @@ -185,6 +190,11 @@ nmv_context *mvctx, int usehp) { const MV diff = { mv->row - ref->row, mv->col - ref->col }; const MV_JOINT_TYPE j = av1_get_mv_joint(&diff); +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level) { + usehp = MV_SUBPEL_NONE; + } +#endif aom_write_symbol(w, j, mvctx->joint_cdf, MV_JOINTS); if (mv_joint_vertical(j)) encode_mv_component(w, diff.row, &mvctx->comps[0], usehp); @@ -226,7 +236,12 @@ #if CONFIG_EXT_INTER static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext, const int_mv mvs[2], const int_mv pred_mvs[2], - nmv_context_counts *nmv_counts) { + nmv_context_counts *nmv_counts +#if CONFIG_AMVR + , + MvSubpelPrecision precision +#endif + ) { int i; PREDICTION_MODE mode = mbmi->mode; @@ -241,7 +256,11 @@ mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; (void)pred_mvs; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif } } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv; @@ -252,7 +271,11 @@ av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) { const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv; const MV diff = { mvs[0].as_mv.row - ref->row, @@ -262,7 +285,11 @@ av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif #if CONFIG_COMPOUND_SINGLEREF } else { assert( // mode == SR_NEAREST_NEWMV || @@ -289,7 +316,12 @@ static void inc_mvs_sub8x8(const MODE_INFO *mi, int block, const int_mv mvs[2], const MB_MODE_INFO_EXT *mbmi_ext, - nmv_context_counts *nmv_counts) { + nmv_context_counts *nmv_counts +#if CONFIG_AMVR + , + MvSubpelPrecision precision +#endif + ) { int i; PREDICTION_MODE mode = mi->bmi[block].as_mode; const MB_MODE_INFO *mbmi = &mi->mbmi; @@ -304,7 +336,11 @@ av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif } } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { const MV *ref = &mi->bmi[block].ref_mv[1].as_mv; @@ -315,7 +351,11 @@ av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) { const MV *ref = &mi->bmi[block].ref_mv[0].as_mv; const MV diff = { mvs[0].as_mv.row - ref->row, @@ -325,7 +365,11 @@ av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx); nmv_context_counts *counts = &nmv_counts[nmv_ctx]; +#if CONFIG_AMVR + av1_inc_mv(&diff, counts, precision); +#else av1_inc_mv(&diff, counts, 1); +#endif } } #else // !CONFIG_EXT_INTER @@ -358,6 +402,12 @@ #else const int unify_bsize = 0; #endif +#if CONFIG_AMVR + MvSubpelPrecision precision = 1; + if (xd->cur_frame_mv_precision_level) { + precision = MV_SUBPEL_NONE; + } +#endif if (mbmi->sb_type < BLOCK_8X8 && !unify_bsize) { const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type]; @@ -370,7 +420,13 @@ #if CONFIG_EXT_INTER if (have_newmv_in_inter_mode(mi->bmi[i].as_mode)) + +#if CONFIG_AMVR + inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, mbmi_ext, td->counts->mv, + precision); +#else inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, mbmi_ext, td->counts->mv); +#endif #else if (mi->bmi[i].as_mode == NEWMV) inc_mvs(mbmi, mbmi_ext, mi->bmi[i].as_mv, mi->bmi[i].pred_mv, @@ -384,6 +440,12 @@ #else if (mbmi->mode == NEWMV) #endif // CONFIG_EXT_INTER + +#if CONFIG_AMVR + inc_mvs(mbmi, mbmi_ext, mbmi->mv, mbmi->pred_mv, td->counts->mv, + precision); +#else inc_mvs(mbmi, mbmi_ext, mbmi->mv, mbmi->pred_mv, td->counts->mv); +#endif } }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 320a8c2..858c9af 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -254,11 +254,21 @@ } } -static void set_high_precision_mv(AV1_COMP *cpi, int allow_high_precision_mv) { +static void set_high_precision_mv(AV1_COMP *cpi, int allow_high_precision_mv +#if CONFIG_AMVR + , + int cur_frame_mv_precision_level +#endif + ) { MACROBLOCK *const mb = &cpi->td.mb; cpi->common.allow_high_precision_mv = allow_high_precision_mv; +#if CONFIG_AMVR + if (cpi->common.allow_high_precision_mv && + cur_frame_mv_precision_level == 0) { +#else if (cpi->common.allow_high_precision_mv) { +#endif int i; for (i = 0; i < NMV_CONTEXTS; ++i) { mb->mv_cost_stack[i] = mb->nmvcost_hp[i]; @@ -998,6 +1008,11 @@ cpi->gld_fb_idx = 1; cpi->alt_fb_idx = 2; #endif // CONFIG_EXT_REFS +#if CONFIG_AMVR + cpi->rate_index = 0; + cpi->rate_size = 0; + cpi->cur_poc = -1; +#endif } static void init_config(struct AV1_COMP *cpi, AV1EncoderConfig *oxcf) { @@ -2320,7 +2335,11 @@ set_compound_tools(cm); #endif // CONFIG_EXT_INTER av1_reset_segment_features(cm); +#if CONFIG_AMVR + set_high_precision_mv(cpi, 0, 0); +#else set_high_precision_mv(cpi, 0); +#endif set_rc_buffer_sizes(rc, &cpi->oxcf); @@ -2384,6 +2403,9 @@ #if CONFIG_ANS && ANS_MAX_SYMBOLS cpi->common.ans_window_size_log2 = cpi->oxcf.ans_window_size_log2; #endif // CONFIG_ANS && ANS_MAX_SYMBOLS +#if CONFIG_AMVR + cm->seq_mv_precision_level = 2; +#endif } AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf, @@ -3940,7 +3962,12 @@ #endif if (!frame_is_intra_only(cm)) { +#if CONFIG_AMVR + set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH, + cpi->common.cur_frame_mv_precision_level); +#else set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH); +#endif } // Configure experimental use of segmentation for enhanced coding of @@ -5829,6 +5856,123 @@ } #endif // CONFIG_INTERNAL_STATS +#if CONFIG_AMVR +static int is_integer_mv(AV1_COMP *cpi, const YV12_BUFFER_CONFIG *cur_picture, + const YV12_BUFFER_CONFIG *last_picture, + hash_table *last_hash_table) { + aom_clear_system_state(); + // check use hash ME + int k; + uint32_t hash_value_1; + uint32_t hash_value_2; + + const int block_size = 8; + const double threshold_current = 0.8; + const double threshold_average = 0.95; + const int max_history_size = 32; + int T = 0; // total block + int C = 0; // match with collocated block + int S = 0; // smooth region but not match with collocated block + int M = 0; // match with other block + + const int pic_width = cur_picture->y_width; + const int pic_height = cur_picture->y_height; + for (int i = 0; i + block_size <= pic_height; i += block_size) { + for (int j = 0; j + block_size <= pic_width; j += block_size) { + const int x_pos = j; + const int y_pos = i; + int match = 1; + T++; + + // check whether collocated block match with current + uint8_t *p_cur = cur_picture->y_buffer; + uint8_t *p_ref = last_picture->y_buffer; + int stride_cur = cur_picture->y_stride; + int stride_ref = last_picture->y_stride; + p_cur += (y_pos * stride_cur + x_pos); + p_ref += (y_pos * stride_ref + x_pos); + + for (int tmpY = 0; tmpY < block_size && match; tmpY++) { + for (int tmpX = 0; tmpX < block_size && match; tmpX++) { + if (p_cur[tmpX] != p_ref[tmpX]) { + match = 0; + } + } + p_cur += stride_cur; + p_ref += stride_ref; + } + + if (match) { + C++; + continue; + } + + if (av1_hash_is_horizontal_perfect(cur_picture, block_size, x_pos, + y_pos) || + av1_hash_is_vertical_perfect(cur_picture, block_size, x_pos, y_pos)) { + S++; + continue; + } + + av1_get_block_hash_value( + cur_picture->y_buffer + y_pos * stride_cur + x_pos, stride_cur, + block_size, &hash_value_1, &hash_value_2); + + if (av1_has_exact_match(last_hash_table, hash_value_1, hash_value_2)) { + M++; + } + } + } + + assert(T > 0); + double csm_rate = ((double)(C + S + M)) / ((double)(T)); + double m_rate = ((double)(M)) / ((double)(T)); + + cpi->csm_rate_array[cpi->rate_index] = csm_rate; + cpi->m_rate_array[cpi->rate_index] = m_rate; + + cpi->rate_index = (cpi->rate_index + 1) % max_history_size; + cpi->rate_size++; + cpi->rate_size = AOMMIN(cpi->rate_size, max_history_size); + + if (csm_rate < threshold_current) { + return 0; + } + + if (C == T) { + return 1; + } + + double csm_average = 0.0; + double m_average = 0.0; + + for (k = 0; k < cpi->rate_size; k++) { + csm_average += cpi->csm_rate_array[k]; + m_average += cpi->m_rate_array[k]; + } + csm_average /= cpi->rate_size; + m_average /= cpi->rate_size; + + if (csm_average < threshold_average) { + return 0; + } + + if (M > (T - C - S) / 3) { + return 1; + } + + if (csm_rate > 0.99 && m_rate > 0.01) { + return 1; + } + + if (csm_average + m_average > 1.01) { + return 1; + } + + return 0; +} +#endif + int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags, size_t *size, uint8_t *dest, int64_t *time_stamp, int64_t *time_end, int flush) { @@ -5859,7 +6003,11 @@ aom_usec_timer_start(&cmptimer); +#if CONFIG_AMVR + set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV, 0); +#else set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV); +#endif // Is multi-arf enabled. // Note that at the moment multi_arf is only configured for 2 pass VBR @@ -6161,6 +6309,22 @@ cpi->common.current_frame_id = -1; } #endif +#if CONFIG_AMVR + cpi->cur_poc++; + if (oxcf->pass != 1 && cpi->common.allow_screen_content_tools) { + if (cpi->common.seq_mv_precision_level == 2) { + struct lookahead_entry *previous_entry = + cpi->lookahead->buf + cpi->previsous_index; + cpi->common.cur_frame_mv_precision_level = is_integer_mv( + cpi, cpi->source, &previous_entry->img, cpi->previsou_hash_table); + } else { + cpi->common.cur_frame_mv_precision_level = + cpi->common.seq_mv_precision_level; + } + } else { + cpi->common.cur_frame_mv_precision_level = 0; + } +#endif #if CONFIG_XIPHRC if (oxcf->pass == 1) { @@ -6250,6 +6414,23 @@ aom_free(is_block_same[k][j]); } } +#if CONFIG_AMVR + cpi->previsou_hash_table = &cm->cur_frame->hash_table; + { + int l; + for (l = -MAX_PRE_FRAMES; l < cpi->lookahead->max_sz; l++) { + if ((cpi->lookahead->buf + l) == source) { + cpi->previsous_index = l; + break; + } + } + + if (l == cpi->lookahead->max_sz) { + aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR, + "Failed to find last frame original buffer"); + } + } +#endif } #endif
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 9fc1f2d..df681fb 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -409,6 +409,15 @@ // For a still frame, this flag is set to 1 to skip partition search. int partition_search_skippable_frame; +#if CONFIG_AMVR + double csm_rate_array[32]; + double m_rate_array[32]; + int rate_size; + int rate_index; + hash_table *previsou_hash_table; + int previsous_index; + int cur_poc; // DebugInfo +#endif int scaled_ref_idx[TOTAL_REFS_PER_FRAME]; #if CONFIG_EXT_REFS
diff --git a/av1/encoder/mbgraph.c b/av1/encoder/mbgraph.c index 3f5daeb..700da56 100644 --- a/av1/encoder/mbgraph.c +++ b/av1/encoder/mbgraph.c
@@ -47,9 +47,16 @@ av1_hex_search(x, &ref_full, step_param, x->errorperbit, 0, cond_cost_list(cpi, cost_list), &v_fn_ptr, 0, ref_mv); - // Try sub-pixel MC - // if (bestsme > error_thresh && bestsme < INT_MAX) +// Try sub-pixel MC +// if (bestsme > error_thresh && bestsme < INT_MAX) +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level == 1) { + x->best_mv.as_mv.row *= 8; + x->best_mv.as_mv.col *= 8; + } else { +#else { +#endif int distortion; unsigned int sse; cpi->find_fractional_mv_step(
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c index 02ac6ef..8573568 100644 --- a/av1/encoder/mcomp.c +++ b/av1/encoder/mcomp.c
@@ -3275,9 +3275,13 @@ bestmv->row = maxr; bestmv->col = maxc; besterr = 0; - // In the sub-pel motion search, if hp is not used, then the last bit of mv - // has to be 0. +// In the sub-pel motion search, if hp is not used, then the last bit of mv +// has to be 0. +#if CONFIG_AMVR + lower_mv_precision(bestmv, allow_hp, 0); +#else lower_mv_precision(bestmv, allow_hp); +#endif return besterr; } // Return the minimum MV. @@ -3301,8 +3305,12 @@ bestmv->row = minr; bestmv->col = minc; besterr = 0; - // In the sub-pel motion search, if hp is not used, then the last bit of mv - // has to be 0. +// In the sub-pel motion search, if hp is not used, then the last bit of mv +// has to be 0. +#if CONFIG_AMVR + lower_mv_precision(bestmv, allow_hp, 0); +#else lower_mv_precision(bestmv, allow_hp); +#endif return besterr; }
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c index dc2e7c8..8a6ce0b 100644 --- a/av1/encoder/rd.c +++ b/av1/encoder/rd.c
@@ -607,11 +607,25 @@ set_block_thresholds(cm, rd); for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) { +#if CONFIG_AMVR + if (cm->cur_frame_mv_precision_level) { + av1_build_nmv_cost_table(x->nmv_vec_cost[nmv_ctx], x->nmvcost[nmv_ctx], + &cm->fc->nmvc[nmv_ctx], MV_SUBPEL_NONE); + } else { + av1_build_nmv_cost_table( + x->nmv_vec_cost[nmv_ctx], + cm->allow_high_precision_mv ? x->nmvcost_hp[nmv_ctx] + : x->nmvcost[nmv_ctx], + &cm->fc->nmvc[nmv_ctx], cm->allow_high_precision_mv); + } + +#else av1_build_nmv_cost_table( x->nmv_vec_cost[nmv_ctx], cm->allow_high_precision_mv ? x->nmvcost_hp[nmv_ctx] : x->nmvcost[nmv_ctx], &cm->fc->nmvc[nmv_ctx], cm->allow_high_precision_mv); +#endif } x->mvcost = x->mv_cost_stack[0]; x->nmvjointcost = x->nmv_vec_cost[0];
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 8fff3b5..6802502 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -6270,7 +6270,12 @@ zeromv[cur_frm].as_int = gm_get_motion_vector(&cpi->common.global_motion[ref_frames[cur_frm]], cpi->common.allow_high_precision_mv, bsize, - mi_col, mi_row, block) + mi_col, mi_row, block +#if CONFIG_AMVR + , + cpi->common.cur_frame_mv_precision_level +#endif + ) .as_int; } } @@ -6587,7 +6592,15 @@ x->mv_limits = tmp_mv_limits; +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level) { + x->best_mv.as_mv.row *= 8; + x->best_mv.as_mv.col *= 8; + } + if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) { +#else if (bestsme < INT_MAX) { +#endif int dis; /* TODO: use dis in distortion calculation later. */ unsigned int sse; bestsme = cpi->find_fractional_mv_step( @@ -6972,11 +6985,16 @@ candidates, mi_row, mi_col, NULL, NULL, mbmi_ext->mode_context); - // Candidate refinement carried out at encoder and decoder +// Candidate refinement carried out at encoder and decoder +#if CONFIG_AMVR + av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates, + &frame_nearest_mv[ref_frame], &frame_near_mv[ref_frame], + cm->cur_frame_mv_precision_level); +#else av1_find_best_ref_mvs(cm->allow_high_precision_mv, candidates, &frame_nearest_mv[ref_frame], &frame_near_mv[ref_frame]); - +#endif // Further refinement that is encode side only to test the top few candidates // in full and choose the best as the centre point for subsequent searches. // The current implementation doesn't support scaling. @@ -7132,7 +7150,15 @@ x->mv_limits = tmp_mv_limits; +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level) { + x->best_mv.as_mv.row *= 8; + x->best_mv.as_mv.col *= 8; + } + if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) { +#else if (bestsme < INT_MAX) { +#endif int dis; /* TODO: use dis in distortion calculation later. */ #if CONFIG_MOTION_VAR switch (mbmi->motion_mode) { @@ -7438,7 +7464,15 @@ x->mv_limits = tmp_mv_limits; +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level) { + x->best_mv.as_mv.row *= 8; + x->best_mv.as_mv.col *= 8; + } + if (bestsme < INT_MAX && cpi->common.cur_frame_mv_precision_level == 0) { +#else if (bestsme < INT_MAX) { +#endif int dis; /* TODO: use dis in distortion calculation later. */ unsigned int sse; bestsme = cpi->find_fractional_mv_step( @@ -9129,7 +9163,12 @@ { cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][0].this_mv; +#if CONFIG_AMVR + lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); +#else lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv); +#endif clamp_mv2(&cur_mv[0].as_mv, xd); if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX; mbmi->mv[0].as_int = cur_mv[0].as_int; @@ -9138,7 +9177,12 @@ if (this_mode == NEW_NEARESTMV) { cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][0].comp_mv; +#if CONFIG_AMVR + lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); +#else lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv); +#endif clamp_mv2(&cur_mv[1].as_mv, xd); if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX; mbmi->mv[1].as_int = cur_mv[1].as_int; @@ -9154,7 +9198,12 @@ this_mode == NEAR_NEARMV) { cur_mv[0] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].this_mv; +#if CONFIG_AMVR + lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); +#else lower_mv_precision(&cur_mv[0].as_mv, cm->allow_high_precision_mv); +#endif clamp_mv2(&cur_mv[0].as_mv, xd); if (mv_check_bounds(&x->mv_limits, &cur_mv[0].as_mv)) return INT64_MAX; mbmi->mv[0].as_int = cur_mv[0].as_int; @@ -9172,7 +9221,12 @@ #endif // CONFIG_COMPOUND_SINGLEREF cur_mv[1] = mbmi_ext->ref_mv_stack[ref_frame_type][ref_mv_idx].comp_mv; +#if CONFIG_AMVR + lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); +#else lower_mv_precision(&cur_mv[1].as_mv, cm->allow_high_precision_mv); +#endif clamp_mv2(&cur_mv[1].as_mv, xd); if (mv_check_bounds(&x->mv_limits, &cur_mv[1].as_mv)) return INT64_MAX; mbmi->mv[1].as_int = cur_mv[1].as_int; @@ -10409,7 +10463,12 @@ frame_mv[ZEROMV][ref_frame].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame], cm->allow_high_precision_mv, bsize, mi_col, mi_row, - 0) + 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; #else // CONFIG_GLOBAL_MOTION frame_mv[ZEROMV][ref_frame].as_int = 0; @@ -10424,7 +10483,12 @@ frame_mv[ZERO_ZEROMV][ref_frame].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame], cm->allow_high_precision_mv, bsize, mi_col, mi_row, - 0) + 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; #else // CONFIG_GLOBAL_MOTION frame_mv[ZERO_ZEROMV][ref_frame].as_int = 0; @@ -10524,7 +10588,12 @@ #if CONFIG_GLOBAL_MOTION zeromv.as_int = gm_get_motion_vector(&cm->global_motion[ALTREF_FRAME], cm->allow_high_precision_mv, bsize, - mi_col, mi_row, 0) + mi_col, mi_row, 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; #else zeromv.as_int = 0; @@ -11908,14 +11977,25 @@ #if CONFIG_GLOBAL_MOTION zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[refs[0]], cm->allow_high_precision_mv, bsize, - mi_col, mi_row, 0) + mi_col, mi_row, 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; - zeromv[1].as_int = comp_pred_mode - ? gm_get_motion_vector(&cm->global_motion[refs[1]], - cm->allow_high_precision_mv, - bsize, mi_col, mi_row, 0) - .as_int - : 0; + zeromv[1].as_int = + comp_pred_mode + ? gm_get_motion_vector(&cm->global_motion[refs[1]], + cm->allow_high_precision_mv, bsize, mi_col, + mi_row, 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) + .as_int + : 0; #else zeromv[0].as_int = 0; zeromv[1].as_int = 0; @@ -12040,16 +12120,40 @@ best_mbmode.ref_frame[1] }; zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[refs[0]], cm->allow_high_precision_mv, - bsize, mi_col, mi_row, 0) + bsize, mi_col, mi_row, 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; - zeromv[1].as_int = (refs[1] != NONE_FRAME) - ? gm_get_motion_vector(&cm->global_motion[refs[1]], - cm->allow_high_precision_mv, - bsize, mi_col, mi_row, 0) - .as_int - : 0; + zeromv[1].as_int = + (refs[1] != NONE_FRAME) + ? +#if CONFIG_AMVR + gm_get_motion_vector(&cm->global_motion[refs[1]], + cm->allow_high_precision_mv, bsize, mi_col, + mi_row, 0, cm->cur_frame_mv_precision_level) + .as_int + : 0; +#else + gm_get_motion_vector(&cm->global_motion[refs[1]], + cm->allow_high_precision_mv, bsize, mi_col, + mi_row, 0) + .as_int + : 0; +#endif + +#if CONFIG_AMVR + lower_mv_precision(&zeromv[0].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); + lower_mv_precision(&zeromv[1].as_mv, cm->allow_high_precision_mv, + cm->cur_frame_mv_precision_level); +#else lower_mv_precision(&zeromv[0].as_mv, cm->allow_high_precision_mv); lower_mv_precision(&zeromv[1].as_mv, cm->allow_high_precision_mv); +#endif + #else zeromv[0].as_int = zeromv[1].as_int = 0; #endif // CONFIG_GLOBAL_MOTION @@ -12219,8 +12323,12 @@ #if CONFIG_GLOBAL_MOTION mbmi->mv[0].as_int = gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]], - cm->allow_high_precision_mv, bsize, mi_col, mi_row, - 0) + cm->allow_high_precision_mv, bsize, mi_col, mi_row, 0 +#if CONFIG_AMVR + , + cm->cur_frame_mv_precision_level +#endif + ) .as_int; #else // CONFIG_GLOBAL_MOTION mbmi->mv[0].as_int = 0;
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c index 5c1fa32..74732e7 100644 --- a/av1/encoder/temporal_filter.c +++ b/av1/encoder/temporal_filter.c
@@ -291,15 +291,33 @@ x->mv_limits = tmp_mv_limits; - // Ignore mv costing by sending NULL pointer instead of cost array - bestsme = cpi->find_fractional_mv_step( - x, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit, - &cpi->fn_ptr[BLOCK_16X16], 0, mv_sf->subpel_iters_per_step, - cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL, -#if CONFIG_EXT_INTER - NULL, 0, 0, +// Ignore mv costing by sending NULL pointer instead of cost array +#if CONFIG_AMVR + if (cpi->common.cur_frame_mv_precision_level == 1) { + const uint8_t *const src_address = x->plane[0].src.buf; + const int src_stride = x->plane[0].src.stride; + const uint8_t *const y = xd->plane[0].pre[0].buf; + const int y_stride = xd->plane[0].pre[0].stride; + const int offset = x->best_mv.as_mv.row * y_stride + x->best_mv.as_mv.col; + + x->best_mv.as_mv.row *= 8; + x->best_mv.as_mv.col *= 8; + + bestsme = cpi->fn_ptr[BLOCK_16X16].vf(y + offset, y_stride, src_address, + src_stride, &sse); + } else { #endif - 0, 0, 0); + bestsme = cpi->find_fractional_mv_step( + x, &best_ref_mv1, cpi->common.allow_high_precision_mv, x->errorperbit, + &cpi->fn_ptr[BLOCK_16X16], 0, mv_sf->subpel_iters_per_step, + cond_cost_list(cpi, cost_list), NULL, NULL, &distortion, &sse, NULL, +#if CONFIG_EXT_INTER + NULL, 0, 0, +#endif + 0, 0, 0); +#if CONFIG_AMVR + } +#endif x->e_mbd.mi[0]->bmi[0].as_mv[0] = x->best_mv;