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