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_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
)
31 vp8_mbloop_filter_horizontal_edge_c(y_ptr
, y_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->mbthr
, 2);
34 vp8_mbloop_filter_horizontal_edge_c(u_ptr
, uv_stride
, lfi
->uvmbflim
, lfi
->uvlim
, lfi
->uvmbthr
, 1);
37 vp8_mbloop_filter_horizontal_edge_c(v_ptr
, uv_stride
, lfi
->uvmbflim
, lfi
->uvlim
, lfi
->uvmbthr
, 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
)
47 vp8_loop_filter_simple_horizontal_edge_c(y_ptr
, y_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->mbthr
, 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
)
55 vp8_mbloop_filter_vertical_edge_c(y_ptr
, y_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->mbthr
, 2);
58 vp8_mbloop_filter_vertical_edge_c(u_ptr
, uv_stride
, lfi
->uvmbflim
, lfi
->uvlim
, lfi
->uvmbthr
, 1);
61 vp8_mbloop_filter_vertical_edge_c(v_ptr
, uv_stride
, lfi
->uvmbflim
, lfi
->uvlim
, lfi
->uvmbthr
, 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
)
71 vp8_loop_filter_simple_vertical_edge_c(y_ptr
, y_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->mbthr
, 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
)
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);
84 vp8_loop_filter_horizontal_edge_c(u_ptr
+ 4 * uv_stride
, uv_stride
, lfi
->uvflim
, lfi
->uvlim
, lfi
->uvthr
, 1);
87 vp8_loop_filter_horizontal_edge_c(v_ptr
+ 4 * uv_stride
, uv_stride
, lfi
->uvflim
, lfi
->uvlim
, lfi
->uvthr
, 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
)
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
)
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);
112 vp8_loop_filter_vertical_edge_c(u_ptr
+ 4, uv_stride
, lfi
->uvflim
, lfi
->uvlim
, lfi
->uvthr
, 1);
115 vp8_loop_filter_vertical_edge_c(v_ptr
+ 4, uv_stride
, lfi
->uvflim
, lfi
->uvlim
, lfi
->uvthr
, 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
)
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
;
138 int block_inside_limit
= 0;
140 const int yhedge_boost
= 2;
141 const int uvhedge_boost
= 2;
143 /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
144 for (i
= 0; i
<= MAX_LOOP_FILTER
; i
++)
148 if (frame_type
== KEY_FRAME
)
152 else if (filt_lvl
>= 15)
161 else if (filt_lvl
>= 20)
163 else if (filt_lvl
>= 15)
169 /* Set loop filter paramaeters that control sharpness. */
170 block_inside_limit
= filt_lvl
>> (sharpness_lvl
> 0);
171 block_inside_limit
= block_inside_limit
>> (sharpness_lvl
> 4);
173 if (sharpness_lvl
> 0)
175 if (block_inside_limit
> (9 - sharpness_lvl
))
176 block_inside_limit
= (9 - sharpness_lvl
);
179 if (block_inside_limit
< 1)
180 block_inside_limit
= 1;
182 for (j
= 0; j
< 16; j
++)
184 lfi
[i
].lim
[j
] = block_inside_limit
;
185 lfi
[i
].mbflim
[j
] = filt_lvl
+ yhedge_boost
;
186 lfi
[i
].mbthr
[j
] = HEVThresh
;
187 lfi
[i
].flim
[j
] = filt_lvl
;
188 lfi
[i
].thr
[j
] = HEVThresh
;
189 lfi
[i
].uvlim
[j
] = block_inside_limit
;
190 lfi
[i
].uvmbflim
[j
] = filt_lvl
+ uvhedge_boost
;
191 lfi
[i
].uvmbthr
[j
] = HEVThresh
;
192 lfi
[i
].uvflim
[j
] = filt_lvl
;
193 lfi
[i
].uvthr
[j
] = HEVThresh
;
198 /* Set up the function pointers depending on the type of loop filtering selected */
199 if (lft
== NORMAL_LOOPFILTER
)
201 cm
->lf_mbv
= LF_INVOKE(&cm
->rtcd
.loopfilter
, normal_mb_v
);
202 cm
->lf_bv
= LF_INVOKE(&cm
->rtcd
.loopfilter
, normal_b_v
);
203 cm
->lf_mbh
= LF_INVOKE(&cm
->rtcd
.loopfilter
, normal_mb_h
);
204 cm
->lf_bh
= LF_INVOKE(&cm
->rtcd
.loopfilter
, normal_b_h
);
208 cm
->lf_mbv
= LF_INVOKE(&cm
->rtcd
.loopfilter
, simple_mb_v
);
209 cm
->lf_bv
= LF_INVOKE(&cm
->rtcd
.loopfilter
, simple_b_v
);
210 cm
->lf_mbh
= LF_INVOKE(&cm
->rtcd
.loopfilter
, simple_mb_h
);
211 cm
->lf_bh
= LF_INVOKE(&cm
->rtcd
.loopfilter
, simple_b_h
);
215 /* Put vp8_init_loop_filter() in vp8dx_create_decompressor(). Only call vp8_frame_init_loop_filter() while decoding
216 * each frame. Check last_frame_type to skip the function most of times.
218 void vp8_frame_init_loop_filter(loop_filter_info
*lfi
, int frame_type
)
223 /* For each possible value for the loop filter fill out a "loop_filter_info" entry. */
224 for (i
= 0; i
<= MAX_LOOP_FILTER
; i
++)
228 if (frame_type
== KEY_FRAME
)
232 else if (filt_lvl
>= 15)
241 else if (filt_lvl
>= 20)
243 else if (filt_lvl
>= 15)
249 for (j
= 0; j
< 16; j
++)
251 /*lfi[i].lim[j] = block_inside_limit;
252 lfi[i].mbflim[j] = filt_lvl+yhedge_boost;*/
253 lfi
[i
].mbthr
[j
] = HEVThresh
;
254 /*lfi[i].flim[j] = filt_lvl;*/
255 lfi
[i
].thr
[j
] = HEVThresh
;
256 /*lfi[i].uvlim[j] = block_inside_limit;
257 lfi[i].uvmbflim[j] = filt_lvl+uvhedge_boost;*/
258 lfi
[i
].uvmbthr
[j
] = HEVThresh
;
259 /*lfi[i].uvflim[j] = filt_lvl;*/
260 lfi
[i
].uvthr
[j
] = HEVThresh
;
266 void vp8_adjust_mb_lf_value(MACROBLOCKD
*mbd
, int *filter_level
)
268 MB_MODE_INFO
*mbmi
= &mbd
->mode_info_context
->mbmi
;
270 if (mbd
->mode_ref_lf_delta_enabled
)
272 /* Apply delta for reference frame */
273 *filter_level
+= mbd
->ref_lf_deltas
[mbmi
->ref_frame
];
275 /* Apply delta for mode */
276 if (mbmi
->ref_frame
== INTRA_FRAME
)
278 /* Only the split mode BPRED has a further special case */
279 if (mbmi
->mode
== B_PRED
)
280 *filter_level
+= mbd
->mode_lf_deltas
[0];
284 /* Zero motion mode */
285 if (mbmi
->mode
== ZEROMV
)
286 *filter_level
+= mbd
->mode_lf_deltas
[1];
288 /* Split MB motion mode */
289 else if (mbmi
->mode
== SPLITMV
)
290 *filter_level
+= mbd
->mode_lf_deltas
[3];
292 /* All other inter motion modes (Nearest, Near, New) */
294 *filter_level
+= mbd
->mode_lf_deltas
[2];
298 if (*filter_level
> MAX_LOOP_FILTER
)
299 *filter_level
= MAX_LOOP_FILTER
;
300 else if (*filter_level
< 0)
306 void vp8_loop_filter_frame
313 YV12_BUFFER_CONFIG
*post
= cm
->frame_to_show
;
314 loop_filter_info
*lfi
= cm
->lf_info
;
315 FRAME_TYPE frame_type
= cm
->frame_type
;
321 int baseline_filter_level
[MAX_MB_SEGMENTS
];
323 int alt_flt_enabled
= mbd
->segmentation_enabled
;
326 unsigned char *y_ptr
, *u_ptr
, *v_ptr
;
328 mbd
->mode_info_context
= cm
->mi
; /* Point at base of Mb MODE_INFO list */
330 /* Note the baseline filter values for each segment */
333 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
336 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
337 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
341 baseline_filter_level
[i
] = default_filt_lvl
+ mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
342 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 */
348 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
349 baseline_filter_level
[i
] = default_filt_lvl
;
352 /* Initialize the loop filter for this frame. */
353 if ((cm
->last_filter_type
!= cm
->filter_type
) || (cm
->last_sharpness_level
!= cm
->sharpness_level
))
354 vp8_init_loop_filter(cm
);
355 else if (frame_type
!= cm
->last_frame_type
)
356 vp8_frame_init_loop_filter(lfi
, frame_type
);
358 /* Set up the buffer pointers */
359 y_ptr
= post
->y_buffer
;
360 u_ptr
= post
->u_buffer
;
361 v_ptr
= post
->v_buffer
;
363 /* vp8_filter each macro block */
364 for (mb_row
= 0; mb_row
< cm
->mb_rows
; mb_row
++)
366 for (mb_col
= 0; mb_col
< cm
->mb_cols
; mb_col
++)
368 int Segment
= (alt_flt_enabled
) ? mbd
->mode_info_context
->mbmi
.segment_id
: 0;
370 filter_level
= baseline_filter_level
[Segment
];
372 /* Distance of Mb to the various image edges.
373 * These specified to 8th pel as they are always compared to values that are in 1/8th pel units
374 * Apply any context driven MB level adjustment
376 vp8_adjust_mb_lf_value(mbd
, &filter_level
);
381 cm
->lf_mbv(y_ptr
, u_ptr
, v_ptr
, post
->y_stride
, post
->uv_stride
, &lfi
[filter_level
], cm
->simpler_lpf
);
383 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
384 cm
->lf_bv(y_ptr
, u_ptr
, v_ptr
, post
->y_stride
, post
->uv_stride
, &lfi
[filter_level
], cm
->simpler_lpf
);
386 /* don't apply across umv border */
388 cm
->lf_mbh(y_ptr
, u_ptr
, v_ptr
, post
->y_stride
, post
->uv_stride
, &lfi
[filter_level
], cm
->simpler_lpf
);
390 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
391 cm
->lf_bh(y_ptr
, u_ptr
, v_ptr
, post
->y_stride
, post
->uv_stride
, &lfi
[filter_level
], cm
->simpler_lpf
);
398 mbd
->mode_info_context
++; /* step to next MB */
401 y_ptr
+= post
->y_stride
* 16 - post
->y_width
;
402 u_ptr
+= post
->uv_stride
* 8 - post
->uv_width
;
403 v_ptr
+= post
->uv_stride
* 8 - post
->uv_width
;
405 mbd
->mode_info_context
++; /* Skip border mb */
410 void vp8_loop_filter_frame_yonly
414 int default_filt_lvl
,
418 YV12_BUFFER_CONFIG
*post
= cm
->frame_to_show
;
421 unsigned char *y_ptr
;
425 loop_filter_info
*lfi
= cm
->lf_info
;
426 int baseline_filter_level
[MAX_MB_SEGMENTS
];
428 int alt_flt_enabled
= mbd
->segmentation_enabled
;
429 FRAME_TYPE frame_type
= cm
->frame_type
;
431 (void) sharpness_lvl
;
433 /*MODE_INFO * this_mb_mode_info = cm->mi;*/ /* Point at base of Mb MODE_INFO list */
434 mbd
->mode_info_context
= cm
->mi
; /* Point at base of Mb MODE_INFO list */
436 /* Note the baseline filter values for each segment */
439 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
442 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
443 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
447 baseline_filter_level
[i
] = default_filt_lvl
+ mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
448 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 */
454 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
455 baseline_filter_level
[i
] = default_filt_lvl
;
458 /* Initialize the loop filter for this frame. */
459 if ((cm
->last_filter_type
!= cm
->filter_type
) || (cm
->last_sharpness_level
!= cm
->sharpness_level
))
460 vp8_init_loop_filter(cm
);
461 else if (frame_type
!= cm
->last_frame_type
)
462 vp8_frame_init_loop_filter(lfi
, frame_type
);
464 /* Set up the buffer pointers */
465 y_ptr
= post
->y_buffer
;
467 /* vp8_filter each macro block */
468 for (mb_row
= 0; mb_row
< cm
->mb_rows
; mb_row
++)
470 for (mb_col
= 0; mb_col
< cm
->mb_cols
; mb_col
++)
472 int Segment
= (alt_flt_enabled
) ? mbd
->mode_info_context
->mbmi
.segment_id
: 0;
473 filter_level
= baseline_filter_level
[Segment
];
475 /* Apply any context driven MB level adjustment */
476 vp8_adjust_mb_lf_value(mbd
, &filter_level
);
481 cm
->lf_mbv(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
483 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
484 cm
->lf_bv(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
486 /* don't apply across umv border */
488 cm
->lf_mbh(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
490 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
491 cm
->lf_bh(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
495 mbd
->mode_info_context
++; /* step to next MB */
499 y_ptr
+= post
->y_stride
* 16 - post
->y_width
;
500 mbd
->mode_info_context
++; /* Skip border mb */
506 void vp8_loop_filter_partial_frame
510 int default_filt_lvl
,
515 YV12_BUFFER_CONFIG
*post
= cm
->frame_to_show
;
518 unsigned char *y_ptr
;
521 /*int mb_rows = post->y_height >> 4;*/
522 int mb_cols
= post
->y_width
>> 4;
526 loop_filter_info
*lfi
= cm
->lf_info
;
527 int baseline_filter_level
[MAX_MB_SEGMENTS
];
529 int alt_flt_enabled
= mbd
->segmentation_enabled
;
530 FRAME_TYPE frame_type
= cm
->frame_type
;
532 (void) sharpness_lvl
;
534 /*MODE_INFO * this_mb_mode_info = cm->mi + (post->y_height>>5) * (mb_cols + 1);*/ /* Point at base of Mb MODE_INFO list */
535 mbd
->mode_info_context
= cm
->mi
+ (post
->y_height
>> 5) * (mb_cols
+ 1); /* Point at base of Mb MODE_INFO list */
537 linestocopy
= (post
->y_height
>> (4 + Fraction
));
544 /* Note the baseline filter values for each segment */
547 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
550 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
551 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
555 baseline_filter_level
[i
] = default_filt_lvl
+ mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
556 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 */
562 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
563 baseline_filter_level
[i
] = default_filt_lvl
;
566 /* Initialize the loop filter for this frame. */
567 if ((cm
->last_filter_type
!= cm
->filter_type
) || (cm
->last_sharpness_level
!= cm
->sharpness_level
))
568 vp8_init_loop_filter(cm
);
569 else if (frame_type
!= cm
->last_frame_type
)
570 vp8_frame_init_loop_filter(lfi
, frame_type
);
572 /* Set up the buffer pointers */
573 y_ptr
= post
->y_buffer
+ (post
->y_height
>> 5) * 16 * post
->y_stride
;
575 /* vp8_filter each macro block */
576 for (mb_row
= 0; mb_row
<(linestocopy
>> 4); mb_row
++)
578 for (mb_col
= 0; mb_col
< mb_cols
; mb_col
++)
580 int Segment
= (alt_flt_enabled
) ? mbd
->mode_info_context
->mbmi
.segment_id
: 0;
581 filter_level
= baseline_filter_level
[Segment
];
586 cm
->lf_mbv(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
588 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
589 cm
->lf_bv(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
591 cm
->lf_mbh(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
593 if (mbd
->mode_info_context
->mbmi
.dc_diff
> 0)
594 cm
->lf_bh(y_ptr
, 0, 0, post
->y_stride
, 0, &lfi
[filter_level
], 0);
598 mbd
->mode_info_context
+= 1; /* step to next MB */
601 y_ptr
+= post
->y_stride
* 16 - post
->y_width
;
602 mbd
->mode_info_context
+= 1; /* Skip border mb */