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
->thr
, 2);
34 vp8_mbloop_filter_horizontal_edge_c(u_ptr
, uv_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->thr
, 1);
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
)
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
)
55 vp8_mbloop_filter_vertical_edge_c(y_ptr
, y_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->thr
, 2);
58 vp8_mbloop_filter_vertical_edge_c(u_ptr
, uv_stride
, lfi
->mbflim
, lfi
->lim
, lfi
->thr
, 1);
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
)
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
)
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
->flim
, lfi
->lim
, lfi
->thr
, 1);
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
)
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
->flim
, lfi
->lim
, lfi
->thr
, 1);
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
)
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;
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
++)
146 if (frame_type
== KEY_FRAME
)
150 else if (filt_lvl
>= 15)
159 else if (filt_lvl
>= 20)
161 else if (filt_lvl
>= 15)
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
);
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
)
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
++)
220 if (frame_type
== KEY_FRAME
)
224 else if (filt_lvl
>= 15)
233 else if (filt_lvl
>= 20)
235 else if (filt_lvl
>= 15)
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];
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) */
280 filter_level
+= mbd
->mode_lf_deltas
[2];
284 if (filter_level
> MAX_LOOP_FILTER
)
285 filter_level
= MAX_LOOP_FILTER
;
286 else if (filter_level
< 0)
293 void vp8_loop_filter_frame
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
;
308 int baseline_filter_level
[MAX_MB_SEGMENTS
];
310 int alt_flt_enabled
= mbd
->segmentation_enabled
;
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 */
320 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
323 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
324 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
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 */
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
);
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 */
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
);
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
401 int default_filt_lvl
,
405 YV12_BUFFER_CONFIG
*post
= cm
->frame_to_show
;
408 unsigned char *y_ptr
;
412 loop_filter_info
*lfi
= cm
->lf_info
;
413 int baseline_filter_level
[MAX_MB_SEGMENTS
];
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 */
426 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
429 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
430 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
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 */
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
);
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 */
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);
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
497 int default_filt_lvl
,
502 YV12_BUFFER_CONFIG
*post
= cm
->frame_to_show
;
505 unsigned char *y_ptr
;
508 /*int mb_rows = post->y_height >> 4;*/
509 int mb_cols
= post
->y_width
>> 4;
513 loop_filter_info
*lfi
= cm
->lf_info
;
514 int baseline_filter_level
[MAX_MB_SEGMENTS
];
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
));
531 /* Note the baseline filter values for each segment */
534 for (i
= 0; i
< MAX_MB_SEGMENTS
; i
++)
537 if (mbd
->mb_segement_abs_delta
== SEGMENT_ABSDATA
)
538 baseline_filter_level
[i
] = mbd
->segment_feature_data
[MB_LVL_ALT_LF
][i
];
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 */
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
];
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);
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 */