ref: 2d60bee1fbfb7e5b6862e4e636151effabae98e3
parent: 3777125ba66d15fef1436ea8871b3901a86c6991
author: Paul Wilkins <paulwilkins@google.com>
date: Fri Aug 24 11:44:01 EDT 2012
New Motion Reference Search Alternative strategy for finding a list of candidate motion vectors to use as reference values in mv coding and as nearest and near. Sort by sad in vp8_find_best_ref_mvs() rather than just pick the best. Allow 0,0 as a best ref option but not a nearest or near unless there are no alternatives. Encode/Decode verified on at least some clips. Some commented out experimental and stats code still in place. Gain over existing code averages about 1% on derf (alll metrics) with improvement on all clips. Other test results pending. The entropy coding of the mode (nearest/near etc) still depends upon and requires the old "findnear" code so this needs looking at and may provide room for further gains. Change-Id: I871d7cba1d1c379c4bad9bcccce1fb19c46b8247
--- a/configure
+++ b/configure
@@ -226,6 +226,7 @@
switchable_interp
tx16x16
newbestrefmv
+ new_mvref
"
CONFIG_LIST="
external_build
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -44,6 +44,9 @@
/* Segment Feature Masks */
#define SEGMENT_DELTADATA 0
#define SEGMENT_ABSDATA 1
+#if CONFIG_NEW_MVREF
+#define MAX_MV_REFS 10
+#endif
typedef struct {
int r, c;
@@ -179,6 +182,14 @@
B_MODE_COUNT
} B_PREDICTION_MODE;
+#if CONFIG_NEW_MVREF
+// Segment level features.
+typedef enum {
+ FIRST_REF = 0,
+ SECOND_REF = 1
+} MV_REF_TYPE;
+#endif
+
#if CONFIG_HYBRIDTRANSFORM8X8
// convert MB_PREDICTION_MODE to B_PREDICTION_MODE
static B_PREDICTION_MODE pred_mode_conv(MB_PREDICTION_MODE mode) {
@@ -268,9 +279,14 @@
MV_REFERENCE_FRAME ref_frame, second_ref_frame;
TX_SIZE txfm_size;
int_mv mv[2]; // for each reference frame used
-#if CONFIG_NEWBESTREFMV
+#if CONFIG_NEWBESTREFMV || CONFIG_NEW_MVREF
int_mv ref_mv, second_ref_mv;
#endif
+#if CONFIG_NEW_MVREF
+ int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REFS];
+ int mv_ref_index[MAX_REF_FRAMES];
+#endif
+
unsigned char partitioning;
unsigned char mb_skip_coeff; /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */
unsigned char need_to_clamp_mvs;
@@ -432,8 +448,13 @@
#endif
int mb_index; // Index of the MB in the SB (0..3)
+
#if CONFIG_NEWBESTREFMV
+#if CONFIG_NEW_MVREF
+ int_mv ref_mv[MAX_MV_REFS];
+#else
int_mv ref_mv[4];
+#endif
#endif
#if CONFIG_HYBRIDTRANSFORM
--- a/vp8/common/findnearmv.c
+++ b/vp8/common/findnearmv.c
@@ -200,6 +200,9 @@
* above and a number cols of pixels in the left to select the one with best
* score to use as ref motion vector
*/
+
+#if CONFIG_NEW_MVREF
+
void vp8_find_best_ref_mvs(MACROBLOCKD *xd,
unsigned char *ref_y_buffer,
int ref_y_stride,
@@ -207,6 +210,136 @@
int_mv *nearest,
int_mv *near) {
int_mv *ref_mv = xd->ref_mv;
+ int i, j;
+ unsigned char *above_src;
+ unsigned char *left_src;
+ unsigned char *above_ref;
+ unsigned char *left_ref;
+ int sad;
+ int sad_scores[MAX_MV_REFS];
+ int_mv sorted_mvs[MAX_MV_REFS];
+ int zero_seen = FALSE;
+
+ // Default all to 0,0 if nothing else available
+ best_mv->as_int = nearest->as_int = near->as_int = 0;
+ vpx_memset(sorted_mvs, 0, sizeof(sorted_mvs));
+
+ above_src = xd->dst.y_buffer - xd->dst.y_stride * 2;
+ left_src = xd->dst.y_buffer - 2;
+ above_ref = ref_y_buffer - ref_y_stride * 2;
+ left_ref = ref_y_buffer - 2;
+
+ for(i = 0; i < MAX_MV_REFS; ++i) {
+ int_mv this_mv;
+ int offset=0;
+ int row_offset, col_offset;
+
+ this_mv.as_int = ref_mv[i].as_int;
+
+ // If we see a 0,0 vector for a second time we have reached the end of
+ // the list of valid candidate vectors.
+ if (!this_mv.as_int)
+ if (zero_seen)
+ break;
+ else
+ zero_seen = TRUE;
+
+ vp8_clamp_mv(&this_mv,
+ xd->mb_to_left_edge - LEFT_TOP_MARGIN + 16,
+ xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
+ xd->mb_to_top_edge - LEFT_TOP_MARGIN + 16,
+ xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN);
+
+ row_offset = (this_mv.as_mv.row > 0) ?
+ ((this_mv.as_mv.row + 3) >> 3):((this_mv.as_mv.row + 4) >> 3);
+ col_offset = (this_mv.as_mv.col > 0) ?
+ ((this_mv.as_mv.col + 3) >> 3):((this_mv.as_mv.col + 4) >> 3);
+ offset = ref_y_stride * row_offset + col_offset;
+
+ sad = vp8_sad16x2_c(above_src, xd->dst.y_stride,
+ above_ref + offset, ref_y_stride, INT_MAX);
+
+ sad += vp8_sad2x16_c(left_src, xd->dst.y_stride,
+ left_ref + offset, ref_y_stride, INT_MAX);
+
+ // Add the entry to our list and then resort the list on score.
+ sad_scores[i] = sad;
+ sorted_mvs[i].as_int = this_mv.as_int;
+ j = i;
+ while (j > 0) {
+ if (sad_scores[j] < sad_scores[j-1]) {
+ sad_scores[j] = sad_scores[j-1];
+ sorted_mvs[j].as_int = sorted_mvs[j-1].as_int;
+ sad_scores[j-1] = sad;
+ sorted_mvs[j-1].as_int = this_mv.as_int;
+ j--;
+ } else
+ break;
+ }
+ }
+
+ // If not see add 0,0 as a possibility
+ /*if ( (i < MAX_MV_REFS) && !zero_seen ) {
+
+ sad = vp8_sad16x2_c(above_src, xd->dst.y_stride,
+ above_ref, ref_y_stride,
+ INT_MAX);
+ sad += vp8_sad2x16_c(left_src, xd->dst.y_stride,
+ left_ref, ref_y_stride,
+ INT_MAX);
+ this_mv.as_int = 0;
+
+ // Add the entry to our list and then resort the list on score.
+ sad_scores[i] = sad;
+ sorted_mvs[i].as_int = this_mv.as_int;
+ j = i;
+ while (j > 0) {
+ if (sad_scores[j] < sad_scores[j-1]) {
+ sad_scores[j] = sad_scores[j-1];
+ sorted_mvs[j].as_int = sorted_mvs[j-1].as_int;
+ sad_scores[j-1] = sad;
+ sorted_mvs[j-1].as_int = this_mv.as_int;
+ j--;
+ } else
+ break;
+ }
+ }*/
+
+ // Set the best mv to the first entry in the sorted list
+ best_mv->as_int = sorted_mvs[0].as_int;
+
+ // Provided that there are non zero vectors available there will not
+ // be more than one 0,0 entry in the sorted list.
+ // The best ref mv is always set to the first entry (which gave the best
+ // results. The nearest is set to the first non zero vector if available and
+ // near to the second non zero vector if avaialable.
+ // We do not use 0,0 as a nearest or near as 0,0 has its own mode.
+ if ( sorted_mvs[0].as_int ) {
+ nearest->as_int = sorted_mvs[0].as_int;
+ if ( sorted_mvs[1].as_int )
+ near->as_int = sorted_mvs[1].as_int;
+ else
+ near->as_int = sorted_mvs[2].as_int;
+ } else {
+ nearest->as_int = sorted_mvs[1].as_int;
+ near->as_int = sorted_mvs[2].as_int;
+ }
+
+ if (!xd->allow_high_precision_mv)
+ lower_mv_precision(best_mv);
+
+ vp8_clamp_mv2(best_mv, xd);
+}
+
+#else // !CONFIG_NEW_MVREF
+
+void vp8_find_best_ref_mvs(MACROBLOCKD *xd,
+ unsigned char *ref_y_buffer,
+ int ref_y_stride,
+ int_mv *best_mv,
+ int_mv *nearest,
+ int_mv *near) {
+ int_mv *ref_mv = xd->ref_mv;
int bestsad = INT_MAX;
int i;
unsigned char *above_src;
@@ -270,5 +403,5 @@
nearest->as_int = best_mv->as_int;
}
}
-
-#endif
+#endif // CONFIG_NEW_MVREF
+#endif // CONFIG_NEWBESTREFMV
--- /dev/null
+++ b/vp8/common/mvref_common.c
@@ -1,0 +1,303 @@
+/*
+ * 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 "mvref_common.h"
+
+#if CONFIG_NEW_MVREF
+
+#define MVREF_NEIGHBOURS 8
+static int mv_ref_search[MVREF_NEIGHBOURS][2] =
+ { {0,-1},{-1,0},{-1,-1},{0,-2},{-2,0},{-1,-2},{-2,-1},{-2,-2} };
+static int ref_distance_weight[MVREF_NEIGHBOURS] =
+ { 3,3,2,1,1,1,1,1 };
+ //{ 4,4,2,1,1,1,1,1 };
+
+// clamp_mv
+#define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
+static void clamp_mv(const MACROBLOCKD *xd, int_mv *mv) {
+
+ if (mv->as_mv.col < (xd->mb_to_left_edge - MV_BORDER))
+ mv->as_mv.col = xd->mb_to_left_edge - MV_BORDER;
+ else if (mv->as_mv.col > xd->mb_to_right_edge + MV_BORDER)
+ mv->as_mv.col = xd->mb_to_right_edge + MV_BORDER;
+
+ if (mv->as_mv.row < (xd->mb_to_top_edge - MV_BORDER))
+ mv->as_mv.row = xd->mb_to_top_edge - MV_BORDER;
+ else if (mv->as_mv.row > xd->mb_to_bottom_edge + MV_BORDER)
+ mv->as_mv.row = xd->mb_to_bottom_edge + MV_BORDER;
+}
+
+// Code for selecting / building and entropy coding a motion vector reference
+// Returns a seperation value for two vectors.
+// This is taken as the sum of the abs x and y difference.
+unsigned int mv_distance(int_mv *mv1, int_mv *mv2) {
+ return (abs(mv1->as_mv.row - mv2->as_mv.row) +
+ abs(mv1->as_mv.col - mv2->as_mv.col));
+}
+
+// Gets a best matching candidate refenence motion vector
+// from the given mode info structure (if available)
+int get_candidate_mvref(
+ const MODE_INFO *candidate_mi,
+ MV_REFERENCE_FRAME ref_frame,
+ MV_REFERENCE_FRAME *candidate_ref_frame,
+ int_mv *candidate_mv
+) {
+
+ int ret_val = FALSE;
+
+ if (ref_frame == candidate_mi->mbmi.ref_frame) {
+ candidate_mv->as_int = candidate_mi->mbmi.mv[FIRST_REF].as_int;
+ *candidate_ref_frame = ref_frame;
+ ret_val = TRUE;
+
+ } else if (ref_frame == candidate_mi->mbmi.second_ref_frame) {
+ candidate_mv->as_int = candidate_mi->mbmi.mv[SECOND_REF].as_int;
+ *candidate_ref_frame = ref_frame;
+ ret_val = TRUE;
+
+ } else if (candidate_mi->mbmi.ref_frame != INTRA_FRAME) {
+ candidate_mv->as_int = candidate_mi->mbmi.mv[FIRST_REF].as_int;
+ *candidate_ref_frame = candidate_mi->mbmi.ref_frame;
+ ret_val = TRUE;
+
+ } else if (candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) {
+ candidate_mv->as_int = candidate_mi->mbmi.mv[SECOND_REF].as_int;
+ *candidate_ref_frame = candidate_mi->mbmi.second_ref_frame;
+ ret_val = TRUE;
+ }
+
+ return ret_val;
+}
+
+// Performs mv adjustment based on reference frame and clamps the MV
+// if it goes off the edge of the buffer.
+void scale_mv(
+ MACROBLOCKD *xd,
+ MV_REFERENCE_FRAME this_ref_frame,
+ MV_REFERENCE_FRAME candidate_ref_frame,
+ int_mv *candidate_mv,
+ int *ref_sign_bias
+) {
+
+ if (candidate_ref_frame != this_ref_frame) {
+
+ //int frame_distances[MAX_REF_FRAMES];
+ //int last_distance = 1;
+ //int gf_distance = xd->frames_since_golden;
+ //int arf_distance = xd->frames_till_alt_ref_frame;
+
+ // Sign inversion where appropriate.
+ if (ref_sign_bias[candidate_ref_frame] != ref_sign_bias[this_ref_frame]) {
+ candidate_mv->as_mv.row = -candidate_mv->as_mv.row;
+ candidate_mv->as_mv.col = -candidate_mv->as_mv.col;
+ }
+
+ // Scale based on frame distance if the reference frames not the same.
+ /*frame_distances[INTRA_FRAME] = 1; // should never be used
+ frame_distances[LAST_FRAME] = 1;
+ frame_distances[GOLDEN_FRAME] =
+ (xd->frames_since_golden) ? xd->frames_since_golden : 1;
+ frame_distances[ALTREF_FRAME] =
+ (xd->frames_till_alt_ref_frame) ? xd->frames_till_alt_ref_frame : 1;
+
+ if (frame_distances[this_ref_frame] &&
+ frame_distances[candidate_ref_frame]) {
+ candidate_mv->as_mv.row =
+ (short)(((int)(candidate_mv->as_mv.row) *
+ frame_distances[this_ref_frame]) /
+ frame_distances[candidate_ref_frame]);
+
+ candidate_mv->as_mv.col =
+ (short)(((int)(candidate_mv->as_mv.col) *
+ frame_distances[this_ref_frame]) /
+ frame_distances[candidate_ref_frame]);
+ }
+ */
+ }
+
+ // Clamp the MV so it does not point out of the frame buffer
+ clamp_mv(xd, candidate_mv);
+}
+
+// Adds a new candidate reference vector to the list if indeed it is new.
+// If it is not new then the score of the existing candidate that it matches
+// is increased and the list is resorted.
+void addmv_and_shuffle(
+ int_mv *mv_list,
+ int *mv_scores,
+ int *index,
+ int_mv candidate_mv,
+ int weight
+) {
+
+ int i = *index;
+ int duplicate_found = FALSE;
+
+ // Check for duplicates. If there is one increment its score.
+ while (i > 0) {
+ i--;
+ if (candidate_mv.as_int == mv_list[i].as_int) {
+ duplicate_found = TRUE;
+ mv_scores[i] += weight;
+ break;
+ }
+ }
+
+ // If no duplicate was found add the new vector and give it a weight
+ if (!duplicate_found) {
+ mv_list[*index].as_int = candidate_mv.as_int;
+ mv_scores[*index] = weight;
+ i = *index;
+ (*index)++;
+ }
+
+ // Reshuffle the list so that highest scoring mvs at the top.
+ while (i > 0) {
+ if (mv_scores[i] > mv_scores[i-1]) {
+ int tmp_score = mv_scores[i-1];
+ int_mv tmp_mv = mv_list[i-1];
+
+ mv_scores[i-1] = mv_scores[i];
+ mv_list[i-1] = mv_list[i];
+ mv_scores[i] = tmp_score;
+ mv_list[i] = tmp_mv;
+ i--;
+ } else
+ break;
+ }
+}
+
+
+// Measure the distance of each reference candidate from the actual
+// residual vector and return the nearest
+unsigned int pick_best_mv_ref( int_mv target_mv,
+ int_mv * mv_ref_list,
+ int_mv * best_ref ) {
+
+ int i;
+ int best_index = 0;
+ unsigned int distance, distance2;
+
+ distance = mv_distance(&target_mv, &mv_ref_list[0]);
+
+ for (i = 1; i < MAX_MV_REFS; ++i ) {
+ distance2 =
+ mv_distance(&target_mv, &mv_ref_list[i]);
+ if (distance2 < distance) {
+ distance = distance2;
+ best_index = i;
+ }
+ }
+
+ (*best_ref).as_int = mv_ref_list[best_index].as_int;
+
+ return best_index;
+}
+
+// This function searches the neighbourhood of a given MB/SB and populates a
+// list of candidate reference vectors.
+//
+void find_mv_refs(
+ MACROBLOCKD *xd,
+ MODE_INFO *here,
+ MODE_INFO *lf_here,
+ MV_REFERENCE_FRAME ref_frame,
+ int_mv *mv_ref_list,
+ int *ref_sign_bias
+) {
+
+ int i;
+ MODE_INFO *candidate_mi;
+ int_mv candidate_mvs[MAX_MV_REFS];
+ int_mv c_refmv;
+ MV_REFERENCE_FRAME c_ref_frame;
+ int candidate_scores[MAX_MV_REFS];
+ int index = 0;
+ int ref_weight = 0;
+ int valid_mv_ref;
+
+ // Blank the reference vector lists and other local structures.
+ vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REFS);
+ vpx_memset(candidate_mvs, 0, sizeof(int_mv) * MAX_MV_REFS);
+ vpx_memset(candidate_scores, 0, sizeof(candidate_scores));
+
+ // Populate a list with candidate reference vectors from the
+ // spatial neighbours.
+ for (i = 0; i < 2; ++i) {
+ if (((mv_ref_search[i][0] << 7) >= xd->mb_to_left_edge) &&
+ ((mv_ref_search[i][1] << 7) >= xd->mb_to_top_edge)) {
+
+ candidate_mi = here + mv_ref_search[i][0] +
+ (mv_ref_search[i][1] * xd->mode_info_stride);
+
+ valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
+ &c_ref_frame, &c_refmv);
+
+ if (valid_mv_ref) {
+ scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
+ ref_weight = ref_distance_weight[i] +
+ ((c_ref_frame == ref_frame) << 3);
+
+ addmv_and_shuffle(candidate_mvs, candidate_scores,
+ &index, c_refmv, ref_weight);
+ }
+ }
+ }
+
+ // Look at the corresponding vector in the last frame
+ candidate_mi = lf_here;
+ valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
+ &c_ref_frame, &c_refmv);
+ if (valid_mv_ref) {
+ scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
+ ref_weight = 2 + ((c_ref_frame == ref_frame) << 3);
+ addmv_and_shuffle(candidate_mvs, candidate_scores,
+ &index, c_refmv, ref_weight);
+ }
+
+ // Populate a list with candidate reference vectors from the
+ // spatial neighbours.
+ for (i = 2; i < MVREF_NEIGHBOURS; ++i) {
+ if (((mv_ref_search[i][0] << 7) >= xd->mb_to_left_edge) &&
+ ((mv_ref_search[i][1] << 7) >= xd->mb_to_top_edge)) {
+
+ candidate_mi = here + mv_ref_search[i][0] +
+ (mv_ref_search[i][1] * xd->mode_info_stride);
+
+ valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
+ &c_ref_frame, &c_refmv);
+
+ if (valid_mv_ref) {
+ scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
+ ref_weight = ref_distance_weight[i] +
+ ((c_ref_frame == ref_frame) << 3);
+
+ addmv_and_shuffle(candidate_mvs, candidate_scores,
+ &index, c_refmv, ref_weight);
+ }
+ }
+ }
+
+ // 0,0 is always a valid reference.
+ for (i = 0; i < index; ++i)
+ if (candidate_mvs[i].as_int == 0)
+ break;
+ if (i == index) {
+ c_refmv.as_int = 0;
+ addmv_and_shuffle(candidate_mvs, candidate_scores,
+ &index, c_refmv, 1);
+ }
+
+ // Copy over the candidate list.
+ vpx_memcpy(mv_ref_list, candidate_mvs, sizeof(candidate_mvs));
+}
+
+#endif
--- /dev/null
+++ b/vp8/common/mvref_common.h
@@ -1,0 +1,37 @@
+/*
+ * 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 "onyxc_int.h"
+#include "blockd.h"
+
+// MR reference entropy header file.
+#if CONFIG_NEW_MVREF
+
+#ifndef __INC_MVREF_COMMON_H
+#define __INC_MVREF_COMMON_H
+
+unsigned int mv_distance(int_mv *mv1, int_mv *mv2);
+
+unsigned int pick_best_mv_ref( int_mv target_mv,
+ int_mv * mv_ref_list,
+ int_mv * best_ref );
+
+void find_mv_refs(
+ MACROBLOCKD *xd,
+ MODE_INFO *here,
+ MODE_INFO *lf_here,
+ MV_REFERENCE_FRAME ref_frame,
+ int_mv * mv_ref_list,
+ int *ref_sign_bias
+);
+
+#endif
+
+#endif
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -657,6 +657,7 @@
prev_mi,
&nearest, &nearby, &best_mv, rct,
mbmi->ref_frame, cm->ref_frame_sign_bias);
+
#if CONFIG_NEWBESTREFMV
{
int ref_fb_idx;
@@ -679,6 +680,23 @@
xd->pre.u_buffer = cm->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = cm->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
+#if CONFIG_NEW_MVREF
+ // Update stats on relative distance of chosen vector to the
+ // possible best reference vectors.
+ {
+ int i;
+ MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame;
+
+ find_mv_refs(xd, mi, prev_mi,
+ ref_frame, mbmi->ref_mvs[ref_frame],
+ cm->ref_frame_sign_bias );
+
+ // Copy over the candidates.
+ vpx_memcpy(xd->ref_mv, mbmi->ref_mvs[ref_frame],
+ (MAX_MV_REFS * sizeof(int_mv)) );
+ }
+#endif
+
vp8_find_best_ref_mvs(xd,
xd->pre.y_buffer,
recon_y_stride,
@@ -763,6 +781,23 @@
rct,
mbmi->second_ref_frame,
cm->ref_frame_sign_bias);
+
+#if CONFIG_NEW_MVREF
+ // Update stats on relative distance of chosen vector to the
+ // possible best reference vectors.
+ {
+ MV_REFERENCE_FRAME ref_frame = mbmi->second_ref_frame;
+
+ find_mv_refs(xd, mi, prev_mi,
+ ref_frame, mbmi->ref_mvs[ref_frame],
+ cm->ref_frame_sign_bias );
+
+ // Copy over the mv candidates
+ vpx_memcpy(xd->ref_mv, mbmi->ref_mvs[ref_frame],
+ (MAX_MV_REFS * sizeof(int_mv)) );
+ }
+#endif
+
vp8_find_best_ref_mvs(xd,
xd->second_pre.y_buffer,
recon_y_stride,
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -28,6 +28,10 @@
#include "vp8/common/pred_common.h"
#include "vp8/common/entropy.h"
+#if CONFIG_NEW_MVREF
+#include "vp8/common/mvref_common.h"
+#endif
+
#if defined(SECTIONBITS_OUTPUT)
unsigned __int64 Sectionbits[500];
#endif
@@ -1043,6 +1047,14 @@
active_section = 5;
#endif
+#if 0 //CONFIG_NEW_MVREF
+ find_mv_refs(xd, m, prev_m,
+ m->mbmi.ref_frame,
+ mi->ref_mvs[rf],
+ cpi->common.ref_frame_sign_bias );
+
+ pick_best_mv_ref( mi->mv[0], mi->ref_mvs[rf], &best_mv);
+#endif
if (xd->allow_high_precision_mv)
write_mv_hp(w, &mi->mv[0].as_mv, &best_mv, mvc_hp);
else
@@ -1049,6 +1061,16 @@
write_mv(w, &mi->mv[0].as_mv, &best_mv, mvc);
if (mi->second_ref_frame) {
+#if 0 //CONFIG_NEW_MVREF
+ find_mv_refs(xd, m, prev_m,
+ m->mbmi.second_ref_frame,
+ mi->ref_mvs[mi->second_ref_frame],
+ cpi->common.ref_frame_sign_bias );
+
+ pick_best_mv_ref( mi->mv[1],
+ mi->ref_mvs[mi->second_ref_frame],
+ &best_second_mv);
+#endif
if (xd->allow_high_precision_mv)
write_mv_hp(w, &mi->mv[1].as_mv, &best_second_mv, mvc_hp);
else
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -34,7 +34,11 @@
#include "vp8/common/pred_common.h"
#define DBG_PRNT_SEGMAP 0
+#if CONFIG_NEW_MVREF
+#include "vp8/common/mvref_common.h"
+#endif
+
#if CONFIG_RUNTIME_CPU_DETECT
#define RTCD(x) &cpi->common.rtcd.x
#define IF_RTCD(x) (x)
@@ -1300,6 +1304,12 @@
// prediction fails. These are based on the current general estimates for
// this frame which may be updated with each iteration of the recode loop.
compute_mod_refprobs(cm);
+
+#if CONFIG_NEW_MVREF
+ // temp stats reset
+ vp8_zero( cpi->mv_ref_sum_distance );
+ vp8_zero( cpi->best_ref_index_counts );
+#endif
// debug output
#if DBG_PRNT_SEGMAP
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -40,6 +40,10 @@
#include "bitstream.h"
#include "ratectrl.h"
+#if CONFIG_NEW_MVREF
+#include "vp8/common/mvref_common.h"
+#endif
+
#if ARCH_ARM
#include "vpx_ports/arm.h"
#endif
@@ -3789,6 +3793,36 @@
// Update the skip mb flag probabilities based on the distribution seen
// in this frame.
update_base_skip_probs(cpi);
+
+
+#if CONFIG_NEW_MVREF
+#if 0 && CONFIG_INTERNAL_STATS
+ {
+ FILE *f = fopen("mv_ref_dist.stt", "a");
+ unsigned int i;
+ //fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d %10d\n",
+ fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d %10d",
+ cpi->common.current_video_frame,
+ cpi->mv_ref_sum_distance[1][0],
+ cpi->mv_ref_sum_distance[1][1],
+ cpi->mv_ref_sum_distance[1][2],
+ cpi->mv_ref_sum_distance[2][0],
+ cpi->mv_ref_sum_distance[2][1],
+ cpi->mv_ref_sum_distance[2][2],
+ cpi->mv_ref_sum_distance[3][0],
+ cpi->mv_ref_sum_distance[3][1],
+ cpi->mv_ref_sum_distance[3][2] );
+
+ for (i = 0; i < MAX_MV_REFS; ++i) {
+ fprintf(f, "%10d", cpi->best_ref_index_counts[i] );
+ }
+ fprintf(f, "\n" );
+
+ fclose(f);
+ }
+#endif
+#endif
+
#if 0// 1 && CONFIG_INTERNAL_STATS
{
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -59,6 +59,13 @@
#define VP8_TEMPORAL_ALT_REF 1
+#if CONFIG_NEW_MVREF
+// temp. relate to mv_ref_sum_distance stats
+#define CUR_BEST 0
+#define NEW_BEST 1
+#define BEST_SELECTED 2
+#endif
+
typedef struct {
MV_CONTEXT mvc[2];
int mvcosts[2][MVvals + 1];
@@ -750,6 +757,12 @@
#if CONFIG_SWITCHABLE_INTERP
unsigned int switchable_interp_count[VP8_SWITCHABLE_FILTERS+1]
[VP8_SWITCHABLE_FILTERS];
+#endif
+
+#if CONFIG_NEW_MVREF
+ // temp stats [REF_FRAME]{REF_METHOD]
+ unsigned int mv_ref_sum_distance[4][3];
+ unsigned int best_ref_index_counts[17];
#endif
} VP8_COMP;
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -41,6 +41,10 @@
#include "vp8/common/seg_common.h"
#include "vp8/common/pred_common.h"
+#if CONFIG_NEW_MVREF
+#include "vp8/common/mvref_common.h"
+#endif
+
#if CONFIG_RUNTIME_CPU_DETECT
#define IF_RTCD(x) (x)
#else
@@ -2892,9 +2896,10 @@
unsigned char *y_buffer[4], unsigned char *u_buffer[4],
unsigned char *v_buffer[4]) {
YV12_BUFFER_CONFIG *yv12 = &cpi->common.yv12_fb[idx];
+ MACROBLOCKD *xd = &x->e_mbd;
- vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context,
- x->e_mbd.prev_mode_info_context,
+ vp8_find_near_mvs(xd, xd->mode_info_context,
+ xd->prev_mode_info_context,
&frame_nearest_mv[frame_type], &frame_near_mv[frame_type],
&frame_best_ref_mv[frame_type], frame_mdcounts[frame_type],
frame_type, cpi->common.ref_frame_sign_bias);
@@ -2902,8 +2907,27 @@
y_buffer[frame_type] = yv12->y_buffer + recon_yoffset;
u_buffer[frame_type] = yv12->u_buffer + recon_uvoffset;
v_buffer[frame_type] = yv12->v_buffer + recon_uvoffset;
+
#if CONFIG_NEWBESTREFMV
- vp8_find_best_ref_mvs(&x->e_mbd, y_buffer[frame_type],
+#if CONFIG_NEW_MVREF
+ // Update stats on relative distance of chosen vector to the
+ // possible best reference vectors.
+ {
+ MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
+
+ find_mv_refs(xd, xd->mode_info_context,
+ xd->prev_mode_info_context,
+ frame_type,
+ mbmi->ref_mvs[frame_type],
+ cpi->common.ref_frame_sign_bias );
+
+ // Copy over the mv candidates
+ vpx_memcpy(xd->ref_mv, mbmi->ref_mvs[frame_type],
+ (MAX_MV_REFS * sizeof(int_mv)) );
+ }
+#endif
+
+ vp8_find_best_ref_mvs(xd, y_buffer[frame_type],
yv12->y_stride,
&frame_best_ref_mv[frame_type],
&frame_nearest_mv[frame_type],
@@ -3406,6 +3430,43 @@
}
d->bmi.as_mv.first.as_int = tmp_mv.as_int;
frame_mv[NEWMV][refs[0]].as_int = d->bmi.as_mv.first.as_int;
+
+#if CONFIG_NEW_MVREF
+ // Update stats on relative distance of chosen vector to the
+ // possible best reference vectors.
+ {
+ unsigned int distance;
+ MV_REFERENCE_FRAME ref = mbmi->ref_frame;
+ int_mv selected_best_ref;
+ unsigned int best_index = 0;
+
+ find_mv_refs(xd, xd->mode_info_context,
+ xd->prev_mode_info_context,
+ ref,
+ mbmi->ref_mvs[ref],
+ cpi->common.ref_frame_sign_bias );
+
+ distance = mv_distance(&tmp_mv, &best_ref_mv);
+ cpi->mv_ref_sum_distance[ref][CUR_BEST] += distance;
+
+ distance =
+ mv_distance(&tmp_mv,
+ &mbmi->ref_mvs[ref][0]);
+ cpi->mv_ref_sum_distance[ref][NEW_BEST] += distance;
+
+ best_index = pick_best_mv_ref(tmp_mv, mbmi->ref_mvs[ref],
+ &selected_best_ref);
+
+ distance = mv_distance(&tmp_mv, &selected_best_ref);
+ mbmi->mv_ref_index[ref] = best_index;
+ cpi->mv_ref_sum_distance[ref][BEST_SELECTED] += distance;
+ cpi->best_ref_index_counts[best_index]++;
+
+ // Temp
+ //mbmi->mv_ref_index[ref] = 0;
+ //mbmi->ref_mvs[ref][0].as_int = best_ref_mv.as_int;
+ }
+#endif
// Add the new motion vector cost to our rolling cost variable
rate2 += vp8_mv_bit_cost(&tmp_mv, &best_ref_mv,
--- a/vp8/vp8_common.mk
+++ b/vp8/vp8_common.mk
@@ -67,6 +67,8 @@
VP8_COMMON_SRCS-yes += common/mbpitch.c
VP8_COMMON_SRCS-yes += common/modecont.c
VP8_COMMON_SRCS-yes += common/modecontext.c
+VP8_COMMON_SRCS-yes += common/mvref_common.c
+VP8_COMMON_SRCS-yes += common/mvref_common.h
VP8_COMMON_SRCS-yes += common/quant_common.c
VP8_COMMON_SRCS-yes += common/recon.c
VP8_COMMON_SRCS-yes += common/reconinter.c