]> git.sesse.net Git - ffmpeg/blob - libswscale/rgb2rgb_template.c
swscale: force --enable-runtime-cpudetect and remove SWS_CPU_CAPS_*.
[ffmpeg] / libswscale / rgb2rgb_template.c
1 /*
2  * software RGB to RGB converter
3  * pluralize by software PAL8 to RGB converter
4  *              software YUV to YUV converter
5  *              software YUV to RGB converter
6  * Written by Nick Kurshev.
7  * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
8  * lot of big-endian byte order fixes by Alex Beregszaszi
9  *
10  * This file is part of Libav.
11  *
12  * Libav is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * Libav is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with Libav; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  */
26
27 #include <stddef.h>
28
29 static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst, long src_size)
30 {
31     uint8_t *dest = dst;
32     const uint8_t *s = src;
33     const uint8_t *end;
34     end = s + src_size;
35
36     while (s < end) {
37 #if HAVE_BIGENDIAN
38         /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
39         *dest++ = 255;
40         *dest++ = s[2];
41         *dest++ = s[1];
42         *dest++ = s[0];
43         s+=3;
44 #else
45         *dest++ = *s++;
46         *dest++ = *s++;
47         *dest++ = *s++;
48         *dest++ = 255;
49 #endif
50     }
51 }
52
53 static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
54 {
55     uint8_t *dest = dst;
56     const uint8_t *s = src;
57     const uint8_t *end;
58
59     end = s + src_size;
60
61     while (s < end) {
62 #if HAVE_BIGENDIAN
63         /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
64         s++;
65         dest[2] = *s++;
66         dest[1] = *s++;
67         dest[0] = *s++;
68         dest += 3;
69 #else
70         *dest++ = *s++;
71         *dest++ = *s++;
72         *dest++ = *s++;
73         s++;
74 #endif
75     }
76 }
77
78 /*
79  original by Strepto/Astral
80  ported to gcc & bugfixed: A'rpi
81  MMX2, 3DNOW optimization by Nick Kurshev
82  32-bit C version, and and&add trick by Michael Niedermayer
83 */
84 static inline void rgb15to16_c(const uint8_t *src, uint8_t *dst, long src_size)
85 {
86     register const uint8_t* s=src;
87     register uint8_t* d=dst;
88     register const uint8_t *end;
89     const uint8_t *mm_end;
90     end = s + src_size;
91     mm_end = end - 3;
92     while (s < mm_end) {
93         register unsigned x= *((const uint32_t *)s);
94         *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
95         d+=4;
96         s+=4;
97     }
98     if (s < end) {
99         register unsigned short x= *((const uint16_t *)s);
100         *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
101     }
102 }
103
104 static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, long src_size)
105 {
106     register const uint8_t* s=src;
107     register uint8_t* d=dst;
108     register const uint8_t *end;
109     const uint8_t *mm_end;
110     end = s + src_size;
111
112     mm_end = end - 3;
113     while (s < mm_end) {
114         register uint32_t x= *((const uint32_t*)s);
115         *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
116         s+=4;
117         d+=4;
118     }
119     if (s < end) {
120         register uint16_t x= *((const uint16_t*)s);
121         *((uint16_t *)d) = ((x>>1)&0x7FE0) | (x&0x001F);
122     }
123 }
124
125 static inline void rgb32to16_c(const uint8_t *src, uint8_t *dst, long src_size)
126 {
127     const uint8_t *s = src;
128     const uint8_t *end;
129     uint16_t *d = (uint16_t *)dst;
130     end = s + src_size;
131
132     while (s < end) {
133         register int rgb = *(const uint32_t*)s; s += 4;
134         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
135     }
136 }
137
138 static inline void rgb32tobgr16_c(const uint8_t *src, uint8_t *dst, long src_size)
139 {
140     const uint8_t *s = src;
141     const uint8_t *end;
142     uint16_t *d = (uint16_t *)dst;
143     end = s + src_size;
144     while (s < end) {
145         register int rgb = *(const uint32_t*)s; s += 4;
146         *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
147     }
148 }
149
150 static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, long src_size)
151 {
152     const uint8_t *s = src;
153     const uint8_t *end;
154     uint16_t *d = (uint16_t *)dst;
155     end = s + src_size;
156     while (s < end) {
157         register int rgb = *(const uint32_t*)s; s += 4;
158         *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
159     }
160 }
161
162 static inline void rgb32tobgr15_c(const uint8_t *src, uint8_t *dst, long src_size)
163 {
164     const uint8_t *s = src;
165     const uint8_t *end;
166     uint16_t *d = (uint16_t *)dst;
167     end = s + src_size;
168     while (s < end) {
169         register int rgb = *(const uint32_t*)s; s += 4;
170         *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
171     }
172 }
173
174 static inline void rgb24tobgr16_c(const uint8_t *src, uint8_t *dst, long src_size)
175 {
176     const uint8_t *s = src;
177     const uint8_t *end;
178     uint16_t *d = (uint16_t *)dst;
179     end = s + src_size;
180     while (s < end) {
181         const int b = *s++;
182         const int g = *s++;
183         const int r = *s++;
184         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
185     }
186 }
187
188 static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, long src_size)
189 {
190     const uint8_t *s = src;
191     const uint8_t *end;
192     uint16_t *d = (uint16_t *)dst;
193     end = s + src_size;
194     while (s < end) {
195         const int r = *s++;
196         const int g = *s++;
197         const int b = *s++;
198         *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
199     }
200 }
201
202 static inline void rgb24tobgr15_c(const uint8_t *src, uint8_t *dst, long src_size)
203 {
204     const uint8_t *s = src;
205     const uint8_t *end;
206     uint16_t *d = (uint16_t *)dst;
207     end = s + src_size;
208     while (s < end) {
209         const int b = *s++;
210         const int g = *s++;
211         const int r = *s++;
212         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
213     }
214 }
215
216 static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, long src_size)
217 {
218     const uint8_t *s = src;
219     const uint8_t *end;
220     uint16_t *d = (uint16_t *)dst;
221     end = s + src_size;
222     while (s < end) {
223         const int r = *s++;
224         const int g = *s++;
225         const int b = *s++;
226         *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
227     }
228 }
229
230 /*
231   I use less accurate approximation here by simply left-shifting the input
232   value and filling the low order bits with zeroes. This method improves PNG
233   compression but this scheme cannot reproduce white exactly, since it does
234   not generate an all-ones maximum value; the net effect is to darken the
235   image slightly.
236
237   The better method should be "left bit replication":
238
239    4 3 2 1 0
240    ---------
241    1 1 0 1 1
242
243    7 6 5 4 3  2 1 0
244    ----------------
245    1 1 0 1 1  1 1 0
246    |=======|  |===|
247        |      leftmost bits repeated to fill open bits
248        |
249    original bits
250 */
251 static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
252 {
253     const uint16_t *end;
254     uint8_t *d = dst;
255     const uint16_t *s = (const uint16_t*)src;
256     end = s + src_size/2;
257     while (s < end) {
258         register uint16_t bgr;
259         bgr = *s++;
260         *d++ = (bgr&0x1F)<<3;
261         *d++ = (bgr&0x3E0)>>2;
262         *d++ = (bgr&0x7C00)>>7;
263     }
264 }
265
266 static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
267 {
268     const uint16_t *end;
269     uint8_t *d = (uint8_t *)dst;
270     const uint16_t *s = (const uint16_t *)src;
271     end = s + src_size/2;
272     while (s < end) {
273         register uint16_t bgr;
274         bgr = *s++;
275         *d++ = (bgr&0x1F)<<3;
276         *d++ = (bgr&0x7E0)>>3;
277         *d++ = (bgr&0xF800)>>8;
278     }
279 }
280
281 static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, long src_size)
282 {
283     const uint16_t *end;
284     uint8_t *d = dst;
285     const uint16_t *s = (const uint16_t *)src;
286     end = s + src_size/2;
287     while (s < end) {
288         register uint16_t bgr;
289         bgr = *s++;
290 #if HAVE_BIGENDIAN
291         *d++ = 255;
292         *d++ = (bgr&0x7C00)>>7;
293         *d++ = (bgr&0x3E0)>>2;
294         *d++ = (bgr&0x1F)<<3;
295 #else
296         *d++ = (bgr&0x1F)<<3;
297         *d++ = (bgr&0x3E0)>>2;
298         *d++ = (bgr&0x7C00)>>7;
299         *d++ = 255;
300 #endif
301     }
302 }
303
304 static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, long src_size)
305 {
306     const uint16_t *end;
307     uint8_t *d = dst;
308     const uint16_t *s = (const uint16_t*)src;
309     end = s + src_size/2;
310     while (s < end) {
311         register uint16_t bgr;
312         bgr = *s++;
313 #if HAVE_BIGENDIAN
314         *d++ = 255;
315         *d++ = (bgr&0xF800)>>8;
316         *d++ = (bgr&0x7E0)>>3;
317         *d++ = (bgr&0x1F)<<3;
318 #else
319         *d++ = (bgr&0x1F)<<3;
320         *d++ = (bgr&0x7E0)>>3;
321         *d++ = (bgr&0xF800)>>8;
322         *d++ = 255;
323 #endif
324     }
325 }
326
327 static inline void shuffle_bytes_2103_c(const uint8_t *src, uint8_t *dst, long src_size)
328 {
329     int idx = 15 - src_size;
330     const uint8_t *s = src-idx;
331     uint8_t *d = dst-idx;
332     for (; idx<15; idx+=4) {
333         register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
334         v &= 0xff00ff;
335         *(uint32_t *)&d[idx] = (v>>16) + g + (v<<16);
336     }
337 }
338
339 static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
340 {
341     unsigned i;
342     for (i=0; i<src_size; i+=3) {
343         register uint8_t x;
344         x          = src[i + 2];
345         dst[i + 1] = src[i + 1];
346         dst[i + 2] = src[i + 0];
347         dst[i + 0] = x;
348     }
349 }
350
351 static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
352                                      const uint8_t *vsrc, uint8_t *dst,
353                                      long width, long height,
354                                      long lumStride, long chromStride,
355                                      long dstStride, long vertLumPerChroma)
356 {
357     long y;
358     const int chromWidth = width >> 1;
359     for (y=0; y<height; y++) {
360 #if HAVE_FAST_64BIT
361         int i;
362         uint64_t *ldst = (uint64_t *) dst;
363         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
364         for (i = 0; i < chromWidth; i += 2) {
365             uint64_t k, l;
366             k = yc[0] + (uc[0] << 8) +
367                 (yc[1] << 16) + (vc[0] << 24);
368             l = yc[2] + (uc[1] << 8) +
369                 (yc[3] << 16) + (vc[1] << 24);
370             *ldst++ = k + (l << 32);
371             yc += 4;
372             uc += 2;
373             vc += 2;
374         }
375
376 #else
377         int i, *idst = (int32_t *) dst;
378         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
379         for (i = 0; i < chromWidth; i++) {
380 #if HAVE_BIGENDIAN
381             *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
382                 (yc[1] << 8) + (vc[0] << 0);
383 #else
384             *idst++ = yc[0] + (uc[0] << 8) +
385                 (yc[1] << 16) + (vc[0] << 24);
386 #endif
387             yc += 2;
388             uc++;
389             vc++;
390         }
391 #endif
392         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
393             usrc += chromStride;
394             vsrc += chromStride;
395         }
396         ysrc += lumStride;
397         dst  += dstStride;
398     }
399 }
400
401 /**
402  * Height should be a multiple of 2 and width should be a multiple of 16.
403  * (If this is a problem for anyone then tell me, and I will fix it.)
404  */
405 static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
406                                 const uint8_t *vsrc, uint8_t *dst,
407                                 long width, long height,
408                                 long lumStride, long chromStride,
409                                 long dstStride)
410 {
411     //FIXME interpolate chroma
412     yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
413                       chromStride, dstStride, 2);
414 }
415
416 static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
417                                      const uint8_t *vsrc, uint8_t *dst,
418                                      long width, long height,
419                                      long lumStride, long chromStride,
420                                      long dstStride, long vertLumPerChroma)
421 {
422     long y;
423     const int chromWidth = width >> 1;
424     for (y=0; y<height; y++) {
425 #if HAVE_FAST_64BIT
426         int i;
427         uint64_t *ldst = (uint64_t *) dst;
428         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
429         for (i = 0; i < chromWidth; i += 2) {
430             uint64_t k, l;
431             k = uc[0] + (yc[0] << 8) +
432                 (vc[0] << 16) + (yc[1] << 24);
433             l = uc[1] + (yc[2] << 8) +
434                 (vc[1] << 16) + (yc[3] << 24);
435             *ldst++ = k + (l << 32);
436             yc += 4;
437             uc += 2;
438             vc += 2;
439         }
440
441 #else
442         int i, *idst = (int32_t *) dst;
443         const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
444         for (i = 0; i < chromWidth; i++) {
445 #if HAVE_BIGENDIAN
446             *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
447                 (vc[0] << 8) + (yc[1] << 0);
448 #else
449             *idst++ = uc[0] + (yc[0] << 8) +
450                (vc[0] << 16) + (yc[1] << 24);
451 #endif
452             yc += 2;
453             uc++;
454             vc++;
455         }
456 #endif
457         if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
458             usrc += chromStride;
459             vsrc += chromStride;
460         }
461         ysrc += lumStride;
462         dst += dstStride;
463     }
464 }
465
466 /**
467  * Height should be a multiple of 2 and width should be a multiple of 16
468  * (If this is a problem for anyone then tell me, and I will fix it.)
469  */
470 static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
471                                 const uint8_t *vsrc, uint8_t *dst,
472                                 long width, long height,
473                                 long lumStride, long chromStride,
474                                 long dstStride)
475 {
476     //FIXME interpolate chroma
477     yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
478                       chromStride, dstStride, 2);
479 }
480
481 /**
482  * Width should be a multiple of 16.
483  */
484 static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
485                                    const uint8_t *vsrc, uint8_t *dst,
486                                    long width, long height,
487                                    long lumStride, long chromStride,
488                                    long dstStride)
489 {
490     yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
491                       chromStride, dstStride, 1);
492 }
493
494 /**
495  * Width should be a multiple of 16.
496  */
497 static inline void yuv422ptoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
498                                    const uint8_t *vsrc, uint8_t *dst,
499                                    long width, long height,
500                                    long lumStride, long chromStride,
501                                    long dstStride)
502 {
503     yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
504                       chromStride, dstStride, 1);
505 }
506
507 /**
508  * Height should be a multiple of 2 and width should be a multiple of 16.
509  * (If this is a problem for anyone then tell me, and I will fix it.)
510  */
511 static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst,
512                                 uint8_t *udst, uint8_t *vdst,
513                                 long width, long height,
514                                 long lumStride, long chromStride,
515                                 long srcStride)
516 {
517     long y;
518     const int chromWidth = width >> 1;
519     for (y=0; y<height; y+=2) {
520         long i;
521         for (i=0; i<chromWidth; i++) {
522             ydst[2*i+0]     = src[4*i+0];
523             udst[i]     = src[4*i+1];
524             ydst[2*i+1]     = src[4*i+2];
525             vdst[i]     = src[4*i+3];
526         }
527         ydst += lumStride;
528         src  += srcStride;
529
530         for (i=0; i<chromWidth; i++) {
531             ydst[2*i+0]     = src[4*i+0];
532             ydst[2*i+1]     = src[4*i+2];
533         }
534         udst += chromStride;
535         vdst += chromStride;
536         ydst += lumStride;
537         src  += srcStride;
538     }
539 }
540
541 static inline void planar2x_c(const uint8_t *src, uint8_t *dst, long srcWidth,
542                               long srcHeight, long srcStride, long dstStride)
543 {
544     long x,y;
545
546     dst[0]= src[0];
547
548     // first line
549     for (x=0; x<srcWidth-1; x++) {
550         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
551         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
552     }
553     dst[2*srcWidth-1]= src[srcWidth-1];
554
555     dst+= dstStride;
556
557     for (y=1; y<srcHeight; y++) {
558         const int mmxSize = 1;
559
560         dst[0        ]= (3*src[0] +   src[srcStride])>>2;
561         dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;
562
563         for (x=mmxSize-1; x<srcWidth-1; x++) {
564             dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
565             dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
566             dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
567             dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
568         }
569         dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
570         dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;
571
572         dst+=dstStride*2;
573         src+=srcStride;
574     }
575
576     // last line
577 #if 1
578     dst[0]= src[0];
579
580     for (x=0; x<srcWidth-1; x++) {
581         dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
582         dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
583     }
584     dst[2*srcWidth-1]= src[srcWidth-1];
585 #else
586     for (x=0; x<srcWidth; x++) {
587         dst[2*x+0]=
588         dst[2*x+1]= src[x];
589     }
590 #endif
591 }
592
593 /**
594  * Height should be a multiple of 2 and width should be a multiple of 16.
595  * (If this is a problem for anyone then tell me, and I will fix it.)
596  * Chrominance data is only taken from every second line, others are ignored.
597  * FIXME: Write HQ version.
598  */
599 static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
600                                 uint8_t *udst, uint8_t *vdst,
601                                 long width, long height,
602                                 long lumStride, long chromStride,
603                                 long srcStride)
604 {
605     long y;
606     const int chromWidth = width >> 1;
607     for (y=0; y<height; y+=2) {
608         long i;
609         for (i=0; i<chromWidth; i++) {
610             udst[i]     = src[4*i+0];
611             ydst[2*i+0] = src[4*i+1];
612             vdst[i]     = src[4*i+2];
613             ydst[2*i+1] = src[4*i+3];
614         }
615         ydst += lumStride;
616         src  += srcStride;
617
618         for (i=0; i<chromWidth; i++) {
619             ydst[2*i+0] = src[4*i+1];
620             ydst[2*i+1] = src[4*i+3];
621         }
622         udst += chromStride;
623         vdst += chromStride;
624         ydst += lumStride;
625         src  += srcStride;
626     }
627 }
628
629 /**
630  * Height should be a multiple of 2 and width should be a multiple of 2.
631  * (If this is a problem for anyone then tell me, and I will fix it.)
632  * Chrominance data is only taken from every second line,
633  * others are ignored in the C version.
634  * FIXME: Write HQ version.
635  */
636 static inline void rgb24toyv12_c(const uint8_t *src, uint8_t *ydst,
637                                  uint8_t *udst, uint8_t *vdst,
638                                  long width, long height,
639                                  long lumStride, long chromStride,
640                                  long srcStride)
641 {
642     long y;
643     const int chromWidth = width >> 1;
644     y=0;
645     for (; y<height; y+=2) {
646         long i;
647         for (i=0; i<chromWidth; i++) {
648             unsigned int b = src[6*i+0];
649             unsigned int g = src[6*i+1];
650             unsigned int r = src[6*i+2];
651
652             unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
653             unsigned int V  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
654             unsigned int U  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
655
656             udst[i]     = U;
657             vdst[i]     = V;
658             ydst[2*i]   = Y;
659
660             b = src[6*i+3];
661             g = src[6*i+4];
662             r = src[6*i+5];
663
664             Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
665             ydst[2*i+1]     = Y;
666         }
667         ydst += lumStride;
668         src  += srcStride;
669
670         for (i=0; i<chromWidth; i++) {
671             unsigned int b = src[6*i+0];
672             unsigned int g = src[6*i+1];
673             unsigned int r = src[6*i+2];
674
675             unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
676
677             ydst[2*i]     = Y;
678
679             b = src[6*i+3];
680             g = src[6*i+4];
681             r = src[6*i+5];
682
683             Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
684             ydst[2*i+1]     = Y;
685         }
686         udst += chromStride;
687         vdst += chromStride;
688         ydst += lumStride;
689         src  += srcStride;
690     }
691 }
692
693 static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
694                               uint8_t *dest, long width,
695                               long height, long src1Stride,
696                               long src2Stride, long dstStride)
697 {
698     long h;
699
700     for (h=0; h < height; h++) {
701         long w;
702         for (w=0; w < width; w++) {
703             dest[2*w+0] = src1[w];
704             dest[2*w+1] = src2[w];
705         }
706         dest += dstStride;
707         src1 += src1Stride;
708         src2 += src2Stride;
709     }
710 }
711
712 static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
713                                  uint8_t *dst1, uint8_t *dst2,
714                                  long width, long height,
715                                  long srcStride1, long srcStride2,
716                                  long dstStride1, long dstStride2)
717 {
718     int y;
719     long x,w,h;
720     w=width/2; h=height/2;
721     for (y=0;y<h;y++) {
722         const uint8_t* s1=src1+srcStride1*(y>>1);
723         uint8_t* d=dst1+dstStride1*y;
724         x=0;
725         for (;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
726     }
727     for (y=0;y<h;y++) {
728         const uint8_t* s2=src2+srcStride2*(y>>1);
729         uint8_t* d=dst2+dstStride2*y;
730         x=0;
731         for (;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
732     }
733 }
734
735 static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
736                                   const uint8_t *src3, uint8_t *dst,
737                                   long width, long height,
738                                   long srcStride1, long srcStride2,
739                                   long srcStride3, long dstStride)
740 {
741     int x;
742     long y,w,h;
743     w=width/2; h=height;
744     for (y=0;y<h;y++) {
745         const uint8_t* yp=src1+srcStride1*y;
746         const uint8_t* up=src2+srcStride2*(y>>2);
747         const uint8_t* vp=src3+srcStride3*(y>>2);
748         uint8_t* d=dst+dstStride*y;
749         x=0;
750         for (; x<w; x++) {
751             const long x2 = x<<2;
752             d[8*x+0] = yp[x2];
753             d[8*x+1] = up[x];
754             d[8*x+2] = yp[x2+1];
755             d[8*x+3] = vp[x];
756             d[8*x+4] = yp[x2+2];
757             d[8*x+5] = up[x];
758             d[8*x+6] = yp[x2+3];
759             d[8*x+7] = vp[x];
760         }
761     }
762 }
763
764 static void extract_even_c(const uint8_t *src, uint8_t *dst, int count)
765 {
766     dst +=   count;
767     src += 2*count;
768     count= - count;
769
770     while(count<0) {
771         dst[count]= src[2*count];
772         count++;
773     }
774 }
775
776 static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
777                             int count)
778 {
779     dst0+=   count;
780     dst1+=   count;
781     src += 4*count;
782     count= - count;
783     while(count<0) {
784         dst0[count]= src[4*count+0];
785         dst1[count]= src[4*count+2];
786         count++;
787     }
788 }
789
790 static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1,
791                                uint8_t *dst0, uint8_t *dst1, int count)
792 {
793     dst0 +=   count;
794     dst1 +=   count;
795     src0 += 4*count;
796     src1 += 4*count;
797     count= - count;
798     while(count<0) {
799         dst0[count]= (src0[4*count+0]+src1[4*count+0])>>1;
800         dst1[count]= (src0[4*count+2]+src1[4*count+2])>>1;
801         count++;
802     }
803 }
804
805 static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
806                            int count)
807 {
808     dst0+=   count;
809     dst1+=   count;
810     src += 4*count;
811     count= - count;
812     src++;
813     while(count<0) {
814         dst0[count]= src[4*count+0];
815         dst1[count]= src[4*count+2];
816         count++;
817     }
818 }
819
820 static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1,
821                               uint8_t *dst0, uint8_t *dst1, int count)
822 {
823     dst0 +=   count;
824     dst1 +=   count;
825     src0 += 4*count;
826     src1 += 4*count;
827     count= - count;
828     src0++;
829     src1++;
830     while(count<0) {
831         dst0[count]= (src0[4*count+0]+src1[4*count+0])>>1;
832         dst1[count]= (src0[4*count+2]+src1[4*count+2])>>1;
833         count++;
834     }
835 }
836
837 static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
838                            const uint8_t *src, long width, long height,
839                            long lumStride, long chromStride, long srcStride)
840 {
841     long y;
842     const long chromWidth= -((-width)>>1);
843
844     for (y=0; y<height; y++) {
845         extract_even_c(src, ydst, width);
846         if(y&1) {
847             extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth);
848             udst+= chromStride;
849             vdst+= chromStride;
850         }
851
852         src += srcStride;
853         ydst+= lumStride;
854     }
855 }
856
857 static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
858                            const uint8_t *src, long width, long height,
859                            long lumStride, long chromStride, long srcStride)
860 {
861     long y;
862     const long chromWidth= -((-width)>>1);
863
864     for (y=0; y<height; y++) {
865         extract_even_c(src, ydst, width);
866         extract_odd2_c(src, udst, vdst, chromWidth);
867
868         src += srcStride;
869         ydst+= lumStride;
870         udst+= chromStride;
871         vdst+= chromStride;
872     }
873 }
874
875 static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
876                            const uint8_t *src, long width, long height,
877                            long lumStride, long chromStride, long srcStride)
878 {
879     long y;
880     const long chromWidth= -((-width)>>1);
881
882     for (y=0; y<height; y++) {
883         extract_even_c(src + 1, ydst, width);
884         if(y&1) {
885             extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth);
886             udst+= chromStride;
887             vdst+= chromStride;
888         }
889
890         src += srcStride;
891         ydst+= lumStride;
892     }
893 }
894
895 static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
896                            const uint8_t *src, long width, long height,
897                            long lumStride, long chromStride, long srcStride)
898 {
899     long y;
900     const long chromWidth= -((-width)>>1);
901
902     for (y=0; y<height; y++) {
903         extract_even_c(src + 1, ydst, width);
904         extract_even2_c(src, udst, vdst, chromWidth);
905
906         src += srcStride;
907         ydst+= lumStride;
908         udst+= chromStride;
909         vdst+= chromStride;
910     }
911 }
912
913 static inline void rgb2rgb_init_c(void)
914 {
915     rgb15to16          = rgb15to16_c;
916     rgb15tobgr24       = rgb15tobgr24_c;
917     rgb15to32          = rgb15to32_c;
918     rgb16tobgr24       = rgb16tobgr24_c;
919     rgb16to32          = rgb16to32_c;
920     rgb16to15          = rgb16to15_c;
921     rgb24tobgr16       = rgb24tobgr16_c;
922     rgb24tobgr15       = rgb24tobgr15_c;
923     rgb24tobgr32       = rgb24tobgr32_c;
924     rgb32to16          = rgb32to16_c;
925     rgb32to15          = rgb32to15_c;
926     rgb32tobgr24       = rgb32tobgr24_c;
927     rgb24to15          = rgb24to15_c;
928     rgb24to16          = rgb24to16_c;
929     rgb24tobgr24       = rgb24tobgr24_c;
930     shuffle_bytes_2103 = shuffle_bytes_2103_c;
931     rgb32tobgr16       = rgb32tobgr16_c;
932     rgb32tobgr15       = rgb32tobgr15_c;
933     yv12toyuy2         = yv12toyuy2_c;
934     yv12touyvy         = yv12touyvy_c;
935     yuv422ptoyuy2      = yuv422ptoyuy2_c;
936     yuv422ptouyvy      = yuv422ptouyvy_c;
937     yuy2toyv12         = yuy2toyv12_c;
938     planar2x           = planar2x_c;
939     rgb24toyv12        = rgb24toyv12_c;
940     interleaveBytes    = interleaveBytes_c;
941     vu9_to_vu12        = vu9_to_vu12_c;
942     yvu9_to_yuy2       = yvu9_to_yuy2_c;
943
944     uyvytoyuv420       = uyvytoyuv420_c;
945     uyvytoyuv422       = uyvytoyuv422_c;
946     yuyvtoyuv420       = yuyvtoyuv420_c;
947     yuyvtoyuv422       = yuyvtoyuv422_c;
948 }