* using pixtype as enum - by Philip Gladstone
[ffmpeg.git] / postproc / rgb2rgb.c
1 /*
2  *
3  *  rgb2rgb.c, Software RGB to RGB convertor
4  *  pluralize by Software PAL8 to RGB convertor
5  *               Software YUV to YUV convertor
6  *               Software YUV to RGB convertor
7  *  Written by Nick Kurshev.
8  *  palette & yuv & runtime cpu stuff by Michael (michaelni@gmx.at) (under GPL)
9  */
10 #include <inttypes.h>
11 #include "../config.h"
12 #include "rgb2rgb.h"
13 #include "../cpudetect.h"
14 #include "../mangle.h"
15
16 #ifdef ARCH_X86
17 #define CAN_COMPILE_X86_ASM
18 #endif
19
20 #define FAST_BGR2YV12 // use 7 bit coeffs instead of 15bit
21
22 #ifdef CAN_COMPILE_X86_ASM
23 static const uint64_t mask32b  __attribute__((aligned(8))) = 0x000000FF000000FFULL;
24 static const uint64_t mask32g  __attribute__((aligned(8))) = 0x0000FF000000FF00ULL;
25 static const uint64_t mask32r  __attribute__((aligned(8))) = 0x00FF000000FF0000ULL;
26 static const uint64_t mask32   __attribute__((aligned(8))) = 0x00FFFFFF00FFFFFFULL;
27 static const uint64_t mask24l  __attribute__((aligned(8))) = 0x0000000000FFFFFFULL;
28 static const uint64_t mask24h  __attribute__((aligned(8))) = 0x0000FFFFFF000000ULL;
29 static const uint64_t mask24hh  __attribute__((aligned(8))) = 0xffff000000000000ULL;
30 static const uint64_t mask24hhh  __attribute__((aligned(8))) = 0xffffffff00000000ULL;
31 static const uint64_t mask24hhhh  __attribute__((aligned(8))) = 0xffffffffffff0000ULL;
32 static const uint64_t mask15b  __attribute__((aligned(8))) = 0x001F001F001F001FULL; /* 00000000 00011111  xxB */
33 static const uint64_t mask15rg __attribute__((aligned(8))) = 0x7FE07FE07FE07FE0ULL; /* 01111111 11100000  RGx */
34 static const uint64_t mask15s  __attribute__((aligned(8))) = 0xFFE0FFE0FFE0FFE0ULL;
35 static const uint64_t red_16mask  __attribute__((aligned(8))) = 0x0000f8000000f800ULL;
36 static const uint64_t green_16mask __attribute__((aligned(8)))= 0x000007e0000007e0ULL;
37 static const uint64_t blue_16mask __attribute__((aligned(8))) = 0x0000001f0000001fULL;
38 static const uint64_t red_15mask  __attribute__((aligned(8))) = 0x00007c000000f800ULL;
39 static const uint64_t green_15mask __attribute__((aligned(8)))= 0x000003e0000007e0ULL;
40 static const uint64_t blue_15mask __attribute__((aligned(8))) = 0x0000001f0000001fULL;
41
42 #ifdef FAST_BGR2YV12
43 static const uint64_t bgr2YCoeff  __attribute__((aligned(8))) = 0x000000210041000DULL;
44 static const uint64_t bgr2UCoeff  __attribute__((aligned(8))) = 0x0000FFEEFFDC0038ULL;
45 static const uint64_t bgr2VCoeff  __attribute__((aligned(8))) = 0x00000038FFD2FFF8ULL;
46 #else
47 static const uint64_t bgr2YCoeff  __attribute__((aligned(8))) = 0x000020E540830C8BULL;
48 static const uint64_t bgr2UCoeff  __attribute__((aligned(8))) = 0x0000ED0FDAC23831ULL;
49 static const uint64_t bgr2VCoeff  __attribute__((aligned(8))) = 0x00003831D0E6F6EAULL;
50 #endif
51 static const uint64_t bgr2YOffset __attribute__((aligned(8))) = 0x1010101010101010ULL;
52 static const uint64_t bgr2UVOffset __attribute__((aligned(8)))= 0x8080808080808080ULL;
53 static const uint64_t w1111       __attribute__((aligned(8))) = 0x0001000100010001ULL;
54
55 #if 0
56 static volatile uint64_t __attribute__((aligned(8))) b5Dither;
57 static volatile uint64_t __attribute__((aligned(8))) g5Dither;
58 static volatile uint64_t __attribute__((aligned(8))) g6Dither;
59 static volatile uint64_t __attribute__((aligned(8))) r5Dither;
60
61 static uint64_t __attribute__((aligned(8))) dither4[2]={
62         0x0103010301030103LL,
63         0x0200020002000200LL,};
64
65 static uint64_t __attribute__((aligned(8))) dither8[2]={
66         0x0602060206020602LL,
67         0x0004000400040004LL,};
68 #endif
69 #endif
70
71 #define RGB2YUV_SHIFT 8
72 #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
73 #define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
74 #define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
75 #define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
76 #define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
77 #define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
78 #define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
79 #define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
80 #define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
81
82 //Note: we have C, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
83 //Plain C versions
84 #undef HAVE_MMX
85 #undef HAVE_MMX2
86 #undef HAVE_3DNOW
87 #undef ARCH_X86
88 #undef HAVE_SSE2
89 #define RENAME(a) a ## _C
90 #include "rgb2rgb_template.c"
91
92 #ifdef CAN_COMPILE_X86_ASM
93
94 //MMX versions
95 #undef RENAME
96 #define HAVE_MMX
97 #undef HAVE_MMX2
98 #undef HAVE_3DNOW
99 #undef HAVE_SSE2
100 #define ARCH_X86
101 #define RENAME(a) a ## _MMX
102 #include "rgb2rgb_template.c"
103
104 //MMX2 versions
105 #undef RENAME
106 #define HAVE_MMX
107 #define HAVE_MMX2
108 #undef HAVE_3DNOW
109 #undef HAVE_SSE2
110 #define ARCH_X86
111 #define RENAME(a) a ## _MMX2
112 #include "rgb2rgb_template.c"
113
114 //3DNOW versions
115 #undef RENAME
116 #define HAVE_MMX
117 #undef HAVE_MMX2
118 #define HAVE_3DNOW
119 #undef HAVE_SSE2
120 #define ARCH_X86
121 #define RENAME(a) a ## _3DNow
122 #include "rgb2rgb_template.c"
123
124 #endif //CAN_COMPILE_X86_ASM
125
126 void rgb24to32(const uint8_t *src,uint8_t *dst,unsigned src_size)
127 {
128 #ifdef CAN_COMPILE_X86_ASM
129         // ordered per speed fasterst first
130         if(gCpuCaps.hasMMX2)
131                 rgb24to32_MMX2(src, dst, src_size);
132         else if(gCpuCaps.has3DNow)
133                 rgb24to32_3DNow(src, dst, src_size);
134         else if(gCpuCaps.hasMMX)
135                 rgb24to32_MMX(src, dst, src_size);
136         else
137                 rgb24to32_C(src, dst, src_size);
138 #else
139                 rgb24to32_C(src, dst, src_size);
140 #endif
141 }
142
143 void rgb32to24(const uint8_t *src,uint8_t *dst,unsigned src_size)
144 {
145 #ifdef CAN_COMPILE_X86_ASM
146         // ordered per speed fasterst first
147         if(gCpuCaps.hasMMX2)
148                 rgb32to24_MMX2(src, dst, src_size);
149         else if(gCpuCaps.has3DNow)
150                 rgb32to24_3DNow(src, dst, src_size);
151         else if(gCpuCaps.hasMMX)
152                 rgb32to24_MMX(src, dst, src_size);
153         else
154                 rgb32to24_C(src, dst, src_size);
155 #else
156                 rgb32to24_C(src, dst, src_size);
157 #endif
158 }
159
160 /*
161  Original by Strepto/Astral
162  ported to gcc & bugfixed : A'rpi
163  MMX2, 3DNOW optimization by Nick Kurshev
164  32bit c version, and and&add trick by Michael Niedermayer
165 */
166 void rgb15to16(const uint8_t *src,uint8_t *dst,unsigned src_size)
167 {
168 #ifdef CAN_COMPILE_X86_ASM
169         // ordered per speed fasterst first
170         if(gCpuCaps.hasMMX2)
171                 rgb15to16_MMX2(src, dst, src_size);
172         else if(gCpuCaps.has3DNow)
173                 rgb15to16_3DNow(src, dst, src_size);
174         else if(gCpuCaps.hasMMX)
175                 rgb15to16_MMX(src, dst, src_size);
176         else
177                 rgb15to16_C(src, dst, src_size);
178 #else
179                 rgb15to16_C(src, dst, src_size);
180 #endif
181 }
182
183 /**
184  * Pallete is assumed to contain bgr32
185  */
186 void palette8torgb32(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
187 {
188         unsigned i;
189         for(i=0; i<num_pixels; i++)
190                 ((unsigned *)dst)[i] = ((unsigned *)palette)[ src[i] ];
191 }
192
193 /**
194  * Pallete is assumed to contain bgr32
195  */
196 void palette8torgb24(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
197 {
198         unsigned i;
199 /*
200         writes 1 byte o much and might cause alignment issues on some architectures?
201         for(i=0; i<num_pixels; i++)
202                 ((unsigned *)(&dst[i*3])) = ((unsigned *)palette)[ src[i] ];
203 */
204         for(i=0; i<num_pixels; i++)
205         {
206                 //FIXME slow?
207                 dst[0]= palette[ src[i]*4+0 ];
208                 dst[1]= palette[ src[i]*4+1 ];
209                 dst[2]= palette[ src[i]*4+2 ];
210                 dst+= 3;
211         }
212 }
213
214 void rgb32to16(const uint8_t *src, uint8_t *dst, unsigned src_size)
215 {
216 #ifdef CAN_COMPILE_X86_ASM
217         // ordered per speed fasterst first
218         if(gCpuCaps.hasMMX2)
219                 rgb32to16_MMX2(src, dst, src_size);
220         else if(gCpuCaps.has3DNow)
221                 rgb32to16_3DNow(src, dst, src_size);
222         else if(gCpuCaps.hasMMX)
223                 rgb32to16_MMX(src, dst, src_size);
224         else
225                 rgb32to16_C(src, dst, src_size);
226 #else
227                 rgb32to16_C(src, dst, src_size);
228 #endif
229 }
230
231 void rgb32to15(const uint8_t *src, uint8_t *dst, unsigned src_size)
232 {
233 #ifdef CAN_COMPILE_X86_ASM
234         // ordered per speed fasterst first
235         if(gCpuCaps.hasMMX2)
236                 rgb32to15_MMX2(src, dst, src_size);
237         else if(gCpuCaps.has3DNow)
238                 rgb32to15_3DNow(src, dst, src_size);
239         else if(gCpuCaps.hasMMX)
240                 rgb32to15_MMX(src, dst, src_size);
241         else
242                 rgb32to15_C(src, dst, src_size);
243 #else
244                 rgb32to15_C(src, dst, src_size);
245 #endif
246 }
247
248 void rgb24to16(const uint8_t *src, uint8_t *dst, unsigned src_size)
249 {
250 #ifdef CAN_COMPILE_X86_ASM
251         // ordered per speed fasterst first
252         if(gCpuCaps.hasMMX2)
253                 rgb24to16_MMX2(src, dst, src_size);
254         else if(gCpuCaps.has3DNow)
255                 rgb24to16_3DNow(src, dst, src_size);
256         else if(gCpuCaps.hasMMX)
257                 rgb24to16_MMX(src, dst, src_size);
258         else
259                 rgb24to16_C(src, dst, src_size);
260 #else
261                 rgb24to16_C(src, dst, src_size);
262 #endif
263 }
264
265 void rgb24to15(const uint8_t *src, uint8_t *dst, unsigned src_size)
266 {
267 #ifdef CAN_COMPILE_X86_ASM
268         // ordered per speed fasterst first
269         if(gCpuCaps.hasMMX2)
270                 rgb24to15_MMX2(src, dst, src_size);
271         else if(gCpuCaps.has3DNow)
272                 rgb24to15_3DNow(src, dst, src_size);
273         else if(gCpuCaps.hasMMX)
274                 rgb24to15_MMX(src, dst, src_size);
275         else
276                 rgb24to15_C(src, dst, src_size);
277 #else
278                 rgb24to15_C(src, dst, src_size);
279 #endif
280 }
281
282 /**
283  * Palette is assumed to contain bgr16, see rgb32to16 to convert the palette
284  */
285 void palette8torgb16(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
286 {
287         unsigned i;
288         for(i=0; i<num_pixels; i++)
289                 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
290 }
291
292 /**
293  * Pallete is assumed to contain bgr15, see rgb32to15 to convert the palette
294  */
295 void palette8torgb15(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
296 {
297         unsigned i;
298         for(i=0; i<num_pixels; i++)
299                 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
300 }
301
302 void rgb32tobgr32(const uint8_t *src, uint8_t *dst, unsigned int src_size)
303 {
304 #ifdef CAN_COMPILE_X86_ASM
305         // ordered per speed fasterst first
306         if(gCpuCaps.hasMMX2)
307                 rgb32tobgr32_MMX2(src, dst, src_size);
308         else if(gCpuCaps.has3DNow)
309                 rgb32tobgr32_3DNow(src, dst, src_size);
310         else if(gCpuCaps.hasMMX)
311                 rgb32tobgr32_MMX(src, dst, src_size);
312         else
313                 rgb32tobgr32_C(src, dst, src_size);
314 #else
315                 rgb32tobgr32_C(src, dst, src_size);
316 #endif
317 }
318
319 /**
320  *
321  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
322  * problem for anyone then tell me, and ill fix it)
323  */
324 void yv12toyuy2(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
325         unsigned int width, unsigned int height,
326         unsigned int lumStride, unsigned int chromStride, unsigned int dstStride)
327 {
328 #ifdef CAN_COMPILE_X86_ASM
329         // ordered per speed fasterst first
330         if(gCpuCaps.hasMMX2)
331                 yv12toyuy2_MMX2(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride);
332         else if(gCpuCaps.has3DNow)
333                 yv12toyuy2_3DNow(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride);
334         else if(gCpuCaps.hasMMX)
335                 yv12toyuy2_MMX(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride);
336         else
337                 yv12toyuy2_C(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride);
338 #else
339                 yv12toyuy2_C(ysrc, usrc, vsrc, dst, width, height, lumStride, chromStride, dstStride);
340 #endif
341 }
342
343 /**
344  *
345  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
346  * problem for anyone then tell me, and ill fix it)
347  */
348 void yuy2toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
349         unsigned int width, unsigned int height,
350         unsigned int lumStride, unsigned int chromStride, unsigned int srcStride)
351 {
352 #ifdef CAN_COMPILE_X86_ASM
353         // ordered per speed fasterst first
354         if(gCpuCaps.hasMMX2)
355                 yuy2toyv12_MMX2(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
356         else if(gCpuCaps.has3DNow)
357                 yuy2toyv12_3DNow(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
358         else if(gCpuCaps.hasMMX)
359                 yuy2toyv12_MMX(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
360         else
361                 yuy2toyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
362 #else
363                 yuy2toyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
364 #endif
365 }
366
367 /**
368  *
369  * height should be a multiple of 2 and width should be a multiple of 16 (if this is a
370  * problem for anyone then tell me, and ill fix it)
371  * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
372  */
373 void uyvytoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
374         unsigned int width, unsigned int height,
375         unsigned int lumStride, unsigned int chromStride, unsigned int srcStride)
376 {
377 #ifdef CAN_COMPILE_X86_ASM
378         // ordered per speed fasterst first
379         if(gCpuCaps.hasMMX2)
380                 uyvytoyv12_MMX2(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
381         else if(gCpuCaps.has3DNow)
382                 uyvytoyv12_3DNow(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
383         else if(gCpuCaps.hasMMX)
384                 uyvytoyv12_MMX(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
385         else
386                 uyvytoyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
387 #else
388                 uyvytoyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
389 #endif
390 }
391
392 /**
393  *
394  * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
395  * problem for anyone then tell me, and ill fix it)
396  * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
397  */
398 void rgb24toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
399         unsigned int width, unsigned int height,
400         unsigned int lumStride, unsigned int chromStride, unsigned int srcStride)
401 {
402 #ifdef CAN_COMPILE_X86_ASM
403         // ordered per speed fasterst first
404         if(gCpuCaps.hasMMX2)
405                 rgb24toyv12_MMX2(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
406         else if(gCpuCaps.has3DNow)
407                 rgb24toyv12_3DNow(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
408         else if(gCpuCaps.hasMMX)
409                 rgb24toyv12_MMX(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
410         else
411                 rgb24toyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
412 #else
413                 rgb24toyv12_C(src, ydst, udst, vdst, width,  height, lumStride, chromStride, srcStride);
414 #endif
415 }
416
417 void interleaveBytes(uint8_t *src1, uint8_t *src2, uint8_t *dst,
418                      int width, int height, int src1Stride, int src2Stride, int dstStride)
419 {
420 #ifdef CAN_COMPILE_X86_ASM
421         // ordered per speed fasterst first
422         if(gCpuCaps.hasMMX2)
423                 interleaveBytes_MMX2(src1, src2, dst, width, height, src1Stride, src2Stride, dstStride);
424         else if(gCpuCaps.has3DNow)
425                 interleaveBytes_3DNow(src1, src2, dst, width, height, src1Stride, src2Stride, dstStride);
426         else if(gCpuCaps.hasMMX)
427                 interleaveBytes_MMX(src1, src2, dst, width, height, src1Stride, src2Stride, dstStride);
428         else
429                 interleaveBytes_C(src1, src2, dst, width, height, src1Stride, src2Stride, dstStride);
430 #else
431                 interleaveBytes_C(src1, src2, dst, width, height, src1Stride, src2Stride, dstStride);
432 #endif
433 }