]> git.sesse.net Git - ffmpeg/blob - postproc/rgb2rgb.c
More standards compilance
[ffmpeg] / postproc / rgb2rgb.c
1 /*
2  *
3  *  rgb2rgb.c, Software RGB to RGB convertor
4  *  Written by Nick Kurshev.
5  *  palette stuff & yuv stuff by Michael
6  */
7 #include <inttypes.h>
8 #include "../config.h"
9 #include "rgb2rgb.h"
10 #include "../mmx_defs.h"
11
12 #ifdef HAVE_MMX
13 static const uint64_t mask32   __attribute__((aligned(8))) = 0x00FFFFFF00FFFFFFULL;
14 static const uint64_t mask24l  __attribute__((aligned(8))) = 0x0000000000FFFFFFULL;
15 static const uint64_t mask24h  __attribute__((aligned(8))) = 0x0000FFFFFF000000ULL;
16 static const uint64_t mask15b  __attribute__((aligned(8))) = 0x001F001F001F001FULL; /* 00000000 00011111  xxB */
17 static const uint64_t mask15rg __attribute__((aligned(8))) = 0x7FE07FE07FE07FE0ULL; /* 01111111 11100000  RGx */
18 static const uint64_t mask15s  __attribute__((aligned(8))) = 0xFFE0FFE0FFE0FFE0ULL;
19 #endif
20
21 void rgb24to32(const uint8_t *src,uint8_t *dst,uint32_t src_size)
22 {
23   uint8_t *dest = dst;
24   const uint8_t *s = src;
25   const uint8_t *end;
26 #ifdef HAVE_MMX
27   uint8_t *mm_end;
28 #endif
29   end = s + src_size;
30 #ifdef HAVE_MMX
31   __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
32   mm_end = (uint8_t*)((((unsigned long)end)/(MMREG_SIZE*2))*(MMREG_SIZE*2));
33   __asm __volatile("movq        %0, %%mm7"::"m"(mask32):"memory");
34   if(mm_end == end) mm_end -= MMREG_SIZE*2;
35   while(s < mm_end)
36   {
37     __asm __volatile(
38         PREFETCH"       32%1\n\t"
39         "movd   %1, %%mm0\n\t"
40         "movd   3%1, %%mm1\n\t"
41         "movd   6%1, %%mm2\n\t"
42         "movd   9%1, %%mm3\n\t"
43         "punpckldq %%mm1, %%mm0\n\t"
44         "punpckldq %%mm3, %%mm2\n\t"
45         "pand   %%mm7, %%mm0\n\t"
46         "pand   %%mm7, %%mm2\n\t"
47         MOVNTQ" %%mm0, %0\n\t"
48         MOVNTQ" %%mm2, 8%0"
49         :"=m"(*dest)
50         :"m"(*s)
51         :"memory");
52     dest += 16;
53     s += 12;
54   }
55   __asm __volatile(SFENCE:::"memory");
56   __asm __volatile(EMMS:::"memory");
57 #endif
58   while(s < end)
59   {
60     *dest++ = *s++;
61     *dest++ = *s++;
62     *dest++ = *s++;
63     *dest++ = 0;
64   }
65 }
66
67 void rgb32to24(const uint8_t *src,uint8_t *dst,uint32_t src_size)
68 {
69   uint8_t *dest = dst;
70   const uint8_t *s = src;
71   const uint8_t *end;
72 #ifdef HAVE_MMX
73   uint8_t *mm_end;
74 #endif
75   end = s + src_size;
76 #ifdef HAVE_MMX
77   __asm __volatile(PREFETCH"    %0"::"m"(*s):"memory");
78   mm_end = (uint8_t*)((((unsigned long)end)/(MMREG_SIZE*2))*(MMREG_SIZE*2));
79   __asm __volatile(
80         "movq   %0, %%mm7\n\t"
81         "movq   %1, %%mm6"
82         ::"m"(mask24l),"m"(mask24h):"memory");
83   if(mm_end == end) mm_end -= MMREG_SIZE*2;
84   while(s < mm_end)
85   {
86     __asm __volatile(
87         PREFETCH"       32%1\n\t"
88         "movq   %1, %%mm0\n\t"
89         "movq   8%1, %%mm1\n\t"
90         "movq   %%mm0, %%mm2\n\t"
91         "movq   %%mm1, %%mm3\n\t"
92         "psrlq  $8, %%mm2\n\t"
93         "psrlq  $8, %%mm3\n\t"
94         "pand   %%mm7, %%mm0\n\t"
95         "pand   %%mm7, %%mm1\n\t"
96         "pand   %%mm6, %%mm2\n\t"
97         "pand   %%mm6, %%mm3\n\t"
98         "por    %%mm2, %%mm0\n\t"
99         "por    %%mm3, %%mm1\n\t"
100         MOVNTQ" %%mm0, %0\n\t"
101         MOVNTQ" %%mm1, 6%0"
102         :"=m"(*dest)
103         :"m"(*s)
104         :"memory");
105     dest += 12;
106     s += 16;
107   }
108   __asm __volatile(SFENCE:::"memory");
109   __asm __volatile(EMMS:::"memory");
110 #endif
111   while(s < end)
112   {
113     *dest++ = *s++;
114     *dest++ = *s++;
115     *dest++ = *s++;
116     s++;
117   }
118 }
119
120 /*
121  Original by Strepto/Astral
122  ported to gcc & bugfixed : A'rpi
123  MMX2, 3DNOW optimization by Nick Kurshev
124  32bit c version, and and&add trick by Michael Niedermayer
125 */
126 void rgb15to16(const uint8_t *src,uint8_t *dst,uint32_t src_size)
127 {
128 #ifdef HAVE_MMX
129   register const char* s=src+src_size;
130   register char* d=dst+src_size;
131   register int offs=-src_size;
132   __asm __volatile(PREFETCH"    %0"::"m"(*(s+offs)));
133   __asm __volatile(
134         "movq   %0, %%mm4\n\t"
135         ::"m"(mask15s));
136   while(offs<0)
137   {
138         __asm __volatile(
139                 PREFETCH"       32%1\n\t"
140                 "movq   %1, %%mm0\n\t"
141                 "movq   8%1, %%mm2\n\t"
142                 "movq   %%mm0, %%mm1\n\t"
143                 "movq   %%mm2, %%mm3\n\t"
144                 "pand   %%mm4, %%mm0\n\t"
145                 "pand   %%mm4, %%mm2\n\t"
146                 "paddw  %%mm1, %%mm0\n\t"
147                 "paddw  %%mm3, %%mm2\n\t"
148                 MOVNTQ" %%mm0, %0\n\t"
149                 MOVNTQ" %%mm2, 8%0"
150                 :"=m"(*(d+offs))
151                 :"m"(*(s+offs))
152                 );
153         offs+=16;
154   }
155   __asm __volatile(SFENCE:::"memory");
156   __asm __volatile(EMMS:::"memory");
157 #else
158 #if 0
159    const uint16_t *s1=( uint16_t * )src;
160    uint16_t *d1=( uint16_t * )dst;
161    uint16_t *e=((uint8_t *)s1)+src_size;
162    while( s1<e ){
163      register int x=*( s1++ );
164      /* rrrrrggggggbbbbb
165         0rrrrrgggggbbbbb
166         0111 1111 1110 0000=0x7FE0
167         00000000000001 1111=0x001F */
168      *( d1++ )=( x&0x001F )|( ( x&0x7FE0 )<<1 );
169    }
170 #else
171         const uint32_t *s1=( uint32_t * )src;
172         uint32_t *d1=( uint32_t * )dst;
173         int i;
174         int size= src_size>>2;
175         for(i=0; i<size; i++)
176         {
177                 register int x= s1[i];
178 //              d1[i] = x + (x&0x7FE07FE0); //faster but need msbit =0 which might not allways be true
179                 d1[i] = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
180
181         }
182 #endif
183 #endif
184 }
185
186 /**
187  * Pallete is assumed to contain bgr32
188  */
189 void palette8torgb32(const uint8_t *src, uint8_t *dst, uint32_t num_pixels, const uint8_t *palette)
190 {
191         uint32_t i;
192         for(i=0; i<num_pixels; i++)
193                 ((uint32_t *)dst)[i] = ((uint32_t *)palette)[ src[i] ];
194 }
195
196 /**
197  * Pallete is assumed to contain bgr32
198  */
199 void palette8torgb24(const uint8_t *src, uint8_t *dst, uint32_t num_pixels, const uint8_t *palette)
200 {
201         uint32_t i;
202 /*
203         writes 1 byte o much and might cause alignment issues on some architectures?
204         for(i=0; i<num_pixels; i++)
205                 ((uint32_t *)(&dst[i*3])) = ((uint32_t *)palette)[ src[i] ];
206 */
207         for(i=0; i<num_pixels; i++)
208         {
209                 //FIXME slow?
210                 dst[0]= palette[ src[i]*4+0 ];
211                 dst[1]= palette[ src[i]*4+1 ];
212                 dst[2]= palette[ src[i]*4+2 ];
213                 dst+= 3;
214         }
215 }
216
217 void rgb32to16(const uint8_t *src, uint8_t *dst, uint32_t num_pixels)
218 {
219         uint32_t i;
220         for(i=0; i<num_pixels; i+=4)
221         {
222                 const int b= src[i+0];
223                 const int g= src[i+1];
224                 const int r= src[i+2];
225
226                 ((uint16_t *)dst)[i]= (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
227         }
228 }
229
230 void rgb32to15(const uint8_t *src, uint8_t *dst, uint32_t num_pixels)
231 {
232         uint32_t i;
233         for(i=0; i<num_pixels; i+=4)
234         {
235                 const int b= src[i+0];
236                 const int g= src[i+1];
237                 const int r= src[i+2];
238
239                 ((uint16_t *)dst)[i]= (b>>3) | ((g&0xF8)<<3) | ((r&0xF8)<<7);
240         }
241 }
242
243
244 /**
245  * Palette is assumed to contain bgr16, see rgb32to16 to convert the palette
246  */
247 void palette8torgb16(const uint8_t *src, uint8_t *dst, uint32_t num_pixels, const uint8_t *palette)
248 {
249         uint32_t i;
250         for(i=0; i<num_pixels; i++)
251                 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
252 }
253
254 /**
255  * Pallete is assumed to contain bgr15, see rgb32to15 to convert the palette
256  */
257 void palette8torgb15(const uint8_t *src, uint8_t *dst, uint32_t num_pixels, const uint8_t *palette)
258 {
259         uint32_t i;
260         for(i=0; i<num_pixels; i++)
261                 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
262 }
263 /**
264  *
265  * num_pixels must be a multiple of 16 for the MMX version
266  */
267 void yv12toyuy2(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst, uint32_t num_pixels)
268 {
269 #ifdef HAVE_MMX
270         asm volatile(
271                 "xorl %%eax, %%eax              \n\t"
272                 "1:                             \n\t"
273                 PREFETCH" 32(%1, %%eax, 2)      \n\t"
274                 PREFETCH" 32(%2, %%eax)         \n\t"
275                 PREFETCH" 32(%3, %%eax)         \n\t"
276                 "movq (%2, %%eax), %%mm0        \n\t" // U(0)
277                 "movq %%mm0, %%mm2              \n\t" // U(0)
278                 "movq (%3, %%eax), %%mm1        \n\t" // V(0)
279                 "punpcklbw %%mm1, %%mm0         \n\t" // UVUV UVUV(0)
280                 "punpckhbw %%mm1, %%mm2         \n\t" // UVUV UVUV(8)
281
282                 "movq (%1, %%eax,2), %%mm3      \n\t" // Y(0)
283                 "movq 8(%1, %%eax,2), %%mm5     \n\t" // Y(8)
284                 "movq %%mm3, %%mm4              \n\t" // Y(0)
285                 "movq %%mm5, %%mm6              \n\t" // Y(8)
286                 "punpcklbw %%mm0, %%mm3         \n\t" // YUYV YUYV(0)
287                 "punpckhbw %%mm0, %%mm4         \n\t" // YUYV YUYV(4)
288                 "punpcklbw %%mm2, %%mm5         \n\t" // YUYV YUYV(8)
289                 "punpckhbw %%mm2, %%mm6         \n\t" // YUYV YUYV(12)
290
291                 MOVNTQ" %%mm3, (%0, %%eax, 4)   \n\t"
292                 MOVNTQ" %%mm4, 8(%0, %%eax, 4)  \n\t"
293                 MOVNTQ" %%mm5, 16(%0, %%eax, 4) \n\t"
294                 MOVNTQ" %%mm6, 24(%0, %%eax, 4) \n\t"
295
296                 "addl $8, %%eax                 \n\t"
297                 "cmpl %4, %%eax                 \n\t"
298                 " jb 1b                         \n\t"
299                 EMMS" \n\t"
300                 SFENCE
301                 ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "r" (num_pixels>>1)
302                 : "memory", "%eax"
303         );
304
305 #else
306         int i;
307         num_pixels>>=1;
308         for(i=0; i<num_pixels; i++)
309         {
310                 dst[4*i+0] = ysrc[2*i+0];
311                 dst[4*i+1] = usrc[i];
312                 dst[4*i+2] = ysrc[2*i+1];
313                 dst[4*i+3] = vsrc[i];
314         }
315 #endif
316 }
317
318 void yuy2toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, uint32_t num_pixels)
319 {
320 #ifdef HAVE_MMX
321         asm volatile(
322                 "xorl %%eax, %%eax              \n\t"
323                 "pcmpeqw %%mm7, %%mm7           \n\t"
324                 "psrlw $8, %%mm7                \n\t" // FF,00,FF,00...
325                 "1:                             \n\t"
326                 PREFETCH" 64(%0, %%eax, 4)      \n\t"
327                 "movq (%0, %%eax, 4), %%mm0     \n\t" // YUYV YUYV(0)
328                 "movq 8(%0, %%eax, 4), %%mm1    \n\t" // YUYV YUYV(4)
329                 "movq %%mm0, %%mm2              \n\t" // YUYV YUYV(0)
330                 "movq %%mm1, %%mm3              \n\t" // YUYV YUYV(4)
331                 "psrlw $8, %%mm0                \n\t" // U0V0 U0V0(0)
332                 "psrlw $8, %%mm1                \n\t" // U0V0 U0V0(4)
333                 "pand %%mm7, %%mm2              \n\t" // Y0Y0 Y0Y0(0)
334                 "pand %%mm7, %%mm3              \n\t" // Y0Y0 Y0Y0(4)
335                 "packuswb %%mm1, %%mm0          \n\t" // UVUV UVUV(0)
336                 "packuswb %%mm3, %%mm2          \n\t" // YYYY YYYY(0)
337
338                 MOVNTQ" %%mm2, (%1, %%eax, 2)   \n\t"
339
340                 "movq 16(%0, %%eax, 4), %%mm1   \n\t" // YUYV YUYV(8)
341                 "movq 24(%0, %%eax, 4), %%mm2   \n\t" // YUYV YUYV(12)
342                 "movq %%mm1, %%mm3              \n\t" // YUYV YUYV(8)
343                 "movq %%mm2, %%mm4              \n\t" // YUYV YUYV(12)
344                 "psrlw $8, %%mm1                \n\t" // U0V0 U0V0(8)
345                 "psrlw $8, %%mm2                \n\t" // U0V0 U0V0(12)
346                 "pand %%mm7, %%mm3              \n\t" // Y0Y0 Y0Y0(8)
347                 "pand %%mm7, %%mm4              \n\t" // Y0Y0 Y0Y0(12)
348                 "packuswb %%mm2, %%mm1          \n\t" // UVUV UVUV(8)
349                 "packuswb %%mm4, %%mm3          \n\t" // YYYY YYYY(8)
350
351                 MOVNTQ" %%mm3, 8(%1, %%eax, 2)  \n\t"
352
353                 "movq %%mm0, %%mm2              \n\t" // UVUV UVUV(0)
354                 "movq %%mm1, %%mm3              \n\t" // UVUV UVUV(8)
355                 "psrlw $8, %%mm0                \n\t" // V0V0 V0V0(0)
356                 "psrlw $8, %%mm1                \n\t" // V0V0 V0V0(8)
357                 "pand %%mm7, %%mm2              \n\t" // U0U0 U0U0(0)
358                 "pand %%mm7, %%mm3              \n\t" // U0U0 U0U0(8)
359                 "packuswb %%mm1, %%mm0          \n\t" // VVVV VVVV(0)
360                 "packuswb %%mm3, %%mm2          \n\t" // UUUU UUUU(0)
361
362                 MOVNTQ" %%mm0, (%3, %%eax)      \n\t"
363                 MOVNTQ" %%mm2, (%2, %%eax)      \n\t"
364
365                 "addl $8, %%eax                 \n\t"
366                 "cmpl %4, %%eax                 \n\t"
367                 " jb 1b                         \n\t"
368                 EMMS" \n\t"
369                 SFENCE
370                 ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "r" (num_pixels>>1)
371                 : "memory", "%eax"
372         );
373 #else
374         int i;
375         num_pixels>>=1;
376         for(i=0; i<num_pixels; i++)
377         {
378                  ydst[2*i+0]    = src[4*i+0];
379                  udst[i]        = src[4*i+1];
380                  ydst[2*i+1]    = src[4*i+2];
381                  vdst[i]        = src[4*i+3];
382         }
383 #endif
384 }