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