rgb2rgb_template.c 31.1 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
 */

A
Arpi 已提交
27 28
#include <stddef.h>

29 30
#include "libavutil/attributes.h"

31 32
static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
N
Nick Kurshev 已提交
33
{
34 35
    uint8_t *dest      = dst;
    const uint8_t *s   = src;
36
    const uint8_t *end = s + src_size;
M
Michael Niedermayer 已提交
37

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

55 56
static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
N
Nick Kurshev 已提交
57
{
58 59
    uint8_t *dest      = dst;
    const uint8_t *s   = src;
60
    const uint8_t *end = s + src_size;
M
Michael Niedermayer 已提交
61

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

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

R
Ramiro Polla 已提交
92
    while (s < mm_end) {
93 94 95 96
        register unsigned x = *((const uint32_t *)s);
        *((uint32_t *)d)    = (x & 0x7FFF7FFF) + (x & 0x7FE07FE0);
        d += 4;
        s += 4;
A
Arpi 已提交
97
    }
R
Ramiro Polla 已提交
98
    if (s < end) {
99 100
        register unsigned short x = *((const uint16_t *)s);
        *((uint16_t *)d)          = (x & 0x7FFF) + (x & 0x7FE0);
A
Arpi 已提交
101
    }
N
Nick Kurshev 已提交
102
}
103

A
Anton Khirnov 已提交
104
static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, int src_size)
105
{
106 107
    register uint8_t *d         = dst;
    register const uint8_t *s   = src;
108 109
    register const uint8_t *end = s + src_size;
    const uint8_t *mm_end       = end - 3;
M
Michael Niedermayer 已提交
110

R
Ramiro Polla 已提交
111
    while (s < mm_end) {
112 113 114 115
        register uint32_t x  = *((const uint32_t *)s);
        *((uint32_t *)d)     = ((x >> 1) & 0x7FE07FE0) | (x & 0x001F001F);
        s                   += 4;
        d                   += 4;
116
    }
R
Ramiro Polla 已提交
117
    if (s < end) {
118 119
        register uint16_t x = *((const uint16_t *)s);
        *((uint16_t *)d)    = ((x >> 1) & 0x7FE0) | (x & 0x001F);
120 121 122
    }
}

A
Anton Khirnov 已提交
123
static inline void rgb32to16_c(const uint8_t *src, uint8_t *dst, int src_size)
124
{
125 126
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
127
    const uint8_t *end = s + src_size;
M
Michael Niedermayer 已提交
128

R
Ramiro Polla 已提交
129
    while (s < end) {
130 131 132 133 134
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xFF)     >> 3) +
                            ((rgb & 0xFC00)   >> 5) +
                            ((rgb & 0xF80000) >> 8);
135
    }
136 137
}

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

R
Ramiro Polla 已提交
145
    while (s < end) {
146 147 148 149 150
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xF8)     << 8) +
                            ((rgb & 0xFC00)   >> 5) +
                            ((rgb & 0xF80000) >> 19);
151
    }
152 153
}

A
Anton Khirnov 已提交
154
static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, int src_size)
155
{
156 157
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
158 159
    const uint8_t *end = s + src_size;

R
Ramiro Polla 已提交
160
    while (s < end) {
161 162 163 164 165
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xFF)     >> 3) +
                            ((rgb & 0xF800)   >> 6) +
                            ((rgb & 0xF80000) >> 9);
166
    }
167 168
}

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

R
Ramiro Polla 已提交
176
    while (s < end) {
177 178 179 180 181
        register int rgb  = *(const uint32_t *)s;
        s                += 4;
        *d++              = ((rgb & 0xF8)     <<  7) +
                            ((rgb & 0xF800)   >>  6) +
                            ((rgb & 0xF80000) >> 19);
182
    }
183 184
}

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

R
Ramiro Polla 已提交
192
    while (s < end) {
193 194 195
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
196
        *d++        = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
197
    }
198 199
}

A
Anton Khirnov 已提交
200
static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, int src_size)
201
{
202 203
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
204 205
    const uint8_t *end = s + src_size;

R
Ramiro Polla 已提交
206
    while (s < end) {
207 208 209
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
210
        *d++        = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8);
211
    }
212 213
}

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

R
Ramiro Polla 已提交
221
    while (s < end) {
222 223 224
        const int b = *s++;
        const int g = *s++;
        const int r = *s++;
225
        *d++        = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
226
    }
A
Arpi 已提交
227 228
}

A
Anton Khirnov 已提交
229
static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, int src_size)
230
{
231 232
    uint16_t *d        = (uint16_t *)dst;
    const uint8_t *s   = src;
233 234
    const uint8_t *end = s + src_size;

R
Ramiro Polla 已提交
235
    while (s < end) {
236 237 238
        const int r = *s++;
        const int g = *s++;
        const int b = *s++;
239
        *d++        = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7);
240
    }
241 242
}

243 244
static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
A
Arpi 已提交
245
{
246 247
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
248 249
    const uint16_t *end = s + src_size / 2;

R
Ramiro Polla 已提交
250
    while (s < end) {
251
        register uint16_t bgr = *s++;
252 253
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
254
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
255
    }
A
Arpi 已提交
256 257
}

258 259
static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst,
                                  int src_size)
A
Arpi 已提交
260
{
261 262
    uint8_t *d          = (uint8_t *)dst;
    const uint16_t *s   = (const uint16_t *)src;
263 264
    const uint16_t *end = s + src_size / 2;

R
Ramiro Polla 已提交
265
    while (s < end) {
266
        register uint16_t bgr = *s++;
267 268
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
269
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
270
    }
A
Arpi 已提交
271 272
}

A
Anton Khirnov 已提交
273
static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, int src_size)
A
Arpi 已提交
274
{
275 276
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
277 278
    const uint16_t *end = s + src_size / 2;

R
Ramiro Polla 已提交
279
    while (s < end) {
280
        register uint16_t bgr = *s++;
281
#if HAVE_BIGENDIAN
282
        *d++ = 255;
283
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
284 285
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
A
Alex Beregszaszi 已提交
286
#else
287 288
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7);
289
        *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12);
290
        *d++ = 255;
M
Michael Niedermayer 已提交
291
#endif
292
    }
A
Arpi 已提交
293
}
294

A
Anton Khirnov 已提交
295
static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, int src_size)
A
Arpi 已提交
296
{
297 298
    uint8_t *d          = dst;
    const uint16_t *s   = (const uint16_t *)src;
299 300
    const uint16_t *end = s + src_size / 2;

R
Ramiro Polla 已提交
301
    while (s < end) {
302
        register uint16_t bgr = *s++;
303
#if HAVE_BIGENDIAN
304
        *d++ = 255;
305
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
306 307
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
A
Alex Beregszaszi 已提交
308
#else
309 310
        *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2);
        *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9);
311
        *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13);
312
        *d++ = 255;
A
Alex Beregszaszi 已提交
313
#endif
314
    }
315
}
316

317 318
static inline void shuffle_bytes_2103_c(const uint8_t *src, uint8_t *dst,
                                        int src_size)
M
Michael Niedermayer 已提交
319
{
320 321 322 323 324
    int idx          = 15  - src_size;
    const uint8_t *s = src - idx;
    uint8_t *d       = dst - idx;

    for (; idx < 15; idx += 4) {
325
        register unsigned v   = *(const uint32_t *)&s[idx], g = v & 0xff00ff00;
326 327
        v                    &= 0xff00ff;
        *(uint32_t *)&d[idx]  = (v >> 16) + g + (v << 16);
328
    }
M
Michael Niedermayer 已提交
329 330
}

331 332 333 334 335 336 337 338 339 340 341 342 343 344
static inline void shuffle_bytes_0321_c(const uint8_t *src, uint8_t *dst,
                                        int src_size)
{
    int idx          = 15  - src_size;
    const uint8_t *s = src - idx;
    uint8_t *d       = dst - idx;

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

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
#define DEFINE_SHUFFLE_BYTES(name, a, b, c, d)                          \
static void shuffle_bytes_##name (const uint8_t *src,                   \
                                        uint8_t *dst, int src_size)     \
{                                                                       \
    int i;                                                              \
                                                                        \
    for (i = 0; i < src_size; i += 4) {                                 \
        dst[i + 0] = src[i + a];                                        \
        dst[i + 1] = src[i + b];                                        \
        dst[i + 2] = src[i + c];                                        \
        dst[i + 3] = src[i + d];                                        \
    }                                                                   \
}

DEFINE_SHUFFLE_BYTES(1230_c, 1, 2, 3, 0)
DEFINE_SHUFFLE_BYTES(3012_c, 3, 0, 1, 2)
DEFINE_SHUFFLE_BYTES(3210_c, 3, 2, 1, 0)

A
Anton Khirnov 已提交
363
static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size)
M
Michael Niedermayer 已提交
364
{
365
    unsigned i;
366 367

    for (i = 0; i < src_size; i += 3) {
368
        register uint8_t x = src[i + 2];
369 370 371
        dst[i + 1]         = src[i + 1];
        dst[i + 2]         = src[i + 0];
        dst[i + 0]         = x;
372
    }
M
Michael Niedermayer 已提交
373 374
}

M
Michael Niedermayer 已提交
375 376
static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
A
Anton Khirnov 已提交
377 378 379
                                     int width, int height,
                                     int lumStride, int chromStride,
                                     int dstStride, int vertLumPerChroma)
M
Michael Niedermayer 已提交
380
{
381
    int y, i;
M
Michael Niedermayer 已提交
382
    const int chromWidth = width >> 1;
383 384

    for (y = 0; y < height; y++) {
M
Michael Niedermayer 已提交
385
#if HAVE_FAST_64BIT
386
        uint64_t *ldst = (uint64_t *)dst;
387
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
R
Ramiro Polla 已提交
388
        for (i = 0; i < chromWidth; i += 2) {
389
            uint64_t k = yc[0] + (uc[0] << 8) +
390
                         (yc[1] << 16) + ((unsigned) vc[0] << 24);
391
            uint64_t l = yc[2] + (uc[1] << 8) +
392
                         (yc[3] << 16) + ((unsigned) vc[1] << 24);
393
            *ldst++ = k + (l << 32);
394 395 396
            yc     += 4;
            uc     += 2;
            vc     += 2;
397
        }
A
Arpi 已提交
398 399

#else
400
        int *idst = (int32_t *)dst;
401
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
402

R
Ramiro Polla 已提交
403
        for (i = 0; i < chromWidth; i++) {
404
#if HAVE_BIGENDIAN
405 406
            *idst++ = (yc[0] << 24) + (uc[0] << 16) +
                      (yc[1] <<  8) + (vc[0] <<  0);
407
#else
408
            *idst++ = yc[0] + (uc[0] << 8) +
409
                      (yc[1] << 16) + (vc[0] << 24);
410 411 412 413 414 415
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
416
        if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
417 418 419 420 421 422
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
        dst  += dstStride;
    }
M
Michael Niedermayer 已提交
423 424
}

M
Michael Niedermayer 已提交
425
/**
426 427
 * 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.)
M
Michael Niedermayer 已提交
428
 */
M
Michael Niedermayer 已提交
429 430
static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
431 432
                                int width, int height, int lumStride,
                                int chromStride, int dstStride)
M
Michael Niedermayer 已提交
433
{
434
    //FIXME interpolate chroma
M
Michael Niedermayer 已提交
435 436
    yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
A
Alex Beregszaszi 已提交
437 438
}

M
Michael Niedermayer 已提交
439 440
static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                     const uint8_t *vsrc, uint8_t *dst,
A
Anton Khirnov 已提交
441 442 443
                                     int width, int height,
                                     int lumStride, int chromStride,
                                     int dstStride, int vertLumPerChroma)
A
Alex Beregszaszi 已提交
444
{
445
    int y, i;
M
Michael Niedermayer 已提交
446
    const int chromWidth = width >> 1;
447 448

    for (y = 0; y < height; y++) {
449
#if HAVE_FAST_64BIT
450
        uint64_t *ldst = (uint64_t *)dst;
451
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
R
Ramiro Polla 已提交
452
        for (i = 0; i < chromWidth; i += 2) {
453
            uint64_t k = uc[0] + (yc[0] << 8) +
454
                         (vc[0] << 16) + ((unsigned) yc[1] << 24);
455
            uint64_t l = uc[1] + (yc[2] << 8) +
456
                         (vc[1] << 16) + ((unsigned) yc[3] << 24);
457
            *ldst++ = k + (l << 32);
458 459 460
            yc     += 4;
            uc     += 2;
            vc     += 2;
461
        }
A
Alex Beregszaszi 已提交
462 463

#else
464
        int *idst = (int32_t *)dst;
465
        const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
466

R
Ramiro Polla 已提交
467
        for (i = 0; i < chromWidth; i++) {
468
#if HAVE_BIGENDIAN
469 470
            *idst++ = (uc[0] << 24) + (yc[0] << 16) +
                      (vc[0] <<  8) + (yc[1] <<  0);
471
#else
472
            *idst++ = uc[0] + (yc[0] << 8) +
473
                      (vc[0] << 16) + (yc[1] << 24);
474 475 476 477 478 479
#endif
            yc += 2;
            uc++;
            vc++;
        }
#endif
480
        if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
481 482 483 484
            usrc += chromStride;
            vsrc += chromStride;
        }
        ysrc += lumStride;
485
        dst  += dstStride;
486
    }
A
Alex Beregszaszi 已提交
487 488 489
}

/**
490 491
 * 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.)
A
Alex Beregszaszi 已提交
492
 */
M
Michael Niedermayer 已提交
493 494
static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                const uint8_t *vsrc, uint8_t *dst,
495 496
                                int width, int height, int lumStride,
                                int chromStride, int dstStride)
A
Alex Beregszaszi 已提交
497
{
498
    //FIXME interpolate chroma
M
Michael Niedermayer 已提交
499 500
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 2);
M
Michael Niedermayer 已提交
501 502
}

503 504 505
/**
 * Width should be a multiple of 16.
 */
M
Michael Niedermayer 已提交
506 507
static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
                                   const uint8_t *vsrc, uint8_t *dst,
508 509
                                   int width, int height, int lumStride,
                                   int chromStride, int dstStride)
510
{
M
Michael Niedermayer 已提交
511 512
    yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 1);
513 514
}

M
Michael Niedermayer 已提交
515
/**
D
Diego Biurrun 已提交
516
 * Width should be a multiple of 16.
M
Michael Niedermayer 已提交
517
 */
M
Michael Niedermayer 已提交
518 519
static inline void yuv422ptoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
                                   const uint8_t *vsrc, uint8_t *dst,
520 521
                                   int width, int height, int lumStride,
                                   int chromStride, int dstStride)
M
Michael Niedermayer 已提交
522
{
M
Michael Niedermayer 已提交
523 524
    yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride,
                      chromStride, dstStride, 1);
M
Michael Niedermayer 已提交
525 526
}

M
Michael Niedermayer 已提交
527
/**
528 529
 * 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.)
M
Michael Niedermayer 已提交
530
 */
M
Michael Niedermayer 已提交
531 532
static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
533 534
                                int width, int height, int lumStride,
                                int chromStride, int srcStride)
M
Michael Niedermayer 已提交
535
{
A
Anton Khirnov 已提交
536
    int y;
M
Michael Niedermayer 已提交
537
    const int chromWidth = width >> 1;
538 539

    for (y = 0; y < height; y += 2) {
A
Anton Khirnov 已提交
540
        int i;
541 542 543 544 545
        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];
546 547 548 549
        }
        ydst += lumStride;
        src  += srcStride;

550 551 552
        for (i = 0; i < chromWidth; i++) {
            ydst[2 * i + 0] = src[4 * i + 0];
            ydst[2 * i + 1] = src[4 * i + 2];
553 554 555 556 557 558
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
M
Michael Niedermayer 已提交
559
}
A
Arpi 已提交
560

A
Anton Khirnov 已提交
561 562
static inline void planar2x_c(const uint8_t *src, uint8_t *dst, int srcWidth,
                              int srcHeight, int srcStride, int dstStride)
563
{
564
    int x, y;
565

566
    dst[0] = src[0];
567

568
    // first line
569 570 571
    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;
572
    }
573
    dst[2 * srcWidth - 1] = src[srcWidth - 1];
574

575
    dst += dstStride;
576

577
    for (y = 1; y < srcHeight; y++) {
M
Michael Niedermayer 已提交
578
        const int mmxSize = 1;
579

580 581
        dst[0]         = (src[0] * 3 + src[srcStride]) >> 2;
        dst[dstStride] = (src[0] + 3 * src[srcStride]) >> 2;
582

583 584 585 586 587
        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;
588
        }
589 590
        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;
591

592 593
        dst += dstStride * 2;
        src += srcStride;
594
    }
595

596
    // last line
597
    dst[0] = src[0];
598

599 600 601
    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;
602
    }
603
    dst[2 * srcWidth - 1] = src[srcWidth - 1];
604 605
}

A
Arpi 已提交
606
/**
607 608 609
 * 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.
D
Diego Biurrun 已提交
610
 * FIXME: Write HQ version.
A
Arpi 已提交
611
 */
M
Michael Niedermayer 已提交
612 613
static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst,
                                uint8_t *udst, uint8_t *vdst,
614 615
                                int width, int height, int lumStride,
                                int chromStride, int srcStride)
A
Arpi 已提交
616
{
A
Anton Khirnov 已提交
617
    int y;
M
Michael Niedermayer 已提交
618
    const int chromWidth = width >> 1;
619 620

    for (y = 0; y < height; y += 2) {
A
Anton Khirnov 已提交
621
        int i;
622 623 624 625 626
        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];
627 628 629 630
        }
        ydst += lumStride;
        src  += srcStride;

631 632 633
        for (i = 0; i < chromWidth; i++) {
            ydst[2 * i + 0] = src[4 * i + 1];
            ydst[2 * i + 1] = src[4 * i + 3];
634 635 636 637 638 639
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
A
Arpi 已提交
640 641
}

M
Michael Niedermayer 已提交
642
/**
643 644 645
 * 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,
D
Diego Biurrun 已提交
646 647
 * others are ignored in the C version.
 * FIXME: Write HQ version.
M
Michael Niedermayer 已提交
648
 */
649
void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst,
A
Anton Khirnov 已提交
650
                   uint8_t *vdst, int width, int height, int lumStride,
651
                   int chromStride, int srcStride, int32_t *rgb2yuv)
M
Michael Niedermayer 已提交
652
{
653 654 655
    int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX];
    int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX];
    int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX];
A
Anton Khirnov 已提交
656
    int y;
M
Michael Niedermayer 已提交
657
    const int chromWidth = width >> 1;
658 659

    for (y = 0; y < height; y += 2) {
A
Anton Khirnov 已提交
660
        int i;
661 662 663 664
        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];
665

666 667 668
            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;
669 670 671

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

674 675 676
            b = src[6 * i + 3];
            g = src[6 * i + 4];
            r = src[6 * i + 5];
677

678
            Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
679
            ydst[2 * i + 1] = Y;
680 681 682 683
        }
        ydst += lumStride;
        src  += srcStride;

684
        if (y+1 == height)
685 686
            break;

687 688 689 690
        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];
691

692
            unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
693

694
            ydst[2 * i] = Y;
695

696 697 698
            b = src[6 * i + 3];
            g = src[6 * i + 4];
            r = src[6 * i + 5];
699

700
            Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16;
701
            ydst[2 * i + 1] = Y;
702 703 704 705 706 707
        }
        udst += chromStride;
        vdst += chromStride;
        ydst += lumStride;
        src  += srcStride;
    }
M
Michael Niedermayer 已提交
708
}
M
Michael Niedermayer 已提交
709

M
Michael Niedermayer 已提交
710
static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2,
711 712
                              uint8_t *dest, int width, int height,
                              int src1Stride, int src2Stride, int dstStride)
R
Ramiro Polla 已提交
713
{
A
Anton Khirnov 已提交
714
    int h;
M
Michael Niedermayer 已提交
715

716
    for (h = 0; h < height; h++) {
A
Anton Khirnov 已提交
717
        int w;
718 719 720
        for (w = 0; w < width; w++) {
            dest[2 * w + 0] = src1[w];
            dest[2 * w + 1] = src2[w];
721 722
        }
        dest += dstStride;
723 724
        src1 += src1Stride;
        src2 += src2Stride;
725
    }
M
Michael Niedermayer 已提交
726
}
727

728 729 730 731 732 733 734 735 736 737 738 739
static void deinterleaveBytes_c(const uint8_t *src, uint8_t *dst1, uint8_t *dst2,
                                int width, int height, int srcStride,
                                int dst1Stride, int dst2Stride)
{
    int h;

    for (h = 0; h < height; h++) {
        int w;
        for (w = 0; w < width; w++) {
            dst1[w] = src[2 * w + 0];
            dst2[w] = src[2 * w + 1];
        }
740
        src  += srcStride;
741 742 743 744 745
        dst1 += dst1Stride;
        dst2 += dst2Stride;
    }
}

M
Michael Niedermayer 已提交
746 747
static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2,
                                 uint8_t *dst1, uint8_t *dst2,
A
Anton Khirnov 已提交
748 749 750
                                 int width, int height,
                                 int srcStride1, int srcStride2,
                                 int dstStride1, int dstStride2)
751
{
752 753 754 755
    int x, y;
    int w = width  / 2;
    int h = height / 2;

756 757 758
    for (y = 0; y < h; y++) {
        const uint8_t *s1 = src1 + srcStride1 * (y >> 1);
        uint8_t *d        = dst1 + dstStride1 *  y;
759 760
        for (x = 0; x < w; x++)
            d[2 * x] = d[2 * x + 1] = s1[x];
761
    }
762 763 764
    for (y = 0; y < h; y++) {
        const uint8_t *s2 = src2 + srcStride2 * (y >> 1);
        uint8_t *d        = dst2 + dstStride2 *  y;
765 766
        for (x = 0; x < w; x++)
            d[2 * x] = d[2 * x + 1] = s2[x];
767 768 769
    }
}

M
Michael Niedermayer 已提交
770 771
static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2,
                                  const uint8_t *src3, uint8_t *dst,
A
Anton Khirnov 已提交
772 773 774
                                  int width, int height,
                                  int srcStride1, int srcStride2,
                                  int srcStride3, int dstStride)
775
{
776 777 778 779
    int x, y;
    int w = width / 2;
    int h = height;

780 781 782 783 784
    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;
785
        for (x = 0; x < w; x++) {
786 787 788 789 790 791 792 793 794
            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];
R
Ramiro Polla 已提交
795
        }
796 797
    }
}
798

M
Michael Niedermayer 已提交
799
static void extract_even_c(const uint8_t *src, uint8_t *dst, int count)
M
Michael Niedermayer 已提交
800
{
801 802 803 804 805
    dst   +=  count;
    src   +=  count * 2;
    count  = -count;
    while (count < 0) {
        dst[count] = src[2 * count];
M
Michael Niedermayer 已提交
806 807 808 809
        count++;
    }
}

M
Michael Niedermayer 已提交
810 811
static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
                            int count)
M
Michael Niedermayer 已提交
812
{
813 814 815 816 817 818 819
    dst0  +=  count;
    dst1  +=  count;
    src   +=  count * 4;
    count  = -count;
    while (count < 0) {
        dst0[count] = src[4 * count + 0];
        dst1[count] = src[4 * count + 2];
M
Michael Niedermayer 已提交
820 821 822 823
        count++;
    }
}

M
Michael Niedermayer 已提交
824 825
static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1,
                               uint8_t *dst0, uint8_t *dst1, int count)
826
{
827 828 829 830 831 832 833 834
    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;
835 836 837 838
        count++;
    }
}

M
Michael Niedermayer 已提交
839 840
static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1,
                           int count)
M
Michael Niedermayer 已提交
841
{
842 843 844 845
    dst0  +=  count;
    dst1  +=  count;
    src   +=  count * 4;
    count  = -count;
846
    src++;
847 848 849
    while (count < 0) {
        dst0[count] = src[4 * count + 0];
        dst1[count] = src[4 * count + 2];
M
Michael Niedermayer 已提交
850 851 852 853
        count++;
    }
}

M
Michael Niedermayer 已提交
854 855
static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1,
                              uint8_t *dst0, uint8_t *dst1, int count)
856
{
857 858 859 860 861
    dst0  +=  count;
    dst1  +=  count;
    src0  +=  count * 4;
    src1  +=  count * 4;
    count  = -count;
862 863
    src0++;
    src1++;
864 865 866
    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;
867 868 869 870
        count++;
    }
}

M
Michael Niedermayer 已提交
871
static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
A
Anton Khirnov 已提交
872 873
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
M
Michael Niedermayer 已提交
874
{
A
Anton Khirnov 已提交
875
    int y;
876
    const int chromWidth = AV_CEIL_RSHIFT(width, 1);
M
Michael Niedermayer 已提交
877

878
    for (y = 0; y < height; y++) {
M
Michael Niedermayer 已提交
879
        extract_even_c(src, ydst, width);
880
        if (y & 1) {
M
Michael Niedermayer 已提交
881
            extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth);
882 883
            udst += chromStride;
            vdst += chromStride;
M
Michael Niedermayer 已提交
884 885
        }

886 887
        src  += srcStride;
        ydst += lumStride;
M
Michael Niedermayer 已提交
888 889 890
    }
}

M
Michael Niedermayer 已提交
891
static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
A
Anton Khirnov 已提交
892 893
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
M
Michael Niedermayer 已提交
894
{
A
Anton Khirnov 已提交
895
    int y;
896
    const int chromWidth = AV_CEIL_RSHIFT(width, 1);
M
Michael Niedermayer 已提交
897

898
    for (y = 0; y < height; y++) {
M
Michael Niedermayer 已提交
899 900
        extract_even_c(src, ydst, width);
        extract_odd2_c(src, udst, vdst, chromWidth);
M
Michael Niedermayer 已提交
901

902 903 904 905
        src  += srcStride;
        ydst += lumStride;
        udst += chromStride;
        vdst += chromStride;
M
Michael Niedermayer 已提交
906 907 908
    }
}

M
Michael Niedermayer 已提交
909
static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
A
Anton Khirnov 已提交
910 911
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
M
Michael Niedermayer 已提交
912
{
A
Anton Khirnov 已提交
913
    int y;
914
    const int chromWidth = AV_CEIL_RSHIFT(width, 1);
M
Michael Niedermayer 已提交
915

916
    for (y = 0; y < height; y++) {
M
Michael Niedermayer 已提交
917
        extract_even_c(src + 1, ydst, width);
918
        if (y & 1) {
M
Michael Niedermayer 已提交
919
            extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth);
920 921
            udst += chromStride;
            vdst += chromStride;
M
Michael Niedermayer 已提交
922 923
        }

924 925
        src  += srcStride;
        ydst += lumStride;
M
Michael Niedermayer 已提交
926 927 928
    }
}

M
Michael Niedermayer 已提交
929
static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
A
Anton Khirnov 已提交
930 931
                           const uint8_t *src, int width, int height,
                           int lumStride, int chromStride, int srcStride)
M
Michael Niedermayer 已提交
932
{
A
Anton Khirnov 已提交
933
    int y;
934
    const int chromWidth = AV_CEIL_RSHIFT(width, 1);
M
Michael Niedermayer 已提交
935

936
    for (y = 0; y < height; y++) {
M
Michael Niedermayer 已提交
937 938
        extract_even_c(src + 1, ydst, width);
        extract_even2_c(src, udst, vdst, chromWidth);
M
Michael Niedermayer 已提交
939

940 941 942 943
        src  += srcStride;
        ydst += lumStride;
        udst += chromStride;
        vdst += chromStride;
M
Michael Niedermayer 已提交
944 945 946
    }
}

947
static av_cold void rgb2rgb_init_c(void)
M
Michael Niedermayer 已提交
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
{
    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;
964 965 966 967 968
#if HAVE_BIGENDIAN
    shuffle_bytes_0321 = shuffle_bytes_2103_c;
    shuffle_bytes_2103 = shuffle_bytes_0321_c;
#else
    shuffle_bytes_0321 = shuffle_bytes_0321_c;
M
Michael Niedermayer 已提交
969
    shuffle_bytes_2103 = shuffle_bytes_2103_c;
970
#endif
971 972 973
    shuffle_bytes_1230 = shuffle_bytes_1230_c;
    shuffle_bytes_3012 = shuffle_bytes_3012_c;
    shuffle_bytes_3210 = shuffle_bytes_3210_c;
M
Michael Niedermayer 已提交
974 975 976 977 978 979 980 981
    rgb32tobgr16       = rgb32tobgr16_c;
    rgb32tobgr15       = rgb32tobgr15_c;
    yv12toyuy2         = yv12toyuy2_c;
    yv12touyvy         = yv12touyvy_c;
    yuv422ptoyuy2      = yuv422ptoyuy2_c;
    yuv422ptouyvy      = yuv422ptouyvy_c;
    yuy2toyv12         = yuy2toyv12_c;
    planar2x           = planar2x_c;
982
    ff_rgb24toyv12     = ff_rgb24toyv12_c;
M
Michael Niedermayer 已提交
983
    interleaveBytes    = interleaveBytes_c;
984
    deinterleaveBytes  = deinterleaveBytes_c;
M
Michael Niedermayer 已提交
985 986 987 988 989 990 991
    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;
992
}