Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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