Commit 2d60bee1 authored by Paul Wilkins's avatar Paul Wilkins

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
parent 3777125b
......@@ -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
/*
* 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
/*
* 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