1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
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 */
10
11
12#include "vpx_config.h"
13#include "vp8_rtcd.h"
14#include "vp8/common/loopfilter.h"
15#include "vp8/common/onyxc_int.h"
16
17#define prototype_loopfilter(sym) \
18    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
19             const unsigned char *limit, const unsigned char *thresh, int count)
20
21#if HAVE_MEDIA
22extern prototype_loopfilter(vp8_loop_filter_horizontal_edge_armv6);
23extern prototype_loopfilter(vp8_loop_filter_vertical_edge_armv6);
24extern prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_armv6);
25extern prototype_loopfilter(vp8_mbloop_filter_vertical_edge_armv6);
26#endif
27
28#if HAVE_NEON_ASM || HAVE_NEON
29typedef void loopfilter_y_neon(unsigned char *src, int pitch,
30        unsigned char blimit, unsigned char limit, unsigned char thresh);
31typedef void loopfilter_uv_neon(unsigned char *u, int pitch,
32        unsigned char blimit, unsigned char limit, unsigned char thresh,
33        unsigned char *v);
34#endif
35
36#if HAVE_NEON_ASM
37extern loopfilter_y_neon vp8_loop_filter_horizontal_edge_y_neon;
38extern loopfilter_y_neon vp8_loop_filter_vertical_edge_y_neon;
39extern loopfilter_uv_neon vp8_loop_filter_horizontal_edge_uv_neon;
40extern loopfilter_uv_neon vp8_loop_filter_vertical_edge_uv_neon;
41#endif
42
43#if HAVE_NEON
44extern loopfilter_y_neon vp8_mbloop_filter_horizontal_edge_y_neon;
45extern loopfilter_y_neon vp8_mbloop_filter_vertical_edge_y_neon;
46extern loopfilter_uv_neon vp8_mbloop_filter_horizontal_edge_uv_neon;
47extern loopfilter_uv_neon vp8_mbloop_filter_vertical_edge_uv_neon;
48#endif
49
50#if HAVE_MEDIA
51/* ARMV6/MEDIA loopfilter functions*/
52/* Horizontal MB filtering */
53void vp8_loop_filter_mbh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
54                               int y_stride, int uv_stride, loop_filter_info *lfi)
55{
56    vp8_mbloop_filter_horizontal_edge_armv6(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
57
58    if (u_ptr)
59        vp8_mbloop_filter_horizontal_edge_armv6(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
60
61    if (v_ptr)
62        vp8_mbloop_filter_horizontal_edge_armv6(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
63}
64
65/* Vertical MB Filtering */
66void vp8_loop_filter_mbv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
67                               int y_stride, int uv_stride, loop_filter_info *lfi)
68{
69    vp8_mbloop_filter_vertical_edge_armv6(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
70
71    if (u_ptr)
72        vp8_mbloop_filter_vertical_edge_armv6(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
73
74    if (v_ptr)
75        vp8_mbloop_filter_vertical_edge_armv6(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
76}
77
78/* Horizontal B Filtering */
79void vp8_loop_filter_bh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
80                              int y_stride, int uv_stride, loop_filter_info *lfi)
81{
82    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
83    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
84    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
85
86    if (u_ptr)
87        vp8_loop_filter_horizontal_edge_armv6(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
88
89    if (v_ptr)
90        vp8_loop_filter_horizontal_edge_armv6(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
91}
92
93void vp8_loop_filter_bhs_armv6(unsigned char *y_ptr, int y_stride,
94                               const unsigned char *blimit)
95{
96    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, blimit);
97    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, blimit);
98    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, blimit);
99}
100
101/* Vertical B Filtering */
102void vp8_loop_filter_bv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
103                              int y_stride, int uv_stride, loop_filter_info *lfi)
104{
105    vp8_loop_filter_vertical_edge_armv6(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
106    vp8_loop_filter_vertical_edge_armv6(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
107    vp8_loop_filter_vertical_edge_armv6(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
108
109    if (u_ptr)
110        vp8_loop_filter_vertical_edge_armv6(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
111
112    if (v_ptr)
113        vp8_loop_filter_vertical_edge_armv6(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
114}
115
116void vp8_loop_filter_bvs_armv6(unsigned char *y_ptr, int y_stride,
117                               const unsigned char *blimit)
118{
119    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 4, y_stride, blimit);
120    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 8, y_stride, blimit);
121    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 12, y_stride, blimit);
122}
123#endif
124
125#if HAVE_NEON
126/* NEON loopfilter functions */
127/* Horizontal MB filtering */
128void vp8_loop_filter_mbh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
129                              int y_stride, int uv_stride, loop_filter_info *lfi)
130{
131    unsigned char mblim = *lfi->mblim;
132    unsigned char lim = *lfi->lim;
133    unsigned char hev_thr = *lfi->hev_thr;
134    vp8_mbloop_filter_horizontal_edge_y_neon(y_ptr, y_stride, mblim, lim, hev_thr);
135
136    if (u_ptr)
137        vp8_mbloop_filter_horizontal_edge_uv_neon(u_ptr, uv_stride, mblim, lim, hev_thr, v_ptr);
138}
139
140/* Vertical MB Filtering */
141void vp8_loop_filter_mbv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
142                              int y_stride, int uv_stride, loop_filter_info *lfi)
143{
144    unsigned char mblim = *lfi->mblim;
145    unsigned char lim = *lfi->lim;
146    unsigned char hev_thr = *lfi->hev_thr;
147
148    vp8_mbloop_filter_vertical_edge_y_neon(y_ptr, y_stride, mblim, lim, hev_thr);
149
150    if (u_ptr)
151        vp8_mbloop_filter_vertical_edge_uv_neon(u_ptr, uv_stride, mblim, lim, hev_thr, v_ptr);
152}
153#endif
154
155#if HAVE_NEON_ASM
156/* Horizontal B Filtering */
157void vp8_loop_filter_bh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
158                             int y_stride, int uv_stride, loop_filter_info *lfi)
159{
160    unsigned char blim = *lfi->blim;
161    unsigned char lim = *lfi->lim;
162    unsigned char hev_thr = *lfi->hev_thr;
163
164    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 4 * y_stride, y_stride, blim, lim, hev_thr);
165    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 8 * y_stride, y_stride, blim, lim, hev_thr);
166    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 12 * y_stride, y_stride, blim, lim, hev_thr);
167
168    if (u_ptr)
169        vp8_loop_filter_horizontal_edge_uv_neon(u_ptr + 4 * uv_stride, uv_stride, blim, lim, hev_thr, v_ptr + 4 * uv_stride);
170}
171
172/* Vertical B Filtering */
173void vp8_loop_filter_bv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
174                             int y_stride, int uv_stride, loop_filter_info *lfi)
175{
176    unsigned char blim = *lfi->blim;
177    unsigned char lim = *lfi->lim;
178    unsigned char hev_thr = *lfi->hev_thr;
179
180    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 4, y_stride, blim, lim, hev_thr);
181    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 8, y_stride, blim, lim, hev_thr);
182    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 12, y_stride, blim, lim, hev_thr);
183
184    if (u_ptr)
185        vp8_loop_filter_vertical_edge_uv_neon(u_ptr + 4, uv_stride, blim, lim, hev_thr, v_ptr + 4);
186}
187#endif
188