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
This commit is contained in:
parent
3777125ba6
commit
2d60bee1fb
1
configure
vendored
1
configure
vendored
@ -226,6 +226,7 @@ EXPERIMENT_LIST="
|
||||
switchable_interp
|
||||
tx16x16
|
||||
newbestrefmv
|
||||
new_mvref
|
||||
"
|
||||
CONFIG_LIST="
|
||||
external_build
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
303
vp8/common/mvref_common.c
Normal file
303
vp8/common/mvref_common.c
Normal file
@ -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
|
37
vp8/common/mvref_common.h
Normal file
37
vp8/common/mvref_common.h
Normal file
@ -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
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user