From ed40ff9e2dfb261db4ab1dd5d5f984a2b59cf936 Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Thu, 10 Mar 2011 11:32:48 -0800 Subject: 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 --- vp8/encoder/firstpass.c | 142 ++---------------------------------------- vp8/encoder/onyx_if.c | 20 +----- vp8/encoder/onyx_int.h | 7 --- vp8/encoder/temporal_filter.c | 77 ++++++----------------- vp8/vp8_cx_iface.c | 2 +- 5 files changed, 28 insertions(+), 220 deletions(-) (limited to 'vp8') diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index d2cc8482e..00c2bc581 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -281,21 +281,6 @@ int frame_max_bits(VP8_COMP *cpi) } -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 @@ void vp8_output_stats(const VP8_COMP *cpi, 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,24 +318,17 @@ void vp8_output_stats(const VP8_COMP *cpi, 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 } 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 @@ void vp8_avg_stats(FIRSTPASS_STATS *section) 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; ifp_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 @@ void vp8_first_pass(VP8_COMP *cpi) 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 @@ void vp8_first_pass(VP8_COMP *cpi) 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 @@ void vp8_first_pass(VP8_COMP *cpi) // 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 @@ void vp8_first_pass(VP8_COMP *cpi) 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,25 +717,6 @@ void vp8_first_pass(VP8_COMP *cpi) 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 @@ void vp8_first_pass(VP8_COMP *cpi) 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 @@ void vp8_first_pass(VP8_COMP *cpi) // 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 @@ void vp8_init_second_pass(VP8_COMP *cpi) 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 @@ void vp8_end_second_pass(VP8_COMP *cpi) } // 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 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) 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 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) 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 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) } 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 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame) 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. @@ -2107,13 +1980,6 @@ void vp8_second_pass(VP8_COMP *cpi) 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; this_frame_coded_error = this_frame.coded_error; diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 797e18b30..8c477ef34 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -281,12 +281,6 @@ void vp8_dealloc_compressor_data(VP8_COMP *cpi) 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 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) #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 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf) #if VP8_TEMPORAL_ALT_REF - cpi->use_weighted_temporal_filter = 0; - { int i; @@ -1927,12 +1919,6 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) 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 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) } 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; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 6d0cbd9fc..0547d57c1 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -496,11 +496,6 @@ typedef struct 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 @@ typedef struct 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; diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c index 0f8e654a0..fd36b22eb 100644 --- a/vp8/encoder/temporal_filter.c +++ b/vp8/encoder/temporal_filter.c @@ -287,8 +287,7 @@ static void vp8_temporal_filter_iterate_c 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 @@ static void vp8_temporal_filter_iterate_c 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 @@ static void vp8_temporal_filter_iterate_c + (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 @@ static void vp8_temporal_filter_iterate_c 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); - - if (filter_weight[frame] < 2) - { - // Set weight depending on error - filter_weight[frame] = errframes[alt_ref_index], + cpi->frames[frame], + mb_y_offset, + THRESH_LOW); + #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 = errg_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; -- cgit v1.2.3 From 6daacdb785f34efcf3c8600c65590199e79847d6 Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Thu, 10 Mar 2011 12:43:49 -0800 Subject: Added missing format specifier in print statement Printout of firstpass stats for frame had one fewer format specifiers than arguments. Change-Id: I5a42c85aa79c471e1a70afd75e24a91546b7a1cd --- vp8/encoder/firstpass.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'vp8') diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 00c2bc581..3030ed798 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -293,13 +293,14 @@ void vp8_output_stats(const VP8_COMP *cpi, // TEMP debug code #if OUTPUT_FPF + { FILE *fpfile; fpfile = fopen("firstpass.stt", "a"); fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f" - " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.0f" - " %12.4f\n", + " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f" + " %12.0f %12.4f\n", stats->frame, stats->intra_error, stats->coded_error, -- cgit v1.2.3