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