clarify *_offsets.asm differences
[libvpx.git] / vp8 / common / loopfilter.c
blob37c5b77405814e2555554f44d3f127993605c9bf
1 /*
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.
9 */
12 #include "vpx_ports/config.h"
13 #include "loopfilter.h"
14 #include "onyxc_int.h"
16 typedef unsigned char uc;
19 prototype_loopfilter(vp8_loop_filter_horizontal_edge_c);
20 prototype_loopfilter(vp8_loop_filter_vertical_edge_c);
21 prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_c);
22 prototype_loopfilter(vp8_mbloop_filter_vertical_edge_c);
23 prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_c);
24 prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_c);
26 /* Horizontal MB filtering */
27 void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
28 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
30 (void) simpler_lpf;
31 vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
33 if (u_ptr)
34 vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
36 if (v_ptr)
37 vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
40 void vp8_loop_filter_mbhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
41 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
43 (void) u_ptr;
44 (void) v_ptr;
45 (void) uv_stride;
46 (void) simpler_lpf;
47 vp8_loop_filter_simple_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
50 /* Vertical MB Filtering */
51 void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
52 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
54 (void) simpler_lpf;
55 vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
57 if (u_ptr)
58 vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
60 if (v_ptr)
61 vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->mbflim, lfi->lim, lfi->thr, 1);
64 void vp8_loop_filter_mbvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
65 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
67 (void) u_ptr;
68 (void) v_ptr;
69 (void) uv_stride;
70 (void) simpler_lpf;
71 vp8_loop_filter_simple_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->thr, 2);
74 /* Horizontal B Filtering */
75 void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
76 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
78 (void) simpler_lpf;
79 vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
80 vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
81 vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
83 if (u_ptr)
84 vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
86 if (v_ptr)
87 vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
90 void vp8_loop_filter_bhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
91 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
93 (void) u_ptr;
94 (void) v_ptr;
95 (void) uv_stride;
96 (void) simpler_lpf;
97 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
98 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
99 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
102 /* Vertical B Filtering */
103 void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
104 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
106 (void) simpler_lpf;
107 vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
108 vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
109 vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
111 if (u_ptr)
112 vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
114 if (v_ptr)
115 vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->flim, lfi->lim, lfi->thr, 1);
118 void vp8_loop_filter_bvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
119 int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
121 (void) u_ptr;
122 (void) v_ptr;
123 (void) uv_stride;
124 (void) simpler_lpf;
125 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
126 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
127 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
130 void vp8_init_loop_filter(VP8_COMMON *cm)
132 loop_filter_info *lfi = cm->lf_info;
133 LOOPFILTERTYPE lft = cm->filter_type;
134 int sharpness_lvl = cm->sharpness_level;
135 int frame_type = cm->frame_type;
136 int i, j;
138 int block_inside_limit = 0;
139 int HEVThresh;
141 /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
142 for (i = 0; i <= MAX_LOOP_FILTER; i++)
144 int filt_lvl = i;
146 if (frame_type == KEY_FRAME)
148 if (filt_lvl >= 40)
149 HEVThresh = 2;
150 else if (filt_lvl >= 15)
151 HEVThresh = 1;
152 else
153 HEVThresh = 0;
155 else
157 if (filt_lvl >= 40)
158 HEVThresh = 3;
159 else if (filt_lvl >= 20)
160 HEVThresh = 2;
161 else if (filt_lvl >= 15)
162 HEVThresh = 1;
163 else
164 HEVThresh = 0;
167 /* Set loop filter paramaeters that control sharpness. */
168 block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
169 block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
171 if (sharpness_lvl > 0)
173 if (block_inside_limit > (9 - sharpness_lvl))
174 block_inside_limit = (9 - sharpness_lvl);
177 if (block_inside_limit < 1)
178 block_inside_limit = 1;
180 for (j = 0; j < 16; j++)
182 lfi[i].lim[j] = block_inside_limit;
183 lfi[i].mbflim[j] = filt_lvl + 2;
184 lfi[i].flim[j] = filt_lvl;
185 lfi[i].thr[j] = HEVThresh;
190 /* Set up the function pointers depending on the type of loop filtering selected */
191 if (lft == NORMAL_LOOPFILTER)
193 cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_v);
194 cm->lf_bv = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v);
195 cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_h);
196 cm->lf_bh = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h);
198 else
200 cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_v);
201 cm->lf_bv = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_v);
202 cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_h);
203 cm->lf_bh = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_h);
207 /* Put vp8_init_loop_filter() in vp8dx_create_decompressor(). Only call vp8_frame_init_loop_filter() while decoding
208 * each frame. Check last_frame_type to skip the function most of times.
210 void vp8_frame_init_loop_filter(loop_filter_info *lfi, int frame_type)
212 int HEVThresh;
213 int i, j;
215 /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
216 for (i = 0; i <= MAX_LOOP_FILTER; i++)
218 int filt_lvl = i;
220 if (frame_type == KEY_FRAME)
222 if (filt_lvl >= 40)
223 HEVThresh = 2;
224 else if (filt_lvl >= 15)
225 HEVThresh = 1;
226 else
227 HEVThresh = 0;
229 else
231 if (filt_lvl >= 40)
232 HEVThresh = 3;
233 else if (filt_lvl >= 20)
234 HEVThresh = 2;
235 else if (filt_lvl >= 15)
236 HEVThresh = 1;
237 else
238 HEVThresh = 0;
241 for (j = 0; j < 16; j++)
243 /*lfi[i].lim[j] = block_inside_limit;
244 lfi[i].mbflim[j] = filt_lvl+2;*/
245 /*lfi[i].flim[j] = filt_lvl;*/
246 lfi[i].thr[j] = HEVThresh;
252 int vp8_adjust_mb_lf_value(MACROBLOCKD *mbd, int filter_level)
254 MB_MODE_INFO *mbmi = &mbd->mode_info_context->mbmi;
256 if (mbd->mode_ref_lf_delta_enabled)
258 /* Apply delta for reference frame */
259 filter_level += mbd->ref_lf_deltas[mbmi->ref_frame];
261 /* Apply delta for mode */
262 if (mbmi->ref_frame == INTRA_FRAME)
264 /* Only the split mode BPRED has a further special case */
265 if (mbmi->mode == B_PRED)
266 filter_level += mbd->mode_lf_deltas[0];
268 else
270 /* Zero motion mode */
271 if (mbmi->mode == ZEROMV)
272 filter_level += mbd->mode_lf_deltas[1];
274 /* Split MB motion mode */
275 else if (mbmi->mode == SPLITMV)
276 filter_level += mbd->mode_lf_deltas[3];
278 /* All other inter motion modes (Nearest, Near, New) */
279 else
280 filter_level += mbd->mode_lf_deltas[2];
283 /* Range check */
284 if (filter_level > MAX_LOOP_FILTER)
285 filter_level = MAX_LOOP_FILTER;
286 else if (filter_level < 0)
287 filter_level = 0;
289 return filter_level;
293 void vp8_loop_filter_frame
295 VP8_COMMON *cm,
296 MACROBLOCKD *mbd,
297 int default_filt_lvl
300 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
301 loop_filter_info *lfi = cm->lf_info;
302 FRAME_TYPE frame_type = cm->frame_type;
304 int mb_row;
305 int mb_col;
308 int baseline_filter_level[MAX_MB_SEGMENTS];
309 int filter_level;
310 int alt_flt_enabled = mbd->segmentation_enabled;
312 int i;
313 unsigned char *y_ptr, *u_ptr, *v_ptr;
315 mbd->mode_info_context = cm->mi; /* Point at base of Mb MODE_INFO list */
317 /* Note the baseline filter values for each segment */
318 if (alt_flt_enabled)
320 for (i = 0; i < MAX_MB_SEGMENTS; i++)
322 /* Abs value */
323 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
324 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
325 /* Delta Value */
326 else
328 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
329 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0; /* Clamp to valid range */
333 else
335 for (i = 0; i < MAX_MB_SEGMENTS; i++)
336 baseline_filter_level[i] = default_filt_lvl;
339 /* Initialize the loop filter for this frame. */
340 if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
341 vp8_init_loop_filter(cm);
342 else if (frame_type != cm->last_frame_type)
343 vp8_frame_init_loop_filter(lfi, frame_type);
345 /* Set up the buffer pointers */
346 y_ptr = post->y_buffer;
347 u_ptr = post->u_buffer;
348 v_ptr = post->v_buffer;
350 /* vp8_filter each macro block */
351 for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
353 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
355 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
357 filter_level = baseline_filter_level[Segment];
359 /* Distance of Mb to the various image edges.
360 * These specified to 8th pel as they are always compared to values that are in 1/8th pel units
361 * Apply any context driven MB level adjustment
363 filter_level = vp8_adjust_mb_lf_value(mbd, filter_level);
365 if (filter_level)
367 if (mb_col > 0)
368 cm->lf_mbv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
370 if (mbd->mode_info_context->mbmi.dc_diff > 0)
371 cm->lf_bv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
373 /* don't apply across umv border */
374 if (mb_row > 0)
375 cm->lf_mbh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
377 if (mbd->mode_info_context->mbmi.dc_diff > 0)
378 cm->lf_bh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
381 y_ptr += 16;
382 u_ptr += 8;
383 v_ptr += 8;
385 mbd->mode_info_context++; /* step to next MB */
388 y_ptr += post->y_stride * 16 - post->y_width;
389 u_ptr += post->uv_stride * 8 - post->uv_width;
390 v_ptr += post->uv_stride * 8 - post->uv_width;
392 mbd->mode_info_context++; /* Skip border mb */
397 void vp8_loop_filter_frame_yonly
399 VP8_COMMON *cm,
400 MACROBLOCKD *mbd,
401 int default_filt_lvl,
402 int sharpness_lvl
405 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
407 int i;
408 unsigned char *y_ptr;
409 int mb_row;
410 int mb_col;
412 loop_filter_info *lfi = cm->lf_info;
413 int baseline_filter_level[MAX_MB_SEGMENTS];
414 int filter_level;
415 int alt_flt_enabled = mbd->segmentation_enabled;
416 FRAME_TYPE frame_type = cm->frame_type;
418 (void) sharpness_lvl;
420 /*MODE_INFO * this_mb_mode_info = cm->mi;*/ /* Point at base of Mb MODE_INFO list */
421 mbd->mode_info_context = cm->mi; /* Point at base of Mb MODE_INFO list */
423 /* Note the baseline filter values for each segment */
424 if (alt_flt_enabled)
426 for (i = 0; i < MAX_MB_SEGMENTS; i++)
428 /* Abs value */
429 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
430 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
431 /* Delta Value */
432 else
434 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
435 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0; /* Clamp to valid range */
439 else
441 for (i = 0; i < MAX_MB_SEGMENTS; i++)
442 baseline_filter_level[i] = default_filt_lvl;
445 /* Initialize the loop filter for this frame. */
446 if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
447 vp8_init_loop_filter(cm);
448 else if (frame_type != cm->last_frame_type)
449 vp8_frame_init_loop_filter(lfi, frame_type);
451 /* Set up the buffer pointers */
452 y_ptr = post->y_buffer;
454 /* vp8_filter each macro block */
455 for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
457 for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
459 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
460 filter_level = baseline_filter_level[Segment];
462 /* Apply any context driven MB level adjustment */
463 filter_level = vp8_adjust_mb_lf_value(mbd, filter_level);
465 if (filter_level)
467 if (mb_col > 0)
468 cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
470 if (mbd->mode_info_context->mbmi.dc_diff > 0)
471 cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
473 /* don't apply across umv border */
474 if (mb_row > 0)
475 cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
477 if (mbd->mode_info_context->mbmi.dc_diff > 0)
478 cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
481 y_ptr += 16;
482 mbd->mode_info_context ++; /* step to next MB */
486 y_ptr += post->y_stride * 16 - post->y_width;
487 mbd->mode_info_context ++; /* Skip border mb */
493 void vp8_loop_filter_partial_frame
495 VP8_COMMON *cm,
496 MACROBLOCKD *mbd,
497 int default_filt_lvl,
498 int sharpness_lvl,
499 int Fraction
502 YV12_BUFFER_CONFIG *post = cm->frame_to_show;
504 int i;
505 unsigned char *y_ptr;
506 int mb_row;
507 int mb_col;
508 /*int mb_rows = post->y_height >> 4;*/
509 int mb_cols = post->y_width >> 4;
511 int linestocopy;
513 loop_filter_info *lfi = cm->lf_info;
514 int baseline_filter_level[MAX_MB_SEGMENTS];
515 int filter_level;
516 int alt_flt_enabled = mbd->segmentation_enabled;
517 FRAME_TYPE frame_type = cm->frame_type;
519 (void) sharpness_lvl;
521 /*MODE_INFO * this_mb_mode_info = cm->mi + (post->y_height>>5) * (mb_cols + 1);*/ /* Point at base of Mb MODE_INFO list */
522 mbd->mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1); /* Point at base of Mb MODE_INFO list */
524 linestocopy = (post->y_height >> (4 + Fraction));
526 if (linestocopy < 1)
527 linestocopy = 1;
529 linestocopy <<= 4;
531 /* Note the baseline filter values for each segment */
532 if (alt_flt_enabled)
534 for (i = 0; i < MAX_MB_SEGMENTS; i++)
536 /* Abs value */
537 if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
538 baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
539 /* Delta Value */
540 else
542 baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
543 baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0; /* Clamp to valid range */
547 else
549 for (i = 0; i < MAX_MB_SEGMENTS; i++)
550 baseline_filter_level[i] = default_filt_lvl;
553 /* Initialize the loop filter for this frame. */
554 if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
555 vp8_init_loop_filter(cm);
556 else if (frame_type != cm->last_frame_type)
557 vp8_frame_init_loop_filter(lfi, frame_type);
559 /* Set up the buffer pointers */
560 y_ptr = post->y_buffer + (post->y_height >> 5) * 16 * post->y_stride;
562 /* vp8_filter each macro block */
563 for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
565 for (mb_col = 0; mb_col < mb_cols; mb_col++)
567 int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
568 filter_level = baseline_filter_level[Segment];
570 if (filter_level)
572 if (mb_col > 0)
573 cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
575 if (mbd->mode_info_context->mbmi.dc_diff > 0)
576 cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
578 cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
580 if (mbd->mode_info_context->mbmi.dc_diff > 0)
581 cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
584 y_ptr += 16;
585 mbd->mode_info_context += 1; /* step to next MB */
588 y_ptr += post->y_stride * 16 - post->y_width;
589 mbd->mode_info_context += 1; /* Skip border mb */