Home | History | Annotate | Download | only in encoder
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "./vpx_dsp_rtcd.h"
     12 #include "./vpx_scale_rtcd.h"
     13 #include "vp8/common/onyxc_int.h"
     14 #include "onyx_int.h"
     15 #include "vp8/encoder/picklpf.h"
     16 #include "vp8/encoder/quantize.h"
     17 #include "vpx_mem/vpx_mem.h"
     18 #include "vpx_scale/vpx_scale.h"
     19 #include "vp8/common/alloccommon.h"
     20 #include "vp8/common/loopfilter.h"
     21 #if ARCH_ARM
     22 #include "vpx_ports/arm.h"
     23 #endif
     24 
     25 extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source,
     26                            YV12_BUFFER_CONFIG *dest);
     27 
     28 static void yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc,
     29                                     YV12_BUFFER_CONFIG *dst_ybc) {
     30   unsigned char *src_y, *dst_y;
     31   int yheight;
     32   int ystride;
     33   int yoffset;
     34   int linestocopy;
     35 
     36   yheight = src_ybc->y_height;
     37   ystride = src_ybc->y_stride;
     38 
     39   /* number of MB rows to use in partial filtering */
     40   linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
     41   linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
     42 
     43   /* Copy extra 4 so that full filter context is available if filtering done
     44    * on the copied partial frame and not original. Partial filter does mb
     45    * filtering for top row also, which can modify3 pixels above.
     46    */
     47   linestocopy += 4;
     48   /* partial image starts at ~middle of frame (macroblock border)*/
     49   yoffset = ystride * (((yheight >> 5) * 16) - 4);
     50   src_y = src_ybc->y_buffer + yoffset;
     51   dst_y = dst_ybc->y_buffer + yoffset;
     52 
     53   memcpy(dst_y, src_y, ystride * linestocopy);
     54 }
     55 
     56 static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
     57                                 YV12_BUFFER_CONFIG *dest) {
     58   int i, j;
     59   int Total = 0;
     60   int srcoffset, dstoffset;
     61   unsigned char *src = source->y_buffer;
     62   unsigned char *dst = dest->y_buffer;
     63 
     64   int linestocopy;
     65 
     66   /* number of MB rows to use in partial filtering */
     67   linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
     68   linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
     69 
     70   /* partial image starts at ~middle of frame (macroblock border)*/
     71   srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
     72   dstoffset = dest->y_stride * ((dest->y_height >> 5) * 16);
     73 
     74   src += srcoffset;
     75   dst += dstoffset;
     76 
     77   /* Loop through the Y plane raw and reconstruction data summing
     78    * (square differences)
     79    */
     80   for (i = 0; i < linestocopy; i += 16) {
     81     for (j = 0; j < source->y_width; j += 16) {
     82       unsigned int sse;
     83       Total += vpx_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride,
     84                             &sse);
     85     }
     86 
     87     src += 16 * source->y_stride;
     88     dst += 16 * dest->y_stride;
     89   }
     90 
     91   return Total;
     92 }
     93 
     94 /* Enforce a minimum filter level based upon baseline Q */
     95 static int get_min_filter_level(VP8_COMP *cpi, int base_qindex) {
     96   int min_filter_level;
     97 
     98   if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
     99       !cpi->common.refresh_alt_ref_frame) {
    100     min_filter_level = 0;
    101   } else {
    102     if (base_qindex <= 6) {
    103       min_filter_level = 0;
    104     } else if (base_qindex <= 16) {
    105       min_filter_level = 1;
    106     } else {
    107       min_filter_level = (base_qindex / 8);
    108     }
    109   }
    110 
    111   return min_filter_level;
    112 }
    113 
    114 /* Enforce a maximum filter level based upon baseline Q */
    115 static int get_max_filter_level(VP8_COMP *cpi, int base_qindex) {
    116   /* PGW August 2006: Highest filter values almost always a bad idea */
    117 
    118   /* jbb chg: 20100118 - not so any more with this overquant stuff allow
    119    * high values with lots of intra coming in.
    120    */
    121   int max_filter_level = MAX_LOOP_FILTER;
    122   (void)base_qindex;
    123 
    124   if (cpi->twopass.section_intra_rating > 8) {
    125     max_filter_level = MAX_LOOP_FILTER * 3 / 4;
    126   }
    127 
    128   return max_filter_level;
    129 }
    130 
    131 void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
    132   VP8_COMMON *cm = &cpi->common;
    133 
    134   int best_err = 0;
    135   int filt_err = 0;
    136   int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
    137   int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
    138   int filt_val;
    139   int best_filt_val;
    140   YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
    141 
    142   /* Replace unfiltered frame buffer with a new one */
    143   cm->frame_to_show = &cpi->pick_lf_lvl_frame;
    144 
    145   if (cm->frame_type == KEY_FRAME) {
    146     cm->sharpness_level = 0;
    147   } else {
    148     cm->sharpness_level = cpi->oxcf.Sharpness;
    149   }
    150 
    151   if (cm->sharpness_level != cm->last_sharpness_level) {
    152     vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
    153     cm->last_sharpness_level = cm->sharpness_level;
    154   }
    155 
    156   /* Start the search at the previous frame filter level unless it is
    157    * now out of range.
    158    */
    159   if (cm->filter_level < min_filter_level) {
    160     cm->filter_level = min_filter_level;
    161   } else if (cm->filter_level > max_filter_level) {
    162     cm->filter_level = max_filter_level;
    163   }
    164 
    165   filt_val = cm->filter_level;
    166   best_filt_val = filt_val;
    167 
    168   /* Get the err using the previous frame's filter value. */
    169 
    170   /* Copy the unfiltered / processed recon buffer to the new buffer */
    171   yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
    172   vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
    173 
    174   best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
    175 
    176   filt_val -= 1 + (filt_val > 10);
    177 
    178   /* Search lower filter levels */
    179   while (filt_val >= min_filter_level) {
    180     /* Apply the loop filter */
    181     yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
    182     vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
    183 
    184     /* Get the err for filtered frame */
    185     filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
    186 
    187     /* Update the best case record or exit loop. */
    188     if (filt_err < best_err) {
    189       best_err = filt_err;
    190       best_filt_val = filt_val;
    191     } else {
    192       break;
    193     }
    194 
    195     /* Adjust filter level */
    196     filt_val -= 1 + (filt_val > 10);
    197   }
    198 
    199   /* Search up (note that we have already done filt_val = cm->filter_level) */
    200   filt_val = cm->filter_level + 1 + (filt_val > 10);
    201 
    202   if (best_filt_val == cm->filter_level) {
    203     /* Resist raising filter level for very small gains */
    204     best_err -= (best_err >> 10);
    205 
    206     while (filt_val < max_filter_level) {
    207       /* Apply the loop filter */
    208       yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
    209 
    210       vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
    211 
    212       /* Get the err for filtered frame */
    213       filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
    214 
    215       /* Update the best case record or exit loop. */
    216       if (filt_err < best_err) {
    217         /* Do not raise filter level if improvement is < 1 part
    218          * in 4096
    219          */
    220         best_err = filt_err - (filt_err >> 10);
    221 
    222         best_filt_val = filt_val;
    223       } else {
    224         break;
    225       }
    226 
    227       /* Adjust filter level */
    228       filt_val += 1 + (filt_val > 10);
    229     }
    230   }
    231 
    232   cm->filter_level = best_filt_val;
    233 
    234   if (cm->filter_level < min_filter_level) cm->filter_level = min_filter_level;
    235 
    236   if (cm->filter_level > max_filter_level) cm->filter_level = max_filter_level;
    237 
    238   /* restore unfiltered frame pointer */
    239   cm->frame_to_show = saved_frame;
    240 }
    241 
    242 /* Stub function for now Alt LF not used */
    243 void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) {
    244   MACROBLOCKD *mbd = &cpi->mb.e_mbd;
    245   (void)filt_val;
    246 
    247   mbd->segment_feature_data[MB_LVL_ALT_LF][0] =
    248       cpi->segment_feature_data[MB_LVL_ALT_LF][0];
    249   mbd->segment_feature_data[MB_LVL_ALT_LF][1] =
    250       cpi->segment_feature_data[MB_LVL_ALT_LF][1];
    251   mbd->segment_feature_data[MB_LVL_ALT_LF][2] =
    252       cpi->segment_feature_data[MB_LVL_ALT_LF][2];
    253   mbd->segment_feature_data[MB_LVL_ALT_LF][3] =
    254       cpi->segment_feature_data[MB_LVL_ALT_LF][3];
    255 }
    256 
    257 void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
    258   VP8_COMMON *cm = &cpi->common;
    259 
    260   int best_err = 0;
    261   int filt_err = 0;
    262   int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
    263   int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
    264 
    265   int filter_step;
    266   int filt_high = 0;
    267   int filt_mid;
    268   int filt_low = 0;
    269   int filt_best;
    270   int filt_direction = 0;
    271 
    272   /* Bias against raising loop filter and in favor of lowering it */
    273   int Bias = 0;
    274 
    275   int ss_err[MAX_LOOP_FILTER + 1];
    276 
    277   YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
    278 
    279   memset(ss_err, 0, sizeof(ss_err));
    280 
    281   /* Replace unfiltered frame buffer with a new one */
    282   cm->frame_to_show = &cpi->pick_lf_lvl_frame;
    283 
    284   if (cm->frame_type == KEY_FRAME) {
    285     cm->sharpness_level = 0;
    286   } else {
    287     cm->sharpness_level = cpi->oxcf.Sharpness;
    288   }
    289 
    290   /* Start the search at the previous frame filter level unless it is
    291    * now out of range.
    292    */
    293   filt_mid = cm->filter_level;
    294 
    295   if (filt_mid < min_filter_level) {
    296     filt_mid = min_filter_level;
    297   } else if (filt_mid > max_filter_level) {
    298     filt_mid = max_filter_level;
    299   }
    300 
    301   /* Define the initial step size */
    302   filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
    303 
    304   /* Get baseline error score */
    305 
    306   /* Copy the unfiltered / processed recon buffer to the new buffer */
    307   vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
    308 
    309   vp8cx_set_alt_lf_level(cpi, filt_mid);
    310   vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
    311 
    312   best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
    313 
    314   ss_err[filt_mid] = best_err;
    315 
    316   filt_best = filt_mid;
    317 
    318   while (filter_step > 0) {
    319     Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
    320 
    321     if (cpi->twopass.section_intra_rating < 20) {
    322       Bias = Bias * cpi->twopass.section_intra_rating / 20;
    323     }
    324 
    325     filt_high = ((filt_mid + filter_step) > max_filter_level)
    326                     ? max_filter_level
    327                     : (filt_mid + filter_step);
    328     filt_low = ((filt_mid - filter_step) < min_filter_level)
    329                    ? min_filter_level
    330                    : (filt_mid - filter_step);
    331 
    332     if ((filt_direction <= 0) && (filt_low != filt_mid)) {
    333       if (ss_err[filt_low] == 0) {
    334         /* Get Low filter error score */
    335         vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
    336         vp8cx_set_alt_lf_level(cpi, filt_low);
    337         vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
    338 
    339         filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
    340         ss_err[filt_low] = filt_err;
    341       } else {
    342         filt_err = ss_err[filt_low];
    343       }
    344 
    345       /* If value is close to the best so far then bias towards a
    346        * lower loop filter value.
    347        */
    348       if ((filt_err - Bias) < best_err) {
    349         /* Was it actually better than the previous best? */
    350         if (filt_err < best_err) best_err = filt_err;
    351 
    352         filt_best = filt_low;
    353       }
    354     }
    355 
    356     /* Now look at filt_high */
    357     if ((filt_direction >= 0) && (filt_high != filt_mid)) {
    358       if (ss_err[filt_high] == 0) {
    359         vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
    360         vp8cx_set_alt_lf_level(cpi, filt_high);
    361         vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
    362 
    363         filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
    364         ss_err[filt_high] = filt_err;
    365       } else {
    366         filt_err = ss_err[filt_high];
    367       }
    368 
    369       /* Was it better than the previous best? */
    370       if (filt_err < (best_err - Bias)) {
    371         best_err = filt_err;
    372         filt_best = filt_high;
    373       }
    374     }
    375 
    376     /* Half the step distance if the best filter value was the same
    377      * as last time
    378      */
    379     if (filt_best == filt_mid) {
    380       filter_step = filter_step / 2;
    381       filt_direction = 0;
    382     } else {
    383       filt_direction = (filt_best < filt_mid) ? -1 : 1;
    384       filt_mid = filt_best;
    385     }
    386   }
    387 
    388   cm->filter_level = filt_best;
    389 
    390   /* restore unfiltered frame pointer */
    391   cm->frame_to_show = saved_frame;
    392 }
    393