shithub: libvpx

Download patch

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;