summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure1
-rw-r--r--vp8/common/blockd.h23
-rw-r--r--vp8/common/findnearmv.c137
-rw-r--r--vp8/common/mvref_common.c303
-rw-r--r--vp8/common/mvref_common.h37
-rw-r--r--vp8/decoder/decodemv.c35
-rw-r--r--vp8/encoder/bitstream.c22
-rw-r--r--vp8/encoder/encodeframe.c10
-rw-r--r--vp8/encoder/onyx_if.c34
-rw-r--r--vp8/encoder/onyx_int.h13
-rw-r--r--vp8/encoder/rdopt.c67
-rw-r--r--vp8/vp8_common.mk2
12 files changed, 678 insertions, 6 deletions
diff --git a/configure b/configure
index b39ddb2b8..5c9e12067 100755
--- a/configure
+++ b/configure
@@ -226,6 +226,7 @@ EXPERIMENT_LIST="
switchable_interp
tx16x16
newbestrefmv
+ new_mvref
"
CONFIG_LIST="
external_build
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
index 4e5d9e813..46d002af9 100644
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -44,6 +44,9 @@ void vpx_log(const char *format, ...);
/* 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 @@ typedef enum {
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 @@ typedef struct {
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,9 +448,14 @@ typedef struct MacroBlockD {
#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
int q_index;
diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c
index 6f7361dd0..694f4cc32 100644
--- a/vp8/common/findnearmv.c
+++ b/vp8/common/findnearmv.c
@@ -200,6 +200,139 @@ vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc,
* 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,
+ int_mv *best_mv,
+ 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,
@@ -270,5 +403,5 @@ void vp8_find_best_ref_mvs(MACROBLOCKD *xd,
nearest->as_int = best_mv->as_int;
}
}
-
-#endif
+#endif // CONFIG_NEW_MVREF
+#endif // CONFIG_NEWBESTREFMV
diff --git a/vp8/common/mvref_common.c b/vp8/common/mvref_common.c
new file mode 100644
index 000000000..1c345dba5
--- /dev/null
+++ b/vp8/common/mvref_common.c
@@ -0,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
diff --git a/vp8/common/mvref_common.h b/vp8/common/mvref_common.h
new file mode 100644
index 000000000..9be408894
--- /dev/null
+++ b/vp8/common/mvref_common.h
@@ -0,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
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
index 5e0600c2d..069d073d4 100644
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -657,6 +657,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
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 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
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 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
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,
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
index 90bc8e987..7e667aa63 100644
--- 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,12 +1047,30 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) {
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
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
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
index f834e0b83..6ade0aa78 100644
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -34,6 +34,10 @@
#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
@@ -1301,6 +1305,12 @@ static void encode_frame_internal(VP8_COMP *cpi) {
// 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
{
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index c3df54481..85a3c5402 100644
--- 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
@@ -3790,6 +3794,36 @@ static void encode_frame_to_data_rate
// 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
{
FILE *f = fopen("tmp.stt", "a");
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 7fb7dd2ff..bff3cdf6c 100644
--- 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];
@@ -752,6 +759,12 @@ typedef struct VP8_COMP {
[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;
void control_data_rate(VP8_COMP *cpi);
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
index d217f2ffc..d07c2383e 100644
--- 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 @@ void setup_buffer_inter(VP8_COMP *cpi, MACROBLOCK *x, int idx, int frame_type,
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 @@ void setup_buffer_inter(VP8_COMP *cpi, MACROBLOCK *x, int idx, int frame_type,
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],
@@ -3407,6 +3431,43 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
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,
XMVCOST, 96,
diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
index 4d3d0345e..f04bc3497 100644
--- a/vp8/vp8_common.mk
+++ b/vp8/vp8_common.mk
@@ -67,6 +67,8 @@ VP8_COMMON_SRCS-yes += common/loopfilter_filters.c
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