rgb2rgb_template.c 28.5 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 11
 * This file is part of FFmpeg.
 *
12 13 14 15
 * FFmpeg is free software; you can redistribute it and/or
 * 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
 * FFmpeg 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 23
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; 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 30
static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
Nick Kurshev's avatar
Nick Kurshev committed
31
{
32 33
    uint8_t *dest      = dst;
    const uint8_t *s   = src;
34
    const uint8_t *end = s + src_size;
35

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

53 54
static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
55
{
56 57
    uint8_t *dest      = dst;
    const uint8_t *s   = src;
58
    const uint8_t *end = s + src_size;
59

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

77
/*
78 79
 * original by Strepto/Astral
 * ported to gcc & bugfixed: A'rpi
80
 * MMXEXT, 3DNOW optimization by Nick Kurshev
81 82
 * 32-bit C version, and and&add trick by Michael Niedermayer
 */
83
static inline void rgb15to16_c(const uint8_t *src, uint8_t *dst, int src_size)
84
{
85 86
    register uint8_t *d         = dst;
    register const uint8_t *s   = src;
87 88 89
    register const uint8_t *end = s + src_size;
    const uint8_t *mm_end       = end - 3;

Ramiro Polla's avatar
Ramiro Polla committed
90
    while (s < mm_end) {
91 92 93 94
        register unsigned x = *((const uint32_t *)s);
        *((uint32_t *)d)    = (x & 0x7FFF7FFF) + (x & 0x7FE07FE0);
        d += 4;
        s += 4;
Arpi's avatar
Arpi committed
95
    }
Ramiro Polla's avatar
Ramiro Polla committed
96
    if (s < end) {
97 98
        register unsigned short x = *((const uint16_t *)s);
        *((uint16_t *)d)          = (x & 0x7FFF) + (x & 0x7FE0);
Arpi's avatar
Arpi committed
99
    }
100
}
101

102
static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, int src_size)
103
{
104 105
    register uint8_t *d         = dst;
    register const uint8_t *s   = src;
106 107
    register const uint8_t *end = s + src_size;
    const uint8_t *mm_end       = end - 3;
108

Ramiro Polla's avatar
Ramiro Polla committed
109
    while (s < mm_end) {
110 111 112 113
        register uint32_t x  = *((const uint32_t *)s);
        *((uint32_t *)d)     = ((x >> 1) & 0x7FE07FE0) | (x & 0x001F001F);
        s                   += 4;
        d                   += 4;
114
    }
Ramiro Polla's avatar
Ramiro Polla committed
115
    if (s < end) {
116 117
        register uint16_t x = *((const uint16_t *)s);
        *((uint16_t *)d)    = ((x >> 1) & 0x7FE0) | (x & 0x001F);
118 119 120
    }
}

121
static inline void rgb32to16_c(const uint8_t *src, uint8_t *dst, int src_size)
122
{
123 124
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
125
    const uint8_t *end = s + src_size;
126

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

136 137
static inline void rgb32tobgr16_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
138
{
139 140
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
141 142
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
143
    while (s < end) {
144 145 146 147 148
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xF8)     << 8) +
                            ((rgb & 0xFC00)   >> 5) +
                            ((rgb & 0xF80000) >> 19);
149
    }
150 151
}

152
static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, int src_size)
153
{
154 155
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
156 157
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
158
    while (s < end) {
159 160 161 162 163
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xFF)     >> 3) +
                            ((rgb & 0xF800)   >> 6) +
                            ((rgb & 0xF80000) >> 9);
164
    }
165 166
}

167 168
static inline void rgb32tobgr15_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
169
{
170 171
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
172 173
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
174
    while (s < end) {
175 176 177 178 179
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xF8)     <<  7) +
                            ((rgb & 0xF800)   >>  6) +
                            ((rgb & 0xF80000) >> 19);
180
    }
181 182
}

183 184
static inline void rgb24tobgr16_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
185
{
186 187
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
188 189
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
190
    while (s < end) {
191 192 193
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
194
        *d++        = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
195
    }
196 197
}

198
static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, int src_size)
199
{
200 201
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
202 203
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
204
    while (s < end) {
205 206 207
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
208
        *d++        = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
209
    }
210 211
}

212 213
static inline void rgb24tobgr15_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
214
{
215 216
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
217 218
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
219
    while (s < end) {
220 221 222
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
223
        *d++        = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
224
    }
Arpi's avatar
Arpi committed
225 226
}

227
static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, int src_size)
228
{
229 230
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
231 232
    const uint8_t *end = s + src_size;

Ramiro Polla's avatar
Ramiro Polla committed
233
    while (s < end) {
234 235 236
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
237
        *d++        = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
238
    }
239 240
}

241 242
static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
Arpi's avatar
Arpi committed
243
{
244 245
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
246 247
    const uint16_t *end = s + src_size / 2;

Ramiro Polla's avatar
Ramiro Polla committed
248
    while (s < end) {
249
        register uint16_t bgr = *s++;
250 251
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
252
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
253
    }
Arpi's avatar
Arpi committed
254 255
}

256 257
static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
Arpi's avatar
Arpi committed
258
{
259 260
    uint8_t *d          = (uint8_t *)dst;
    const uint16_t *s   = (const uint16_t *)src;
261 262
    const uint16_t *end = s + src_size / 2;

Ramiro Polla's avatar
Ramiro Polla committed
263
    while (s < end) {
264
        register uint16_t bgr = *s++;
265 266
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
267
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
268
    }
Arpi's avatar
Arpi committed
269 270
}

271
static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, int src_size)
Arpi's avatar
Arpi committed
272
{
273 274
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
275 276
    const uint16_t *end = s + src_size / 2;

Ramiro Polla's avatar
Ramiro Polla committed
277
    while (s < end) {
278
        register uint16_t bgr = *s++;
279
#if HAVE_BIGENDIAN
280
        *d++ = 255;
281
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
282 283
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
284
#else
285 286
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
287
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
288
        *d++ = 255;
Michael Niedermayer's avatar
Michael Niedermayer committed
289
#endif
290
    }
Arpi's avatar
Arpi committed
291
}
292

293
static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, int src_size)
Arpi's avatar
Arpi committed
294
{
295 296
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
297 298
    const uint16_t *end = s + src_size / 2;

Ramiro Polla's avatar
Ramiro Polla committed
299
    while (s < end) {
300
        register uint16_t bgr = *s++;
301
#if HAVE_BIGENDIAN
302
        *d++ = 255;
303
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
304 305
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
306
#else
307 308
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
309
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
310
        *d++ = 255;
311
#endif
312
    }
313
}
314

315 316
static inline void shuffle_bytes_2103_c(const uint8_t *src, uint8_t *dst,
                                        int src_size)
317
{
318 319 320 321 322 323 324 325
    int idx          = 15  - src_size;
    const uint8_t *s = src - idx;
    uint8_t *d       = dst - idx;

    for (; idx < 15; idx += 4) {
        register int v        = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
        v                    &= 0xff00ff;
        *(uint32_t *)&d[idx]  = (v >> 16) + g + (v << 16);
326
    }
327 328
}

329
static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size)
Michael Niedermayer's avatar
Michael Niedermayer committed
330
{
331
    unsigned i;
332 333

    for (i = 0; i < src_size; i += 3) {
334
        register uint8_t x = src[i + 2];
335 336 337
        dst[i + 1]         = src[i + 1];
        dst[i + 2]         = src[i + 0];
        dst[i + 0]         = x;
338
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
339 340
}

341 342
static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
343 344 345
                                     int width, int height,
                                     int lumStride, int chromStride,
                                     int dstStride, int vertLumPerChroma)
Michael Niedermayer's avatar
Michael Niedermayer committed
346
{
347
    int y, i;
348
    const int chromWidth = width >> 1;
349 350

    for (y = 0; y < height; y++) {
351
#if HAVE_FAST_64BIT
352
        uint64_t *ldst = (uint64_t *)dst;
353
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
354
        for (i = 0; i < chromWidth; i += 2) {
355
            uint64_t k = yc[0] + (uc[0] << 8) +
356
                         (yc[1] << 16) + (unsigned)(vc[0] << 24);
357
            uint64_t l = yc[2] + (uc[1] << 8) +
358
                         (yc[3] << 16) + (unsigned)(vc[1] << 24);
359
            *ldst++ = k + (l << 32);
360 361 362
            yc     += 4;
            uc     += 2;
            vc     += 2;
363
        }
Arpi's avatar
Arpi committed
364 365

#else
366
        int *idst = (int32_t *)dst;
367
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
368

Ramiro Polla's avatar
Ramiro Polla committed
369
        for (i = 0; i < chromWidth; i++) {
370
#if HAVE_BIGENDIAN
371 372
            *idst++ = (yc[0] << 24) + (uc[0] << 16) +
                      (yc[1] <<  8) + (vc[0] <<  0);
373
#else
374
            *idst++ = yc[0] + (uc[0] << 8) +
375
                      (yc[1] << 16) + (vc[0] << 24);
376 377 378 379 380 381
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
382
        if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
383 384 385 386 387 388
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
        dst  += dstStride;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
389 390
}

391
/**
392 393
 * 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.)
394
 */
395 396
static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
397 398
                                int width, int height, int lumStride,
                                int chromStride, int dstStride)
399
{
400
    //FIXME interpolate chroma
401 402
    yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
403 404
}

405 406
static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
407 408 409
                                     int width, int height,
                                     int lumStride, int chromStride,
                                     int dstStride, int vertLumPerChroma)
410
{
411
    int y, i;
412
    const int chromWidth = width >> 1;
413 414

    for (y = 0; y < height; y++) {
415
#if HAVE_FAST_64BIT
416
        uint64_t *ldst = (uint64_t *)dst;
417
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
Ramiro Polla's avatar
Ramiro Polla committed
418
        for (i = 0; i < chromWidth; i += 2) {
419
            uint64_t k = uc[0] + (yc[0] << 8) +
420
                         (vc[0] << 16) + (unsigned)(yc[1] << 24);
421
            uint64_t l = uc[1] + (yc[2] << 8) +
422
                         (vc[1] << 16) + (unsigned)(yc[3] << 24);
423
            *ldst++ = k + (l << 32);
424 425 426
            yc     += 4;
            uc     += 2;
            vc     += 2;
427
        }
428 429

#else
430
        int *idst = (int32_t *)dst;
431
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
432

Ramiro Polla's avatar
Ramiro Polla committed
433
        for (i = 0; i < chromWidth; i++) {
434
#if HAVE_BIGENDIAN
435 436
            *idst++ = (uc[0] << 24) + (yc[0] << 16) +
                      (vc[0] <<  8) + (yc[1] <<  0);
437
#else
438
            *idst++ = uc[0] + (yc[0] << 8) +
439
                      (vc[0] << 16) + (yc[1] << 24);
440 441 442 443 444 445
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
446
        if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
447 448 449 450
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
451
        dst  += dstStride;
452
    }
453 454 455
}

/**
456 457
 * 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.)
458
 */
459 460
static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
461 462
                                int width, int height, int lumStride,
                                int chromStride, int dstStride)
463
{
464
    //FIXME interpolate chroma
465 466
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
467 468
}

469 470 471
/**
 * Width should be a multiple of 16.
 */
472 473
static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                   const uint8_t *vsrc, uint8_t *dst,
474 475
                                   int width, int height, int lumStride,
                                   int chromStride, int dstStride)
476
{
477 478
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 1);
479 480
}

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

493
/**
494 495
 * 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.)
496
 */
497 498
static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
499 500
                                int width, int height, int lumStride,
                                int chromStride, int srcStride)
Michael Niedermayer's avatar
Michael Niedermayer committed
501
{
502
    int y;
503
    const int chromWidth = width >> 1;
504 505

    for (y = 0; y < height; y += 2) {
506
        int i;
507 508 509 510 511
        for (i = 0; i < chromWidth; i++) {
            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];
512 513 514 515
        }
        ydst += lumStride;
        src  += srcStride;

516 517 518
        for (i = 0; i < chromWidth; i++) {
            ydst[2 * i + 0] = src[4 * i + 0];
            ydst[2 * i + 1] = src[4 * i + 2];
519 520 521 522 523 524
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
525
}
Arpi's avatar
Arpi committed
526

527 528
static inline void planar2x_c(const uint8_t *src, uint8_t *dst, int srcWidth,
                              int srcHeight, int srcStride, int dstStride)
529
{
530
    int x, y;
531

532
    dst[0] = src[0];
533

534
    // first line
535 536 537
    for (x = 0; x < srcWidth - 1; x++) {
        dst[2 * x + 1] = (3 * src[x] + src[x + 1]) >> 2;
        dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2;
538
    }
539
    dst[2 * srcWidth - 1] = src[srcWidth - 1];
540

541
    dst += dstStride;
542

543
    for (y = 1; y < srcHeight; y++) {
544
        const int mmxSize = 1;
545

546 547
        dst[0]         = (src[0] * 3 + src[srcStride]) >> 2;
        dst[dstStride] = (src[0] + 3 * src[srcStride]) >> 2;
548

549 550 551 552 553
        for (x = mmxSize - 1; x < srcWidth - 1; x++) {
            dst[2 * x + 1]             = (src[x + 0] * 3 + 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]             = (src[x + 1] * 3 + src[x + srcStride])     >> 2;
554
        }
555 556
        dst[srcWidth * 2 - 1]             = (src[srcWidth - 1] * 3 + src[srcWidth - 1 + srcStride]) >> 2;
        dst[srcWidth * 2 - 1 + dstStride] = (src[srcWidth - 1] + 3 * src[srcWidth - 1 + srcStride]) >> 2;
557

558 559
        dst += dstStride * 2;
        src += srcStride;
560
    }
561

562
    // last line
563
    dst[0] = src[0];
564

565 566 567
    for (x = 0; x < srcWidth - 1; x++) {
        dst[2 * x + 1] = (src[x] * 3 + src[x + 1]) >> 2;
        dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2;
568
    }
569
    dst[2 * srcWidth - 1] = src[srcWidth - 1];
570 571
}

Arpi's avatar
Arpi committed
572
/**
573 574 575
 * 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.
576
 * FIXME: Write HQ version.
Arpi's avatar
Arpi committed
577
 */
578 579
static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
580 581
                                int width, int height, int lumStride,
                                int chromStride, int srcStride)
Arpi's avatar
Arpi committed
582
{
583
    int y;
584
    const int chromWidth = width >> 1;
585 586

    for (y = 0; y < height; y += 2) {
587
        int i;
588 589 590 591 592
        for (i = 0; i < chromWidth; i++) {
            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];
593 594 595 596
        }
        ydst += lumStride;
        src  += srcStride;

597 598 599
        for (i = 0; i < chromWidth; i++) {
            ydst[2 * i + 0] = src[4 * i + 1];
            ydst[2 * i + 1] = src[4 * i + 3];
600 601 602 603 604 605
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
Arpi's avatar
Arpi committed
606 607
}

608
/**
609 610 611
 * 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,
612 613
 * others are ignored in the C version.
 * FIXME: Write HQ version.
614
 */
615
void rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
616 617
                   uint8_t *vdst, int width, int height, int lumStride,
                   int chromStride, int srcStride)
618
{
619
    int y;
620
    const int chromWidth = width >> 1;
621 622

    for (y = 0; y < height; y += 2) {
623
        int i;
624 625 626 627
        for (i = 0; i < chromWidth; i++) {
            unsigned int b = src[6 * i + 0];
            unsigned int g = src[6 * i + 1];
            unsigned int r = src[6 * i + 2];
628

629 630 631
            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;
632 633 634

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

637 638 639
            b = src[6 * i + 3];
            g = src[6 * i + 4];
            r = src[6 * i + 5];
640

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

647
        if (y+1 == height)
648 649
            break;

650 651 652 653
        for (i = 0; i < chromWidth; i++) {
            unsigned int b = src[6 * i + 0];
            unsigned int g = src[6 * i + 1];
            unsigned int r = src[6 * i + 2];
654

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

657
            ydst[2 * i] = Y;
658

659 660 661
            b = src[6 * i + 3];
            g = src[6 * i + 4];
            r = src[6 * i + 5];
662

663 664
            Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
            ydst[2 * i + 1] = Y;
665 666 667 668 669 670
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
671
}
672

673
static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
674 675
                              uint8_t *dest, int width, int height,
                              int src1Stride, int src2Stride, int dstStride)
Ramiro Polla's avatar
Ramiro Polla committed
676
{
677
    int h;
678

679
    for (h = 0; h < height; h++) {
680
        int w;
681 682 683
        for (w = 0; w < width; w++) {
            dest[2 * w + 0] = src1[w];
            dest[2 * w + 1] = src2[w];
684 685
        }
        dest += dstStride;
686 687
        src1 += src1Stride;
        src2 += src2Stride;
688
    }
689
}
690

691 692
static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
                                 uint8_t *dst1, uint8_t *dst2,
693 694 695
                                 int width, int height,
                                 int srcStride1, int srcStride2,
                                 int dstStride1, int dstStride2)
696
{
697 698 699 700
    int x, y;
    int w = width  / 2;
    int h = height / 2;

701 702 703
    for (y = 0; y < h; y++) {
        const uint8_t *s1 = src1 + srcStride1 * (y >> 1);
        uint8_t *d        = dst1 + dstStride1 *  y;
704 705
        for (x = 0; x < w; x++)
            d[2 * x] = d[2 * x + 1] = s1[x];
706
    }
707 708 709
    for (y = 0; y < h; y++) {
        const uint8_t *s2 = src2 + srcStride2 * (y >> 1);
        uint8_t *d        = dst2 + dstStride2 *  y;
710 711
        for (x = 0; x < w; x++)
            d[2 * x] = d[2 * x + 1] = s2[x];
712 713 714
    }
}

715 716
static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
                                  const uint8_t *src3, uint8_t *dst,
717 718 719
                                  int width, int height,
                                  int srcStride1, int srcStride2,
                                  int srcStride3, int dstStride)
720
{
721 722 723 724
    int x, y;
    int w = width / 2;
    int h = height;

725 726 727 728 729
    for (y = 0; y < h; y++) {
        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;
730
        for (x = 0; x < w; x++) {
731 732 733 734 735 736 737 738 739
            const int 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];
Ramiro Polla's avatar
Ramiro Polla committed
740
        }
741 742
    }
}
743

744
static void extract_even_c(const uint8_t *src, uint8_t *dst, int count)
745
{
746 747 748 749 750
    dst   +=  count;
    src   +=  count * 2;
    count  = -count;
    while (count < 0) {
        dst[count] = src[2 * count];
751 752 753 754
        count++;
    }
}

755 756
static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
                            int count)
757
{
758 759 760 761 762 763 764
    dst0  +=  count;
    dst1  +=  count;
    src   +=  count * 4;
    count  = -count;
    while (count < 0) {
        dst0[count] = src[4 * count + 0];
        dst1[count] = src[4 * count + 2];
765 766 767 768
        count++;
    }
}

769 770
static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1,
                               uint8_t *dst0, uint8_t *dst1, int count)
771
{
772 773 774 775 776 777 778 779
    dst0  +=  count;
    dst1  +=  count;
    src0  +=  count * 4;
    src1  +=  count * 4;
    count  = -count;
    while (count < 0) {
        dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
        dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
780 781 782 783
        count++;
    }
}

784 785
static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
                           int count)
786
{
787 788 789 790
    dst0  +=  count;
    dst1  +=  count;
    src   +=  count * 4;
    count  = -count;
791
    src++;
792 793 794
    while (count < 0) {
        dst0[count] = src[4 * count + 0];
        dst1[count] = src[4 * count + 2];
795 796 797 798
        count++;
    }
}

799 800
static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1,
                              uint8_t *dst0, uint8_t *dst1, int count)
801
{
802 803 804 805 806
    dst0  +=  count;
    dst1  +=  count;
    src0  +=  count * 4;
    src1  +=  count * 4;
    count  = -count;
807 808
    src0++;
    src1++;
809 810 811
    while (count < 0) {
        dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1;
        dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1;
812 813 814 815
        count++;
    }
}

816
static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
817 818
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
819
{
820
    int y;
821
    const int chromWidth = -((-width) >> 1);
822

823
    for (y = 0; y < height; y++) {
824
        extract_even_c(src, ydst, width);
825
        if (y & 1) {
826
            extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth);
827 828
            udst += chromStride;
            vdst += chromStride;
829 830
        }

831 832
        src  += srcStride;
        ydst += lumStride;
833 834 835
    }
}

836
static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
837 838
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
839
{
840
    int y;
841
    const int chromWidth = -((-width) >> 1);
842

843
    for (y = 0; y < height; y++) {
844 845
        extract_even_c(src, ydst, width);
        extract_odd2_c(src, udst, vdst, chromWidth);
846

847 848 849 850
        src  += srcStride;
        ydst += lumStride;
        udst += chromStride;
        vdst += chromStride;
851 852 853
    }
}

854
static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
855 856
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
857
{
858
    int y;
859
    const int chromWidth = -((-width) >> 1);
860

861
    for (y = 0; y < height; y++) {
862
        extract_even_c(src + 1, ydst, width);
863
        if (y & 1) {
864
            extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth);
865 866
            udst += chromStride;
            vdst += chromStride;
867 868
        }

869 870
        src  += srcStride;
        ydst += lumStride;
871 872 873
    }
}

874
static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
875 876
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
877
{
878
    int y;
879
    const int chromWidth = -((-width) >> 1);
880

881
    for (y = 0; y < height; y++) {
882 883
        extract_even_c(src + 1, ydst, width);
        extract_even2_c(src, udst, vdst, chromWidth);
884

885 886 887 888
        src  += srcStride;
        ydst += lumStride;
        udst += chromStride;
        vdst += chromStride;
889 890 891
    }
}

892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
static inline void rgb2rgb_init_c(void)
{
    rgb15to16          = rgb15to16_c;
    rgb15tobgr24       = rgb15tobgr24_c;
    rgb15to32          = rgb15to32_c;
    rgb16tobgr24       = rgb16tobgr24_c;
    rgb16to32          = rgb16to32_c;
    rgb16to15          = rgb16to15_c;
    rgb24tobgr16       = rgb24tobgr16_c;
    rgb24tobgr15       = rgb24tobgr15_c;
    rgb24tobgr32       = rgb24tobgr32_c;
    rgb32to16          = rgb32to16_c;
    rgb32to15          = rgb32to15_c;
    rgb32tobgr24       = rgb32tobgr24_c;
    rgb24to15          = rgb24to15_c;
    rgb24to16          = rgb24to16_c;
    rgb24tobgr24       = rgb24tobgr24_c;
    shuffle_bytes_2103 = shuffle_bytes_2103_c;
    rgb32tobgr16       = rgb32tobgr16_c;
    rgb32tobgr15       = rgb32tobgr15_c;
    yv12toyuy2         = yv12toyuy2_c;
    yv12touyvy         = yv12touyvy_c;
    yuv422ptoyuy2      = yuv422ptoyuy2_c;
    yuv422ptouyvy      = yuv422ptouyvy_c;
    yuy2toyv12         = yuy2toyv12_c;
    planar2x           = planar2x_c;
    rgb24toyv12        = rgb24toyv12_c;
    interleaveBytes    = interleaveBytes_c;
    vu9_to_vu12        = vu9_to_vu12_c;
    yvu9_to_yuy2       = yvu9_to_yuy2_c;

    uyvytoyuv420       = uyvytoyuv420_c;
    uyvytoyuv422       = uyvytoyuv422_c;
    yuyvtoyuv420       = yuyvtoyuv420_c;
    yuyvtoyuv422       = yuyvtoyuv422_c;
927
}