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 +}