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