2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
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.
12 #include "vpx_config.h"
14 #include "loopfilter.h"
15 #include "onyxc_int.h"
16 #include "vpx_mem/vpx_mem.h"
18 typedef unsigned char uc;
20 static void lf_init_lut(loop_filter_info_n *lfi)
24 for (filt_lvl = 0; filt_lvl <= MAX_LOOP_FILTER; filt_lvl++)
28 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 2;
29 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 3;
31 else if (filt_lvl >= 20)
33 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
34 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 2;
36 else if (filt_lvl >= 15)
38 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
39 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 1;
43 lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 0;
44 lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 0;
48 lfi->mode_lf_lut[DC_PRED] = 1;
49 lfi->mode_lf_lut[V_PRED] = 1;
50 lfi->mode_lf_lut[H_PRED] = 1;
51 lfi->mode_lf_lut[TM_PRED] = 1;
52 lfi->mode_lf_lut[B_PRED] = 0;
54 lfi->mode_lf_lut[ZEROMV] = 1;
55 lfi->mode_lf_lut[NEARESTMV] = 2;
56 lfi->mode_lf_lut[NEARMV] = 2;
57 lfi->mode_lf_lut[NEWMV] = 2;
58 lfi->mode_lf_lut[SPLITMV] = 3;
62 void vp8_loop_filter_update_sharpness(loop_filter_info_n *lfi,
67 /* For each possible value for the loop filter fill out limits */
68 for (i = 0; i <= MAX_LOOP_FILTER; i++)
71 int block_inside_limit = 0;
73 /* Set loop filter paramaeters that control sharpness. */
74 block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
75 block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
77 if (sharpness_lvl > 0)
79 if (block_inside_limit > (9 - sharpness_lvl))
80 block_inside_limit = (9 - sharpness_lvl);
83 if (block_inside_limit < 1)
84 block_inside_limit = 1;
86 vpx_memset(lfi->lim[i], block_inside_limit, SIMD_WIDTH);
87 vpx_memset(lfi->blim[i], (2 * filt_lvl + block_inside_limit),
89 vpx_memset(lfi->mblim[i], (2 * (filt_lvl + 2) + block_inside_limit),
94 void vp8_loop_filter_init(VP8_COMMON *cm)
96 loop_filter_info_n *lfi = &cm->lf_info;
99 /* init limits for given sharpness*/
100 vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
101 cm->last_sharpness_level = cm->sharpness_level;
103 /* init LUT for lvl and hev thr picking */
106 /* init hev threshold const vectors */
107 for(i = 0; i < 4 ; i++)
109 vpx_memset(lfi->hev_thr[i], i, SIMD_WIDTH);
113 void vp8_loop_filter_frame_init(VP8_COMMON *cm,
115 int default_filt_lvl)
117 int seg, /* segment number */
118 ref, /* index in ref_lf_deltas */
119 mode; /* index in mode_lf_deltas */
121 loop_filter_info_n *lfi = &cm->lf_info;
123 /* update limits if sharpness has changed */
124 if(cm->last_sharpness_level != cm->sharpness_level)
126 vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
127 cm->last_sharpness_level = cm->sharpness_level;
130 for(seg = 0; seg < MAX_MB_SEGMENTS; seg++)
132 int lvl_seg = default_filt_lvl;
133 int lvl_ref, lvl_mode;
135 /* Note the baseline filter values for each segment */
136 if (mbd->segmentation_enabled)
139 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
141 lvl_seg = mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
143 else /* Delta Value */
145 lvl_seg += mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
146 lvl_seg = (lvl_seg > 0) ? ((lvl_seg > 63) ? 63: lvl_seg) : 0;
150 if (!mbd->mode_ref_lf_delta_enabled)
152 /* we could get rid of this if we assume that deltas are set to
153 * zero when not in use; encoder always uses deltas
155 vpx_memset(lfi->lvl[seg][0], lvl_seg, 4 * 4 );
164 /* Apply delta for reference frame */
165 lvl_ref += mbd->ref_lf_deltas[ref];
167 /* Apply delta for Intra modes */
168 mode = 0; /* B_PRED */
169 /* Only the split mode BPRED has a further special case */
170 lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
171 lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
173 lfi->lvl[seg][ref][mode] = lvl_mode;
175 mode = 1; /* all the rest of Intra modes */
176 lvl_mode = (lvl_ref > 0) ? (lvl_ref > 63 ? 63 : lvl_ref) : 0; /* clamp */
177 lfi->lvl[seg][ref][mode] = lvl_mode;
179 /* LAST, GOLDEN, ALT */
180 for(ref = 1; ref < MAX_REF_FRAMES; ref++)
182 int lvl_ref = lvl_seg;
184 /* Apply delta for reference frame */
185 lvl_ref += mbd->ref_lf_deltas[ref];
187 /* Apply delta for Inter modes */
188 for (mode = 1; mode < 4; mode++)
190 lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
191 lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0; /* clamp */
193 lfi->lvl[seg][ref][mode] = lvl_mode;
199 void vp8_loop_filter_frame(VP8_COMMON *cm,
203 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
204 loop_filter_info_n *lfi_n = &cm->lf_info;
205 loop_filter_info lfi;
209 int mb_rows = cm->mb_rows;
210 int mb_cols = cm->mb_cols;
214 unsigned char *y_ptr, *u_ptr, *v_ptr;
216 /* Point at base of Mb MODE_INFO list */
217 const MODE_INFO *mode_info_context = cm->mi;
218 int post_y_stride = post->y_stride;
219 int post_uv_stride = post->uv_stride;
221 /* Initialize the loop filter for this frame. */
222 vp8_loop_filter_frame_init(cm, mbd, cm->filter_level);
224 /* Set up the buffer pointers */
225 y_ptr = post->y_buffer;
226 u_ptr = post->u_buffer;
227 v_ptr = post->v_buffer;
229 /* vp8_filter each macro block */
230 if (cm->filter_type == NORMAL_LOOPFILTER)
232 for (mb_row = 0; mb_row < mb_rows; mb_row++)
234 for (mb_col = 0; mb_col < mb_cols; mb_col++)
236 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
237 mode_info_context->mbmi.mode != SPLITMV &&
238 mode_info_context->mbmi.mb_skip_coeff);
240 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
241 const int seg = mode_info_context->mbmi.segment_id;
242 const int ref_frame = mode_info_context->mbmi.ref_frame;
244 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
248 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
249 lfi.mblim = lfi_n->mblim[filter_level];
250 lfi.blim = lfi_n->blim[filter_level];
251 lfi.lim = lfi_n->lim[filter_level];
252 lfi.hev_thr = lfi_n->hev_thr[hev_index];
256 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
260 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
262 /* don't apply across umv border */
265 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
269 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
276 mode_info_context++; /* step to next MB */
278 y_ptr += post_y_stride * 16 - post->y_width;
279 u_ptr += post_uv_stride * 8 - post->uv_width;
280 v_ptr += post_uv_stride * 8 - post->uv_width;
282 mode_info_context++; /* Skip border mb */
286 else /* SIMPLE_LOOPFILTER */
288 for (mb_row = 0; mb_row < mb_rows; mb_row++)
290 for (mb_col = 0; mb_col < mb_cols; mb_col++)
292 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
293 mode_info_context->mbmi.mode != SPLITMV &&
294 mode_info_context->mbmi.mb_skip_coeff);
296 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
297 const int seg = mode_info_context->mbmi.segment_id;
298 const int ref_frame = mode_info_context->mbmi.ref_frame;
300 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
303 const unsigned char * mblim = lfi_n->mblim[filter_level];
304 const unsigned char * blim = lfi_n->blim[filter_level];
307 vp8_loop_filter_simple_mbv
308 (y_ptr, post_y_stride, mblim);
311 vp8_loop_filter_simple_bv
312 (y_ptr, post_y_stride, blim);
314 /* don't apply across umv border */
316 vp8_loop_filter_simple_mbh
317 (y_ptr, post_y_stride, mblim);
320 vp8_loop_filter_simple_bh
321 (y_ptr, post_y_stride, blim);
328 mode_info_context++; /* step to next MB */
330 y_ptr += post_y_stride * 16 - post->y_width;
331 u_ptr += post_uv_stride * 8 - post->uv_width;
332 v_ptr += post_uv_stride * 8 - post->uv_width;
334 mode_info_context++; /* Skip border mb */
340 void vp8_loop_filter_frame_yonly
347 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
349 unsigned char *y_ptr;
353 loop_filter_info_n *lfi_n = &cm->lf_info;
354 loop_filter_info lfi;
357 FRAME_TYPE frame_type = cm->frame_type;
359 /* Point at base of Mb MODE_INFO list */
360 const MODE_INFO *mode_info_context = cm->mi;
363 if(default_filt_lvl == 0) /* no filter applied */
367 /* Initialize the loop filter for this frame. */
368 vp8_loop_filter_frame_init( cm, mbd, default_filt_lvl);
370 /* Set up the buffer pointers */
371 y_ptr = post->y_buffer;
373 /* vp8_filter each macro block */
374 for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
376 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
378 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
379 mode_info_context->mbmi.mode != SPLITMV &&
380 mode_info_context->mbmi.mb_skip_coeff);
382 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
383 const int seg = mode_info_context->mbmi.segment_id;
384 const int ref_frame = mode_info_context->mbmi.ref_frame;
386 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
390 if (cm->filter_type == NORMAL_LOOPFILTER)
392 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
393 lfi.mblim = lfi_n->mblim[filter_level];
394 lfi.blim = lfi_n->blim[filter_level];
395 lfi.lim = lfi_n->lim[filter_level];
396 lfi.hev_thr = lfi_n->hev_thr[hev_index];
400 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
404 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
406 /* don't apply across umv border */
409 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
413 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
418 vp8_loop_filter_simple_mbv
419 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
422 vp8_loop_filter_simple_bv
423 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
425 /* don't apply across umv border */
427 vp8_loop_filter_simple_mbh
428 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
431 vp8_loop_filter_simple_bh
432 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
437 mode_info_context ++; /* step to next MB */
441 y_ptr += post->y_stride * 16 - post->y_width;
442 mode_info_context ++; /* Skip border mb */
447 void vp8_loop_filter_partial_frame
454 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
456 unsigned char *y_ptr;
459 int mb_cols = post->y_width >> 4;
460 int mb_rows = post->y_height >> 4;
464 loop_filter_info_n *lfi_n = &cm->lf_info;
465 loop_filter_info lfi;
468 int alt_flt_enabled = mbd->segmentation_enabled;
469 FRAME_TYPE frame_type = cm->frame_type;
471 const MODE_INFO *mode_info_context;
473 int lvl_seg[MAX_MB_SEGMENTS];
475 /* number of MB rows to use in partial filtering */
476 linestocopy = mb_rows / PARTIAL_FRAME_FRACTION;
477 linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
479 /* Note the baseline filter values for each segment */
480 /* See vp8_loop_filter_frame_init. Rather than call that for each change
481 * to default_filt_lvl, copy the relevant calculation here.
485 for (i = 0; i < MAX_MB_SEGMENTS; i++)
487 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
489 lvl_seg[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
494 lvl_seg[i] = default_filt_lvl
495 + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
496 lvl_seg[i] = (lvl_seg[i] > 0) ?
497 ((lvl_seg[i] > 63) ? 63: lvl_seg[i]) : 0;
502 /* Set up the buffer pointers; partial image starts at ~middle of frame */
503 y_ptr = post->y_buffer + ((post->y_height >> 5) * 16) * post->y_stride;
504 mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);
506 /* vp8_filter each macro block */
507 for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
509 for (mb_col = 0; mb_col < mb_cols; mb_col++)
511 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
512 mode_info_context->mbmi.mode != SPLITMV &&
513 mode_info_context->mbmi.mb_skip_coeff);
516 filter_level = lvl_seg[mode_info_context->mbmi.segment_id];
518 filter_level = default_filt_lvl;
522 if (cm->filter_type == NORMAL_LOOPFILTER)
524 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
525 lfi.mblim = lfi_n->mblim[filter_level];
526 lfi.blim = lfi_n->blim[filter_level];
527 lfi.lim = lfi_n->lim[filter_level];
528 lfi.hev_thr = lfi_n->hev_thr[hev_index];
532 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
536 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
539 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
543 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
548 vp8_loop_filter_simple_mbv
549 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
552 vp8_loop_filter_simple_bv
553 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
555 vp8_loop_filter_simple_mbh
556 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
559 vp8_loop_filter_simple_bh
560 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
565 mode_info_context += 1; /* step to next MB */
568 y_ptr += post->y_stride * 16 - post->y_width;
569 mode_info_context += 1; /* Skip border mb */