ref: ed40ff9e2dfb261db4ab1dd5d5f984a2b59cf936
parent: a0306ea660b2a35d09645e6d3e98d786614a874d
author: Adrian Grange <agrange@google.com>
date: Thu Mar 10 06:32:48 EST 2011
Removed firstpass motion map The firstpass motion map consists of an 8-bit flag for each MB indicating how strongly the firstpass code believes it should be filtered during the second pass ARNR filtering. For long or large format material the motion map can become extremely large and hamper the operation of the encoding process. This change removes the motion map altogether, leaving the second pass to rely on the magnitude of the motion compensated error to determine the filter weight to use for the MB during ARNR filtering. Tests on the derf set indicate that the effect of this change is neutral, with some small wins and losses. The motion map has therefore been removed based on a cost/benefit evaluation. Change-Id: I53e07d236f5ce09a6f0c54e7c4ffbb490fb870f6
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -281,21 +281,6 @@
}
-extern size_t vp8_firstpass_stats_sz(unsigned int mb_count)
-{
- /* Calculate the size of a stats packet, which is dependent on the frame
- * resolution. The FIRSTPASS_STATS struct has a single element array,
- * motion_map, which is virtually expanded to have one element per
- * macroblock.
- */
- size_t stats_sz;
-
- stats_sz = sizeof(FIRSTPASS_STATS) + mb_count;
- stats_sz = (stats_sz + 7) & ~7;
- return stats_sz;
-}
-
-
void vp8_output_stats(const VP8_COMP *cpi,
struct vpx_codec_pkt_list *pktlist,
FIRSTPASS_STATS *stats)
@@ -303,7 +288,7 @@
struct vpx_codec_cx_pkt pkt;
pkt.kind = VPX_CODEC_STATS_PKT;
pkt.data.twopass_stats.buf = stats;
- pkt.data.twopass_stats.sz = vp8_firstpass_stats_sz(cpi->common.MBs);
+ pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
vpx_codec_pkt_list_add(pktlist, &pkt);
// TEMP debug code
@@ -333,11 +318,6 @@
stats->count,
stats->duration);
fclose(fpfile);
-
-
- fpfile = fopen("fpmotionmap.stt", "a");
- if(fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, fpfile));
- fclose(fpfile);
}
#endif
}
@@ -344,13 +324,11 @@
int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
{
- size_t stats_sz = vp8_firstpass_stats_sz(cpi->common.MBs);
-
if (cpi->stats_in >= cpi->stats_in_end)
return EOF;
*fps = *cpi->stats_in;
- cpi->stats_in = (void*)((char *)cpi->stats_in + stats_sz);
+ cpi->stats_in = (void*)((char *)cpi->stats_in + sizeof(FIRSTPASS_STATS));
return 1;
}
@@ -416,57 +394,9 @@
section->duration /= section->count;
}
-unsigned char *vp8_fpmm_get_pos(VP8_COMP *cpi)
-{
- return cpi->fp_motion_map_stats;
-}
-void vp8_fpmm_reset_pos(VP8_COMP *cpi, unsigned char *target_pos)
-{
- cpi->fp_motion_map_stats = target_pos;
-}
-
-void vp8_advance_fpmm(VP8_COMP *cpi, int count)
-{
- cpi->fp_motion_map_stats = (void*)((char*)cpi->fp_motion_map_stats +
- count * vp8_firstpass_stats_sz(cpi->common.MBs));
-}
-
-void vp8_input_fpmm(VP8_COMP *cpi)
-{
- unsigned char *fpmm = cpi->fp_motion_map;
- int MBs = cpi->common.MBs;
- int max_frames = cpi->active_arnr_frames;
- int i;
-
- for (i=0; i<max_frames; i++)
- {
- char *motion_map = (char*)cpi->fp_motion_map_stats
- + sizeof(FIRSTPASS_STATS);
-
- memcpy(fpmm, motion_map, MBs);
- fpmm += MBs;
- vp8_advance_fpmm(cpi, 1);
- }
-
- // Flag the use of weights in the temporal filter
- cpi->use_weighted_temporal_filter = 1;
-}
-
void vp8_init_first_pass(VP8_COMP *cpi)
{
vp8_zero_stats(cpi->total_stats);
-
-// TEMP debug code
-#ifdef OUTPUT_FPF
- {
- FILE *fpfile;
- fpfile = fopen("firstpass.stt", "w");
- fclose(fpfile);
- fpfile = fopen("fpmotionmap.stt", "wb");
- fclose(fpfile);
- }
-#endif
-
}
void vp8_end_first_pass(VP8_COMP *cpi)
@@ -583,8 +513,6 @@
MV zero_ref_mv = {0, 0};
- unsigned char *fp_motion_map_ptr = cpi->fp_motion_map;
-
vp8_clear_system_state(); //__asm emms;
x->src = * cpi->Source;
@@ -636,7 +564,6 @@
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
{
int this_error;
- int zero_error;
int zz_to_best_ratio;
int gf_motion_error = INT_MAX;
int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
@@ -658,9 +585,6 @@
// Cumulative intra error total
intra_error += (long long)this_error;
- // Indicate default assumption of intra in the motion map
- *fp_motion_map_ptr = 0;
-
// Set up limit values for motion vectors to prevent them extending outside the UMV borders
x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
@@ -679,9 +603,6 @@
d->bmi.mv.as_mv.row = 0;
d->bmi.mv.as_mv.col = 0;
- // Save (0,0) error for later use
- zero_error = motion_error;
-
// Test last reference frame using the previous best mv as the
// starting point (best reference) for the search
vp8_first_pass_motion_search(cpi, x, &best_ref_mv.as_mv,
@@ -796,26 +717,7 @@
else if (d->bmi.mv.as_mv.col < 0)
sum_in_vectors--;
}
-
- // Compute how close (0,0) predictor is to best
- // predictor in terms of their prediction error
- zz_to_best_ratio = (10*zero_error + this_error/2)
- / (this_error+!this_error);
-
- if ((zero_error < 50000) &&
- (zz_to_best_ratio <= 11) )
- *fp_motion_map_ptr = 1;
- else
- *fp_motion_map_ptr = 0;
}
- else
- {
- // 0,0 mv was best
- if( zero_error<50000 )
- *fp_motion_map_ptr = 2;
- else
- *fp_motion_map_ptr = 1;
- }
}
}
@@ -828,9 +730,6 @@
recon_yoffset += 16;
recon_uvoffset += 8;
-
- // Update the motion map
- fp_motion_map_ptr++;
}
// adjust to the next row of mbs
@@ -892,13 +791,10 @@
// than the full time between subsequent cpi->source_time_stamp s .
fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp;
- // don't want to do outputstats with a stack variable!
+ // don't want to do output stats with a stack variable!
memcpy(cpi->this_frame_stats,
&fps,
sizeof(FIRSTPASS_STATS));
- memcpy((char*)cpi->this_frame_stats + sizeof(FIRSTPASS_STATS),
- cpi->fp_motion_map,
- sizeof(cpi->fp_motion_map[0]) * cpi->common.MBs);
vp8_output_stats(cpi, cpi->output_pkt_list, cpi->this_frame_stats);
vp8_accumulate_stats(cpi->total_stats, &fps);
}
@@ -1351,8 +1247,6 @@
cpi->clip_bpe = cpi->bits_left /
DOUBLE_DIVIDE_CHECK(cpi->modified_error_total);
cpi->observed_bpe = cpi->clip_bpe;
-
- cpi->fp_motion_map_stats = (unsigned char *)cpi->stats_in;
}
void vp8_end_second_pass(VP8_COMP *cpi)
@@ -1360,7 +1254,7 @@
}
// This function gives and estimate of how badly we believe
-// the predicition quality is decaying from frame to frame.
+// the prediction quality is decaying from frame to frame.
double get_prediction_decay_rate(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
{
double prediction_decay_rate;
@@ -1472,8 +1366,6 @@
int max_bits = frame_max_bits(cpi); // Max for a single frame
- unsigned char *fpmm_pos;
-
unsigned int allow_alt_ref =
cpi->oxcf.play_alternate && cpi->oxcf.lag_in_frames;
@@ -1482,8 +1374,6 @@
vp8_clear_system_state(); //__asm emms;
- fpmm_pos = vp8_fpmm_get_pos(cpi);
-
start_pos = cpi->stats_in;
vpx_memset(&next_frame, 0, sizeof(next_frame)); // assure clean
@@ -1780,20 +1670,6 @@
}
cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
-
- {
- // Advance to & read in the motion map for those frames
- // to be considered for filtering based on the position
- // of the ARF
- vp8_fpmm_reset_pos(cpi, cpi->fp_motion_map_stats_save);
-
- // Position at the 'earliest' frame to be filtered
- vp8_advance_fpmm(cpi,
- cpi->baseline_gf_interval - frames_bwd);
-
- // Read / create a motion map for the region of interest
- vp8_input_fpmm(cpi);
- }
}
else
{
@@ -2023,9 +1899,6 @@
reset_fpf_position(cpi, start_pos);
}
-
- // Reset the First pass motion map file position
- vp8_fpmm_reset_pos(cpi, fpmm_pos);
}
// Allocate bits to a normal frame that is neither a gf an arf or a key frame.
@@ -2106,13 +1979,6 @@
if (EOF == vp8_input_stats(cpi, &this_frame))
return;
-
- vpx_memset(cpi->fp_motion_map, 0,
- cpi->oxcf.arnr_max_frames*cpi->common.MBs);
- cpi->fp_motion_map_stats_save = vp8_fpmm_get_pos(cpi);
-
- // Step over this frame's first pass motion map
- vp8_advance_fpmm(cpi, 1);
this_frame_error = this_frame.ssim_weighted_pred_err;
this_frame_intra_error = this_frame.intra_error;
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -281,12 +281,6 @@
vpx_free(cpi->active_map);
cpi->active_map = 0;
-#if !(CONFIG_REALTIME_ONLY)
- // Delete first pass motion map
- vpx_free(cpi->fp_motion_map);
- cpi->fp_motion_map = 0;
-#endif
-
vp8_de_alloc_frame_buffers(&cpi->common);
vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf);
@@ -1360,11 +1354,11 @@
#if !(CONFIG_REALTIME_ONLY)
vpx_free(cpi->total_stats);
- cpi->total_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs));
+ cpi->total_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
vpx_free(cpi->this_frame_stats);
- cpi->this_frame_stats = vpx_calloc(1, vp8_firstpass_stats_sz(cpi->common.MBs));
+ cpi->this_frame_stats = vpx_calloc(1, sizeof(FIRSTPASS_STATS));
if(!cpi->total_stats || !cpi->this_frame_stats)
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
@@ -1543,8 +1537,6 @@
#if VP8_TEMPORAL_ALT_REF
- cpi->use_weighted_temporal_filter = 0;
-
{
int i;
@@ -1927,12 +1919,6 @@
vpx_memset(cpi->active_map , 1, (cpi->common.mb_rows * cpi->common.mb_cols));
cpi->active_map_enabled = 0;
-#if !(CONFIG_REALTIME_ONLY)
- // Create the first pass motion map structure and set to 0
- // Allocate space for maximum of 15 buffers
- CHECK_MEM_ERROR(cpi->fp_motion_map, vpx_calloc(15*cpi->common.MBs, 1));
-#endif
-
#if 0
// Experimental code for lagged and one pass
// Initialise one_pass GF frames stats
@@ -2082,7 +2068,7 @@
}
else if (cpi->pass == 2)
{
- size_t packet_sz = vp8_firstpass_stats_sz(cpi->common.MBs);
+ size_t packet_sz = sizeof(FIRSTPASS_STATS);
int packets = oxcf->two_pass_stats_in.sz / packet_sz;
cpi->stats_in = oxcf->two_pass_stats_in.buf;
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -496,11 +496,6 @@
struct vpx_codec_pkt_list *output_pkt_list;
int first_pass_done;
-#if !(CONFIG_REALTIME_ONLY)
- unsigned char *fp_motion_map;
- unsigned char *fp_motion_map_stats, *fp_motion_map_stats_save;
-#endif
-
#if 0
// Experimental code for lagged and one pass
ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
@@ -642,8 +637,6 @@
YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
int fixed_divide[512];
#endif
- // Flag to indicate temporal filter method
- int use_weighted_temporal_filter;
#if CONFIG_PSNR
int count;
--- a/vp8/encoder/temporal_filter.c
+++ b/vp8/encoder/temporal_filter.c
@@ -287,8 +287,7 @@
int byte;
int frame;
int mb_col, mb_row;
- unsigned int filter_weight[MAX_LAG_BUFFERS];
- unsigned char *mm_ptr = cpi->fp_motion_map;
+ unsigned int filter_weight;
int mb_cols = cpi->common.mb_cols;
int mb_rows = cpi->common.mb_rows;
int MBs = cpi->common.MBs;
@@ -306,13 +305,6 @@
unsigned char *u_buffer = mbd->pre.u_buffer;
unsigned char *v_buffer = mbd->pre.v_buffer;
- if (!cpi->use_weighted_temporal_filter)
- {
- // Temporal filtering is unweighted
- for (frame = 0; frame < frame_count; frame++)
- filter_weight[frame] = 1;
- }
-
for (mb_row = 0; mb_row < mb_rows; mb_row++)
{
#if ALT_REF_MC_ENABLED
@@ -338,34 +330,9 @@
+ (VP8BORDERINPIXELS - 19);
#endif
- // Read & process macroblock weights from motion map
- if (cpi->use_weighted_temporal_filter)
- {
- weight_cap = 2;
-
- for (frame = alt_ref_index-1; frame >= 0; frame--)
- {
- w = *(mm_ptr + (frame+1)*MBs);
- filter_weight[frame] = w < weight_cap ? w : weight_cap;
- weight_cap = w;
- }
-
- filter_weight[alt_ref_index] = 2;
-
- weight_cap = 2;
-
- for (frame = alt_ref_index+1; frame < frame_count; frame++)
- {
- w = *(mm_ptr + frame*MBs);
- filter_weight[frame] = w < weight_cap ? w : weight_cap;
- weight_cap = w;
- }
-
- }
-
for (frame = 0; frame < frame_count; frame++)
{
- int err;
+ int err = 0;
if (cpi->frames[frame] == NULL)
continue;
@@ -374,28 +341,25 @@
mbd->block[0].bmi.mv.as_mv.col = 0;
#if ALT_REF_MC_ENABLED
- //if (filter_weight[frame] == 0)
- {
#define THRESH_LOW 10000
#define THRESH_HIGH 20000
- // Correlation has been lost try MC
- err = vp8_temporal_filter_find_matching_mb_c
- (cpi,
- cpi->frames[alt_ref_index],
- cpi->frames[frame],
- mb_y_offset,
- THRESH_LOW);
+ // Find best match in this frame by MC
+ err = vp8_temporal_filter_find_matching_mb_c
+ (cpi,
+ cpi->frames[alt_ref_index],
+ cpi->frames[frame],
+ mb_y_offset,
+ THRESH_LOW);
- if (filter_weight[frame] < 2)
- {
- // Set weight depending on error
- filter_weight[frame] = err<THRESH_LOW
- ? 2 : err<THRESH_HIGH ? 1 : 0;
- }
- }
#endif
- if (filter_weight[frame] != 0)
+ // Assign higher weight to matching MB if it's error
+ // score is lower. If not applying MC default behavior
+ // is to weight all MBs equal.
+ filter_weight = err<THRESH_LOW
+ ? 2 : err<THRESH_HIGH ? 1 : 0;
+
+ if (filter_weight != 0)
{
// Construct the predictors
vp8_temporal_filter_predictors_mb_c
@@ -415,7 +379,7 @@
predictor,
16,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator,
count);
@@ -425,7 +389,7 @@
predictor + 256,
8,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator + 256,
count + 256);
@@ -435,7 +399,7 @@
predictor + 320,
8,
strength,
- filter_weight[frame],
+ filter_weight,
accumulator + 320,
count + 320);
}
@@ -491,7 +455,6 @@
byte += stride - 8;
}
- mm_ptr++;
mb_y_offset += 16;
mb_uv_offset += 8;
}
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -199,7 +199,7 @@
{
int mb_r = (cfg->g_h + 15) / 16;
int mb_c = (cfg->g_w + 15) / 16;
- size_t packet_sz = vp8_firstpass_stats_sz(mb_r * mb_c);
+ size_t packet_sz = sizeof(FIRSTPASS_STATS);
int n_packets = cfg->rc_twopass_stats_in.sz / packet_sz;
FIRSTPASS_STATS *stats;