1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/encoder/vp9_picklpf.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,205 @@ 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 +#include <assert.h> 1.15 +#include <limits.h> 1.16 +#include "vp9/common/vp9_onyxc_int.h" 1.17 +#include "vp9/encoder/vp9_onyx_int.h" 1.18 +#include "vp9/encoder/vp9_picklpf.h" 1.19 +#include "vp9/encoder/vp9_quantize.h" 1.20 +#include "vpx_mem/vpx_mem.h" 1.21 +#include "vpx_scale/vpx_scale.h" 1.22 +#include "vp9/common/vp9_alloccommon.h" 1.23 +#include "vp9/common/vp9_loopfilter.h" 1.24 +#include "./vpx_scale_rtcd.h" 1.25 + 1.26 +void vp9_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc, 1.27 + YV12_BUFFER_CONFIG *dst_ybc, int fraction) { 1.28 + const int height = src_ybc->y_height; 1.29 + const int stride = src_ybc->y_stride; 1.30 + const int offset = stride * ((height >> 5) * 16 - 8); 1.31 + const int lines_to_copy = MAX(height >> (fraction + 4), 1) << 4; 1.32 + 1.33 + assert(src_ybc->y_stride == dst_ybc->y_stride); 1.34 + vpx_memcpy(dst_ybc->y_buffer + offset, src_ybc->y_buffer + offset, 1.35 + stride * (lines_to_copy + 16)); 1.36 +} 1.37 + 1.38 +static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, 1.39 + YV12_BUFFER_CONFIG *dest, int Fraction) { 1.40 + int i, j; 1.41 + int Total = 0; 1.42 + int srcoffset, dstoffset; 1.43 + uint8_t *src = source->y_buffer; 1.44 + uint8_t *dst = dest->y_buffer; 1.45 + 1.46 + int linestocopy = (source->y_height >> (Fraction + 4)); 1.47 + 1.48 + if (linestocopy < 1) 1.49 + linestocopy = 1; 1.50 + 1.51 + linestocopy <<= 4; 1.52 + 1.53 + 1.54 + srcoffset = source->y_stride * (dest->y_height >> 5) * 16; 1.55 + dstoffset = dest->y_stride * (dest->y_height >> 5) * 16; 1.56 + 1.57 + src += srcoffset; 1.58 + dst += dstoffset; 1.59 + 1.60 + // Loop through the raw Y plane and reconstruction data summing the square 1.61 + // differences. 1.62 + for (i = 0; i < linestocopy; i += 16) { 1.63 + for (j = 0; j < source->y_width; j += 16) { 1.64 + unsigned int sse; 1.65 + Total += vp9_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride, 1.66 + &sse); 1.67 + } 1.68 + 1.69 + src += 16 * source->y_stride; 1.70 + dst += 16 * dest->y_stride; 1.71 + } 1.72 + 1.73 + return Total; 1.74 +} 1.75 + 1.76 +// Enforce a minimum filter level based upon baseline Q 1.77 +static int get_min_filter_level(VP9_COMP *cpi, int base_qindex) { 1.78 + int min_filter_level; 1.79 + min_filter_level = 0; 1.80 + 1.81 + return min_filter_level; 1.82 +} 1.83 + 1.84 +// Enforce a maximum filter level based upon baseline Q 1.85 +static int get_max_filter_level(VP9_COMP *cpi, int base_qindex) { 1.86 + int max_filter_level = MAX_LOOP_FILTER; 1.87 + (void)base_qindex; 1.88 + 1.89 + if (cpi->twopass.section_intra_rating > 8) 1.90 + max_filter_level = MAX_LOOP_FILTER * 3 / 4; 1.91 + 1.92 + return max_filter_level; 1.93 +} 1.94 + 1.95 + 1.96 +// Stub function for now Alt LF not used 1.97 +void vp9_set_alt_lf_level(VP9_COMP *cpi, int filt_val) { 1.98 +} 1.99 + 1.100 +void vp9_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP9_COMP *cpi, int partial) { 1.101 + VP9_COMMON *const cm = &cpi->common; 1.102 + struct loopfilter *const lf = &cm->lf; 1.103 + 1.104 + int best_err = 0; 1.105 + int filt_err = 0; 1.106 + const int min_filter_level = get_min_filter_level(cpi, cm->base_qindex); 1.107 + const int max_filter_level = get_max_filter_level(cpi, cm->base_qindex); 1.108 + 1.109 + int filter_step; 1.110 + int filt_high = 0; 1.111 + // Start search at previous frame filter level 1.112 + int filt_mid = lf->filter_level; 1.113 + int filt_low = 0; 1.114 + int filt_best; 1.115 + int filt_direction = 0; 1.116 + 1.117 + int Bias = 0; // Bias against raising loop filter in favor of lowering it. 1.118 + 1.119 + // Make a copy of the unfiltered / processed recon buffer 1.120 + vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf); 1.121 + 1.122 + lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 1.123 + : cpi->oxcf.Sharpness; 1.124 + 1.125 + // Start the search at the previous frame filter level unless it is now out of 1.126 + // range. 1.127 + filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level); 1.128 + 1.129 + // Define the initial step size 1.130 + filter_step = filt_mid < 16 ? 4 : filt_mid / 4; 1.131 + 1.132 + // Get baseline error score 1.133 + vp9_set_alt_lf_level(cpi, filt_mid); 1.134 + vp9_loop_filter_frame(cm, &cpi->mb.e_mbd, filt_mid, 1, partial); 1.135 + 1.136 + best_err = vp9_calc_ss_err(sd, cm->frame_to_show); 1.137 + filt_best = filt_mid; 1.138 + 1.139 + // Re-instate the unfiltered frame 1.140 + vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); 1.141 + 1.142 + while (filter_step > 0) { 1.143 + Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; 1.144 + 1.145 + if (cpi->twopass.section_intra_rating < 20) 1.146 + Bias = Bias * cpi->twopass.section_intra_rating / 20; 1.147 + 1.148 + // yx, bias less for large block size 1.149 + if (cpi->common.tx_mode != ONLY_4X4) 1.150 + Bias >>= 1; 1.151 + 1.152 + filt_high = ((filt_mid + filter_step) > max_filter_level) 1.153 + ? max_filter_level 1.154 + : (filt_mid + filter_step); 1.155 + filt_low = ((filt_mid - filter_step) < min_filter_level) 1.156 + ? min_filter_level 1.157 + : (filt_mid - filter_step); 1.158 + 1.159 + if ((filt_direction <= 0) && (filt_low != filt_mid)) { 1.160 + // Get Low filter error score 1.161 + vp9_set_alt_lf_level(cpi, filt_low); 1.162 + vp9_loop_filter_frame(cm, &cpi->mb.e_mbd, filt_low, 1, partial); 1.163 + 1.164 + filt_err = vp9_calc_ss_err(sd, cm->frame_to_show); 1.165 + 1.166 + // Re-instate the unfiltered frame 1.167 + vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); 1.168 + 1.169 + // If value is close to the best so far then bias towards a lower loop 1.170 + // filter value. 1.171 + if ((filt_err - Bias) < best_err) { 1.172 + // Was it actually better than the previous best? 1.173 + if (filt_err < best_err) 1.174 + best_err = filt_err; 1.175 + 1.176 + filt_best = filt_low; 1.177 + } 1.178 + } 1.179 + 1.180 + // Now look at filt_high 1.181 + if ((filt_direction >= 0) && (filt_high != filt_mid)) { 1.182 + vp9_set_alt_lf_level(cpi, filt_high); 1.183 + vp9_loop_filter_frame(cm, &cpi->mb.e_mbd, filt_high, 1, partial); 1.184 + 1.185 + filt_err = vp9_calc_ss_err(sd, cm->frame_to_show); 1.186 + 1.187 + // Re-instate the unfiltered frame 1.188 + vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); 1.189 + 1.190 + // Was it better than the previous best? 1.191 + if (filt_err < (best_err - Bias)) { 1.192 + best_err = filt_err; 1.193 + filt_best = filt_high; 1.194 + } 1.195 + } 1.196 + 1.197 + // Half the step distance if the best filter value was the same as last time 1.198 + if (filt_best == filt_mid) { 1.199 + filter_step = filter_step / 2; 1.200 + filt_direction = 0; 1.201 + } else { 1.202 + filt_direction = (filt_best < filt_mid) ? -1 : 1; 1.203 + filt_mid = filt_best; 1.204 + } 1.205 + } 1.206 + 1.207 + lf->filter_level = filt_best; 1.208 +}