Reduce mem copies in encoder loopfilter level picking
authorAttila Nagy <attilanagy@google.com>
Tue, 29 Nov 2011 11:48:02 +0000 (13:48 +0200)
committerAttila Nagy <attilanagy@google.com>
Wed, 7 Dec 2011 07:59:50 +0000 (09:59 +0200)
Do the test filtering in the existing backup frame buffer instead of
the original. Copy the original data into extra buffer before doing
the  filtering. This way there is no need to restore the original
unfiltered  frame at the end of level picking process.

This came up in some discussions with Johann. Thanks!

Change-Id: I495f4301d983854673276c34ec0ddf9a9d622122

vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h
vp8/encoder/picklpf.c

index 4df2a78..78ba9d5 100644 (file)
@@ -355,7 +355,7 @@ static void dealloc_compressor_data(VP8_COMP *cpi)
 
     vp8_de_alloc_frame_buffers(&cpi->common);
 
-    vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf);
+    vp8_yv12_de_alloc_frame_buffer(&cpi->pick_lf_lvl_frame);
     vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source);
 #if VP8_TEMPORAL_ALT_REF
     vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer);
@@ -1365,7 +1365,7 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi)
         height += 16 - (height & 0xf);
 
 
-    if (vp8_yv12_alloc_frame_buffer(&cpi->last_frame_uf,
+    if (vp8_yv12_alloc_frame_buffer(&cpi->pick_lf_lvl_frame,
                                     width, height, VP8BORDERINPIXELS))
         vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                            "Failed to allocate last frame buffer");
index 7382de4..2919807 100644 (file)
@@ -336,7 +336,7 @@ typedef struct VP8_COMP
     int gold_is_alt;  // don't do both alt and gold search ( just do gold).
 
     //int refresh_alt_ref_frame;
-    YV12_BUFFER_CONFIG last_frame_uf;
+    YV12_BUFFER_CONFIG pick_lf_lvl_frame;
 
     TOKENEXTRA *tok;
     unsigned int tok_count;
index c1e5f77..e97a560 100644 (file)
@@ -152,9 +152,10 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
     int filt_val;
     int best_filt_val = cm->filter_level;
+    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
 
-    //  Make a copy of the unfiltered / processed recon buffer
-    vp8_yv12_copy_partial_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf);
+    /* Replace unfiltered frame buffer with a new one */
+    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
 
     if (cm->frame_type == KEY_FRAME)
         cm->sharpness_level = 0;
@@ -177,12 +178,13 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     best_filt_val = filt_val;
 
     // Get the err using the previous frame's filter value.
-    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
 
-    best_err = calc_partial_ssl_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+    /* Copy the unfiltered / processed recon buffer to the new buffer */
+    vp8_yv12_copy_partial_frame_ptr(saved_frame, cm->frame_to_show);
+    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
 
-    //  Re-instate the unfiltered frame
-    vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+    best_err = calc_partial_ssl_err(sd, cm->frame_to_show,
+                                    IF_RTCD(&cpi->rtcd.variance));
 
     filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
 
@@ -190,13 +192,12 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     while (filt_val >= min_filter_level)
     {
         // Apply the loop filter
+        vp8_yv12_copy_partial_frame_ptr(saved_frame, cm->frame_to_show);
         vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
 
         // Get the err for filtered frame
-        filt_err = calc_partial_ssl_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
-
-        //  Re-instate the unfiltered frame
-        vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+        filt_err = calc_partial_ssl_err(sd, cm->frame_to_show,
+                                        IF_RTCD(&cpi->rtcd.variance));
 
         // Update the best case record or exit loop.
         if (filt_err < best_err)
@@ -222,13 +223,13 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
         while (filt_val < max_filter_level)
         {
             // Apply the loop filter
+            vp8_yv12_copy_partial_frame_ptr(saved_frame, cm->frame_to_show);
+
             vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
 
             // Get the err for filtered frame
-            filt_err = calc_partial_ssl_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
-
-            //  Re-instate the unfiltered frame
-            vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+            filt_err = calc_partial_ssl_err(sd, cm->frame_to_show,
+                                            IF_RTCD(&cpi->rtcd.variance));
 
             // Update the best case record or exit loop.
             if (filt_err < best_err)
@@ -253,6 +254,9 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
 
     if (cm->filter_level > max_filter_level)
         cm->filter_level = max_filter_level;
+
+    /* restore unfiltered frame pointer */
+    cm->frame_to_show = saved_frame;
 }
 
 // Stub function for now Alt LF not used
@@ -283,10 +287,12 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     int filt_best;
     int filt_direction = 0;
 
-    int Bias = 0;                       // Bias against raising loop filter and in favour of lowering it
+    int Bias = 0;                       // Bias against raising loop filter and in favor of lowering it
+
+    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
 
-    //  Make a copy of the unfiltered / processed recon buffer
-    vp8_yv12_copy_y_ptr(cm->frame_to_show, &cpi->last_frame_uf);
+    /* Replace unfiltered frame buffer with a new one */
+    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
 
     if (cm->frame_type == KEY_FRAME)
         cm->sharpness_level = 0;
@@ -305,15 +311,17 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
 
     // Get baseline error score
+
+    /* Copy the unfiltered / processed recon buffer to the new buffer */
+    vp8_yv12_copy_y_ptr(saved_frame, cm->frame_to_show);
+
     vp8cx_set_alt_lf_level(cpi, filt_mid);
     vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
 
-    best_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+    best_err = vp8_calc_ss_err(sd, cm->frame_to_show,
+                               IF_RTCD(&cpi->rtcd.variance));
     filt_best = filt_mid;
 
-    //  Re-instate the unfiltered frame
-    vp8_yv12_copy_y_ptr(&cpi->last_frame_uf, cm->frame_to_show);
-
     while (filter_step > 0)
     {
         Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; //PGW change 12/12/06 for small images
@@ -328,13 +336,12 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
         if ((filt_direction <= 0) && (filt_low != filt_mid))
         {
             // Get Low filter error score
+            vp8_yv12_copy_y_ptr(saved_frame, cm->frame_to_show);
             vp8cx_set_alt_lf_level(cpi, filt_low);
             vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
 
-            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
-
-            //  Re-instate the unfiltered frame
-            vp8_yv12_copy_y_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show,
+                                       IF_RTCD(&cpi->rtcd.variance));
 
             // If value is close to the best so far then bias towards a lower loop filter value.
             if ((filt_err - Bias) < best_err)
@@ -350,13 +357,12 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
         // Now look at filt_high
         if ((filt_direction >= 0) && (filt_high != filt_mid))
         {
+            vp8_yv12_copy_y_ptr(saved_frame, cm->frame_to_show);
             vp8cx_set_alt_lf_level(cpi, filt_high);
             vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
 
-            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
-
-            //  Re-instate the unfiltered frame
-            vp8_yv12_copy_y_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show,
+                                       IF_RTCD(&cpi->rtcd.variance));
 
             // Was it better than the previous best?
             if (filt_err < (best_err - Bias))
@@ -380,4 +386,7 @@ void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
     }
 
     cm->filter_level = filt_best;
+
+    /* restore unfiltered frame pointer */
+    cm->frame_to_show = saved_frame;
 }