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
205 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
206 loop_filter_info_n *lfi_n = &cm->lf_info;
207 loop_filter_info lfi;
209 FRAME_TYPE frame_type = cm->frame_type;
213 int mb_rows = cm->mb_rows;
214 int mb_cols = cm->mb_cols;
218 unsigned char *y_ptr, *u_ptr, *v_ptr;
220 /* Point at base of Mb MODE_INFO list */
221 const MODE_INFO *mode_info_context = cm->mi;
222 int post_y_stride = post->y_stride;
223 int post_uv_stride = post->uv_stride;
225 /* Initialize the loop filter for this frame. */
226 vp8_loop_filter_frame_init(cm, mbd, cm->filter_level);
228 /* Set up the buffer pointers */
229 y_ptr = post->y_buffer;
230 u_ptr = post->u_buffer;
231 v_ptr = post->v_buffer;
233 /* vp8_filter each macro block */
234 if (cm->filter_type == NORMAL_LOOPFILTER)
236 for (mb_row = 0; mb_row < mb_rows; mb_row++)
238 for (mb_col = 0; mb_col < mb_cols; mb_col++)
240 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
241 mode_info_context->mbmi.mode != SPLITMV &&
242 mode_info_context->mbmi.mb_skip_coeff);
244 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
245 const int seg = mode_info_context->mbmi.segment_id;
246 const int ref_frame = mode_info_context->mbmi.ref_frame;
248 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
252 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
253 lfi.mblim = lfi_n->mblim[filter_level];
254 lfi.blim = lfi_n->blim[filter_level];
255 lfi.lim = lfi_n->lim[filter_level];
256 lfi.hev_thr = lfi_n->hev_thr[hev_index];
260 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
264 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
266 /* don't apply across umv border */
269 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
273 (y_ptr, u_ptr, v_ptr, post_y_stride, post_uv_stride, &lfi);
280 mode_info_context++; /* step to next MB */
282 y_ptr += post_y_stride * 16 - post->y_width;
283 u_ptr += post_uv_stride * 8 - post->uv_width;
284 v_ptr += post_uv_stride * 8 - post->uv_width;
286 mode_info_context++; /* Skip border mb */
290 else /* SIMPLE_LOOPFILTER */
292 for (mb_row = 0; mb_row < mb_rows; mb_row++)
294 for (mb_col = 0; mb_col < mb_cols; mb_col++)
296 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
297 mode_info_context->mbmi.mode != SPLITMV &&
298 mode_info_context->mbmi.mb_skip_coeff);
300 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
301 const int seg = mode_info_context->mbmi.segment_id;
302 const int ref_frame = mode_info_context->mbmi.ref_frame;
304 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
307 const unsigned char * mblim = lfi_n->mblim[filter_level];
308 const unsigned char * blim = lfi_n->blim[filter_level];
311 vp8_loop_filter_simple_mbv
312 (y_ptr, post_y_stride, mblim);
315 vp8_loop_filter_simple_bv
316 (y_ptr, post_y_stride, blim);
318 /* don't apply across umv border */
320 vp8_loop_filter_simple_mbh
321 (y_ptr, post_y_stride, mblim);
324 vp8_loop_filter_simple_bh
325 (y_ptr, post_y_stride, blim);
332 mode_info_context++; /* step to next MB */
334 y_ptr += post_y_stride * 16 - post->y_width;
335 u_ptr += post_uv_stride * 8 - post->uv_width;
336 v_ptr += post_uv_stride * 8 - post->uv_width;
338 mode_info_context++; /* Skip border mb */
344 void vp8_loop_filter_frame_yonly
351 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
353 unsigned char *y_ptr;
357 loop_filter_info_n *lfi_n = &cm->lf_info;
358 loop_filter_info lfi;
361 FRAME_TYPE frame_type = cm->frame_type;
363 /* Point at base of Mb MODE_INFO list */
364 const MODE_INFO *mode_info_context = cm->mi;
367 if(default_filt_lvl == 0) /* no filter applied */
371 /* Initialize the loop filter for this frame. */
372 vp8_loop_filter_frame_init( cm, mbd, default_filt_lvl);
374 /* Set up the buffer pointers */
375 y_ptr = post->y_buffer;
377 /* vp8_filter each macro block */
378 for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
380 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
382 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
383 mode_info_context->mbmi.mode != SPLITMV &&
384 mode_info_context->mbmi.mb_skip_coeff);
386 const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
387 const int seg = mode_info_context->mbmi.segment_id;
388 const int ref_frame = mode_info_context->mbmi.ref_frame;
390 filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
394 if (cm->filter_type == NORMAL_LOOPFILTER)
396 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
397 lfi.mblim = lfi_n->mblim[filter_level];
398 lfi.blim = lfi_n->blim[filter_level];
399 lfi.lim = lfi_n->lim[filter_level];
400 lfi.hev_thr = lfi_n->hev_thr[hev_index];
404 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
408 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
410 /* don't apply across umv border */
413 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
417 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
422 vp8_loop_filter_simple_mbv
423 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
426 vp8_loop_filter_simple_bv
427 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
429 /* don't apply across umv border */
431 vp8_loop_filter_simple_mbh
432 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
435 vp8_loop_filter_simple_bh
436 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
441 mode_info_context ++; /* step to next MB */
445 y_ptr += post->y_stride * 16 - post->y_width;
446 mode_info_context ++; /* Skip border mb */
451 void vp8_loop_filter_partial_frame
458 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
460 unsigned char *y_ptr;
463 int mb_cols = post->y_width >> 4;
464 int mb_rows = post->y_height >> 4;
468 loop_filter_info_n *lfi_n = &cm->lf_info;
469 loop_filter_info lfi;
472 int alt_flt_enabled = mbd->segmentation_enabled;
473 FRAME_TYPE frame_type = cm->frame_type;
475 const MODE_INFO *mode_info_context;
477 int lvl_seg[MAX_MB_SEGMENTS];
479 /* number of MB rows to use in partial filtering */
480 linestocopy = mb_rows / PARTIAL_FRAME_FRACTION;
481 linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
483 /* Note the baseline filter values for each segment */
484 /* See vp8_loop_filter_frame_init. Rather than call that for each change
485 * to default_filt_lvl, copy the relevant calculation here.
489 for (i = 0; i < MAX_MB_SEGMENTS; i++)
491 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
493 lvl_seg[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
498 lvl_seg[i] = default_filt_lvl
499 + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
500 lvl_seg[i] = (lvl_seg[i] > 0) ?
501 ((lvl_seg[i] > 63) ? 63: lvl_seg[i]) : 0;
506 /* Set up the buffer pointers; partial image starts at ~middle of frame */
507 y_ptr = post->y_buffer + ((post->y_height >> 5) * 16) * post->y_stride;
508 mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);
510 /* vp8_filter each macro block */
511 for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
513 for (mb_col = 0; mb_col < mb_cols; mb_col++)
515 int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
516 mode_info_context->mbmi.mode != SPLITMV &&
517 mode_info_context->mbmi.mb_skip_coeff);
520 filter_level = lvl_seg[mode_info_context->mbmi.segment_id];
522 filter_level = default_filt_lvl;
526 if (cm->filter_type == NORMAL_LOOPFILTER)
528 const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
529 lfi.mblim = lfi_n->mblim[filter_level];
530 lfi.blim = lfi_n->blim[filter_level];
531 lfi.lim = lfi_n->lim[filter_level];
532 lfi.hev_thr = lfi_n->hev_thr[hev_index];
536 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
540 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
543 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
547 (y_ptr, 0, 0, post->y_stride, 0, &lfi);
552 vp8_loop_filter_simple_mbv
553 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
556 vp8_loop_filter_simple_bv
557 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
559 vp8_loop_filter_simple_mbh
560 (y_ptr, post->y_stride, lfi_n->mblim[filter_level]);
563 vp8_loop_filter_simple_bh
564 (y_ptr, post->y_stride, lfi_n->blim[filter_level]);
569 mode_info_context += 1; /* step to next MB */
572 y_ptr += post->y_stride * 16 - post->y_width;
573 mode_info_context += 1; /* Skip border mb */