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_ports/config.h"
13 #include <math.h>
14 #include "subpixel.h"
15 #include "vpx_ports/mem.h"
16
17 #define BLOCK_HEIGHT_WIDTH 4
18 #define VP8_FILTER_WEIGHT 128
19 #define VP8_FILTER_SHIFT 7
20
21 DECLARE_ALIGNED(16, static const short, sub_pel_filters[8][6]) =
22 {
23 { 0, 0, 128, 0, 0, 0 }, /* note that 1/8 pel positions are just as per alpha -0.5 bicubic */
24 { 0, -6, 123, 12, -1, 0 },
25 { 2, -11, 108, 36, -8, 1 }, /* New 1/4 pel 6 tap filter */
26 { 0, -9, 93, 50, -6, 0 },
27 { 3, -16, 77, 77, -16, 3 }, /* New 1/2 pel 6 tap filter */
28 { 0, -6, 50, 93, -9, 0 },
29 { 1, -8, 36, 108, -11, 2 }, /* New 1/4 pel 6 tap filter */
30 { 0, -1, 12, 123, -6, 0 },
31 };
32
33
34 extern void vp8_filter_block2d_first_pass_armv6
35 (
36 unsigned char *src_ptr,
37 short *output_ptr,
38 unsigned int src_pixels_per_line,
39 unsigned int output_width,
40 unsigned int output_height,
41 const short *vp8_filter
42 );
43
44 extern void vp8_filter_block2d_second_pass_armv6
45 (
46 short *src_ptr,
47 unsigned char *output_ptr,
48 unsigned int output_pitch,
49 unsigned int cnt,
50 const short *vp8_filter
51 );
52
53 extern void vp8_filter4_block2d_second_pass_armv6
54 (
55 short *src_ptr,
56 unsigned char *output_ptr,
57 unsigned int output_pitch,
58 unsigned int cnt,
59 const short *vp8_filter
60 );
61
62 extern void vp8_filter_block2d_first_pass_only_armv6
63 (
64 unsigned char *src_ptr,
65 unsigned char *output_ptr,
66 unsigned int src_pixels_per_line,
67 unsigned int cnt,
68 unsigned int output_pitch,
69 const short *vp8_filter
70 );
71
72
73 extern void vp8_filter_block2d_second_pass_only_armv6
74 (
75 unsigned char *src_ptr,
76 unsigned char *output_ptr,
77 unsigned int src_pixels_per_line,
78 unsigned int cnt,
79 unsigned int output_pitch,
80 const short *vp8_filter
81 );
82
83 #if HAVE_ARMV6
vp8_sixtap_predict_armv6(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)84 void vp8_sixtap_predict_armv6
85 (
86 unsigned char *src_ptr,
87 int src_pixels_per_line,
88 int xoffset,
89 int yoffset,
90 unsigned char *dst_ptr,
91 int dst_pitch
92 )
93 {
94 const short *HFilter;
95 const short *VFilter;
96 DECLARE_ALIGNED_ARRAY(4, short, FData, 12*4); /* Temp data bufffer used in filtering */
97
98
99 HFilter = sub_pel_filters[xoffset]; /* 6 tap */
100 VFilter = sub_pel_filters[yoffset]; /* 6 tap */
101
102 /* Vfilter is null. First pass only */
103 if (xoffset && !yoffset)
104 {
105 /*vp8_filter_block2d_first_pass_armv6 ( src_ptr, FData+2, src_pixels_per_line, 4, 4, HFilter );
106 vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, VFilter );*/
107
108 vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, HFilter);
109 }
110 /* Hfilter is null. Second pass only */
111 else if (!xoffset && yoffset)
112 {
113 vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, VFilter);
114 }
115 else
116 {
117 /* Vfilter is a 4 tap filter */
118 if (yoffset & 0x1)
119 {
120 vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 4, 7, HFilter);
121 vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
122 }
123 /* Vfilter is 6 tap filter */
124 else
125 {
126 vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 4, 9, HFilter);
127 vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
128 }
129 }
130 }
131
132 #if 0
133 void vp8_sixtap_predict8x4_armv6
134 (
135 unsigned char *src_ptr,
136 int src_pixels_per_line,
137 int xoffset,
138 int yoffset,
139 unsigned char *dst_ptr,
140 int dst_pitch
141 )
142 {
143 const short *HFilter;
144 const short *VFilter;
145 DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); /* Temp data bufffer used in filtering */
146
147 HFilter = sub_pel_filters[xoffset]; /* 6 tap */
148 VFilter = sub_pel_filters[yoffset]; /* 6 tap */
149
150
151 /*if (xoffset && !yoffset)
152 {
153 vp8_filter_block2d_first_pass_only_armv6 ( src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter );
154 }*/
155 /* Hfilter is null. Second pass only */
156 /*else if (!xoffset && yoffset)
157 {
158 vp8_filter_block2d_second_pass_only_armv6 ( src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter );
159 }
160 else
161 {
162 if (yoffset & 0x1)
163 vp8_filter_block2d_first_pass_armv6 ( src_ptr-src_pixels_per_line, FData+1, src_pixels_per_line, 8, 7, HFilter );
164 else*/
165
166 vp8_filter_block2d_first_pass_armv6 ( src_ptr-(2*src_pixels_per_line), FData, src_pixels_per_line, 8, 9, HFilter );
167
168 vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, 8, VFilter );
169 /*}*/
170 }
171 #endif
172
vp8_sixtap_predict8x8_armv6(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)173 void vp8_sixtap_predict8x8_armv6
174 (
175 unsigned char *src_ptr,
176 int src_pixels_per_line,
177 int xoffset,
178 int yoffset,
179 unsigned char *dst_ptr,
180 int dst_pitch
181 )
182 {
183 const short *HFilter;
184 const short *VFilter;
185 DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); /* Temp data bufffer used in filtering */
186
187 HFilter = sub_pel_filters[xoffset]; /* 6 tap */
188 VFilter = sub_pel_filters[yoffset]; /* 6 tap */
189
190 if (xoffset && !yoffset)
191 {
192 vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter);
193 }
194 /* Hfilter is null. Second pass only */
195 else if (!xoffset && yoffset)
196 {
197 vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter);
198 }
199 else
200 {
201 if (yoffset & 0x1)
202 {
203 vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
204 vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
205 }
206 else
207 {
208 vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
209 vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
210 }
211 }
212 }
213
214
vp8_sixtap_predict16x16_armv6(unsigned char * src_ptr,int src_pixels_per_line,int xoffset,int yoffset,unsigned char * dst_ptr,int dst_pitch)215 void vp8_sixtap_predict16x16_armv6
216 (
217 unsigned char *src_ptr,
218 int src_pixels_per_line,
219 int xoffset,
220 int yoffset,
221 unsigned char *dst_ptr,
222 int dst_pitch
223 )
224 {
225 const short *HFilter;
226 const short *VFilter;
227 DECLARE_ALIGNED_ARRAY(4, short, FData, 24*16); /* Temp data bufffer used in filtering */
228
229 HFilter = sub_pel_filters[xoffset]; /* 6 tap */
230 VFilter = sub_pel_filters[yoffset]; /* 6 tap */
231
232 if (xoffset && !yoffset)
233 {
234 vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, HFilter);
235 }
236 /* Hfilter is null. Second pass only */
237 else if (!xoffset && yoffset)
238 {
239 vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, VFilter);
240 }
241 else
242 {
243 if (yoffset & 0x1)
244 {
245 vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
246 vp8_filter4_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
247 }
248 else
249 {
250 vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
251 vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
252 }
253 }
254
255 }
256 #endif
257