media/libvpx/vp8/encoder/picklpf.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/vp8/encoder/picklpf.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,407 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +
    1.15 +#include "./vpx_scale_rtcd.h"
    1.16 +#include "vp8/common/onyxc_int.h"
    1.17 +#include "onyx_int.h"
    1.18 +#include "quantize.h"
    1.19 +#include "vpx_mem/vpx_mem.h"
    1.20 +#include "vpx_scale/vpx_scale.h"
    1.21 +#include "vp8/common/alloccommon.h"
    1.22 +#include "vp8/common/loopfilter.h"
    1.23 +#if ARCH_ARM
    1.24 +#include "vpx_ports/arm.h"
    1.25 +#endif
    1.26 +
    1.27 +extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
    1.28 +
    1.29 +void vp8_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc,
    1.30 +                                   YV12_BUFFER_CONFIG *dst_ybc)
    1.31 +{
    1.32 +    unsigned char *src_y, *dst_y;
    1.33 +    int yheight;
    1.34 +    int ystride;
    1.35 +    int yoffset;
    1.36 +    int linestocopy;
    1.37 +
    1.38 +    yheight  = src_ybc->y_height;
    1.39 +    ystride  = src_ybc->y_stride;
    1.40 +
    1.41 +    /* number of MB rows to use in partial filtering */
    1.42 +    linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
    1.43 +    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
    1.44 +
    1.45 +    /* Copy extra 4 so that full filter context is available if filtering done
    1.46 +     * on the copied partial frame and not original. Partial filter does mb
    1.47 +     * filtering for top row also, which can modify3 pixels above.
    1.48 +     */
    1.49 +    linestocopy += 4;
    1.50 +    /* partial image starts at ~middle of frame (macroblock border)*/
    1.51 +    yoffset  = ystride * (((yheight >> 5) * 16) - 4);
    1.52 +    src_y = src_ybc->y_buffer + yoffset;
    1.53 +    dst_y = dst_ybc->y_buffer + yoffset;
    1.54 +
    1.55 +    vpx_memcpy(dst_y, src_y, ystride * linestocopy);
    1.56 +}
    1.57 +
    1.58 +static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
    1.59 +                                YV12_BUFFER_CONFIG *dest)
    1.60 +{
    1.61 +    int i, j;
    1.62 +    int Total = 0;
    1.63 +    int srcoffset, dstoffset;
    1.64 +    unsigned char *src = source->y_buffer;
    1.65 +    unsigned char *dst = dest->y_buffer;
    1.66 +
    1.67 +    int linestocopy;
    1.68 +
    1.69 +    /* number of MB rows to use in partial filtering */
    1.70 +    linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
    1.71 +    linestocopy = linestocopy ? linestocopy << 4 : 16;     /* 16 lines per MB */
    1.72 +
    1.73 +
    1.74 +    /* partial image starts at ~middle of frame (macroblock border)*/
    1.75 +    srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
    1.76 +    dstoffset = dest->y_stride   * ((dest->y_height >> 5) * 16);
    1.77 +
    1.78 +    src += srcoffset;
    1.79 +    dst += dstoffset;
    1.80 +
    1.81 +    /* Loop through the Y plane raw and reconstruction data summing
    1.82 +     * (square differences)
    1.83 +     */
    1.84 +    for (i = 0; i < linestocopy; i += 16)
    1.85 +    {
    1.86 +        for (j = 0; j < source->y_width; j += 16)
    1.87 +        {
    1.88 +            unsigned int sse;
    1.89 +            Total += vp8_mse16x16(src + j, source->y_stride,
    1.90 +                                                     dst + j, dest->y_stride,
    1.91 +                                                     &sse);
    1.92 +        }
    1.93 +
    1.94 +        src += 16 * source->y_stride;
    1.95 +        dst += 16 * dest->y_stride;
    1.96 +    }
    1.97 +
    1.98 +    return Total;
    1.99 +}
   1.100 +
   1.101 +/* Enforce a minimum filter level based upon baseline Q */
   1.102 +static int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
   1.103 +{
   1.104 +    int min_filter_level;
   1.105 +
   1.106 +    if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
   1.107 +        !cpi->common.refresh_alt_ref_frame)
   1.108 +        min_filter_level = 0;
   1.109 +    else
   1.110 +    {
   1.111 +        if (base_qindex <= 6)
   1.112 +            min_filter_level = 0;
   1.113 +        else if (base_qindex <= 16)
   1.114 +            min_filter_level = 1;
   1.115 +        else
   1.116 +            min_filter_level = (base_qindex / 8);
   1.117 +    }
   1.118 +
   1.119 +    return min_filter_level;
   1.120 +}
   1.121 +
   1.122 +/* Enforce a maximum filter level based upon baseline Q */
   1.123 +static int get_max_filter_level(VP8_COMP *cpi, int base_qindex)
   1.124 +{
   1.125 +    /* PGW August 2006: Highest filter values almost always a bad idea */
   1.126 +
   1.127 +    /* jbb chg: 20100118 - not so any more with this overquant stuff allow
   1.128 +     * high values with lots of intra coming in.
   1.129 +     */
   1.130 +    int max_filter_level = MAX_LOOP_FILTER;
   1.131 +    (void)base_qindex;
   1.132 +
   1.133 +    if (cpi->twopass.section_intra_rating > 8)
   1.134 +        max_filter_level = MAX_LOOP_FILTER * 3 / 4;
   1.135 +
   1.136 +    return max_filter_level;
   1.137 +}
   1.138 +
   1.139 +void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
   1.140 +{
   1.141 +    VP8_COMMON *cm = &cpi->common;
   1.142 +
   1.143 +    int best_err = 0;
   1.144 +    int filt_err = 0;
   1.145 +    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
   1.146 +    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
   1.147 +    int filt_val;
   1.148 +    int best_filt_val = cm->filter_level;
   1.149 +    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
   1.150 +
   1.151 +    /* Replace unfiltered frame buffer with a new one */
   1.152 +    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
   1.153 +
   1.154 +    if (cm->frame_type == KEY_FRAME)
   1.155 +        cm->sharpness_level = 0;
   1.156 +    else
   1.157 +        cm->sharpness_level = cpi->oxcf.Sharpness;
   1.158 +
   1.159 +    if (cm->sharpness_level != cm->last_sharpness_level)
   1.160 +    {
   1.161 +        vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
   1.162 +        cm->last_sharpness_level = cm->sharpness_level;
   1.163 +    }
   1.164 +
   1.165 +    /* Start the search at the previous frame filter level unless it is
   1.166 +     * now out of range.
   1.167 +     */
   1.168 +    if (cm->filter_level < min_filter_level)
   1.169 +        cm->filter_level = min_filter_level;
   1.170 +    else if (cm->filter_level > max_filter_level)
   1.171 +        cm->filter_level = max_filter_level;
   1.172 +
   1.173 +    filt_val = cm->filter_level;
   1.174 +    best_filt_val = filt_val;
   1.175 +
   1.176 +    /* Get the err using the previous frame's filter value. */
   1.177 +
   1.178 +    /* Copy the unfiltered / processed recon buffer to the new buffer */
   1.179 +    vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
   1.180 +    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
   1.181 +
   1.182 +    best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
   1.183 +
   1.184 +    filt_val -= 1 + (filt_val > 10);
   1.185 +
   1.186 +    /* Search lower filter levels */
   1.187 +    while (filt_val >= min_filter_level)
   1.188 +    {
   1.189 +        /* Apply the loop filter */
   1.190 +        vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
   1.191 +        vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
   1.192 +
   1.193 +        /* Get the err for filtered frame */
   1.194 +        filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
   1.195 +
   1.196 +        /* Update the best case record or exit loop. */
   1.197 +        if (filt_err < best_err)
   1.198 +        {
   1.199 +            best_err = filt_err;
   1.200 +            best_filt_val = filt_val;
   1.201 +        }
   1.202 +        else
   1.203 +            break;
   1.204 +
   1.205 +        /* Adjust filter level */
   1.206 +        filt_val -= 1 + (filt_val > 10);
   1.207 +    }
   1.208 +
   1.209 +    /* Search up (note that we have already done filt_val = cm->filter_level) */
   1.210 +    filt_val = cm->filter_level + 1 + (filt_val > 10);
   1.211 +
   1.212 +    if (best_filt_val == cm->filter_level)
   1.213 +    {
   1.214 +        /* Resist raising filter level for very small gains */
   1.215 +        best_err -= (best_err >> 10);
   1.216 +
   1.217 +        while (filt_val < max_filter_level)
   1.218 +        {
   1.219 +            /* Apply the loop filter */
   1.220 +            vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
   1.221 +
   1.222 +            vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
   1.223 +
   1.224 +            /* Get the err for filtered frame */
   1.225 +            filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
   1.226 +
   1.227 +            /* Update the best case record or exit loop. */
   1.228 +            if (filt_err < best_err)
   1.229 +            {
   1.230 +                /* Do not raise filter level if improvement is < 1 part
   1.231 +                 * in 4096
   1.232 +                 */
   1.233 +                best_err = filt_err - (filt_err >> 10);
   1.234 +
   1.235 +                best_filt_val = filt_val;
   1.236 +            }
   1.237 +            else
   1.238 +                break;
   1.239 +
   1.240 +            /* Adjust filter level */
   1.241 +            filt_val += 1 + (filt_val > 10);
   1.242 +        }
   1.243 +    }
   1.244 +
   1.245 +    cm->filter_level = best_filt_val;
   1.246 +
   1.247 +    if (cm->filter_level < min_filter_level)
   1.248 +        cm->filter_level = min_filter_level;
   1.249 +
   1.250 +    if (cm->filter_level > max_filter_level)
   1.251 +        cm->filter_level = max_filter_level;
   1.252 +
   1.253 +    /* restore unfiltered frame pointer */
   1.254 +    cm->frame_to_show = saved_frame;
   1.255 +}
   1.256 +
   1.257 +/* Stub function for now Alt LF not used */
   1.258 +void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
   1.259 +{
   1.260 +    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
   1.261 +    (void) filt_val;
   1.262 +
   1.263 +    mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
   1.264 +    mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
   1.265 +    mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
   1.266 +    mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
   1.267 +}
   1.268 +
   1.269 +void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
   1.270 +{
   1.271 +    VP8_COMMON *cm = &cpi->common;
   1.272 +
   1.273 +    int best_err = 0;
   1.274 +    int filt_err = 0;
   1.275 +    int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
   1.276 +    int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
   1.277 +
   1.278 +    int filter_step;
   1.279 +    int filt_high = 0;
   1.280 +    /* Start search at previous frame filter level */
   1.281 +    int filt_mid = cm->filter_level;
   1.282 +    int filt_low = 0;
   1.283 +    int filt_best;
   1.284 +    int filt_direction = 0;
   1.285 +
   1.286 +    /* Bias against raising loop filter and in favor of lowering it */
   1.287 +    int Bias = 0;
   1.288 +
   1.289 +    int ss_err[MAX_LOOP_FILTER + 1];
   1.290 +
   1.291 +    YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show;
   1.292 +
   1.293 +    vpx_memset(ss_err, 0, sizeof(ss_err));
   1.294 +
   1.295 +    /* Replace unfiltered frame buffer with a new one */
   1.296 +    cm->frame_to_show = &cpi->pick_lf_lvl_frame;
   1.297 +
   1.298 +    if (cm->frame_type == KEY_FRAME)
   1.299 +        cm->sharpness_level = 0;
   1.300 +    else
   1.301 +        cm->sharpness_level = cpi->oxcf.Sharpness;
   1.302 +
   1.303 +    /* Start the search at the previous frame filter level unless it is
   1.304 +     * now out of range.
   1.305 +     */
   1.306 +    filt_mid = cm->filter_level;
   1.307 +
   1.308 +    if (filt_mid < min_filter_level)
   1.309 +        filt_mid = min_filter_level;
   1.310 +    else if (filt_mid > max_filter_level)
   1.311 +        filt_mid = max_filter_level;
   1.312 +
   1.313 +    /* Define the initial step size */
   1.314 +    filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
   1.315 +
   1.316 +    /* Get baseline error score */
   1.317 +
   1.318 +    /* Copy the unfiltered / processed recon buffer to the new buffer */
   1.319 +    vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
   1.320 +
   1.321 +    vp8cx_set_alt_lf_level(cpi, filt_mid);
   1.322 +    vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
   1.323 +
   1.324 +    best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
   1.325 +
   1.326 +    ss_err[filt_mid] = best_err;
   1.327 +
   1.328 +    filt_best = filt_mid;
   1.329 +
   1.330 +    while (filter_step > 0)
   1.331 +    {
   1.332 +        Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
   1.333 +
   1.334 +        if (cpi->twopass.section_intra_rating < 20)
   1.335 +            Bias = Bias * cpi->twopass.section_intra_rating / 20;
   1.336 +
   1.337 +        filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
   1.338 +        filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
   1.339 +
   1.340 +        if ((filt_direction <= 0) && (filt_low != filt_mid))
   1.341 +        {
   1.342 +            if(ss_err[filt_low] == 0)
   1.343 +            {
   1.344 +                /* Get Low filter error score */
   1.345 +                vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
   1.346 +                vp8cx_set_alt_lf_level(cpi, filt_low);
   1.347 +                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
   1.348 +
   1.349 +                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
   1.350 +                ss_err[filt_low] = filt_err;
   1.351 +            }
   1.352 +            else
   1.353 +                filt_err = ss_err[filt_low];
   1.354 +
   1.355 +            /* If value is close to the best so far then bias towards a
   1.356 +             * lower loop filter value.
   1.357 +             */
   1.358 +            if ((filt_err - Bias) < best_err)
   1.359 +            {
   1.360 +                /* Was it actually better than the previous best? */
   1.361 +                if (filt_err < best_err)
   1.362 +                    best_err = filt_err;
   1.363 +
   1.364 +                filt_best = filt_low;
   1.365 +            }
   1.366 +        }
   1.367 +
   1.368 +        /* Now look at filt_high */
   1.369 +        if ((filt_direction >= 0) && (filt_high != filt_mid))
   1.370 +        {
   1.371 +            if(ss_err[filt_high] == 0)
   1.372 +            {
   1.373 +                vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
   1.374 +                vp8cx_set_alt_lf_level(cpi, filt_high);
   1.375 +                vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
   1.376 +
   1.377 +                filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
   1.378 +                ss_err[filt_high] = filt_err;
   1.379 +            }
   1.380 +            else
   1.381 +                filt_err = ss_err[filt_high];
   1.382 +
   1.383 +            /* Was it better than the previous best? */
   1.384 +            if (filt_err < (best_err - Bias))
   1.385 +            {
   1.386 +                best_err = filt_err;
   1.387 +                filt_best = filt_high;
   1.388 +            }
   1.389 +        }
   1.390 +
   1.391 +        /* Half the step distance if the best filter value was the same
   1.392 +         * as last time
   1.393 +         */
   1.394 +        if (filt_best == filt_mid)
   1.395 +        {
   1.396 +            filter_step = filter_step / 2;
   1.397 +            filt_direction = 0;
   1.398 +        }
   1.399 +        else
   1.400 +        {
   1.401 +            filt_direction = (filt_best < filt_mid) ? -1 : 1;
   1.402 +            filt_mid = filt_best;
   1.403 +        }
   1.404 +    }
   1.405 +
   1.406 +    cm->filter_level = filt_best;
   1.407 +
   1.408 +    /* restore unfiltered frame pointer */
   1.409 +    cm->frame_to_show = saved_frame;
   1.410 +}

mercurial