1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan * 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Use of this source code is governed by a BSD-style license 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * that can be found in the LICENSE file in the root of the source 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan * tree. An additional intellectual property rights grant can be found 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in the file PATENTS. All contributing project authors may 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan * be found in the AUTHORS file in the root of the source tree. 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_scale_rtcd.h" 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/onyxc_int.h" 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "onyx_int.h" 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "quantize.h" 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_mem/vpx_mem.h" 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_scale/vpx_scale.h" 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/alloccommon.h" 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp8/common/loopfilter.h" 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_ARM 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_ports/arm.h" 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan 24233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest); 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan 26233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8_yv12_copy_partial_frame_c(YV12_BUFFER_CONFIG *src_ybc, 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan YV12_BUFFER_CONFIG *dst_ybc) 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char *src_y, *dst_y; 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan int yheight; 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan int ystride; 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan int yoffset; 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan int linestocopy; 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan yheight = src_ybc->y_height; 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan ystride = src_ybc->y_stride; 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* number of MB rows to use in partial filtering */ 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION; 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */ 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Copy extra 4 so that full filter context is available if filtering done 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan * on the copied partial frame and not original. Partial filter does mb 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan * filtering for top row also, which can modify3 pixels above. 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan linestocopy += 4; 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* partial image starts at ~middle of frame (macroblock border)*/ 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan yoffset = ystride * (((yheight >> 5) * 16) - 4); 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan src_y = src_ybc->y_buffer + yoffset; 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan dst_y = dst_ybc->y_buffer + yoffset; 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_memcpy(dst_y, src_y, ystride * linestocopy); 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan 55233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan YV12_BUFFER_CONFIG *dest) 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i, j; 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan int Total = 0; 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan int srcoffset, dstoffset; 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char *src = source->y_buffer; 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char *dst = dest->y_buffer; 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan int linestocopy; 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* number of MB rows to use in partial filtering */ 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION; 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */ 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* partial image starts at ~middle of frame (macroblock border)*/ 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan srcoffset = source->y_stride * ((dest->y_height >> 5) * 16); 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan dstoffset = dest->y_stride * ((dest->y_height >> 5) * 16); 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan src += srcoffset; 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan dst += dstoffset; 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Loop through the Y plane raw and reconstruction data summing 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan * (square differences) 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < linestocopy; i += 16) 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (j = 0; j < source->y_width; j += 16) 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int sse; 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan Total += vp8_mse16x16(src + j, source->y_stride, 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan dst + j, dest->y_stride, 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan &sse); 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan src += 16 * source->y_stride; 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan dst += 16 * dest->y_stride; 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan return Total; 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Enforce a minimum filter level based upon baseline Q */ 99233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_min_filter_level(VP8_COMP *cpi, int base_qindex) 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan int min_filter_level; 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame && 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan !cpi->common.refresh_alt_ref_frame) 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan min_filter_level = 0; 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (base_qindex <= 6) 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan min_filter_level = 0; 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (base_qindex <= 16) 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan min_filter_level = 1; 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan min_filter_level = (base_qindex / 8); 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan return min_filter_level; 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Enforce a maximum filter level based upon baseline Q */ 120233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int get_max_filter_level(VP8_COMP *cpi, int base_qindex) 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* PGW August 2006: Highest filter values almost always a bad idea */ 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* jbb chg: 20100118 - not so any more with this overquant stuff allow 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan * high values with lots of intra coming in. 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan int max_filter_level = MAX_LOOP_FILTER; 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void)base_qindex; 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cpi->twopass.section_intra_rating > 8) 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan max_filter_level = MAX_LOOP_FILTER * 3 / 4; 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan return max_filter_level; 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan 136233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8_COMMON *cm = &cpi->common; 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan int best_err = 0; 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_err = 0; 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan int min_filter_level = get_min_filter_level(cpi, cm->base_qindex); 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan int max_filter_level = get_max_filter_level(cpi, cm->base_qindex); 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_val; 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan int best_filt_val = cm->filter_level; 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show; 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Replace unfiltered frame buffer with a new one */ 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->frame_to_show = &cpi->pick_lf_lvl_frame; 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->frame_type == KEY_FRAME) 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->sharpness_level = 0; 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->sharpness_level = cpi->oxcf.Sharpness; 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->sharpness_level != cm->last_sharpness_level) 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level); 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->last_sharpness_level = cm->sharpness_level; 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Start the search at the previous frame filter level unless it is 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan * now out of range. 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->filter_level < min_filter_level) 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = min_filter_level; 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (cm->filter_level > max_filter_level) 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = max_filter_level; 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_val = cm->filter_level; 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_filt_val = filt_val; 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get the err using the previous frame's filter value. */ 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Copy the unfiltered / processed recon buffer to the new buffer */ 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show); 177233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val); 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = calc_partial_ssl_err(sd, cm->frame_to_show); 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan 181233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_val -= 1 + (filt_val > 10); 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Search lower filter levels */ 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (filt_val >= min_filter_level) 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Apply the loop filter */ 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show); 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val); 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get the err for filtered frame */ 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = calc_partial_ssl_err(sd, cm->frame_to_show); 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Update the best case record or exit loop. */ 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_err < best_err) 195233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = filt_err; 197233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_filt_val = filt_val; 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Adjust filter level */ 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_val -= 1 + (filt_val > 10); 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Search up (note that we have already done filt_val = cm->filter_level) */ 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_val = cm->filter_level + 1 + (filt_val > 10); 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (best_filt_val == cm->filter_level) 210233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Resist raising filter level for very small gains */ 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err -= (best_err >> 10); 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (filt_val < max_filter_level) 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Apply the loop filter */ 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_yv12_copy_partial_frame(saved_frame, cm->frame_to_show); 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val); 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get the err for filtered frame */ 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = calc_partial_ssl_err(sd, cm->frame_to_show); 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Update the best case record or exit loop. */ 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_err < best_err) 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 227233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Do not raise filter level if improvement is < 1 part 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in 4096 229233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = filt_err - (filt_err >> 10); 231233d2500723e5594f3e7c70896ffeeef32b9c950ywan 232233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_filt_val = filt_val; 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 234233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 235233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Adjust filter level */ 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_val += 1 + (filt_val > 10); 239233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 240233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 242233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = best_filt_val; 243233d2500723e5594f3e7c70896ffeeef32b9c950ywan 244233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->filter_level < min_filter_level) 245233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = min_filter_level; 246233d2500723e5594f3e7c70896ffeeef32b9c950ywan 247233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->filter_level > max_filter_level) 248233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = max_filter_level; 249233d2500723e5594f3e7c70896ffeeef32b9c950ywan 250233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* restore unfiltered frame pointer */ 251233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->frame_to_show = saved_frame; 252233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 253233d2500723e5594f3e7c70896ffeeef32b9c950ywan 254233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Stub function for now Alt LF not used */ 255233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) 256233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 257233d2500723e5594f3e7c70896ffeeef32b9c950ywan MACROBLOCKD *mbd = &cpi->mb.e_mbd; 258233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void) filt_val; 259233d2500723e5594f3e7c70896ffeeef32b9c950ywan 260233d2500723e5594f3e7c70896ffeeef32b9c950ywan mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0]; 261233d2500723e5594f3e7c70896ffeeef32b9c950ywan mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1]; 262233d2500723e5594f3e7c70896ffeeef32b9c950ywan mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2]; 263233d2500723e5594f3e7c70896ffeeef32b9c950ywan mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3]; 264233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 265233d2500723e5594f3e7c70896ffeeef32b9c950ywan 266233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) 267233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 268233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP8_COMMON *cm = &cpi->common; 269233d2500723e5594f3e7c70896ffeeef32b9c950ywan 270233d2500723e5594f3e7c70896ffeeef32b9c950ywan int best_err = 0; 271233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_err = 0; 272233d2500723e5594f3e7c70896ffeeef32b9c950ywan int min_filter_level = get_min_filter_level(cpi, cm->base_qindex); 273233d2500723e5594f3e7c70896ffeeef32b9c950ywan int max_filter_level = get_max_filter_level(cpi, cm->base_qindex); 274233d2500723e5594f3e7c70896ffeeef32b9c950ywan 275233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filter_step; 276233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_high = 0; 277233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Start search at previous frame filter level */ 278233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_mid = cm->filter_level; 279233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_low = 0; 280233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_best; 281233d2500723e5594f3e7c70896ffeeef32b9c950ywan int filt_direction = 0; 282233d2500723e5594f3e7c70896ffeeef32b9c950ywan 283233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Bias against raising loop filter and in favor of lowering it */ 284233d2500723e5594f3e7c70896ffeeef32b9c950ywan int Bias = 0; 285233d2500723e5594f3e7c70896ffeeef32b9c950ywan 286233d2500723e5594f3e7c70896ffeeef32b9c950ywan int ss_err[MAX_LOOP_FILTER + 1]; 287233d2500723e5594f3e7c70896ffeeef32b9c950ywan 288233d2500723e5594f3e7c70896ffeeef32b9c950ywan YV12_BUFFER_CONFIG * saved_frame = cm->frame_to_show; 289233d2500723e5594f3e7c70896ffeeef32b9c950ywan 290233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_memset(ss_err, 0, sizeof(ss_err)); 291233d2500723e5594f3e7c70896ffeeef32b9c950ywan 292233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Replace unfiltered frame buffer with a new one */ 293233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->frame_to_show = &cpi->pick_lf_lvl_frame; 294233d2500723e5594f3e7c70896ffeeef32b9c950ywan 295233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cm->frame_type == KEY_FRAME) 296233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->sharpness_level = 0; 297233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 298233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->sharpness_level = cpi->oxcf.Sharpness; 299233d2500723e5594f3e7c70896ffeeef32b9c950ywan 300233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Start the search at the previous frame filter level unless it is 301233d2500723e5594f3e7c70896ffeeef32b9c950ywan * now out of range. 302233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 303233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_mid = cm->filter_level; 304233d2500723e5594f3e7c70896ffeeef32b9c950ywan 305233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_mid < min_filter_level) 306233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_mid = min_filter_level; 307233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (filt_mid > max_filter_level) 308233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_mid = max_filter_level; 309233d2500723e5594f3e7c70896ffeeef32b9c950ywan 310233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Define the initial step size */ 311233d2500723e5594f3e7c70896ffeeef32b9c950ywan filter_step = (filt_mid < 16) ? 4 : filt_mid / 4; 312233d2500723e5594f3e7c70896ffeeef32b9c950ywan 313233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get baseline error score */ 314233d2500723e5594f3e7c70896ffeeef32b9c950ywan 315233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Copy the unfiltered / processed recon buffer to the new buffer */ 316233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_yv12_copy_y(saved_frame, cm->frame_to_show); 317233d2500723e5594f3e7c70896ffeeef32b9c950ywan 318233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8cx_set_alt_lf_level(cpi, filt_mid); 319233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid); 320233d2500723e5594f3e7c70896ffeeef32b9c950ywan 321233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = vp8_calc_ss_err(sd, cm->frame_to_show); 322233d2500723e5594f3e7c70896ffeeef32b9c950ywan 323233d2500723e5594f3e7c70896ffeeef32b9c950ywan ss_err[filt_mid] = best_err; 324233d2500723e5594f3e7c70896ffeeef32b9c950ywan 325233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_best = filt_mid; 326233d2500723e5594f3e7c70896ffeeef32b9c950ywan 327233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (filter_step > 0) 328233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 329233d2500723e5594f3e7c70896ffeeef32b9c950ywan Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; 330233d2500723e5594f3e7c70896ffeeef32b9c950ywan 331233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cpi->twopass.section_intra_rating < 20) 332233d2500723e5594f3e7c70896ffeeef32b9c950ywan Bias = Bias * cpi->twopass.section_intra_rating / 20; 333233d2500723e5594f3e7c70896ffeeef32b9c950ywan 334233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step); 335233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step); 336233d2500723e5594f3e7c70896ffeeef32b9c950ywan 337233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ((filt_direction <= 0) && (filt_low != filt_mid)) 338233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 339233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(ss_err[filt_low] == 0) 340233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 341233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Get Low filter error score */ 342233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_yv12_copy_y(saved_frame, cm->frame_to_show); 343233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8cx_set_alt_lf_level(cpi, filt_low); 344233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low); 345233d2500723e5594f3e7c70896ffeeef32b9c950ywan 346233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = vp8_calc_ss_err(sd, cm->frame_to_show); 347233d2500723e5594f3e7c70896ffeeef32b9c950ywan ss_err[filt_low] = filt_err; 348233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 349233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 350233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = ss_err[filt_low]; 351233d2500723e5594f3e7c70896ffeeef32b9c950ywan 352233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* If value is close to the best so far then bias towards a 353233d2500723e5594f3e7c70896ffeeef32b9c950ywan * lower loop filter value. 354233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 355233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ((filt_err - Bias) < best_err) 356233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 357233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Was it actually better than the previous best? */ 358233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_err < best_err) 359233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = filt_err; 360233d2500723e5594f3e7c70896ffeeef32b9c950ywan 361233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_best = filt_low; 362233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 363233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 364233d2500723e5594f3e7c70896ffeeef32b9c950ywan 365233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Now look at filt_high */ 366233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ((filt_direction >= 0) && (filt_high != filt_mid)) 367233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 368233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(ss_err[filt_high] == 0) 369233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 370233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_yv12_copy_y(saved_frame, cm->frame_to_show); 371233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8cx_set_alt_lf_level(cpi, filt_high); 372233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high); 373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 374233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = vp8_calc_ss_err(sd, cm->frame_to_show); 375233d2500723e5594f3e7c70896ffeeef32b9c950ywan ss_err[filt_high] = filt_err; 376233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 377233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 378233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_err = ss_err[filt_high]; 379233d2500723e5594f3e7c70896ffeeef32b9c950ywan 380233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Was it better than the previous best? */ 381233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_err < (best_err - Bias)) 382233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 383233d2500723e5594f3e7c70896ffeeef32b9c950ywan best_err = filt_err; 384233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_best = filt_high; 385233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 386233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 387233d2500723e5594f3e7c70896ffeeef32b9c950ywan 388233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Half the step distance if the best filter value was the same 389233d2500723e5594f3e7c70896ffeeef32b9c950ywan * as last time 390233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 391233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filt_best == filt_mid) 392233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 393233d2500723e5594f3e7c70896ffeeef32b9c950ywan filter_step = filter_step / 2; 394233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_direction = 0; 395233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 396233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 397233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 398233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_direction = (filt_best < filt_mid) ? -1 : 1; 399233d2500723e5594f3e7c70896ffeeef32b9c950ywan filt_mid = filt_best; 400233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 401233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 402233d2500723e5594f3e7c70896ffeeef32b9c950ywan 403233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->filter_level = filt_best; 404233d2500723e5594f3e7c70896ffeeef32b9c950ywan 405233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* restore unfiltered frame pointer */ 406233d2500723e5594f3e7c70896ffeeef32b9c950ywan cm->frame_to_show = saved_frame; 407233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 408