rgb2rgb_template.c 27.2 KB
Newer Older
1
/*
2 3 4 5 6 7 8
 * software RGB to RGB converter
 * pluralize by software PAL8 to RGB converter
 *              software YUV to YUV converter
 *              software YUV to RGB converter
 * Written by Nick Kurshev.
 * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at)
 * 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 14 15
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * 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 20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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
 */

Arpi's avatar
Arpi committed
27 28
#include <stddef.h>

29
static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst, long src_size)
Nick Kurshev's avatar
Nick Kurshev committed
30
{
31 32 33 34
    uint8_t *dest = dst;
    const uint8_t *s = src;
    const uint8_t *end;
    end = s + src_size;
35

Ramiro Polla's avatar
Ramiro Polla committed
36
    while (s < end) {
Ramiro Polla's avatar
Indent.  
Ramiro Polla committed
37
#if HAVE_BIGENDIAN
38
        /* RGB24 (= R,G,B) -> RGB32 (= A,B,G,R) */
39
        *dest++ = 255;
40 41 42 43
        *dest++ = s[2];
        *dest++ = s[1];
        *dest++ = s[0];
        s+=3;
Ramiro Polla's avatar
Indent.  
Ramiro Polla committed
44
#else
45 46 47
        *dest++ = *s++;
        *dest++ = *s++;
        *dest++ = *s++;
48
        *dest++ = 255;
Ramiro Polla's avatar
Indent.  
Ramiro Polla committed
49
#endif
50
    }
Nick Kurshev's avatar
Nick Kurshev committed
51
}
Nick Kurshev's avatar
Nick Kurshev committed
52

53
static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
Nick Kurshev's avatar
Nick Kurshev committed
54
{
55 56 57
    uint8_t *dest = dst;
    const uint8_t *s = src;
    const uint8_t *end;
58

59
    end = s + src_size;
60

Ramiro Polla's avatar
Ramiro Polla committed
61
    while (s < end) {
62
#if HAVE_BIGENDIAN
63 64 65 66 67 68
        /* RGB32 (= A,B,G,R) -> RGB24 (= R,G,B) */
        s++;
        dest[2] = *s++;
        dest[1] = *s++;
        dest[0] = *s++;
        dest += 3;
Alex Beregszaszi's avatar
Alex Beregszaszi committed
69
#else
70 71 72 73
        *dest++ = *s++;
        *dest++ = *s++;
        *dest++ = *s++;
        s++;
Alex Beregszaszi's avatar
Alex Beregszaszi committed
74
#endif
75
    }
Nick Kurshev's avatar
Nick Kurshev committed
76
}
Nick Kurshev's avatar
Nick Kurshev committed
77

78
/*
79 80
 original by Strepto/Astral
 ported to gcc & bugfixed: A'rpi
Nick Kurshev's avatar
Nick Kurshev committed
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)
Nick Kurshev's avatar
Nick Kurshev committed
85
{
86 87 88 89 90
    register const uint8_t* s=src;
    register uint8_t* d=dst;
    register const uint8_t *end;
    const uint8_t *mm_end;
    end = s + src_size;
91
    mm_end = end - 3;
Ramiro Polla's avatar
Ramiro Polla committed
92
    while (s < mm_end) {
93
        register unsigned x= *((const uint32_t *)s);
94 95 96
        *((uint32_t *)d) = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
        d+=4;
        s+=4;
Arpi's avatar
Arpi committed
97
    }
Ramiro Polla's avatar
Ramiro Polla committed
98
    if (s < end) {
99
        register unsigned short x= *((const uint16_t *)s);
100
        *((uint16_t *)d) = (x&0x7FFF) + (x&0x7FE0);
Arpi's avatar
Arpi committed
101
    }
Nick Kurshev's avatar
Nick Kurshev committed
102
}
103

104
static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, long src_size)
105
{
106 107 108 109 110
    register const uint8_t* s=src;
    register uint8_t* d=dst;
    register const uint8_t *end;
    const uint8_t *mm_end;
    end = s + src_size;
111

112
    mm_end = end - 3;
Ramiro Polla's avatar
Ramiro Polla committed
113
    while (s < mm_end) {
114
        register uint32_t x= *((const uint32_t*)s);
115 116 117
        *((uint32_t *)d) = ((x>>1)&0x7FE07FE0) | (x&0x001F001F);
        s+=4;
        d+=4;
118
    }
Ramiro Polla's avatar
Ramiro Polla committed
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 128 129 130
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
131

Ramiro Polla's avatar
Ramiro Polla committed
132
    while (s < end) {
133
        register int rgb = *(const uint32_t*)s; s += 4;
134 135
        *d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);
    }
136 137
}

138
static inline void rgb32tobgr16_c(const uint8_t *src, uint8_t *dst, long src_size)
139
{
140 141 142 143
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
144
    while (s < end) {
145
        register int rgb = *(const uint32_t*)s; s += 4;
146 147
        *d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);
    }
148 149
}

150
static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, long src_size)
151
{
152 153 154 155
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
156
    while (s < end) {
157
        register int rgb = *(const uint32_t*)s; s += 4;
158 159
        *d++ = ((rgb&0xFF)>>3) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>9);
    }
160 161
}

162
static inline void rgb32tobgr15_c(const uint8_t *src, uint8_t *dst, long src_size)
163
{
164 165 166 167
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
168
    while (s < end) {
169
        register int rgb = *(const uint32_t*)s; s += 4;
170 171
        *d++ = ((rgb&0xF8)<<7) + ((rgb&0xF800)>>6) + ((rgb&0xF80000)>>19);
    }
172 173
}

174
static inline void rgb24tobgr16_c(const uint8_t *src, uint8_t *dst, long src_size)
175
{
176 177 178 179
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
180
    while (s < end) {
181 182 183 184 185
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
        *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
    }
186 187
}

188
static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, long src_size)
189
{
190 191 192 193
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
194
    while (s < end) {
195 196 197 198 199
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
        *d++ = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
    }
200 201
}

202
static inline void rgb24tobgr15_c(const uint8_t *src, uint8_t *dst, long src_size)
203
{
204 205 206 207
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
208
    while (s < end) {
209 210 211 212 213
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
        *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
    }
Arpi's avatar
Arpi committed
214 215
}

216
static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, long src_size)
217
{
218 219 220 221
    const uint8_t *s = src;
    const uint8_t *end;
    uint16_t *d = (uint16_t *)dst;
    end = s + src_size;
Ramiro Polla's avatar
Ramiro Polla committed
222
    while (s < end) {
223 224 225 226 227
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
        *d++ = (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
    }
228 229
}

Arpi's avatar
Arpi committed
230
/*
Diego Biurrun's avatar
Diego Biurrun committed
231 232 233 234
  I use less accurate approximation here by simply left-shifting the input
  value and filling the low order bits with zeroes. This method improves PNG
  compression but this scheme cannot reproduce white exactly, since it does
  not generate an all-ones maximum value; the net effect is to darken the
Arpi's avatar
Arpi committed
235 236 237 238 239 240 241 242 243 244 245 246
  image slightly.

  The better method should be "left bit replication":

   4 3 2 1 0
   ---------
   1 1 0 1 1

   7 6 5 4 3  2 1 0
   ----------------
   1 1 0 1 1  1 1 0
   |=======|  |===|
247
       |      leftmost bits repeated to fill open bits
Arpi's avatar
Arpi committed
248
       |
249
   original bits
Arpi's avatar
Arpi committed
250
*/
251
static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
Arpi's avatar
Arpi committed
252
{
253
    const uint16_t *end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
254
    uint8_t *d = dst;
255
    const uint16_t *s = (const uint16_t*)src;
256
    end = s + src_size/2;
Ramiro Polla's avatar
Ramiro Polla committed
257
    while (s < end) {
258 259 260 261 262 263
        register uint16_t bgr;
        bgr = *s++;
        *d++ = (bgr&0x1F)<<3;
        *d++ = (bgr&0x3E0)>>2;
        *d++ = (bgr&0x7C00)>>7;
    }
Arpi's avatar
Arpi committed
264 265
}

266
static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
Arpi's avatar
Arpi committed
267
{
268 269 270 271
    const uint16_t *end;
    uint8_t *d = (uint8_t *)dst;
    const uint16_t *s = (const uint16_t *)src;
    end = s + src_size/2;
Ramiro Polla's avatar
Ramiro Polla committed
272
    while (s < end) {
273 274 275 276 277 278
        register uint16_t bgr;
        bgr = *s++;
        *d++ = (bgr&0x1F)<<3;
        *d++ = (bgr&0x7E0)>>3;
        *d++ = (bgr&0xF800)>>8;
    }
Arpi's avatar
Arpi committed
279 280
}

281
static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, long src_size)
Arpi's avatar
Arpi committed
282
{
283
    const uint16_t *end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
284
    uint8_t *d = dst;
285 286
    const uint16_t *s = (const uint16_t *)src;
    end = s + src_size/2;
Ramiro Polla's avatar
Ramiro Polla committed
287
    while (s < end) {
288 289
        register uint16_t bgr;
        bgr = *s++;
290
#if HAVE_BIGENDIAN
291
        *d++ = 255;
292 293 294
        *d++ = (bgr&0x7C00)>>7;
        *d++ = (bgr&0x3E0)>>2;
        *d++ = (bgr&0x1F)<<3;
Alex Beregszaszi's avatar
Alex Beregszaszi committed
295
#else
296 297 298
        *d++ = (bgr&0x1F)<<3;
        *d++ = (bgr&0x3E0)>>2;
        *d++ = (bgr&0x7C00)>>7;
299
        *d++ = 255;
Michael Niedermayer's avatar
Michael Niedermayer committed
300
#endif
301
    }
Arpi's avatar
Arpi committed
302
}
303

304
static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, long src_size)
Arpi's avatar
Arpi committed
305
{
306
    const uint16_t *end;
Baptiste Coudurier's avatar
Baptiste Coudurier committed
307
    uint8_t *d = dst;
308
    const uint16_t *s = (const uint16_t*)src;
309
    end = s + src_size/2;
Ramiro Polla's avatar
Ramiro Polla committed
310
    while (s < end) {
311 312
        register uint16_t bgr;
        bgr = *s++;
313
#if HAVE_BIGENDIAN
314
        *d++ = 255;
315 316 317
        *d++ = (bgr&0xF800)>>8;
        *d++ = (bgr&0x7E0)>>3;
        *d++ = (bgr&0x1F)<<3;
Alex Beregszaszi's avatar
Alex Beregszaszi committed
318
#else
319 320 321
        *d++ = (bgr&0x1F)<<3;
        *d++ = (bgr&0x7E0)>>3;
        *d++ = (bgr&0xF800)>>8;
322
        *d++ = 255;
Alex Beregszaszi's avatar
Alex Beregszaszi committed
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 331
    const uint8_t *s = src-idx;
    uint8_t *d = dst-idx;
332
    for (; idx<15; idx+=4) {
333
        register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
334 335 336
        v &= 0xff00ff;
        *(uint32_t *)&d[idx] = (v>>16) + g + (v<<16);
    }
337 338
}

339
static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, long src_size)
Michael Niedermayer's avatar
Michael Niedermayer committed
340
{
341
    unsigned i;
Ramiro Polla's avatar
Ramiro Polla committed
342
    for (i=0; i<src_size; i+=3) {
343 344 345 346 347 348
        register uint8_t x;
        x          = src[i + 2];
        dst[i + 1] = src[i + 1];
        dst[i + 2] = src[i + 0];
        dst[i + 0] = x;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
349 350
}

351 352 353 354 355
static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
                                     long width, long height,
                                     long lumStride, long chromStride,
                                     long dstStride, long vertLumPerChroma)
Michael Niedermayer's avatar
Michael Niedermayer committed
356
{
357
    long y;
358
    const int chromWidth = width >> 1;
Ramiro Polla's avatar
Ramiro Polla committed
359
    for (y=0; y<height; y++) {
360
#if HAVE_FAST_64BIT
361 362 363
        int i;
        uint64_t *ldst = (uint64_t *) dst;
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
364
        for (i = 0; i < chromWidth; i += 2) {
365 366 367 368 369 370 371 372 373 374
            uint64_t k, l;
            k = yc[0] + (uc[0] << 8) +
                (yc[1] << 16) + (vc[0] << 24);
            l = yc[2] + (uc[1] << 8) +
                (yc[3] << 16) + (vc[1] << 24);
            *ldst++ = k + (l << 32);
            yc += 4;
            uc += 2;
            vc += 2;
        }
Arpi's avatar
Arpi committed
375 376

#else
377 378
        int i, *idst = (int32_t *) dst;
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
379
        for (i = 0; i < chromWidth; i++) {
380
#if HAVE_BIGENDIAN
381 382
            *idst++ = (yc[0] << 24)+ (uc[0] << 16) +
                (yc[1] << 8) + (vc[0] << 0);
383
#else
384 385 386 387 388 389 390 391
            *idst++ = yc[0] + (uc[0] << 8) +
                (yc[1] << 16) + (vc[0] << 24);
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
Ramiro Polla's avatar
Ramiro Polla committed
392
        if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
393 394 395 396 397 398
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
        dst  += dstStride;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
399 400
}

401
/**
402 403
 * Height should be a multiple of 2 and width should be a multiple of 16.
 * (If this is a problem for anyone then tell me, and I will fix it.)
404
 */
405 406 407 408 409
static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
                                long width, long height,
                                long lumStride, long chromStride,
                                long dstStride)
410
{
411
    //FIXME interpolate chroma
412 413
    yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
414 415
}

416 417 418 419 420
static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
                                     long width, long height,
                                     long lumStride, long chromStride,
                                     long dstStride, long vertLumPerChroma)
421
{
422
    long y;
423
    const int chromWidth = width >> 1;
Ramiro Polla's avatar
Ramiro Polla committed
424
    for (y=0; y<height; y++) {
425
#if HAVE_FAST_64BIT
426 427 428
        int i;
        uint64_t *ldst = (uint64_t *) dst;
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
429
        for (i = 0; i < chromWidth; i += 2) {
430 431 432 433 434 435 436 437 438 439
            uint64_t k, l;
            k = uc[0] + (yc[0] << 8) +
                (vc[0] << 16) + (yc[1] << 24);
            l = uc[1] + (yc[2] << 8) +
                (vc[1] << 16) + (yc[3] << 24);
            *ldst++ = k + (l << 32);
            yc += 4;
            uc += 2;
            vc += 2;
        }
440 441

#else
442 443
        int i, *idst = (int32_t *) dst;
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
444
        for (i = 0; i < chromWidth; i++) {
445
#if HAVE_BIGENDIAN
446 447
            *idst++ = (uc[0] << 24)+ (yc[0] << 16) +
                (vc[0] << 8) + (yc[1] << 0);
448
#else
449
            *idst++ = uc[0] + (yc[0] << 8) +
450
               (vc[0] << 16) + (yc[1] << 24);
451 452 453 454 455 456
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
Ramiro Polla's avatar
Ramiro Polla committed
457
        if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {
458 459 460 461 462 463
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
        dst += dstStride;
    }
464 465 466
}

/**
467 468
 * Height should be a multiple of 2 and width should be a multiple of 16
 * (If this is a problem for anyone then tell me, and I will fix it.)
469
 */
470 471 472 473 474
static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
                                long width, long height,
                                long lumStride, long chromStride,
                                long dstStride)
475
{
476
    //FIXME interpolate chroma
477 478
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
479 480
}

481 482 483
/**
 * Width should be a multiple of 16.
 */
484 485 486 487 488
static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                   const uint8_t *vsrc, uint8_t *dst,
                                   long width, long height,
                                   long lumStride, long chromStride,
                                   long dstStride)
489
{
490 491
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 1);
492 493
}

494
/**
Diego Biurrun's avatar
Diego Biurrun committed
495
 * Width should be a multiple of 16.
496
 */
497 498 499 500 501
static inline void yuv422ptoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                   const uint8_t *vsrc, uint8_t *dst,
                                   long width, long height,
                                   long lumStride, long chromStride,
                                   long dstStride)
502
{
503 504
    yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 1);
505 506
}

507
/**
508 509
 * Height should be a multiple of 2 and width should be a multiple of 16.
 * (If this is a problem for anyone then tell me, and I will fix it.)
510
 */
511 512 513 514 515
static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
                                long width, long height,
                                long lumStride, long chromStride,
                                long srcStride)
Michael Niedermayer's avatar
Michael Niedermayer committed
516
{
517
    long y;
518
    const int chromWidth = width >> 1;
Ramiro Polla's avatar
Ramiro Polla committed
519
    for (y=0; y<height; y+=2) {
520
        long i;
Ramiro Polla's avatar
Ramiro Polla committed
521
        for (i=0; i<chromWidth; i++) {
522 523 524 525 526 527 528 529
            ydst[2*i+0]     = src[4*i+0];
            udst[i]     = src[4*i+1];
            ydst[2*i+1]     = src[4*i+2];
            vdst[i]     = src[4*i+3];
        }
        ydst += lumStride;
        src  += srcStride;

Ramiro Polla's avatar
Ramiro Polla committed
530
        for (i=0; i<chromWidth; i++) {
531 532 533 534 535 536 537 538
            ydst[2*i+0]     = src[4*i+0];
            ydst[2*i+1]     = src[4*i+2];
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
539
}
Arpi's avatar
Arpi committed
540

541 542
static inline void planar2x_c(const uint8_t *src, uint8_t *dst, long srcWidth,
                              long srcHeight, long srcStride, long dstStride)
543
{
544
    long x,y;
545

546
    dst[0]= src[0];
547

548
    // first line
Ramiro Polla's avatar
Ramiro Polla committed
549
    for (x=0; x<srcWidth-1; x++) {
550 551 552 553
        dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
        dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
    }
    dst[2*srcWidth-1]= src[srcWidth-1];
554

Ramiro Polla's avatar
Ramiro Polla committed
555
    dst+= dstStride;
556

Ramiro Polla's avatar
Ramiro Polla committed
557
    for (y=1; y<srcHeight; y++) {
558
        const int mmxSize = 1;
559

560 561 562
        dst[0        ]= (3*src[0] +   src[srcStride])>>2;
        dst[dstStride]= (  src[0] + 3*src[srcStride])>>2;

Ramiro Polla's avatar
Ramiro Polla committed
563
        for (x=mmxSize-1; x<srcWidth-1; x++) {
564 565 566 567 568 569 570 571 572 573 574
            dst[2*x          +1]= (3*src[x+0] +   src[x+srcStride+1])>>2;
            dst[2*x+dstStride+2]= (  src[x+0] + 3*src[x+srcStride+1])>>2;
            dst[2*x+dstStride+1]= (  src[x+1] + 3*src[x+srcStride  ])>>2;
            dst[2*x          +2]= (3*src[x+1] +   src[x+srcStride  ])>>2;
        }
        dst[srcWidth*2 -1            ]= (3*src[srcWidth-1] +   src[srcWidth-1 + srcStride])>>2;
        dst[srcWidth*2 -1 + dstStride]= (  src[srcWidth-1] + 3*src[srcWidth-1 + srcStride])>>2;

        dst+=dstStride*2;
        src+=srcStride;
    }
575

576
    // last line
Michael Niedermayer's avatar
Michael Niedermayer committed
577
#if 1
578
    dst[0]= src[0];
579

Ramiro Polla's avatar
Ramiro Polla committed
580
    for (x=0; x<srcWidth-1; x++) {
581 582 583 584
        dst[2*x+1]= (3*src[x] +   src[x+1])>>2;
        dst[2*x+2]= (  src[x] + 3*src[x+1])>>2;
    }
    dst[2*srcWidth-1]= src[srcWidth-1];
Michael Niedermayer's avatar
Michael Niedermayer committed
585
#else
Ramiro Polla's avatar
Ramiro Polla committed
586
    for (x=0; x<srcWidth; x++) {
587 588 589
        dst[2*x+0]=
        dst[2*x+1]= src[x];
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
590
#endif
591 592
}

Arpi's avatar
Arpi committed
593
/**
594 595 596
 * Height should be a multiple of 2 and width should be a multiple of 16.
 * (If this is a problem for anyone then tell me, and I will fix it.)
 * Chrominance data is only taken from every second line, others are ignored.
Diego Biurrun's avatar
Diego Biurrun committed
597
 * FIXME: Write HQ version.
Arpi's avatar
Arpi committed
598
 */
599 600 601 602 603
static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
                                long width, long height,
                                long lumStride, long chromStride,
                                long srcStride)
Arpi's avatar
Arpi committed
604
{
605
    long y;
606
    const int chromWidth = width >> 1;
Ramiro Polla's avatar
Ramiro Polla committed
607
    for (y=0; y<height; y+=2) {
608
        long i;
Ramiro Polla's avatar
Ramiro Polla committed
609
        for (i=0; i<chromWidth; i++) {
610 611 612 613 614 615 616 617
            udst[i]     = src[4*i+0];
            ydst[2*i+0] = src[4*i+1];
            vdst[i]     = src[4*i+2];
            ydst[2*i+1] = src[4*i+3];
        }
        ydst += lumStride;
        src  += srcStride;

Ramiro Polla's avatar
Ramiro Polla committed
618
        for (i=0; i<chromWidth; i++) {
619 620 621 622 623 624 625 626
            ydst[2*i+0] = src[4*i+1];
            ydst[2*i+1] = src[4*i+3];
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
Arpi's avatar
Arpi committed
627 628
}

Michael Niedermayer's avatar
Michael Niedermayer committed
629
/**
630 631 632
 * Height should be a multiple of 2 and width should be a multiple of 2.
 * (If this is a problem for anyone then tell me, and I will fix it.)
 * Chrominance data is only taken from every second line,
Diego Biurrun's avatar
Diego Biurrun committed
633 634
 * others are ignored in the C version.
 * FIXME: Write HQ version.
Michael Niedermayer's avatar
Michael Niedermayer committed
635
 */
636 637 638
void rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
                   uint8_t *vdst, long width, long height, long lumStride,
                   long chromStride, long srcStride)
Michael Niedermayer's avatar
Michael Niedermayer committed
639
{
640
    long y;
641
    const int chromWidth = width >> 1;
642
    y=0;
Ramiro Polla's avatar
Ramiro Polla committed
643
    for (; y<height; y+=2) {
644
        long i;
Ramiro Polla's avatar
Ramiro Polla committed
645
        for (i=0; i<chromWidth; i++) {
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
            unsigned int b = src[6*i+0];
            unsigned int g = src[6*i+1];
            unsigned int r = src[6*i+2];

            unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
            unsigned int V  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
            unsigned int U  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;

            udst[i]     = U;
            vdst[i]     = V;
            ydst[2*i]   = Y;

            b = src[6*i+3];
            g = src[6*i+4];
            r = src[6*i+5];

            Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
            ydst[2*i+1]     = Y;
        }
        ydst += lumStride;
        src  += srcStride;

Ramiro Polla's avatar
Ramiro Polla committed
668
        for (i=0; i<chromWidth; i++) {
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
            unsigned int b = src[6*i+0];
            unsigned int g = src[6*i+1];
            unsigned int r = src[6*i+2];

            unsigned int Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;

            ydst[2*i]     = Y;

            b = src[6*i+3];
            g = src[6*i+4];
            r = src[6*i+5];

            Y  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
            ydst[2*i+1]     = Y;
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
689
}
690

691 692 693 694
static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
                              uint8_t *dest, long width,
                              long height, long src1Stride,
                              long src2Stride, long dstStride)
Ramiro Polla's avatar
Ramiro Polla committed
695
{
696
    long h;
697

Ramiro Polla's avatar
Ramiro Polla committed
698
    for (h=0; h < height; h++) {
699
        long w;
Ramiro Polla's avatar
Ramiro Polla committed
700
        for (w=0; w < width; w++) {
701 702 703 704
            dest[2*w+0] = src1[w];
            dest[2*w+1] = src2[w];
        }
        dest += dstStride;
705 706
        src1 += src1Stride;
        src2 += src2Stride;
707
    }
708
}
709

710 711 712 713 714
static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
                                 uint8_t *dst1, uint8_t *dst2,
                                 long width, long height,
                                 long srcStride1, long srcStride2,
                                 long dstStride1, long dstStride2)
715
{
716
    int y;
Michael Niedermayer's avatar
Revert  
Michael Niedermayer committed
717
    long x,w,h;
718
    w=width/2; h=height/2;
Ramiro Polla's avatar
Ramiro Polla committed
719
    for (y=0;y<h;y++) {
Ramiro Polla's avatar
Ramiro Polla committed
720 721 722 723
        const uint8_t* s1=src1+srcStride1*(y>>1);
        uint8_t* d=dst1+dstStride1*y;
        x=0;
        for (;x<w;x++) d[2*x]=d[2*x+1]=s1[x];
724
    }
Ramiro Polla's avatar
Ramiro Polla committed
725
    for (y=0;y<h;y++) {
Ramiro Polla's avatar
Ramiro Polla committed
726 727 728 729
        const uint8_t* s2=src2+srcStride2*(y>>1);
        uint8_t* d=dst2+dstStride2*y;
        x=0;
        for (;x<w;x++) d[2*x]=d[2*x+1]=s2[x];
730 731 732
    }
}

733 734 735 736 737
static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
                                  const uint8_t *src3, uint8_t *dst,
                                  long width, long height,
                                  long srcStride1, long srcStride2,
                                  long srcStride3, long dstStride)
738
{
739
    int x;
740
    long y,w,h;
741
    w=width/2; h=height;
Ramiro Polla's avatar
Ramiro Polla committed
742
    for (y=0;y<h;y++) {
Ramiro Polla's avatar
Ramiro Polla committed
743 744 745 746 747
        const uint8_t* yp=src1+srcStride1*y;
        const uint8_t* up=src2+srcStride2*(y>>2);
        const uint8_t* vp=src3+srcStride3*(y>>2);
        uint8_t* d=dst+dstStride*y;
        x=0;
Ramiro Polla's avatar
Ramiro Polla committed
748
        for (; x<w; x++) {
Ramiro Polla's avatar
Ramiro Polla committed
749 750 751 752 753 754 755 756 757 758
            const long x2 = x<<2;
            d[8*x+0] = yp[x2];
            d[8*x+1] = up[x];
            d[8*x+2] = yp[x2+1];
            d[8*x+3] = vp[x];
            d[8*x+4] = yp[x2+2];
            d[8*x+5] = up[x];
            d[8*x+6] = yp[x2+3];
            d[8*x+7] = vp[x];
        }
759 760
    }
}
761