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 #include "vpx_config.h" 12 #include "vp8_rtcd.h" 13 #include "loopfilter.h" 14 #include "onyxc_int.h" 15 #include "vpx_mem/vpx_mem.h" 16 17 static void lf_init_lut(loop_filter_info_n *lfi) { 18 int filt_lvl; 19 20 for (filt_lvl = 0; filt_lvl <= MAX_LOOP_FILTER; ++filt_lvl) { 21 if (filt_lvl >= 40) { 22 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 2; 23 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 3; 24 } else if (filt_lvl >= 20) { 25 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1; 26 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 2; 27 } else if (filt_lvl >= 15) { 28 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1; 29 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 1; 30 } else { 31 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 0; 32 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 0; 33 } 34 } 35 36 lfi->mode_lf_lut[DC_PRED] = 1; 37 lfi->mode_lf_lut[V_PRED] = 1; 38 lfi->mode_lf_lut[H_PRED] = 1; 39 lfi->mode_lf_lut[TM_PRED] = 1; 40 lfi->mode_lf_lut[B_PRED] = 0; 41 42 lfi->mode_lf_lut[ZEROMV] = 1; 43 lfi->mode_lf_lut[NEARESTMV] = 2; 44 lfi->mode_lf_lut[NEARMV] = 2; 45 lfi->mode_lf_lut[NEWMV] = 2; 46 lfi->mode_lf_lut[SPLITMV] = 3; 47 } 48 49 void vp8_loop_filter_update_sharpness(loop_filter_info_n *lfi, 50 int sharpness_lvl) { 51 int i; 52 53 /* For each possible value for the loop filter fill out limits */ 54 for (i = 0; i <= MAX_LOOP_FILTER; ++i) { 55 int filt_lvl = i; 56 int block_inside_limit = 0; 57 58 /* Set loop filter paramaeters that control sharpness. */ 59 block_inside_limit = filt_lvl >> (sharpness_lvl > 0); 60 block_inside_limit = block_inside_limit >> (sharpness_lvl > 4); 61 62 if (sharpness_lvl > 0) { 63 if (block_inside_limit > (9 - sharpness_lvl)) { 64 block_inside_limit = (9 - sharpness_lvl); 65 } 66 } 67 68 if (block_inside_limit < 1) block_inside_limit = 1; 69 70 memset(lfi->lim[i], block_inside_limit, SIMD_WIDTH); 71 memset(lfi->blim[i], (2 * filt_lvl + block_inside_limit), SIMD_WIDTH); 72 memset(lfi->mblim[i], (2 * (filt_lvl + 2) + block_inside_limit), 73 SIMD_WIDTH); 74 } 75 } 76 77 void vp8_loop_filter_init(VP8_COMMON *cm) { 78 loop_filter_info_n *lfi = &cm->lf_info; 79 int i; 80 81 /* init limits for given sharpness*/ 82 vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level); 83 cm->last_sharpness_level = cm->sharpness_level; 84 85 /* init LUT for lvl and hev thr picking */ 86 lf_init_lut(lfi); 87 88 /* init hev threshold const vectors */ 89 for (i = 0; i < 4; ++i) { 90 memset(lfi->hev_thr[i], i, SIMD_WIDTH); 91 } 92 } 93 94 void vp8_loop_filter_frame_init(VP8_COMMON *cm, MACROBLOCKD *mbd, 95 int default_filt_lvl) { 96 int seg, /* segment number */ 97 ref, /* index in ref_lf_deltas */ 98 mode; /* index in mode_lf_deltas */ 99 100 loop_filter_info_n *lfi = &cm->lf_info; 101 102 /* update limits if sharpness has changed */ 103 if (cm->last_sharpness_level != cm->sharpness_level) { 104 vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level); 105 cm->last_sharpness_level = cm->sharpness_level; 106 } 107 108 for (seg = 0; seg < MAX_MB_SEGMENTS; ++seg) { 109 int lvl_seg = default_filt_lvl; 110 int lvl_ref, lvl_mode; 111 112 /* Note the baseline filter values for each segment */ 113 if (mbd->segmentation_enabled) { 114 /* Abs value */ 115 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA) { 116 lvl_seg = mbd->segment_feature_data[MB_LVL_ALT_LF][seg]; 117 } else /* Delta Value */ 118 { 119 lvl_seg += mbd->segment_feature_data[MB_LVL_ALT_LF][seg]; 120 } 121 lvl_seg = (lvl_seg > 0) ? ((lvl_seg > 63) ? 63 : lvl_seg) : 0; 122 } 123 124 if (!mbd->mode_ref_lf_delta_enabled) { 125 /* we could get rid of this if we assume that deltas are set to 126 * zero when not in use; encoder always uses deltas 127 */ 128 memset(lfi->lvl[seg][0], lvl_seg, 4 * 4); 129 continue; 130 } 131 132 /* INTRA_FRAME */ 133 ref = INTRA_FRAME; 134 135 /* Apply delta for reference frame */ 136 lvl_ref = lvl_seg + mbd->ref_lf_deltas[ref]; 137 138 /* Apply delta for Intra modes */ 139 mode = 0; /* B_PRED */ 140 /* Only the split mode BPRED has a further special case */ 141 lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode]; 142 /* clamp */ 143 lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; 144 145 lfi->lvl[seg][ref][mode] = lvl_mode; 146 147 mode = 1; /* all the rest of Intra modes */ 148 /* clamp */ 149 lvl_mode = (lvl_ref > 0) ? (lvl_ref > 63 ? 63 : lvl_ref) : 0; 150 lfi->lvl[seg][ref][mode] = lvl_mode; 151 152 /* LAST, GOLDEN, ALT */ 153 for (ref = 1; ref < MAX_REF_FRAMES; ++ref) { 154 /* Apply delta for reference frame */ 155 lvl_ref = lvl_seg + mbd->ref_lf_deltas[ref]; 156 157 /* Apply delta for Inter modes */ 158 for (mode = 1; mode < 4; ++mode) { 159 lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode]; 160 /* clamp */ 161 lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; 162 163 lfi->lvl[seg][ref][mode] = lvl_mode; 164 } 165 } 166 } 167 } 168 169 void vp8_loop_filter_row_normal(VP8_COMMON *cm, MODE_INFO *mode_info_context, 170 int mb_row, int post_ystride, int post_uvstride, 171 unsigned char *y_ptr, unsigned char *u_ptr, 172 unsigned char *v_ptr) { 173 int mb_col; 174 int filter_level; 175 loop_filter_info_n *lfi_n = &cm->lf_info; 176 loop_filter_info lfi; 177 FRAME_TYPE frame_type = cm->frame_type; 178 179 for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { 180 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 181 mode_info_context->mbmi.mode != SPLITMV && 182 mode_info_context->mbmi.mb_skip_coeff); 183 184 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 185 const int seg = mode_info_context->mbmi.segment_id; 186 const int ref_frame = mode_info_context->mbmi.ref_frame; 187 188 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 189 190 if (filter_level) { 191 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level]; 192 lfi.mblim = lfi_n->mblim[filter_level]; 193 lfi.blim = lfi_n->blim[filter_level]; 194 lfi.lim = lfi_n->lim[filter_level]; 195 lfi.hev_thr = lfi_n->hev_thr[hev_index]; 196 197 if (mb_col > 0) 198 vp8_loop_filter_mbv(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride, 199 &lfi); 200 201 if (!skip_lf) 202 vp8_loop_filter_bv(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride, 203 &lfi); 204 205 /* don't apply across umv border */ 206 if (mb_row > 0) 207 vp8_loop_filter_mbh(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride, 208 &lfi); 209 210 if (!skip_lf) 211 vp8_loop_filter_bh(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride, 212 &lfi); 213 } 214 215 y_ptr += 16; 216 u_ptr += 8; 217 v_ptr += 8; 218 219 mode_info_context++; /* step to next MB */ 220 } 221 } 222 223 void vp8_loop_filter_row_simple(VP8_COMMON *cm, MODE_INFO *mode_info_context, 224 int mb_row, int post_ystride, int post_uvstride, 225 unsigned char *y_ptr, unsigned char *u_ptr, 226 unsigned char *v_ptr) { 227 int mb_col; 228 int filter_level; 229 loop_filter_info_n *lfi_n = &cm->lf_info; 230 (void)post_uvstride; 231 232 for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { 233 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 234 mode_info_context->mbmi.mode != SPLITMV && 235 mode_info_context->mbmi.mb_skip_coeff); 236 237 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 238 const int seg = mode_info_context->mbmi.segment_id; 239 const int ref_frame = mode_info_context->mbmi.ref_frame; 240 241 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 242 243 if (filter_level) { 244 if (mb_col > 0) 245 vp8_loop_filter_simple_mbv(y_ptr, post_ystride, 246 lfi_n->mblim[filter_level]); 247 248 if (!skip_lf) 249 vp8_loop_filter_simple_bv(y_ptr, post_ystride, 250 lfi_n->blim[filter_level]); 251 252 /* don't apply across umv border */ 253 if (mb_row > 0) 254 vp8_loop_filter_simple_mbh(y_ptr, post_ystride, 255 lfi_n->mblim[filter_level]); 256 257 if (!skip_lf) 258 vp8_loop_filter_simple_bh(y_ptr, post_ystride, 259 lfi_n->blim[filter_level]); 260 } 261 262 y_ptr += 16; 263 u_ptr += 8; 264 v_ptr += 8; 265 266 mode_info_context++; /* step to next MB */ 267 } 268 } 269 void vp8_loop_filter_frame(VP8_COMMON *cm, MACROBLOCKD *mbd, int frame_type) { 270 YV12_BUFFER_CONFIG *post = cm->frame_to_show; 271 loop_filter_info_n *lfi_n = &cm->lf_info; 272 loop_filter_info lfi; 273 274 int mb_row; 275 int mb_col; 276 int mb_rows = cm->mb_rows; 277 int mb_cols = cm->mb_cols; 278 279 int filter_level; 280 281 unsigned char *y_ptr, *u_ptr, *v_ptr; 282 283 /* Point at base of Mb MODE_INFO list */ 284 const MODE_INFO *mode_info_context = cm->mi; 285 int post_y_stride = post->y_stride; 286 int post_uv_stride = post->uv_stride; 287 288 /* Initialize the loop filter for this frame. */ 289 vp8_loop_filter_frame_init(cm, mbd, cm->filter_level); 290 291 /* Set up the buffer pointers */ 292 y_ptr = post->y_buffer; 293 u_ptr = post->u_buffer; 294 v_ptr = post->v_buffer; 295 296 /* vp8_filter each macro block */ 297 if (cm->filter_type == NORMAL_LOOPFILTER) { 298 for (mb_row = 0; mb_row < mb_rows; ++mb_row) { 299 for (mb_col = 0; mb_col < mb_cols; ++mb_col) { 300 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 301 mode_info_context->mbmi.mode != SPLITMV && 302 mode_info_context->mbmi.mb_skip_coeff); 303 304 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 305 const int seg = mode_info_context->mbmi.segment_id; 306 const int ref_frame = mode_info_context->mbmi.ref_frame; 307 308 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 309 310 if (filter_level) { 311 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level]; 312 lfi.mblim = lfi_n->mblim[filter_level]; 313 lfi.blim = lfi_n->blim[filter_level]; 314 lfi.lim = lfi_n->lim[filter_level]; 315 lfi.hev_thr = lfi_n->hev_thr[hev_index]; 316 317 if (mb_col > 0) 318 vp8_loop_filter_mbv(y_ptr, u_ptr, v_ptr, post_y_stride, 319 post_uv_stride, &lfi); 320 321 if (!skip_lf) 322 vp8_loop_filter_bv(y_ptr, u_ptr, v_ptr, post_y_stride, 323 post_uv_stride, &lfi); 324 325 /* don't apply across umv border */ 326 if (mb_row > 0) 327 vp8_loop_filter_mbh(y_ptr, u_ptr, v_ptr, post_y_stride, 328 post_uv_stride, &lfi); 329 330 if (!skip_lf) 331 vp8_loop_filter_bh(y_ptr, u_ptr, v_ptr, post_y_stride, 332 post_uv_stride, &lfi); 333 } 334 335 y_ptr += 16; 336 u_ptr += 8; 337 v_ptr += 8; 338 339 mode_info_context++; /* step to next MB */ 340 } 341 y_ptr += post_y_stride * 16 - post->y_width; 342 u_ptr += post_uv_stride * 8 - post->uv_width; 343 v_ptr += post_uv_stride * 8 - post->uv_width; 344 345 mode_info_context++; /* Skip border mb */ 346 } 347 } else /* SIMPLE_LOOPFILTER */ 348 { 349 for (mb_row = 0; mb_row < mb_rows; ++mb_row) { 350 for (mb_col = 0; mb_col < mb_cols; ++mb_col) { 351 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 352 mode_info_context->mbmi.mode != SPLITMV && 353 mode_info_context->mbmi.mb_skip_coeff); 354 355 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 356 const int seg = mode_info_context->mbmi.segment_id; 357 const int ref_frame = mode_info_context->mbmi.ref_frame; 358 359 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 360 if (filter_level) { 361 const unsigned char *mblim = lfi_n->mblim[filter_level]; 362 const unsigned char *blim = lfi_n->blim[filter_level]; 363 364 if (mb_col > 0) 365 vp8_loop_filter_simple_mbv(y_ptr, post_y_stride, mblim); 366 367 if (!skip_lf) vp8_loop_filter_simple_bv(y_ptr, post_y_stride, blim); 368 369 /* don't apply across umv border */ 370 if (mb_row > 0) 371 vp8_loop_filter_simple_mbh(y_ptr, post_y_stride, mblim); 372 373 if (!skip_lf) vp8_loop_filter_simple_bh(y_ptr, post_y_stride, blim); 374 } 375 376 y_ptr += 16; 377 u_ptr += 8; 378 v_ptr += 8; 379 380 mode_info_context++; /* step to next MB */ 381 } 382 y_ptr += post_y_stride * 16 - post->y_width; 383 u_ptr += post_uv_stride * 8 - post->uv_width; 384 v_ptr += post_uv_stride * 8 - post->uv_width; 385 386 mode_info_context++; /* Skip border mb */ 387 } 388 } 389 } 390 391 void vp8_loop_filter_frame_yonly(VP8_COMMON *cm, MACROBLOCKD *mbd, 392 int default_filt_lvl) { 393 YV12_BUFFER_CONFIG *post = cm->frame_to_show; 394 395 unsigned char *y_ptr; 396 int mb_row; 397 int mb_col; 398 399 loop_filter_info_n *lfi_n = &cm->lf_info; 400 loop_filter_info lfi; 401 402 int filter_level; 403 FRAME_TYPE frame_type = cm->frame_type; 404 405 /* Point at base of Mb MODE_INFO list */ 406 const MODE_INFO *mode_info_context = cm->mi; 407 408 #if 0 409 if(default_filt_lvl == 0) /* no filter applied */ 410 return; 411 #endif 412 413 /* Initialize the loop filter for this frame. */ 414 vp8_loop_filter_frame_init(cm, mbd, default_filt_lvl); 415 416 /* Set up the buffer pointers */ 417 y_ptr = post->y_buffer; 418 419 /* vp8_filter each macro block */ 420 for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) { 421 for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) { 422 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 423 mode_info_context->mbmi.mode != SPLITMV && 424 mode_info_context->mbmi.mb_skip_coeff); 425 426 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 427 const int seg = mode_info_context->mbmi.segment_id; 428 const int ref_frame = mode_info_context->mbmi.ref_frame; 429 430 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 431 432 if (filter_level) { 433 if (cm->filter_type == NORMAL_LOOPFILTER) { 434 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level]; 435 lfi.mblim = lfi_n->mblim[filter_level]; 436 lfi.blim = lfi_n->blim[filter_level]; 437 lfi.lim = lfi_n->lim[filter_level]; 438 lfi.hev_thr = lfi_n->hev_thr[hev_index]; 439 440 if (mb_col > 0) 441 vp8_loop_filter_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi); 442 443 if (!skip_lf) 444 vp8_loop_filter_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi); 445 446 /* don't apply across umv border */ 447 if (mb_row > 0) 448 vp8_loop_filter_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi); 449 450 if (!skip_lf) 451 vp8_loop_filter_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi); 452 } else { 453 if (mb_col > 0) 454 vp8_loop_filter_simple_mbv(y_ptr, post->y_stride, 455 lfi_n->mblim[filter_level]); 456 457 if (!skip_lf) 458 vp8_loop_filter_simple_bv(y_ptr, post->y_stride, 459 lfi_n->blim[filter_level]); 460 461 /* don't apply across umv border */ 462 if (mb_row > 0) 463 vp8_loop_filter_simple_mbh(y_ptr, post->y_stride, 464 lfi_n->mblim[filter_level]); 465 466 if (!skip_lf) 467 vp8_loop_filter_simple_bh(y_ptr, post->y_stride, 468 lfi_n->blim[filter_level]); 469 } 470 } 471 472 y_ptr += 16; 473 mode_info_context++; /* step to next MB */ 474 } 475 476 y_ptr += post->y_stride * 16 - post->y_width; 477 mode_info_context++; /* Skip border mb */ 478 } 479 } 480 481 void vp8_loop_filter_partial_frame(VP8_COMMON *cm, MACROBLOCKD *mbd, 482 int default_filt_lvl) { 483 YV12_BUFFER_CONFIG *post = cm->frame_to_show; 484 485 unsigned char *y_ptr; 486 int mb_row; 487 int mb_col; 488 int mb_cols = post->y_width >> 4; 489 int mb_rows = post->y_height >> 4; 490 491 int linestocopy; 492 493 loop_filter_info_n *lfi_n = &cm->lf_info; 494 loop_filter_info lfi; 495 496 int filter_level; 497 FRAME_TYPE frame_type = cm->frame_type; 498 499 const MODE_INFO *mode_info_context; 500 501 #if 0 502 if(default_filt_lvl == 0) /* no filter applied */ 503 return; 504 #endif 505 506 /* Initialize the loop filter for this frame. */ 507 vp8_loop_filter_frame_init(cm, mbd, default_filt_lvl); 508 509 /* number of MB rows to use in partial filtering */ 510 linestocopy = mb_rows / PARTIAL_FRAME_FRACTION; 511 linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */ 512 513 /* Set up the buffer pointers; partial image starts at ~middle of frame */ 514 y_ptr = post->y_buffer + ((post->y_height >> 5) * 16) * post->y_stride; 515 mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1); 516 517 /* vp8_filter each macro block */ 518 for (mb_row = 0; mb_row < (linestocopy >> 4); ++mb_row) { 519 for (mb_col = 0; mb_col < mb_cols; ++mb_col) { 520 int skip_lf = (mode_info_context->mbmi.mode != B_PRED && 521 mode_info_context->mbmi.mode != SPLITMV && 522 mode_info_context->mbmi.mb_skip_coeff); 523 524 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode]; 525 const int seg = mode_info_context->mbmi.segment_id; 526 const int ref_frame = mode_info_context->mbmi.ref_frame; 527 528 filter_level = lfi_n->lvl[seg][ref_frame][mode_index]; 529 530 if (filter_level) { 531 if (cm->filter_type == NORMAL_LOOPFILTER) { 532 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level]; 533 lfi.mblim = lfi_n->mblim[filter_level]; 534 lfi.blim = lfi_n->blim[filter_level]; 535 lfi.lim = lfi_n->lim[filter_level]; 536 lfi.hev_thr = lfi_n->hev_thr[hev_index]; 537 538 if (mb_col > 0) 539 vp8_loop_filter_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi); 540 541 if (!skip_lf) 542 vp8_loop_filter_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi); 543 544 vp8_loop_filter_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi); 545 546 if (!skip_lf) 547 vp8_loop_filter_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi); 548 } else { 549 if (mb_col > 0) 550 vp8_loop_filter_simple_mbv(y_ptr, post->y_stride, 551 lfi_n->mblim[filter_level]); 552 553 if (!skip_lf) 554 vp8_loop_filter_simple_bv(y_ptr, post->y_stride, 555 lfi_n->blim[filter_level]); 556 557 vp8_loop_filter_simple_mbh(y_ptr, post->y_stride, 558 lfi_n->mblim[filter_level]); 559 560 if (!skip_lf) 561 vp8_loop_filter_simple_bh(y_ptr, post->y_stride, 562 lfi_n->blim[filter_level]); 563 } 564 } 565 566 y_ptr += 16; 567 mode_info_context += 1; /* step to next MB */ 568 } 569 570 y_ptr += post->y_stride * 16 - post->y_width; 571 mode_info_context += 1; /* Skip border mb */ 572 } 573 } 574