svq3: use hpeldsp instead of dsputil for half-pel functions.
[ffmpeg.git] / libavcodec / dsputil_template.c
1 /*
2  * DSP utils
3  * Copyright (c) 2000, 2001 Fabrice Bellard
4  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer <michaelni@gmx.at>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24
25 /**
26  * @file
27  * DSP utils
28  */
29
30 #include "bit_depth_template.c"
31
32 /* draw the edges of width 'w' of an image of size width, height */
33 //FIXME check that this is ok for mpeg4 interlaced
34 static void FUNCC(draw_edges)(uint8_t *p_buf, int p_wrap, int width, int height, int w, int h, int sides)
35 {
36     pixel *buf = (pixel*)p_buf;
37     int wrap = p_wrap / sizeof(pixel);
38     pixel *ptr, *last_line;
39     int i;
40
41     /* left and right */
42     ptr = buf;
43     for(i=0;i<height;i++) {
44 #if BIT_DEPTH > 8
45         int j;
46         for (j = 0; j < w; j++) {
47             ptr[j-w] = ptr[0];
48             ptr[j+width] = ptr[width-1];
49         }
50 #else
51         memset(ptr - w, ptr[0], w);
52         memset(ptr + width, ptr[width-1], w);
53 #endif
54         ptr += wrap;
55     }
56
57     /* top and bottom + corners */
58     buf -= w;
59     last_line = buf + (height - 1) * wrap;
60     if (sides & EDGE_TOP)
61         for(i = 0; i < h; i++)
62             memcpy(buf - (i + 1) * wrap, buf, (width + w + w) * sizeof(pixel)); // top
63     if (sides & EDGE_BOTTOM)
64         for (i = 0; i < h; i++)
65             memcpy(last_line + (i + 1) * wrap, last_line, (width + w + w) * sizeof(pixel)); // bottom
66 }
67
68 #define DCTELEM_FUNCS(dctcoef, suffix)                                  \
69 static void FUNCC(get_pixels ## suffix)(int16_t *av_restrict _block,    \
70                                         const uint8_t *_pixels,         \
71                                         int line_size)                  \
72 {                                                                       \
73     const pixel *pixels = (const pixel *) _pixels;                      \
74     dctcoef *av_restrict block = (dctcoef *) _block;                    \
75     int i;                                                              \
76                                                                         \
77     /* read the pixels */                                               \
78     for(i=0;i<8;i++) {                                                  \
79         block[0] = pixels[0];                                           \
80         block[1] = pixels[1];                                           \
81         block[2] = pixels[2];                                           \
82         block[3] = pixels[3];                                           \
83         block[4] = pixels[4];                                           \
84         block[5] = pixels[5];                                           \
85         block[6] = pixels[6];                                           \
86         block[7] = pixels[7];                                           \
87         pixels += line_size / sizeof(pixel);                            \
88         block += 8;                                                     \
89     }                                                                   \
90 }                                                                       \
91                                                                         \
92 static void FUNCC(clear_block ## suffix)(int16_t *block)                \
93 {                                                                       \
94     memset(block, 0, sizeof(dctcoef)*64);                               \
95 }                                                                       \
96                                                                         \
97 /**                                                                     \
98  * memset(blocks, 0, sizeof(int16_t)*6*64)                              \
99  */                                                                     \
100 static void FUNCC(clear_blocks ## suffix)(int16_t *blocks)              \
101 {                                                                       \
102     memset(blocks, 0, sizeof(dctcoef)*6*64);                            \
103 }
104
105 DCTELEM_FUNCS(int16_t, _16)
106 #if BIT_DEPTH > 8
107 DCTELEM_FUNCS(dctcoef, _32)
108 #endif
109
110 #if BIT_DEPTH == 8
111 #include "hpel_template.c"
112 #endif
113
114 #define PIXOP2(OPNAME, OP) \
115 static inline void FUNC(OPNAME ## _no_rnd_pixels8_l2)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, \
116                                                 int src_stride1, int src_stride2, int h){\
117     int i;\
118     for(i=0; i<h; i++){\
119         pixel4 a,b;\
120         a= AV_RN4P(&src1[i*src_stride1  ]);\
121         b= AV_RN4P(&src2[i*src_stride2  ]);\
122         OP(*((pixel4*)&dst[i*dst_stride  ]), no_rnd_avg_pixel4(a, b));\
123         a= AV_RN4P(&src1[i*src_stride1+4*sizeof(pixel)]);\
124         b= AV_RN4P(&src2[i*src_stride2+4*sizeof(pixel)]);\
125         OP(*((pixel4*)&dst[i*dst_stride+4*sizeof(pixel)]), no_rnd_avg_pixel4(a, b));\
126     }\
127 }\
128 \
129 static inline void FUNC(OPNAME ## _no_rnd_pixels16_l2)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, \
130                                                 int src_stride1, int src_stride2, int h){\
131     FUNC(OPNAME ## _no_rnd_pixels8_l2)(dst  , src1  , src2  , dst_stride, src_stride1, src_stride2, h);\
132     FUNC(OPNAME ## _no_rnd_pixels8_l2)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, h);\
133 }\
134 \
135 static inline void FUNCC(OPNAME ## _no_rnd_pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
136     FUNC(OPNAME ## _no_rnd_pixels8_l2)(block, pixels, pixels+sizeof(pixel), line_size, line_size, line_size, h);\
137 }\
138 \
139 static inline void FUNCC(OPNAME ## _pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
140     FUNC(OPNAME ## _pixels8_l2)(block, pixels, pixels+sizeof(pixel), line_size, line_size, line_size, h);\
141 }\
142 \
143 static inline void FUNCC(OPNAME ## _no_rnd_pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
144     FUNC(OPNAME ## _no_rnd_pixels8_l2)(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
145 }\
146 \
147 static inline void FUNCC(OPNAME ## _pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
148     FUNC(OPNAME ## _pixels8_l2)(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
149 }\
150 \
151 static inline void FUNC(OPNAME ## _pixels8_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\
152                  int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\
153     /* FIXME HIGH BIT DEPTH */\
154     int i;\
155     for(i=0; i<h; i++){\
156         uint32_t a, b, c, d, l0, l1, h0, h1;\
157         a= AV_RN32(&src1[i*src_stride1]);\
158         b= AV_RN32(&src2[i*src_stride2]);\
159         c= AV_RN32(&src3[i*src_stride3]);\
160         d= AV_RN32(&src4[i*src_stride4]);\
161         l0=  (a&0x03030303UL)\
162            + (b&0x03030303UL)\
163            + 0x02020202UL;\
164         h0= ((a&0xFCFCFCFCUL)>>2)\
165           + ((b&0xFCFCFCFCUL)>>2);\
166         l1=  (c&0x03030303UL)\
167            + (d&0x03030303UL);\
168         h1= ((c&0xFCFCFCFCUL)>>2)\
169           + ((d&0xFCFCFCFCUL)>>2);\
170         OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
171         a= AV_RN32(&src1[i*src_stride1+4]);\
172         b= AV_RN32(&src2[i*src_stride2+4]);\
173         c= AV_RN32(&src3[i*src_stride3+4]);\
174         d= AV_RN32(&src4[i*src_stride4+4]);\
175         l0=  (a&0x03030303UL)\
176            + (b&0x03030303UL)\
177            + 0x02020202UL;\
178         h0= ((a&0xFCFCFCFCUL)>>2)\
179           + ((b&0xFCFCFCFCUL)>>2);\
180         l1=  (c&0x03030303UL)\
181            + (d&0x03030303UL);\
182         h1= ((c&0xFCFCFCFCUL)>>2)\
183           + ((d&0xFCFCFCFCUL)>>2);\
184         OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
185     }\
186 }\
187 \
188 static inline void FUNCC(OPNAME ## _pixels4_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
189     FUNC(OPNAME ## _pixels4_l2)(block, pixels, pixels+sizeof(pixel), line_size, line_size, line_size, h);\
190 }\
191 \
192 static inline void FUNCC(OPNAME ## _pixels4_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
193     FUNC(OPNAME ## _pixels4_l2)(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
194 }\
195 \
196 static inline void FUNCC(OPNAME ## _pixels2_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
197     FUNC(OPNAME ## _pixels2_l2)(block, pixels, pixels+sizeof(pixel), line_size, line_size, line_size, h);\
198 }\
199 \
200 static inline void FUNCC(OPNAME ## _pixels2_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\
201     FUNC(OPNAME ## _pixels2_l2)(block, pixels, pixels+line_size, line_size, line_size, line_size, h);\
202 }\
203 \
204 static inline void FUNC(OPNAME ## _no_rnd_pixels8_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\
205                  int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\
206     /* FIXME HIGH BIT DEPTH*/\
207     int i;\
208     for(i=0; i<h; i++){\
209         uint32_t a, b, c, d, l0, l1, h0, h1;\
210         a= AV_RN32(&src1[i*src_stride1]);\
211         b= AV_RN32(&src2[i*src_stride2]);\
212         c= AV_RN32(&src3[i*src_stride3]);\
213         d= AV_RN32(&src4[i*src_stride4]);\
214         l0=  (a&0x03030303UL)\
215            + (b&0x03030303UL)\
216            + 0x01010101UL;\
217         h0= ((a&0xFCFCFCFCUL)>>2)\
218           + ((b&0xFCFCFCFCUL)>>2);\
219         l1=  (c&0x03030303UL)\
220            + (d&0x03030303UL);\
221         h1= ((c&0xFCFCFCFCUL)>>2)\
222           + ((d&0xFCFCFCFCUL)>>2);\
223         OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
224         a= AV_RN32(&src1[i*src_stride1+4]);\
225         b= AV_RN32(&src2[i*src_stride2+4]);\
226         c= AV_RN32(&src3[i*src_stride3+4]);\
227         d= AV_RN32(&src4[i*src_stride4+4]);\
228         l0=  (a&0x03030303UL)\
229            + (b&0x03030303UL)\
230            + 0x01010101UL;\
231         h0= ((a&0xFCFCFCFCUL)>>2)\
232           + ((b&0xFCFCFCFCUL)>>2);\
233         l1=  (c&0x03030303UL)\
234            + (d&0x03030303UL);\
235         h1= ((c&0xFCFCFCFCUL)>>2)\
236           + ((d&0xFCFCFCFCUL)>>2);\
237         OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
238     }\
239 }\
240 static inline void FUNC(OPNAME ## _pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\
241                  int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\
242     FUNC(OPNAME ## _pixels8_l4)(dst  , src1  , src2  , src3  , src4  , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
243     FUNC(OPNAME ## _pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
244 }\
245 static inline void FUNC(OPNAME ## _no_rnd_pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\
246                  int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\
247     FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst  , src1  , src2  , src3  , src4  , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
248     FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\
249 }\
250 \
251 static inline void FUNCC(OPNAME ## _pixels2_xy2)(uint8_t *_block, const uint8_t *_pixels, ptrdiff_t line_size, int h)\
252 {\
253         int i, a0, b0, a1, b1;\
254         pixel *block = (pixel*)_block;\
255         const pixel *pixels = (const pixel*)_pixels;\
256         line_size >>= sizeof(pixel)-1;\
257         a0= pixels[0];\
258         b0= pixels[1] + 2;\
259         a0 += b0;\
260         b0 += pixels[2];\
261 \
262         pixels+=line_size;\
263         for(i=0; i<h; i+=2){\
264             a1= pixels[0];\
265             b1= pixels[1];\
266             a1 += b1;\
267             b1 += pixels[2];\
268 \
269             block[0]= (a1+a0)>>2; /* FIXME non put */\
270             block[1]= (b1+b0)>>2;\
271 \
272             pixels+=line_size;\
273             block +=line_size;\
274 \
275             a0= pixels[0];\
276             b0= pixels[1] + 2;\
277             a0 += b0;\
278             b0 += pixels[2];\
279 \
280             block[0]= (a1+a0)>>2;\
281             block[1]= (b1+b0)>>2;\
282             pixels+=line_size;\
283             block +=line_size;\
284         }\
285 }\
286 \
287 static inline void FUNCC(OPNAME ## _pixels4_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\
288 {\
289         /* FIXME HIGH BIT DEPTH */\
290         int i;\
291         const uint32_t a= AV_RN32(pixels  );\
292         const uint32_t b= AV_RN32(pixels+1);\
293         uint32_t l0=  (a&0x03030303UL)\
294                     + (b&0x03030303UL)\
295                     + 0x02020202UL;\
296         uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\
297                    + ((b&0xFCFCFCFCUL)>>2);\
298         uint32_t l1,h1;\
299 \
300         pixels+=line_size;\
301         for(i=0; i<h; i+=2){\
302             uint32_t a= AV_RN32(pixels  );\
303             uint32_t b= AV_RN32(pixels+1);\
304             l1=  (a&0x03030303UL)\
305                + (b&0x03030303UL);\
306             h1= ((a&0xFCFCFCFCUL)>>2)\
307               + ((b&0xFCFCFCFCUL)>>2);\
308             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
309             pixels+=line_size;\
310             block +=line_size;\
311             a= AV_RN32(pixels  );\
312             b= AV_RN32(pixels+1);\
313             l0=  (a&0x03030303UL)\
314                + (b&0x03030303UL)\
315                + 0x02020202UL;\
316             h0= ((a&0xFCFCFCFCUL)>>2)\
317               + ((b&0xFCFCFCFCUL)>>2);\
318             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
319             pixels+=line_size;\
320             block +=line_size;\
321         }\
322 }\
323 \
324 static inline void FUNCC(OPNAME ## _pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\
325 {\
326     /* FIXME HIGH BIT DEPTH */\
327     int j;\
328     for(j=0; j<2; j++){\
329         int i;\
330         const uint32_t a= AV_RN32(pixels  );\
331         const uint32_t b= AV_RN32(pixels+1);\
332         uint32_t l0=  (a&0x03030303UL)\
333                     + (b&0x03030303UL)\
334                     + 0x02020202UL;\
335         uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\
336                    + ((b&0xFCFCFCFCUL)>>2);\
337         uint32_t l1,h1;\
338 \
339         pixels+=line_size;\
340         for(i=0; i<h; i+=2){\
341             uint32_t a= AV_RN32(pixels  );\
342             uint32_t b= AV_RN32(pixels+1);\
343             l1=  (a&0x03030303UL)\
344                + (b&0x03030303UL);\
345             h1= ((a&0xFCFCFCFCUL)>>2)\
346               + ((b&0xFCFCFCFCUL)>>2);\
347             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
348             pixels+=line_size;\
349             block +=line_size;\
350             a= AV_RN32(pixels  );\
351             b= AV_RN32(pixels+1);\
352             l0=  (a&0x03030303UL)\
353                + (b&0x03030303UL)\
354                + 0x02020202UL;\
355             h0= ((a&0xFCFCFCFCUL)>>2)\
356               + ((b&0xFCFCFCFCUL)>>2);\
357             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
358             pixels+=line_size;\
359             block +=line_size;\
360         }\
361         pixels+=4-line_size*(h+1);\
362         block +=4-line_size*h;\
363     }\
364 }\
365 \
366 static inline void FUNCC(OPNAME ## _no_rnd_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\
367 {\
368     /* FIXME HIGH BIT DEPTH */\
369     int j;\
370     for(j=0; j<2; j++){\
371         int i;\
372         const uint32_t a= AV_RN32(pixels  );\
373         const uint32_t b= AV_RN32(pixels+1);\
374         uint32_t l0=  (a&0x03030303UL)\
375                     + (b&0x03030303UL)\
376                     + 0x01010101UL;\
377         uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\
378                    + ((b&0xFCFCFCFCUL)>>2);\
379         uint32_t l1,h1;\
380 \
381         pixels+=line_size;\
382         for(i=0; i<h; i+=2){\
383             uint32_t a= AV_RN32(pixels  );\
384             uint32_t b= AV_RN32(pixels+1);\
385             l1=  (a&0x03030303UL)\
386                + (b&0x03030303UL);\
387             h1= ((a&0xFCFCFCFCUL)>>2)\
388               + ((b&0xFCFCFCFCUL)>>2);\
389             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
390             pixels+=line_size;\
391             block +=line_size;\
392             a= AV_RN32(pixels  );\
393             b= AV_RN32(pixels+1);\
394             l0=  (a&0x03030303UL)\
395                + (b&0x03030303UL)\
396                + 0x01010101UL;\
397             h0= ((a&0xFCFCFCFCUL)>>2)\
398               + ((b&0xFCFCFCFCUL)>>2);\
399             OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\
400             pixels+=line_size;\
401             block +=line_size;\
402         }\
403         pixels+=4-line_size*(h+1);\
404         block +=4-line_size*h;\
405     }\
406 }\
407 \
408 CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_x2) , FUNCC(OPNAME ## _pixels8_x2) , 8*sizeof(pixel))\
409 CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_y2) , FUNCC(OPNAME ## _pixels8_y2) , 8*sizeof(pixel))\
410 CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_xy2), FUNCC(OPNAME ## _pixels8_xy2), 8*sizeof(pixel))\
411 av_unused CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16)    , FUNCC(OPNAME ## _pixels8) , 8*sizeof(pixel))\
412 CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_x2) , FUNCC(OPNAME ## _no_rnd_pixels8_x2) , 8*sizeof(pixel))\
413 CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_y2) , FUNCC(OPNAME ## _no_rnd_pixels8_y2) , 8*sizeof(pixel))\
414 CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_xy2), FUNCC(OPNAME ## _no_rnd_pixels8_xy2), 8*sizeof(pixel))\
415
416 #define op_avg(a, b) a = rnd_avg_pixel4(a, b)
417 #define op_put(a, b) a = b
418 #if BIT_DEPTH == 8
419 #define put_no_rnd_pixels8_8_c put_pixels8_8_c
420 PIXOP2(avg, op_avg)
421 PIXOP2(put, op_put)
422 #endif
423 #undef op_avg
424 #undef op_put