Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libswscale/yuv2rgb.c
Line
Count
Source
1
/*
2
 * software YUV to RGB converter
3
 *
4
 * Copyright (C) 2009 Konstantin Shishkov
5
 *
6
 * 1,4,8bpp support and context / deglobalize stuff
7
 * by Michael Niedermayer (michaelni@gmx.at)
8
 *
9
 * This file is part of FFmpeg.
10
 *
11
 * FFmpeg is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU Lesser General Public
13
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
15
 *
16
 * FFmpeg is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 * Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with FFmpeg; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
 */
25
26
#include <stddef.h>
27
#include <stdint.h>
28
29
#include "libavutil/bswap.h"
30
#include "libavutil/mem.h"
31
#include "config.h"
32
#include "swscale.h"
33
#include "swscale_internal.h"
34
#include "libavutil/pixdesc.h"
35
36
/* Color space conversion coefficients for YCbCr -> RGB mapping.
37
 *
38
 * Entries are {crv, cbu, cgu, cgv}
39
 *
40
 *   crv = (255 / 224) * 65536 * (1 - cr) / 0.5
41
 *   cbu = (255 / 224) * 65536 * (1 - cb) / 0.5
42
 *   cgu = (255 / 224) * 65536 * (cb / cg) * (1 - cb) / 0.5
43
 *   cgv = (255 / 224) * 65536 * (cr / cg) * (1 - cr) / 0.5
44
 *
45
 * where Y = cr * R + cg * G + cb * B and cr + cg + cb = 1.
46
 */
47
const int32_t ff_yuv2rgb_coeffs[11][4] = {
48
    { 104597, 132201, 25675, 53279 }, /* no sequence_display_extension */
49
    { 117489, 138438, 13975, 34925 }, /* ITU-R Rec. 709 (1990) */
50
    { 104597, 132201, 25675, 53279 }, /* unspecified */
51
    { 104597, 132201, 25675, 53279 }, /* reserved */
52
    { 104448, 132798, 24759, 53109 }, /* FCC */
53
    { 104597, 132201, 25675, 53279 }, /* ITU-R Rec. 624-4 System B, G */
54
    { 104597, 132201, 25675, 53279 }, /* SMPTE 170M */
55
    { 117579, 136230, 16907, 35559 }, /* SMPTE 240M (1987) */
56
    {      0                       }, /* YCgCo */
57
    { 110013, 140363, 12277, 42626 }, /* Bt-2020-NCL */
58
    { 110013, 140363, 12277, 42626 }, /* Bt-2020-CL */
59
};
60
61
const int *sws_getCoefficients(int colorspace)
62
0
{
63
0
    if (colorspace > 10 || colorspace < 0 || colorspace == 8)
64
0
        colorspace = SWS_CS_DEFAULT;
65
0
    return ff_yuv2rgb_coeffs[colorspace];
66
0
}
67
68
#define LOADCHROMA(l, i)                            \
69
0
    U = pu_##l[i];                                  \
70
0
    V = pv_##l[i];                                  \
71
0
    r = (void *)c->table_rV[V+YUVRGB_TABLE_HEADROOM];                     \
72
0
    g = (void *)(c->table_gU[U+YUVRGB_TABLE_HEADROOM] + c->table_gV[V+YUVRGB_TABLE_HEADROOM]);  \
73
0
    b = (void *)c->table_bU[U+YUVRGB_TABLE_HEADROOM];
74
75
#define PUTRGB(l, i, abase)                         \
76
0
    Y                  = py_##l[2 * i];             \
77
0
    dst_##l[2 * i]     = r[Y] + g[Y] + b[Y];        \
78
0
    Y                  = py_##l[2 * i + 1];         \
79
0
    dst_##l[2 * i + 1] = r[Y] + g[Y] + b[Y];
80
81
#define PUTRGB24(l, i, abase)                       \
82
0
    Y                  = py_##l[2 * i];             \
83
0
    dst_##l[6 * i + 0] = r[Y];                      \
84
0
    dst_##l[6 * i + 1] = g[Y];                      \
85
0
    dst_##l[6 * i + 2] = b[Y];                      \
86
0
    Y                  = py_##l[2 * i + 1];         \
87
0
    dst_##l[6 * i + 3] = r[Y];                      \
88
0
    dst_##l[6 * i + 4] = g[Y];                      \
89
0
    dst_##l[6 * i + 5] = b[Y];
90
91
#define PUTBGR24(l, i, abase)                       \
92
0
    Y                  = py_##l[2 * i];             \
93
0
    dst_##l[6 * i + 0] = b[Y];                      \
94
0
    dst_##l[6 * i + 1] = g[Y];                      \
95
0
    dst_##l[6 * i + 2] = r[Y];                      \
96
0
    Y                  = py_##l[2 * i + 1];         \
97
0
    dst_##l[6 * i + 3] = b[Y];                      \
98
0
    dst_##l[6 * i + 4] = g[Y];                      \
99
0
    dst_##l[6 * i + 5] = r[Y];
100
101
#define PUTRGBA(l, i, abase)                        \
102
0
    Y                  = py_##l[2 * i];             \
103
0
    dst_##l[2 * i]     = r[Y] + g[Y] + b[Y] + ((uint32_t)(pa_##l[2 * i])     << abase); \
104
0
    Y                  = py_##l[2 * i + 1];         \
105
0
    dst_##l[2 * i + 1] = r[Y] + g[Y] + b[Y] + ((uint32_t)(pa_##l[2 * i + 1]) << abase);
106
107
#define PUTRGB48(l, i, abase)                       \
108
0
    Y                    = py_##l[ 2 * i];          \
109
0
    dst_##l[12 * i +  0] = dst_##l[12 * i +  1] = r[Y]; \
110
0
    dst_##l[12 * i +  2] = dst_##l[12 * i +  3] = g[Y]; \
111
0
    dst_##l[12 * i +  4] = dst_##l[12 * i +  5] = b[Y]; \
112
0
    Y                    = py_##l[ 2 * i + 1];      \
113
0
    dst_##l[12 * i +  6] = dst_##l[12 * i +  7] = r[Y]; \
114
0
    dst_##l[12 * i +  8] = dst_##l[12 * i +  9] = g[Y]; \
115
0
    dst_##l[12 * i + 10] = dst_##l[12 * i + 11] = b[Y];
116
117
#define PUTBGR48(l, i, abase)                       \
118
0
    Y                    = py_##l[2 * i];           \
119
0
    dst_##l[12 * i +  0] = dst_##l[12 * i +  1] = b[Y]; \
120
0
    dst_##l[12 * i +  2] = dst_##l[12 * i +  3] = g[Y]; \
121
0
    dst_##l[12 * i +  4] = dst_##l[12 * i +  5] = r[Y]; \
122
0
    Y                    = py_##l[2  * i +  1];     \
123
0
    dst_##l[12 * i +  6] = dst_##l[12 * i +  7] = b[Y]; \
124
0
    dst_##l[12 * i +  8] = dst_##l[12 * i +  9] = g[Y]; \
125
0
    dst_##l[12 * i + 10] = dst_##l[12 * i + 11] = r[Y];
126
127
#define PUTGBRP(l, i, abase)                        \
128
0
    Y                   = py_##l[2 * i];            \
129
0
    dst_##l [2 * i + 0] = g[Y];                     \
130
0
    dst1_##l[2 * i + 0] = b[Y];                     \
131
0
    dst2_##l[2 * i + 0] = r[Y];                     \
132
0
    Y                   = py_##l[2 * i + 1];        \
133
0
    dst_##l [2 * i + 1] = g[Y];                     \
134
0
    dst1_##l[2 * i + 1] = b[Y];                     \
135
0
    dst2_##l[2 * i + 1] = r[Y];
136
137
#define YUV2RGBFUNC(func_name, dst_type, alpha, yuv422, nb_dst_planes)      \
138
    static int func_name(SwsInternal *c, const uint8_t *const src[],         \
139
                         const int srcStride[], int srcSliceY, int srcSliceH, \
140
                         uint8_t *const dst[], const int dstStride[])       \
141
0
    {                                                                       \
142
0
        int y;                                                              \
143
0
                                                                            \
144
0
        for (y = 0; y < srcSliceH; y += 2) {                                \
145
0
            int yd = y + srcSliceY;                                         \
146
0
            dst_type *dst_1 =                                               \
147
0
                (dst_type *)(dst[0] + (yd)     * dstStride[0]);             \
148
0
            dst_type *dst_2 =                                               \
149
0
                (dst_type *)(dst[0] + (yd + 1) * dstStride[0]);             \
150
0
            av_unused dst_type *dst1_1, *dst1_2, *dst2_1, *dst2_2;          \
151
0
            av_unused dst_type *r, *g, *b;                                  \
152
0
            const uint8_t *py_1 = src[0] +  y       * srcStride[0];         \
153
0
            const uint8_t *py_2 = py_1   +            srcStride[0];         \
154
0
            av_unused const uint8_t *pu_1 = src[1] + (y >> !yuv422) * srcStride[1]; \
155
0
            av_unused const uint8_t *pv_1 = src[2] + (y >> !yuv422) * srcStride[2]; \
156
0
            av_unused const uint8_t *pu_2, *pv_2;                           \
157
0
            av_unused const uint8_t *pa_1, *pa_2;                           \
158
0
            unsigned int h_size = c->opts.dst_w >> 3;                       \
159
0
            if (nb_dst_planes > 1) {                                        \
160
0
                dst1_1 = (dst_type *)(dst[1] + (yd)     * dstStride[1]);    \
161
0
                dst1_2 = (dst_type *)(dst[1] + (yd + 1) * dstStride[1]);    \
162
0
                dst2_1 = (dst_type *)(dst[2] + (yd)     * dstStride[2]);    \
163
0
                dst2_2 = (dst_type *)(dst[2] + (yd + 1) * dstStride[2]);    \
164
0
            }                                                               \
165
0
            if (yuv422) {                                                   \
166
0
                pu_2 = pu_1 + srcStride[1];                                 \
167
0
                pv_2 = pv_1 + srcStride[2];                                 \
168
0
            }                                                               \
169
0
            if (alpha) {                                                    \
170
0
                pa_1 = src[3] + y * srcStride[3];                           \
171
0
                pa_2 = pa_1   +     srcStride[3];                           \
172
0
            }                                                               \
173
0
            while (h_size--) {                                              \
174
0
                av_unused int U, V, Y;                                      \
175
176
#define ENDYUV2RGBLINE(dst_delta, ss, alpha, yuv422, nb_dst_planes) \
177
0
    pu_1  += 4 >> ss;                               \
178
0
    pv_1  += 4 >> ss;                               \
179
0
    if (yuv422) {                                   \
180
0
        pu_2 += 4 >> ss;                            \
181
0
        pv_2 += 4 >> ss;                            \
182
0
    }                                               \
183
0
    py_1  += 8 >> ss;                               \
184
0
    py_2  += 8 >> ss;                               \
185
0
    if (alpha) {                                    \
186
0
        pa_1 += 8 >> ss;                            \
187
0
        pa_2 += 8 >> ss;                            \
188
0
    }                                               \
189
0
    dst_1 += dst_delta >> ss;                       \
190
0
    dst_2 += dst_delta >> ss;                       \
191
0
    if (nb_dst_planes > 1) {                        \
192
0
        dst1_1 += dst_delta >> ss;                  \
193
0
        dst1_2 += dst_delta >> ss;                  \
194
0
        dst2_1 += dst_delta >> ss;                  \
195
0
        dst2_2 += dst_delta >> ss;                  \
196
0
    }                                               \
197
0
    }                                               \
198
0
    if (c->opts.dst_w & (4 >> ss)) {                \
199
0
        av_unused int Y, U, V;                      \
200
201
#define ENDYUV2RGBFUNC()                            \
202
0
            }                                       \
203
0
        }                                           \
204
0
        return srcSliceH;                           \
205
0
    }
206
207
#define YUV420FUNC(func_name, dst_type, alpha, abase, PUTFUNC, dst_delta, nb_dst_planes) \
208
0
    YUV2RGBFUNC(func_name, dst_type, alpha, 0, nb_dst_planes)           \
209
0
        LOADCHROMA(1, 0);                                               \
210
0
        PUTFUNC(1, 0, abase);                                           \
211
0
        PUTFUNC(2, 0, abase);                                           \
212
0
                                                                        \
213
0
        LOADCHROMA(1, 1);                                               \
214
0
        PUTFUNC(2, 1, abase);                                           \
215
0
        PUTFUNC(1, 1, abase);                                           \
216
0
                                                                        \
217
0
        LOADCHROMA(1, 2);                                               \
218
0
        PUTFUNC(1, 2, abase);                                           \
219
0
        PUTFUNC(2, 2, abase);                                           \
220
0
                                                                        \
221
0
        LOADCHROMA(1, 3);                                               \
222
0
        PUTFUNC(2, 3, abase);                                           \
223
0
        PUTFUNC(1, 3, abase);                                           \
224
0
    ENDYUV2RGBLINE(dst_delta, 0, alpha, 0, nb_dst_planes)               \
225
0
        LOADCHROMA(1, 0);                                               \
226
0
        PUTFUNC(1, 0, abase);                                           \
227
0
        PUTFUNC(2, 0, abase);                                           \
228
0
                                                                        \
229
0
        LOADCHROMA(1, 1);                                               \
230
0
        PUTFUNC(2, 1, abase);                                           \
231
0
        PUTFUNC(1, 1, abase);                                           \
232
0
    ENDYUV2RGBLINE(dst_delta, 1, alpha, 0, nb_dst_planes)               \
233
0
        LOADCHROMA(1, 0);                                               \
234
0
        PUTFUNC(1, 0, abase);                                           \
235
0
        PUTFUNC(2, 0, abase);                                           \
236
0
    ENDYUV2RGBFUNC()
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_bgr48
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_48
Unexecuted instantiation: yuv2rgb.c:yuva2argb_c
Unexecuted instantiation: yuv2rgb.c:yuva2rgba_c
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_32
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_24_rgb
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_24_bgr
Unexecuted instantiation: yuv2rgb.c:yuv420p_gbrp_c
237
238
#define YUV422FUNC(func_name, dst_type, alpha, abase, PUTFUNC, dst_delta, nb_dst_planes) \
239
0
    YUV2RGBFUNC(func_name, dst_type, alpha, 1, nb_dst_planes)           \
240
0
        LOADCHROMA(1, 0);                                               \
241
0
        PUTFUNC(1, 0, abase);                                           \
242
0
                                                                        \
243
0
        LOADCHROMA(2, 0);                                               \
244
0
        PUTFUNC(2, 0, abase);                                           \
245
0
                                                                        \
246
0
        LOADCHROMA(2, 1);                                               \
247
0
        PUTFUNC(2, 1, abase);                                           \
248
0
                                                                        \
249
0
        LOADCHROMA(1, 1);                                               \
250
0
        PUTFUNC(1, 1, abase);                                           \
251
0
                                                                        \
252
0
        LOADCHROMA(1, 2);                                               \
253
0
        PUTFUNC(1, 2, abase);                                           \
254
0
                                                                        \
255
0
        LOADCHROMA(2, 2);                                               \
256
0
        PUTFUNC(2, 2, abase);                                           \
257
0
                                                                        \
258
0
        LOADCHROMA(2, 3);                                               \
259
0
        PUTFUNC(2, 3, abase);                                           \
260
0
                                                                        \
261
0
        LOADCHROMA(1, 3);                                               \
262
0
        PUTFUNC(1, 3, abase);                                           \
263
0
    ENDYUV2RGBLINE(dst_delta, 0, alpha, 1, nb_dst_planes)               \
264
0
        LOADCHROMA(1, 0);                                               \
265
0
        PUTFUNC(1, 0, abase);                                           \
266
0
                                                                        \
267
0
        LOADCHROMA(2, 0);                                               \
268
0
        PUTFUNC(2, 0, abase);                                           \
269
0
                                                                        \
270
0
        LOADCHROMA(2, 1);                                               \
271
0
        PUTFUNC(2, 1, abase);                                           \
272
0
                                                                        \
273
0
        LOADCHROMA(1, 1);                                               \
274
0
        PUTFUNC(1, 1, abase);                                           \
275
0
    ENDYUV2RGBLINE(dst_delta, 1, alpha, 1, nb_dst_planes)               \
276
0
        LOADCHROMA(1, 0);                                               \
277
0
        PUTFUNC(1, 0, abase);                                           \
278
0
                                                                        \
279
0
        LOADCHROMA(2, 0);                                               \
280
0
        PUTFUNC(2, 0, abase);                                           \
281
0
    ENDYUV2RGBFUNC()
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr48_c
Unexecuted instantiation: yuv2rgb.c:yuv422p_rgb48_c
Unexecuted instantiation: yuv2rgb.c:yuva422p_argb_c
Unexecuted instantiation: yuv2rgb.c:yuva422p_rgba_c
Unexecuted instantiation: yuv2rgb.c:yuv422p_rgb32_c
Unexecuted instantiation: yuv2rgb.c:yuv422p_rgb24_c
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr24_c
Unexecuted instantiation: yuv2rgb.c:yuv422p_gbrp_c
282
283
#define YUV420FUNC_DITHER(func_name, dst_type, LOADDITHER, PUTFUNC, dst_delta) \
284
0
    YUV2RGBFUNC(func_name, dst_type, 0, 0, 1)                           \
285
0
        LOADDITHER                                                      \
286
0
                                                                        \
287
0
        LOADCHROMA(1, 0);                                               \
288
0
        PUTFUNC(1, 0, 0);                                               \
289
0
        PUTFUNC(2, 0, 0 + 8);                                           \
290
0
                                                                        \
291
0
        LOADCHROMA(1, 1);                                               \
292
0
        PUTFUNC(2, 1, 2 + 8);                                           \
293
0
        PUTFUNC(1, 1, 2);                                               \
294
0
                                                                        \
295
0
        LOADCHROMA(1, 2);                                               \
296
0
        PUTFUNC(1, 2, 4);                                               \
297
0
        PUTFUNC(2, 2, 4 + 8);                                           \
298
0
                                                                        \
299
0
        LOADCHROMA(1, 3);                                               \
300
0
        PUTFUNC(2, 3, 6 + 8);                                           \
301
0
        PUTFUNC(1, 3, 6);                                               \
302
0
    ENDYUV2RGBLINE(dst_delta, 0, 0, 0, 1)                               \
303
0
        LOADDITHER                                                      \
304
0
                                                                        \
305
0
        LOADCHROMA(1, 0);                                               \
306
0
        PUTFUNC(1, 0, 0);                                               \
307
0
        PUTFUNC(2, 0, 0 + 8);                                           \
308
0
                                                                        \
309
0
        LOADCHROMA(1, 1);                                               \
310
0
        PUTFUNC(2, 1, 2 + 8);                                           \
311
0
        PUTFUNC(1, 1, 2);                                               \
312
0
    ENDYUV2RGBLINE(dst_delta, 1, 0, 0, 1)                               \
313
0
        LOADDITHER                                                      \
314
0
                                                                        \
315
0
        LOADCHROMA(1, 0);                                               \
316
0
        PUTFUNC(1, 0, 0);                                               \
317
0
        PUTFUNC(2, 0, 0 + 8);                                           \
318
0
    ENDYUV2RGBFUNC()
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_16_ordered_dither
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_15_ordered_dither
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_12_ordered_dither
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_8_ordered_dither
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_4_ordered_dither
Unexecuted instantiation: yuv2rgb.c:yuv2rgb_c_4b_ordered_dither
319
320
#define YUV422FUNC_DITHER(func_name, dst_type, LOADDITHER, PUTFUNC, dst_delta) \
321
0
    YUV2RGBFUNC(func_name, dst_type, 0, 1, 1)                           \
322
0
        LOADDITHER                                                      \
323
0
                                                                        \
324
0
        LOADCHROMA(1, 0);                                               \
325
0
        PUTFUNC(1, 0, 0);                                               \
326
0
                                                                        \
327
0
        LOADCHROMA(2, 0);                                               \
328
0
        PUTFUNC(2, 0, 0 + 8);                                           \
329
0
                                                                        \
330
0
        LOADCHROMA(2, 1);                                               \
331
0
        PUTFUNC(2, 1, 2 + 8);                                           \
332
0
                                                                        \
333
0
        LOADCHROMA(1, 1);                                               \
334
0
        PUTFUNC(1, 1, 2);                                               \
335
0
                                                                        \
336
0
        LOADCHROMA(1, 2);                                               \
337
0
        PUTFUNC(1, 2, 4);                                               \
338
0
                                                                        \
339
0
        LOADCHROMA(2, 2);                                               \
340
0
        PUTFUNC(2, 2, 4 + 8);                                           \
341
0
                                                                        \
342
0
        LOADCHROMA(2, 3);                                               \
343
0
        PUTFUNC(2, 3, 6 + 8);                                           \
344
0
                                                                        \
345
0
        LOADCHROMA(1, 3);                                               \
346
0
        PUTFUNC(1, 3, 6);                                               \
347
0
    ENDYUV2RGBLINE(dst_delta, 0, 0, 1, 1)                               \
348
0
        LOADDITHER                                                      \
349
0
                                                                        \
350
0
        LOADCHROMA(1, 0);                                               \
351
0
        PUTFUNC(1, 0, 0);                                               \
352
0
                                                                        \
353
0
        LOADCHROMA(2, 0);                                               \
354
0
        PUTFUNC(2, 0, 0 + 8);                                           \
355
0
                                                                        \
356
0
        LOADCHROMA(2, 1);                                               \
357
0
        PUTFUNC(2, 1, 2 + 8);                                           \
358
0
                                                                        \
359
0
        LOADCHROMA(1, 1);                                               \
360
0
        PUTFUNC(1, 1, 2);                                               \
361
0
    ENDYUV2RGBLINE(dst_delta, 1, 0, 1, 1)                               \
362
0
        LOADDITHER                                                      \
363
0
                                                                        \
364
0
        LOADCHROMA(1, 0);                                               \
365
0
        PUTFUNC(1, 0, 0);                                               \
366
0
                                                                        \
367
0
        LOADCHROMA(2, 0);                                               \
368
0
        PUTFUNC(2, 0, 0 + 8);                                           \
369
0
    ENDYUV2RGBFUNC()
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr16
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr15
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr12
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr8
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr4
Unexecuted instantiation: yuv2rgb.c:yuv422p_bgr4_byte
370
371
#define LOADDITHER16                                    \
372
    const uint8_t *d16 = ff_dither_2x2_8[y & 1];        \
373
    const uint8_t *e16 = ff_dither_2x2_4[y & 1];        \
374
    const uint8_t *f16 = ff_dither_2x2_8[(y & 1)^1];
375
376
#define PUTRGB16(l, i, o)                           \
377
0
    Y                  = py_##l[2 * i];             \
378
0
    dst_##l[2 * i]     = r[Y + d16[0 + o]] +        \
379
0
                         g[Y + e16[0 + o]] +        \
380
0
                         b[Y + f16[0 + o]];         \
381
0
    Y                  = py_##l[2 * i + 1];         \
382
0
    dst_##l[2 * i + 1] = r[Y + d16[1 + o]] +        \
383
0
                         g[Y + e16[1 + o]] +        \
384
0
                         b[Y + f16[1 + o]];
385
386
#define LOADDITHER15                                    \
387
    const uint8_t *d16 = ff_dither_2x2_8[y & 1];        \
388
    const uint8_t *e16 = ff_dither_2x2_8[(y & 1)^1];
389
390
#define PUTRGB15(l, i, o)                           \
391
0
    Y                  = py_##l[2 * i];             \
392
0
    dst_##l[2 * i]     = r[Y + d16[0 + o]] +        \
393
0
                         g[Y + d16[1 + o]] +        \
394
0
                         b[Y + e16[0 + o]];         \
395
0
    Y                  = py_##l[2 * i + 1];         \
396
0
    dst_##l[2 * i + 1] = r[Y + d16[1 + o]] +        \
397
0
                         g[Y + d16[0 + o]] +        \
398
0
                         b[Y + e16[1 + o]];
399
400
#define LOADDITHER12                                    \
401
    const uint8_t *d16 = ff_dither_4x4_16[y & 3];
402
403
#define PUTRGB12(l, i, o)                           \
404
0
    Y                  = py_##l[2 * i];             \
405
0
    dst_##l[2 * i]     = r[Y + d16[0 + o]] +        \
406
0
                         g[Y + d16[0 + o]] +        \
407
0
                         b[Y + d16[0 + o]];         \
408
0
    Y                  = py_##l[2 * i + 1];         \
409
0
    dst_##l[2 * i + 1] = r[Y + d16[1 + o]] +        \
410
0
                         g[Y + d16[1 + o]] +        \
411
0
                         b[Y + d16[1 + o]];
412
413
#define LOADDITHER8                                     \
414
    const uint8_t *d32 = ff_dither_8x8_32[yd & 7];      \
415
    const uint8_t *d64 = ff_dither_8x8_73[yd & 7];
416
417
#define PUTRGB8(l, i, o)                            \
418
0
    Y                  = py_##l[2 * i];             \
419
0
    dst_##l[2 * i]     = r[Y + d32[0 + o]] +        \
420
0
                         g[Y + d32[0 + o]] +        \
421
0
                         b[Y + d64[0 + o]];         \
422
0
    Y                  = py_##l[2 * i + 1];         \
423
0
    dst_##l[2 * i + 1] = r[Y + d32[1 + o]] +        \
424
0
                         g[Y + d32[1 + o]] +        \
425
0
                         b[Y + d64[1 + o]];
426
427
#define LOADDITHER4D                                    \
428
    const uint8_t * d64 = ff_dither_8x8_73[yd & 7];     \
429
    const uint8_t *d128 = ff_dither_8x8_220[yd & 7];    \
430
    int acc;
431
432
#define PUTRGB4D(l, i, o)                           \
433
0
    Y      = py_##l[2 * i];                         \
434
0
    acc    = r[Y + d128[0 + o]] +                   \
435
0
             g[Y +  d64[0 + o]] +                   \
436
0
             b[Y + d128[0 + o]];                    \
437
0
    Y      = py_##l[2 * i + 1];                     \
438
0
    acc   |= (r[Y + d128[1 + o]] +                  \
439
0
              g[Y +  d64[1 + o]] +                  \
440
0
              b[Y + d128[1 + o]]) << 4;             \
441
0
    dst_##l[i] = acc;
442
443
#define LOADDITHER4DB                                   \
444
    const uint8_t *d64  = ff_dither_8x8_73[yd & 7];     \
445
    const uint8_t *d128 = ff_dither_8x8_220[yd & 7];
446
447
#define PUTRGB4DB(l, i, o)                          \
448
0
    Y                  = py_##l[2 * i];             \
449
0
    dst_##l[2 * i]     = r[Y + d128[0 + o]] +       \
450
0
                         g[Y +  d64[0 + o]] +       \
451
0
                         b[Y + d128[0 + o]];        \
452
0
    Y                  = py_##l[2 * i + 1];         \
453
0
    dst_##l[2 * i + 1] = r[Y + d128[1 + o]] +       \
454
0
                         g[Y +  d64[1 + o]] +       \
455
0
                         b[Y + d128[1 + o]];
456
457
0
YUV2RGBFUNC(yuv2rgb_c_1_ordered_dither, uint8_t, 0, 0, 1)
458
0
    const uint8_t *d128 = ff_dither_8x8_220[yd & 7];
459
0
    char out_1 = 0, out_2 = 0;
460
0
    g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM];
461
462
0
#define PUTRGB1(out, src, i, o)                     \
463
0
    Y    = src[2 * i];                              \
464
0
    out += out + g[Y + d128[0 + o]];                \
465
0
    Y    = src[2 * i + 1];                          \
466
0
    out += out + g[Y + d128[1 + o]];
467
468
0
    PUTRGB1(out_1, py_1, 0, 0);
469
0
    PUTRGB1(out_2, py_2, 0, 0 + 8);
470
471
0
    PUTRGB1(out_2, py_2, 1, 2 + 8);
472
0
    PUTRGB1(out_1, py_1, 1, 2);
473
474
0
    PUTRGB1(out_1, py_1, 2, 4);
475
0
    PUTRGB1(out_2, py_2, 2, 4 + 8);
476
477
0
    PUTRGB1(out_2, py_2, 3, 6 + 8);
478
0
    PUTRGB1(out_1, py_1, 3, 6);
479
480
0
    dst_1[0] = out_1;
481
0
    dst_2[0] = out_2;
482
483
0
    py_1  += 8;
484
0
    py_2  += 8;
485
0
    dst_1 += 1;
486
0
    dst_2 += 1;
487
0
    }
488
0
    if (c->opts.dst_w & 7) {
489
0
        av_unused int Y, U, V;
490
0
        int pixels_left = c->opts.dst_w & 7;
491
0
    const uint8_t *d128 = ff_dither_8x8_220[yd & 7];
492
0
    char out_1 = 0, out_2 = 0;
493
0
    g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM];
494
495
0
#define PUTRGB1_OR00(out, src, i, o)                \
496
0
    if (pixels_left) {                              \
497
0
        PUTRGB1(out, src, i, o)                     \
498
0
        pixels_left--;                              \
499
0
    } else {                                        \
500
0
        out <<= 2;                                  \
501
0
    }
502
503
0
    PUTRGB1_OR00(out_1, py_1, 0, 0);
504
0
    PUTRGB1_OR00(out_2, py_2, 0, 0 + 8);
505
506
0
    PUTRGB1_OR00(out_2, py_2, 1, 2 + 8);
507
0
    PUTRGB1_OR00(out_1, py_1, 1, 2);
508
509
0
    PUTRGB1_OR00(out_1, py_1, 2, 4);
510
0
    PUTRGB1_OR00(out_2, py_2, 2, 4 + 8);
511
512
0
    PUTRGB1_OR00(out_2, py_2, 3, 6 + 8);
513
0
    PUTRGB1_OR00(out_1, py_1, 3, 6);
514
515
0
    dst_1[0] = out_1;
516
0
    dst_2[0] = out_2;
517
0
ENDYUV2RGBFUNC()
518
519
// YUV420
520
0
YUV420FUNC(yuv2rgb_c_48,     uint8_t,  0,  0, PUTRGB48, 48, 1)
521
0
YUV420FUNC(yuv2rgb_c_bgr48,  uint8_t,  0,  0, PUTBGR48, 48, 1)
522
0
YUV420FUNC(yuv2rgb_c_32,     uint32_t, 0,  0, PUTRGB,    8, 1)
523
#if HAVE_BIGENDIAN
524
YUV420FUNC(yuva2argb_c,      uint32_t, 1, 24, PUTRGBA,   8, 1)
525
YUV420FUNC(yuva2rgba_c,      uint32_t, 1,  0, PUTRGBA,   8, 1)
526
#else
527
0
YUV420FUNC(yuva2rgba_c,      uint32_t, 1, 24, PUTRGBA,   8, 1)
528
0
YUV420FUNC(yuva2argb_c,      uint32_t, 1,  0, PUTRGBA,   8, 1)
529
#endif
530
0
YUV420FUNC(yuv2rgb_c_24_rgb, uint8_t,  0,  0, PUTRGB24, 24, 1)
531
0
YUV420FUNC(yuv2rgb_c_24_bgr, uint8_t,  0,  0, PUTBGR24, 24, 1)
532
0
YUV420FUNC(yuv420p_gbrp_c,   uint8_t,  0,  0, PUTGBRP,   8, 3)
533
0
YUV420FUNC_DITHER(yuv2rgb_c_16_ordered_dither, uint16_t, LOADDITHER16,  PUTRGB16,  8)
534
0
YUV420FUNC_DITHER(yuv2rgb_c_15_ordered_dither, uint16_t, LOADDITHER15,  PUTRGB15,  8)
535
0
YUV420FUNC_DITHER(yuv2rgb_c_12_ordered_dither, uint16_t, LOADDITHER12,  PUTRGB12,  8)
536
0
YUV420FUNC_DITHER(yuv2rgb_c_8_ordered_dither,  uint8_t,  LOADDITHER8,   PUTRGB8,   8)
537
0
YUV420FUNC_DITHER(yuv2rgb_c_4_ordered_dither,  uint8_t,  LOADDITHER4D,  PUTRGB4D,  4)
538
0
YUV420FUNC_DITHER(yuv2rgb_c_4b_ordered_dither, uint8_t,  LOADDITHER4DB, PUTRGB4DB, 8)
539
540
// YUV422
541
0
YUV422FUNC(yuv422p_rgb48_c,  uint8_t,  0,  0, PUTRGB48, 48, 1)
542
0
YUV422FUNC(yuv422p_bgr48_c,  uint8_t,  0,  0, PUTBGR48, 48, 1)
543
0
YUV422FUNC(yuv422p_rgb32_c,  uint32_t, 0,  0, PUTRGB,    8, 1)
544
#if HAVE_BIGENDIAN
545
YUV422FUNC(yuva422p_argb_c,  uint32_t, 1, 24, PUTRGBA,   8, 1)
546
YUV422FUNC(yuva422p_rgba_c,  uint32_t, 1,  0, PUTRGBA,   8, 1)
547
#else
548
0
YUV422FUNC(yuva422p_rgba_c,  uint32_t, 1, 24, PUTRGBA,   8, 1)
549
0
YUV422FUNC(yuva422p_argb_c,  uint32_t, 1,  0, PUTRGBA,   8, 1)
550
#endif
551
0
YUV422FUNC(yuv422p_rgb24_c,  uint8_t,  0,  0, PUTRGB24, 24, 1)
552
0
YUV422FUNC(yuv422p_bgr24_c,  uint8_t,  0,  0, PUTBGR24, 24, 1)
553
0
YUV422FUNC(yuv422p_gbrp_c,   uint8_t,  0,  0, PUTGBRP,   8, 3)
554
0
YUV422FUNC_DITHER(yuv422p_bgr16,     uint16_t, LOADDITHER16,  PUTRGB16,  8)
555
0
YUV422FUNC_DITHER(yuv422p_bgr15,     uint16_t, LOADDITHER15,  PUTRGB15,  8)
556
0
YUV422FUNC_DITHER(yuv422p_bgr12,     uint16_t, LOADDITHER12,  PUTRGB12,  8)
557
0
YUV422FUNC_DITHER(yuv422p_bgr8,      uint8_t,  LOADDITHER8,   PUTRGB8,   8)
558
0
YUV422FUNC_DITHER(yuv422p_bgr4,      uint8_t,  LOADDITHER4D,  PUTRGB4D,  4)
559
0
YUV422FUNC_DITHER(yuv422p_bgr4_byte, uint8_t,  LOADDITHER4DB, PUTRGB4DB, 8)
560
561
SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c)
562
0
{
563
0
    SwsFunc t = NULL;
564
565
#if ARCH_PPC
566
    t = ff_yuv2rgb_init_ppc(c);
567
#elif ARCH_X86
568
    t = ff_yuv2rgb_init_x86(c);
569
#elif ARCH_LOONGARCH64
570
    t = ff_yuv2rgb_init_loongarch(c);
571
#endif
572
573
0
    if (t)
574
0
        return t;
575
576
0
    av_log(c, AV_LOG_WARNING,
577
0
           "No accelerated colorspace conversion found from %s to %s.\n",
578
0
           av_get_pix_fmt_name(c->opts.src_format), av_get_pix_fmt_name(c->opts.dst_format));
579
580
0
    if (c->opts.src_format == AV_PIX_FMT_YUV422P) {
581
0
        switch (c->opts.dst_format) {
582
0
        case AV_PIX_FMT_BGR48BE:
583
0
        case AV_PIX_FMT_BGR48LE:
584
0
            return yuv422p_bgr48_c;
585
0
        case AV_PIX_FMT_RGB48BE:
586
0
        case AV_PIX_FMT_RGB48LE:
587
0
            return yuv422p_rgb48_c;
588
0
        case AV_PIX_FMT_ARGB:
589
0
        case AV_PIX_FMT_ABGR:
590
0
            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format))
591
0
                return yuva422p_argb_c;
592
0
        case AV_PIX_FMT_RGBA:
593
0
        case AV_PIX_FMT_BGRA:
594
0
            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) ? yuva422p_rgba_c : yuv422p_rgb32_c;
595
0
        case AV_PIX_FMT_RGB24:
596
0
            return yuv422p_rgb24_c;
597
0
        case AV_PIX_FMT_BGR24:
598
0
            return yuv422p_bgr24_c;
599
0
        case AV_PIX_FMT_RGB565:
600
0
        case AV_PIX_FMT_BGR565:
601
0
            return yuv422p_bgr16;
602
0
        case AV_PIX_FMT_RGB555:
603
0
        case AV_PIX_FMT_BGR555:
604
0
            return yuv422p_bgr15;
605
0
        case AV_PIX_FMT_RGB444:
606
0
        case AV_PIX_FMT_BGR444:
607
0
            return yuv422p_bgr12;
608
0
        case AV_PIX_FMT_RGB8:
609
0
        case AV_PIX_FMT_BGR8:
610
0
            return yuv422p_bgr8;
611
0
        case AV_PIX_FMT_RGB4:
612
0
        case AV_PIX_FMT_BGR4:
613
0
            return yuv422p_bgr4;
614
0
        case AV_PIX_FMT_RGB4_BYTE:
615
0
        case AV_PIX_FMT_BGR4_BYTE:
616
0
            return yuv422p_bgr4_byte;
617
0
        case AV_PIX_FMT_MONOBLACK:
618
0
            return yuv2rgb_c_1_ordered_dither;
619
0
        case AV_PIX_FMT_GBRP:
620
0
            return yuv422p_gbrp_c;
621
0
        }
622
0
    } else {
623
0
        switch (c->opts.dst_format) {
624
0
        case AV_PIX_FMT_BGR48BE:
625
0
        case AV_PIX_FMT_BGR48LE:
626
0
            return yuv2rgb_c_bgr48;
627
0
        case AV_PIX_FMT_RGB48BE:
628
0
        case AV_PIX_FMT_RGB48LE:
629
0
            return yuv2rgb_c_48;
630
0
        case AV_PIX_FMT_ARGB:
631
0
        case AV_PIX_FMT_ABGR:
632
0
            if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format))
633
0
                return yuva2argb_c;
634
0
        case AV_PIX_FMT_RGBA:
635
0
        case AV_PIX_FMT_BGRA:
636
0
            return (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) ? yuva2rgba_c : yuv2rgb_c_32;
637
0
        case AV_PIX_FMT_RGB24:
638
0
            return yuv2rgb_c_24_rgb;
639
0
        case AV_PIX_FMT_BGR24:
640
0
            return yuv2rgb_c_24_bgr;
641
0
        case AV_PIX_FMT_RGB565:
642
0
        case AV_PIX_FMT_BGR565:
643
0
            return yuv2rgb_c_16_ordered_dither;
644
0
        case AV_PIX_FMT_RGB555:
645
0
        case AV_PIX_FMT_BGR555:
646
0
            return yuv2rgb_c_15_ordered_dither;
647
0
        case AV_PIX_FMT_RGB444:
648
0
        case AV_PIX_FMT_BGR444:
649
0
            return yuv2rgb_c_12_ordered_dither;
650
0
        case AV_PIX_FMT_RGB8:
651
0
        case AV_PIX_FMT_BGR8:
652
0
            return yuv2rgb_c_8_ordered_dither;
653
0
        case AV_PIX_FMT_RGB4:
654
0
        case AV_PIX_FMT_BGR4:
655
0
            return yuv2rgb_c_4_ordered_dither;
656
0
        case AV_PIX_FMT_RGB4_BYTE:
657
0
        case AV_PIX_FMT_BGR4_BYTE:
658
0
            return yuv2rgb_c_4b_ordered_dither;
659
0
        case AV_PIX_FMT_MONOBLACK:
660
0
            return yuv2rgb_c_1_ordered_dither;
661
0
        case AV_PIX_FMT_GBRP:
662
0
            return yuv420p_gbrp_c;
663
0
        }
664
0
    }
665
0
    return NULL;
666
0
}
667
668
static void fill_table(uint8_t* table[256 + 2*YUVRGB_TABLE_HEADROOM], const int elemsize,
669
                       const int64_t inc, void *y_tab)
670
0
{
671
0
    int i;
672
0
    uint8_t *y_table = y_tab;
673
674
0
    y_table -= elemsize * (inc >> 9);
675
676
0
    for (i = 0; i < 256 + 2*YUVRGB_TABLE_HEADROOM; i++) {
677
0
        int64_t cb = av_clip_uint8(i-YUVRGB_TABLE_HEADROOM)*inc;
678
0
        table[i] = y_table + elemsize * (cb >> 16);
679
0
    }
680
0
}
681
682
static void fill_gv_table(int table[256 + 2*YUVRGB_TABLE_HEADROOM], const int elemsize, const int64_t inc)
683
0
{
684
0
    int i;
685
0
    int off    = -(inc >> 9);
686
687
0
    for (i = 0; i < 256 + 2*YUVRGB_TABLE_HEADROOM; i++) {
688
0
        int64_t cb = av_clip_uint8(i-YUVRGB_TABLE_HEADROOM)*inc;
689
0
        table[i] = elemsize * (off + (cb >> 16));
690
0
    }
691
0
}
692
693
static uint16_t roundToInt16(int64_t f)
694
0
{
695
0
    int r = (f + (1 << 15)) >> 16;
696
697
0
    if (r < -0x7FFF)
698
0
        return 0x8000;
699
0
    else if (r > 0x7FFF)
700
0
        return 0x7FFF;
701
0
    else
702
0
        return r;
703
0
}
704
705
av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4],
706
                                     int fullRange, int brightness,
707
                                     int contrast, int saturation)
708
0
{
709
0
    const int isRgb = c->opts.dst_format == AV_PIX_FMT_RGB32     ||
710
0
                      c->opts.dst_format == AV_PIX_FMT_RGB32_1   ||
711
0
                      c->opts.dst_format == AV_PIX_FMT_BGR24     ||
712
0
                      c->opts.dst_format == AV_PIX_FMT_RGB565BE  ||
713
0
                      c->opts.dst_format == AV_PIX_FMT_RGB565LE  ||
714
0
                      c->opts.dst_format == AV_PIX_FMT_RGB555BE  ||
715
0
                      c->opts.dst_format == AV_PIX_FMT_RGB555LE  ||
716
0
                      c->opts.dst_format == AV_PIX_FMT_RGB444BE  ||
717
0
                      c->opts.dst_format == AV_PIX_FMT_RGB444LE  ||
718
0
                      c->opts.dst_format == AV_PIX_FMT_X2RGB10BE ||
719
0
                      c->opts.dst_format == AV_PIX_FMT_X2RGB10LE ||
720
0
                      c->opts.dst_format == AV_PIX_FMT_RGB8      ||
721
0
                      c->opts.dst_format == AV_PIX_FMT_RGB4      ||
722
0
                      c->opts.dst_format == AV_PIX_FMT_RGB4_BYTE ||
723
0
                      c->opts.dst_format == AV_PIX_FMT_MONOBLACK;
724
0
    const int isNotNe = c->opts.dst_format == AV_PIX_FMT_NE(RGB565LE, RGB565BE) ||
725
0
                        c->opts.dst_format == AV_PIX_FMT_NE(RGB555LE, RGB555BE) ||
726
0
                        c->opts.dst_format == AV_PIX_FMT_NE(RGB444LE, RGB444BE) ||
727
0
                        c->opts.dst_format == AV_PIX_FMT_NE(BGR565LE, BGR565BE) ||
728
0
                        c->opts.dst_format == AV_PIX_FMT_NE(BGR555LE, BGR555BE) ||
729
0
                        c->opts.dst_format == AV_PIX_FMT_NE(BGR444LE, BGR444BE) ||
730
0
                        c->opts.dst_format == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE) ||
731
0
                        c->opts.dst_format == AV_PIX_FMT_NE(X2BGR10LE, X2BGR10BE);
732
0
    const int bpp = c->dstFormatBpp;
733
0
    uint8_t *y_table;
734
0
    uint16_t *y_table16;
735
0
    uint32_t *y_table32;
736
0
    int i, base, rbase, gbase, bbase, av_uninit(abase), needAlpha;
737
0
    const int yoffs = (fullRange ? 384 : 326) + YUVRGB_TABLE_LUMA_HEADROOM;
738
0
    const int table_plane_size = 1024 + 2*YUVRGB_TABLE_LUMA_HEADROOM;
739
740
0
    int64_t crv =  inv_table[0];
741
0
    int64_t cbu =  inv_table[1];
742
0
    int64_t cgu = -inv_table[2];
743
0
    int64_t cgv = -inv_table[3];
744
0
    int64_t cy  = 1 << 16;
745
0
    int64_t oy  = 0;
746
0
    int64_t yb  = 0;
747
748
0
    if (!fullRange) {
749
0
        cy = (cy * 255) / 219;
750
0
        oy = 16 << 16;
751
0
    } else {
752
0
        crv = (crv * 224) / 255;
753
0
        cbu = (cbu * 224) / 255;
754
0
        cgu = (cgu * 224) / 255;
755
0
        cgv = (cgv * 224) / 255;
756
0
    }
757
758
0
    cy   = (cy  * contrast)              >> 16;
759
0
    crv  = (crv * contrast * saturation) >> 32;
760
0
    cbu  = (cbu * contrast * saturation) >> 32;
761
0
    cgu  = (cgu * contrast * saturation) >> 32;
762
0
    cgv  = (cgv * contrast * saturation) >> 32;
763
0
    oy  -= 256LL * brightness;
764
765
0
    c->uOffset = 0x0400040004000400LL;
766
0
    c->vOffset = 0x0400040004000400LL;
767
0
    c->yCoeff  = roundToInt16(cy  * (1 << 13)) * 0x0001000100010001ULL;
768
0
    c->vrCoeff = roundToInt16(crv * (1 << 13)) * 0x0001000100010001ULL;
769
0
    c->ubCoeff = roundToInt16(cbu * (1 << 13)) * 0x0001000100010001ULL;
770
0
    c->vgCoeff = roundToInt16(cgv * (1 << 13)) * 0x0001000100010001ULL;
771
0
    c->ugCoeff = roundToInt16(cgu * (1 << 13)) * 0x0001000100010001ULL;
772
0
    c->yOffset = roundToInt16(oy  * (1 <<  3)) * 0x0001000100010001ULL;
773
774
0
    c->yuv2rgb_y_coeff   = (int16_t)roundToInt16(cy  * (1 << 13));
775
0
    c->yuv2rgb_y_offset  = (int16_t)roundToInt16(oy  * (1 <<  9));
776
0
    c->yuv2rgb_v2r_coeff = (int16_t)roundToInt16(crv * (1 << 13));
777
0
    c->yuv2rgb_v2g_coeff = (int16_t)roundToInt16(cgv * (1 << 13));
778
0
    c->yuv2rgb_u2g_coeff = (int16_t)roundToInt16(cgu * (1 << 13));
779
0
    c->yuv2rgb_u2b_coeff = (int16_t)roundToInt16(cbu * (1 << 13));
780
781
    //scale coefficients by cy
782
0
    crv = ((crv * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
783
0
    cbu = ((cbu * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
784
0
    cgu = ((cgu * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
785
0
    cgv = ((cgv * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
786
787
0
    av_freep(&c->yuvTable);
788
789
0
#define ALLOC_YUV_TABLE(x)          \
790
0
        c->yuvTable = av_malloc(x); \
791
0
        if (!c->yuvTable)           \
792
0
            return AVERROR(ENOMEM);
793
0
    switch (bpp) {
794
0
    case 1:
795
0
        ALLOC_YUV_TABLE(table_plane_size);
796
0
        y_table     = c->yuvTable;
797
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
798
0
        for (i = 0; i < table_plane_size - 110; i++) {
799
0
            y_table[i + 110]  = av_clip_uint8((yb + 0x8000) >> 16) >> 7;
800
0
            yb               += cy;
801
0
        }
802
0
        fill_table(c->table_gU, 1, cgu, y_table + yoffs);
803
0
        fill_gv_table(c->table_gV, 1, cgv);
804
0
        break;
805
0
    case 4:
806
0
    case 4 | 128:
807
0
        rbase       = isRgb ? 3 : 0;
808
0
        gbase       = 1;
809
0
        bbase       = isRgb ? 0 : 3;
810
0
        ALLOC_YUV_TABLE(table_plane_size * 3);
811
0
        y_table     = c->yuvTable;
812
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
813
0
        for (i = 0; i < table_plane_size - 110; i++) {
814
0
            int yval                = av_clip_uint8((yb + 0x8000) >> 16);
815
0
            y_table[i + 110]        = (yval >> 7)        << rbase;
816
0
            y_table[i +  37 +   table_plane_size] = ((yval + 43) / 85) << gbase;
817
0
            y_table[i + 110 + 2*table_plane_size] = (yval >> 7)        << bbase;
818
0
            yb += cy;
819
0
        }
820
0
        fill_table(c->table_rV, 1, crv, y_table + yoffs);
821
0
        fill_table(c->table_gU, 1, cgu, y_table + yoffs +   table_plane_size);
822
0
        fill_table(c->table_bU, 1, cbu, y_table + yoffs + 2*table_plane_size);
823
0
        fill_gv_table(c->table_gV, 1, cgv);
824
0
        break;
825
0
    case 8:
826
0
        rbase       = isRgb ? 5 : 0;
827
0
        gbase       = isRgb ? 2 : 3;
828
0
        bbase       = isRgb ? 0 : 6;
829
0
        ALLOC_YUV_TABLE(table_plane_size * 3);
830
0
        y_table     = c->yuvTable;
831
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
832
0
        for (i = 0; i < table_plane_size - 38; i++) {
833
0
            int yval               = av_clip_uint8((yb + 0x8000) >> 16);
834
0
            y_table[i + 16]        = ((yval + 18) / 36) << rbase;
835
0
            y_table[i + 16 +   table_plane_size] = ((yval + 18) / 36) << gbase;
836
0
            y_table[i + 37 + 2*table_plane_size] = ((yval + 43) / 85) << bbase;
837
0
            yb += cy;
838
0
        }
839
0
        fill_table(c->table_rV, 1, crv, y_table + yoffs);
840
0
        fill_table(c->table_gU, 1, cgu, y_table + yoffs +   table_plane_size);
841
0
        fill_table(c->table_bU, 1, cbu, y_table + yoffs + 2*table_plane_size);
842
0
        fill_gv_table(c->table_gV, 1, cgv);
843
0
        break;
844
0
    case 12:
845
0
        rbase       = isRgb ? 8 : 0;
846
0
        gbase       = 4;
847
0
        bbase       = isRgb ? 0 : 8;
848
0
        ALLOC_YUV_TABLE(table_plane_size * 3 * 2);
849
0
        y_table16   = c->yuvTable;
850
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
851
0
        for (i = 0; i < table_plane_size; i++) {
852
0
            uint8_t yval        = av_clip_uint8((yb + 0x8000) >> 16);
853
0
            y_table16[i]        = (yval >> 4) << rbase;
854
0
            y_table16[i +   table_plane_size] = (yval >> 4) << gbase;
855
0
            y_table16[i + 2*table_plane_size] = (yval >> 4) << bbase;
856
0
            yb += cy;
857
0
        }
858
0
        if (isNotNe)
859
0
            for (i = 0; i < table_plane_size * 3; i++)
860
0
                y_table16[i] = av_bswap16(y_table16[i]);
861
0
        fill_table(c->table_rV, 2, crv, y_table16 + yoffs);
862
0
        fill_table(c->table_gU, 2, cgu, y_table16 + yoffs +   table_plane_size);
863
0
        fill_table(c->table_bU, 2, cbu, y_table16 + yoffs + 2*table_plane_size);
864
0
        fill_gv_table(c->table_gV, 2, cgv);
865
0
        break;
866
0
    case 15:
867
0
    case 16:
868
0
        rbase       = isRgb ? bpp - 5 : 0;
869
0
        gbase       = 5;
870
0
        bbase       = isRgb ? 0 : (bpp - 5);
871
0
        ALLOC_YUV_TABLE(table_plane_size * 3 * 2);
872
0
        y_table16   = c->yuvTable;
873
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
874
0
        for (i = 0; i < table_plane_size; i++) {
875
0
            uint8_t yval        = av_clip_uint8((yb + 0x8000) >> 16);
876
0
            y_table16[i]        = (yval >> 3)          << rbase;
877
0
            y_table16[i +   table_plane_size] = (yval >> (18 - bpp)) << gbase;
878
0
            y_table16[i + 2*table_plane_size] = (yval >> 3)          << bbase;
879
0
            yb += cy;
880
0
        }
881
0
        if (isNotNe)
882
0
            for (i = 0; i < table_plane_size * 3; i++)
883
0
                y_table16[i] = av_bswap16(y_table16[i]);
884
0
        fill_table(c->table_rV, 2, crv, y_table16 + yoffs);
885
0
        fill_table(c->table_gU, 2, cgu, y_table16 + yoffs +   table_plane_size);
886
0
        fill_table(c->table_bU, 2, cbu, y_table16 + yoffs + 2*table_plane_size);
887
0
        fill_gv_table(c->table_gV, 2, cgv);
888
0
        break;
889
0
    case 24:
890
0
    case 48:
891
0
        ALLOC_YUV_TABLE(table_plane_size);
892
0
        y_table     = c->yuvTable;
893
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
894
0
        for (i = 0; i < table_plane_size; i++) {
895
0
            y_table[i]  = av_clip_uint8((yb + 0x8000) >> 16);
896
0
            yb         += cy;
897
0
        }
898
0
        fill_table(c->table_rV, 1, crv, y_table + yoffs);
899
0
        fill_table(c->table_gU, 1, cgu, y_table + yoffs);
900
0
        fill_table(c->table_bU, 1, cbu, y_table + yoffs);
901
0
        fill_gv_table(c->table_gV, 1, cgv);
902
0
        break;
903
0
    case 30:
904
0
        rbase = isRgb ? 20 : 0;
905
0
        gbase = 10;
906
0
        bbase = isRgb ? 0 : 20;
907
0
        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format);
908
0
        if (!needAlpha)
909
0
            abase = 30;
910
0
        ALLOC_YUV_TABLE(table_plane_size * 3 * 4);
911
0
        y_table32   = c->yuvTable;
912
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
913
0
        for (i = 0; i < table_plane_size; i++) {
914
0
            unsigned yval = av_clip_uintp2((yb + 0x8000) >> 14, 10);
915
0
            y_table32[i]= (yval << rbase) + (needAlpha ? 0 : (255u << abase));
916
0
            y_table32[i + table_plane_size] = yval << gbase;
917
0
            y_table32[i + 2 * table_plane_size] = yval << bbase;
918
0
            yb += cy;
919
0
        }
920
0
        if (isNotNe) {
921
0
            for (i = 0; i < table_plane_size * 3; i++)
922
0
                y_table32[i] = av_bswap32(y_table32[i]);
923
0
        }
924
0
        fill_table(c->table_rV, 4, crv, y_table32 + yoffs);
925
0
        fill_table(c->table_gU, 4, cgu, y_table32 + yoffs + table_plane_size);
926
0
        fill_table(c->table_bU, 4, cbu, y_table32 + yoffs + 2 * table_plane_size);
927
0
        fill_gv_table(c->table_gV, 4, cgv);
928
0
        break;
929
0
    case 32:
930
0
    case 64:
931
0
        base      = (c->opts.dst_format == AV_PIX_FMT_RGB32_1 ||
932
0
                     c->opts.dst_format == AV_PIX_FMT_BGR32_1) ? 8 : 0;
933
0
        rbase     = base + (isRgb ? 16 : 0);
934
0
        gbase     = base + 8;
935
0
        bbase     = base + (isRgb ? 0 : 16);
936
0
        needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format);
937
0
        if (!needAlpha)
938
0
            abase = (base + 24) & 31;
939
0
        ALLOC_YUV_TABLE(table_plane_size * 3 * 4);
940
0
        y_table32   = c->yuvTable;
941
0
        yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy;
942
0
        for (i = 0; i < table_plane_size; i++) {
943
0
            unsigned yval       = av_clip_uint8((yb + 0x8000) >> 16);
944
0
            y_table32[i]        = (yval << rbase) +
945
0
                                  (needAlpha ? 0 : (255u << abase));
946
0
            y_table32[i +   table_plane_size] =  yval << gbase;
947
0
            y_table32[i + 2*table_plane_size] =  yval << bbase;
948
0
            yb += cy;
949
0
        }
950
0
        fill_table(c->table_rV, 4, crv, y_table32 + yoffs);
951
0
        fill_table(c->table_gU, 4, cgu, y_table32 + yoffs +   table_plane_size);
952
0
        fill_table(c->table_bU, 4, cbu, y_table32 + yoffs + 2*table_plane_size);
953
0
        fill_gv_table(c->table_gV, 4, cgv);
954
0
        break;
955
0
    default:
956
0
        if(!isPlanar(c->opts.dst_format) || bpp <= 24)
957
0
            av_log(c, AV_LOG_ERROR, "%ibpp not supported by yuv2rgb\n", bpp);
958
0
        return AVERROR(EINVAL);
959
0
    }
960
0
    return 0;
961
0
}