Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libswscale/format.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2024 Niklas Haas
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "libavutil/avassert.h"
22
#include "libavutil/hdr_dynamic_metadata.h"
23
#include "libavutil/mastering_display_metadata.h"
24
#include "libavutil/refstruct.h"
25
26
#include "format.h"
27
#include "csputils.h"
28
#include "ops_internal.h"
29
30
0
#define Q(N) ((AVRational) { N, 1 })
31
0
#define Q0   Q(0)
32
0
#define Q1   Q(1)
33
34
#define RET(x)                                                                 \
35
0
    do {                                                                       \
36
0
        int _ret = (x);                                                        \
37
0
        if (_ret  < 0)                                                         \
38
0
            return _ret;                                                       \
39
0
    } while (0)
40
41
typedef struct LegacyFormatEntry {
42
    uint8_t is_supported_in         :1;
43
    uint8_t is_supported_out        :1;
44
    uint8_t is_supported_endianness :1;
45
} LegacyFormatEntry;
46
47
/* Format support table for legacy swscale */
48
static const LegacyFormatEntry legacy_format_entries[] = {
49
    [AV_PIX_FMT_YUV420P]        = { 1, 1 },
50
    [AV_PIX_FMT_YUYV422]        = { 1, 1 },
51
    [AV_PIX_FMT_RGB24]          = { 1, 1 },
52
    [AV_PIX_FMT_BGR24]          = { 1, 1 },
53
    [AV_PIX_FMT_YUV422P]        = { 1, 1 },
54
    [AV_PIX_FMT_YUV444P]        = { 1, 1 },
55
    [AV_PIX_FMT_YUV410P]        = { 1, 1 },
56
    [AV_PIX_FMT_YUV411P]        = { 1, 1 },
57
    [AV_PIX_FMT_GRAY8]          = { 1, 1 },
58
    [AV_PIX_FMT_MONOWHITE]      = { 1, 1 },
59
    [AV_PIX_FMT_MONOBLACK]      = { 1, 1 },
60
    [AV_PIX_FMT_PAL8]           = { 1, 0 },
61
    [AV_PIX_FMT_YUVJ420P]       = { 1, 1 },
62
    [AV_PIX_FMT_YUVJ411P]       = { 1, 1 },
63
    [AV_PIX_FMT_YUVJ422P]       = { 1, 1 },
64
    [AV_PIX_FMT_YUVJ444P]       = { 1, 1 },
65
    [AV_PIX_FMT_YVYU422]        = { 1, 1 },
66
    [AV_PIX_FMT_UYVY422]        = { 1, 1 },
67
    [AV_PIX_FMT_UYYVYY411]      = { 1, 0 },
68
    [AV_PIX_FMT_BGR8]           = { 1, 1 },
69
    [AV_PIX_FMT_BGR4]           = { 0, 1 },
70
    [AV_PIX_FMT_BGR4_BYTE]      = { 1, 1 },
71
    [AV_PIX_FMT_RGB8]           = { 1, 1 },
72
    [AV_PIX_FMT_RGB4]           = { 0, 1 },
73
    [AV_PIX_FMT_RGB4_BYTE]      = { 1, 1 },
74
    [AV_PIX_FMT_NV12]           = { 1, 1 },
75
    [AV_PIX_FMT_NV21]           = { 1, 1 },
76
    [AV_PIX_FMT_ARGB]           = { 1, 1 },
77
    [AV_PIX_FMT_RGBA]           = { 1, 1 },
78
    [AV_PIX_FMT_ABGR]           = { 1, 1 },
79
    [AV_PIX_FMT_BGRA]           = { 1, 1 },
80
    [AV_PIX_FMT_0RGB]           = { 1, 1 },
81
    [AV_PIX_FMT_RGB0]           = { 1, 1 },
82
    [AV_PIX_FMT_0BGR]           = { 1, 1 },
83
    [AV_PIX_FMT_BGR0]           = { 1, 1 },
84
    [AV_PIX_FMT_GRAY9BE]        = { 1, 1 },
85
    [AV_PIX_FMT_GRAY9LE]        = { 1, 1 },
86
    [AV_PIX_FMT_GRAY10BE]       = { 1, 1 },
87
    [AV_PIX_FMT_GRAY10LE]       = { 1, 1 },
88
    [AV_PIX_FMT_GRAY12BE]       = { 1, 1 },
89
    [AV_PIX_FMT_GRAY12LE]       = { 1, 1 },
90
    [AV_PIX_FMT_GRAY14BE]       = { 1, 1 },
91
    [AV_PIX_FMT_GRAY14LE]       = { 1, 1 },
92
    [AV_PIX_FMT_GRAY16BE]       = { 1, 1 },
93
    [AV_PIX_FMT_GRAY16LE]       = { 1, 1 },
94
    [AV_PIX_FMT_YUV440P]        = { 1, 1 },
95
    [AV_PIX_FMT_YUVJ440P]       = { 1, 1 },
96
    [AV_PIX_FMT_YUV440P10LE]    = { 1, 1 },
97
    [AV_PIX_FMT_YUV440P10BE]    = { 1, 1 },
98
    [AV_PIX_FMT_YUV440P12LE]    = { 1, 1 },
99
    [AV_PIX_FMT_YUV440P12BE]    = { 1, 1 },
100
    [AV_PIX_FMT_YUVA420P]       = { 1, 1 },
101
    [AV_PIX_FMT_YUVA422P]       = { 1, 1 },
102
    [AV_PIX_FMT_YUVA444P]       = { 1, 1 },
103
    [AV_PIX_FMT_YUVA420P9BE]    = { 1, 1 },
104
    [AV_PIX_FMT_YUVA420P9LE]    = { 1, 1 },
105
    [AV_PIX_FMT_YUVA422P9BE]    = { 1, 1 },
106
    [AV_PIX_FMT_YUVA422P9LE]    = { 1, 1 },
107
    [AV_PIX_FMT_YUVA444P9BE]    = { 1, 1 },
108
    [AV_PIX_FMT_YUVA444P9LE]    = { 1, 1 },
109
    [AV_PIX_FMT_YUVA420P10BE]   = { 1, 1 },
110
    [AV_PIX_FMT_YUVA420P10LE]   = { 1, 1 },
111
    [AV_PIX_FMT_YUVA422P10BE]   = { 1, 1 },
112
    [AV_PIX_FMT_YUVA422P10LE]   = { 1, 1 },
113
    [AV_PIX_FMT_YUVA444P10BE]   = { 1, 1 },
114
    [AV_PIX_FMT_YUVA444P10LE]   = { 1, 1 },
115
    [AV_PIX_FMT_YUVA420P16BE]   = { 1, 1 },
116
    [AV_PIX_FMT_YUVA420P16LE]   = { 1, 1 },
117
    [AV_PIX_FMT_YUVA422P16BE]   = { 1, 1 },
118
    [AV_PIX_FMT_YUVA422P16LE]   = { 1, 1 },
119
    [AV_PIX_FMT_YUVA444P16BE]   = { 1, 1 },
120
    [AV_PIX_FMT_YUVA444P16LE]   = { 1, 1 },
121
    [AV_PIX_FMT_RGB48BE]        = { 1, 1 },
122
    [AV_PIX_FMT_RGB48LE]        = { 1, 1 },
123
    [AV_PIX_FMT_RGBA64BE]       = { 1, 1, 1 },
124
    [AV_PIX_FMT_RGBA64LE]       = { 1, 1, 1 },
125
    [AV_PIX_FMT_RGB565BE]       = { 1, 1 },
126
    [AV_PIX_FMT_RGB565LE]       = { 1, 1 },
127
    [AV_PIX_FMT_RGB555BE]       = { 1, 1 },
128
    [AV_PIX_FMT_RGB555LE]       = { 1, 1 },
129
    [AV_PIX_FMT_BGR565BE]       = { 1, 1 },
130
    [AV_PIX_FMT_BGR565LE]       = { 1, 1 },
131
    [AV_PIX_FMT_BGR555BE]       = { 1, 1 },
132
    [AV_PIX_FMT_BGR555LE]       = { 1, 1 },
133
    [AV_PIX_FMT_YUV420P16LE]    = { 1, 1 },
134
    [AV_PIX_FMT_YUV420P16BE]    = { 1, 1 },
135
    [AV_PIX_FMT_YUV422P16LE]    = { 1, 1 },
136
    [AV_PIX_FMT_YUV422P16BE]    = { 1, 1 },
137
    [AV_PIX_FMT_YUV444P16LE]    = { 1, 1 },
138
    [AV_PIX_FMT_YUV444P16BE]    = { 1, 1 },
139
    [AV_PIX_FMT_RGB444LE]       = { 1, 1 },
140
    [AV_PIX_FMT_RGB444BE]       = { 1, 1 },
141
    [AV_PIX_FMT_BGR444LE]       = { 1, 1 },
142
    [AV_PIX_FMT_BGR444BE]       = { 1, 1 },
143
    [AV_PIX_FMT_YA8]            = { 1, 1 },
144
    [AV_PIX_FMT_YA16BE]         = { 1, 1 },
145
    [AV_PIX_FMT_YA16LE]         = { 1, 1 },
146
    [AV_PIX_FMT_BGR48BE]        = { 1, 1 },
147
    [AV_PIX_FMT_BGR48LE]        = { 1, 1 },
148
    [AV_PIX_FMT_BGRA64BE]       = { 1, 1, 1 },
149
    [AV_PIX_FMT_BGRA64LE]       = { 1, 1, 1 },
150
    [AV_PIX_FMT_YUV420P9BE]     = { 1, 1 },
151
    [AV_PIX_FMT_YUV420P9LE]     = { 1, 1 },
152
    [AV_PIX_FMT_YUV420P10BE]    = { 1, 1 },
153
    [AV_PIX_FMT_YUV420P10LE]    = { 1, 1 },
154
    [AV_PIX_FMT_YUV420P12BE]    = { 1, 1 },
155
    [AV_PIX_FMT_YUV420P12LE]    = { 1, 1 },
156
    [AV_PIX_FMT_YUV420P14BE]    = { 1, 1 },
157
    [AV_PIX_FMT_YUV420P14LE]    = { 1, 1 },
158
    [AV_PIX_FMT_YUV422P9BE]     = { 1, 1 },
159
    [AV_PIX_FMT_YUV422P9LE]     = { 1, 1 },
160
    [AV_PIX_FMT_YUV422P10BE]    = { 1, 1 },
161
    [AV_PIX_FMT_YUV422P10LE]    = { 1, 1 },
162
    [AV_PIX_FMT_YUV422P12BE]    = { 1, 1 },
163
    [AV_PIX_FMT_YUV422P12LE]    = { 1, 1 },
164
    [AV_PIX_FMT_YUV422P14BE]    = { 1, 1 },
165
    [AV_PIX_FMT_YUV422P14LE]    = { 1, 1 },
166
    [AV_PIX_FMT_YUV444P9BE]     = { 1, 1 },
167
    [AV_PIX_FMT_YUV444P9LE]     = { 1, 1 },
168
    [AV_PIX_FMT_YUV444P10BE]    = { 1, 1 },
169
    [AV_PIX_FMT_YUV444P10LE]    = { 1, 1 },
170
    [AV_PIX_FMT_YUV444P12BE]    = { 1, 1 },
171
    [AV_PIX_FMT_YUV444P12LE]    = { 1, 1 },
172
    [AV_PIX_FMT_YUV444P14BE]    = { 1, 1 },
173
    [AV_PIX_FMT_YUV444P14LE]    = { 1, 1 },
174
    [AV_PIX_FMT_YUV444P10MSBBE] = { 1, 1 },
175
    [AV_PIX_FMT_YUV444P10MSBLE] = { 1, 1 },
176
    [AV_PIX_FMT_YUV444P12MSBBE] = { 1, 1 },
177
    [AV_PIX_FMT_YUV444P12MSBLE] = { 1, 1 },
178
    [AV_PIX_FMT_GBRP]           = { 1, 1 },
179
    [AV_PIX_FMT_GBRP9LE]        = { 1, 1 },
180
    [AV_PIX_FMT_GBRP9BE]        = { 1, 1 },
181
    [AV_PIX_FMT_GBRP10LE]       = { 1, 1 },
182
    [AV_PIX_FMT_GBRP10BE]       = { 1, 1 },
183
    [AV_PIX_FMT_GBRAP10LE]      = { 1, 1 },
184
    [AV_PIX_FMT_GBRAP10BE]      = { 1, 1 },
185
    [AV_PIX_FMT_GBRP10MSBLE]    = { 1, 1 },
186
    [AV_PIX_FMT_GBRP10MSBBE]    = { 1, 1 },
187
    [AV_PIX_FMT_GBRP12LE]       = { 1, 1 },
188
    [AV_PIX_FMT_GBRP12BE]       = { 1, 1 },
189
    [AV_PIX_FMT_GBRP12MSBLE]    = { 1, 1 },
190
    [AV_PIX_FMT_GBRP12MSBBE]    = { 1, 1 },
191
    [AV_PIX_FMT_GBRAP12LE]      = { 1, 1 },
192
    [AV_PIX_FMT_GBRAP12BE]      = { 1, 1 },
193
    [AV_PIX_FMT_GBRP14LE]       = { 1, 1 },
194
    [AV_PIX_FMT_GBRP14BE]       = { 1, 1 },
195
    [AV_PIX_FMT_GBRAP14LE]      = { 1, 1 },
196
    [AV_PIX_FMT_GBRAP14BE]      = { 1, 1 },
197
    [AV_PIX_FMT_GBRP16LE]       = { 1, 1 },
198
    [AV_PIX_FMT_GBRP16BE]       = { 1, 1 },
199
    [AV_PIX_FMT_GBRPF32LE]      = { 1, 1 },
200
    [AV_PIX_FMT_GBRPF32BE]      = { 1, 1 },
201
    [AV_PIX_FMT_GBRAPF32LE]     = { 1, 1 },
202
    [AV_PIX_FMT_GBRAPF32BE]     = { 1, 1 },
203
    [AV_PIX_FMT_GBRPF16LE]      = { 1, 0 },
204
    [AV_PIX_FMT_GBRPF16BE]      = { 1, 0 },
205
    [AV_PIX_FMT_GBRAPF16LE]     = { 1, 0 },
206
    [AV_PIX_FMT_GBRAPF16BE]     = { 1, 0 },
207
    [AV_PIX_FMT_GBRAP]          = { 1, 1 },
208
    [AV_PIX_FMT_GBRAP16LE]      = { 1, 1 },
209
    [AV_PIX_FMT_GBRAP16BE]      = { 1, 1 },
210
    [AV_PIX_FMT_BAYER_BGGR8]    = { 1, 0 },
211
    [AV_PIX_FMT_BAYER_RGGB8]    = { 1, 0 },
212
    [AV_PIX_FMT_BAYER_GBRG8]    = { 1, 0 },
213
    [AV_PIX_FMT_BAYER_GRBG8]    = { 1, 0 },
214
    [AV_PIX_FMT_BAYER_BGGR16LE] = { 1, 0 },
215
    [AV_PIX_FMT_BAYER_BGGR16BE] = { 1, 0 },
216
    [AV_PIX_FMT_BAYER_RGGB16LE] = { 1, 0 },
217
    [AV_PIX_FMT_BAYER_RGGB16BE] = { 1, 0 },
218
    [AV_PIX_FMT_BAYER_GBRG16LE] = { 1, 0 },
219
    [AV_PIX_FMT_BAYER_GBRG16BE] = { 1, 0 },
220
    [AV_PIX_FMT_BAYER_GRBG16LE] = { 1, 0 },
221
    [AV_PIX_FMT_BAYER_GRBG16BE] = { 1, 0 },
222
    [AV_PIX_FMT_XYZ12BE]        = { 1, 1, 1 },
223
    [AV_PIX_FMT_XYZ12LE]        = { 1, 1, 1 },
224
    [AV_PIX_FMT_AYUV64LE]       = { 1, 1},
225
    [AV_PIX_FMT_AYUV64BE]       = { 1, 1 },
226
    [AV_PIX_FMT_P010LE]         = { 1, 1 },
227
    [AV_PIX_FMT_P010BE]         = { 1, 1 },
228
    [AV_PIX_FMT_P012LE]         = { 1, 1 },
229
    [AV_PIX_FMT_P012BE]         = { 1, 1 },
230
    [AV_PIX_FMT_P016LE]         = { 1, 1 },
231
    [AV_PIX_FMT_P016BE]         = { 1, 1 },
232
    [AV_PIX_FMT_GRAYF32LE]      = { 1, 1 },
233
    [AV_PIX_FMT_GRAYF32BE]      = { 1, 1 },
234
    [AV_PIX_FMT_GRAYF16LE]      = { 1, 0 },
235
    [AV_PIX_FMT_GRAYF16BE]      = { 1, 0 },
236
    [AV_PIX_FMT_YAF32LE]        = { 1, 0 },
237
    [AV_PIX_FMT_YAF32BE]        = { 1, 0 },
238
    [AV_PIX_FMT_YAF16LE]        = { 1, 0 },
239
    [AV_PIX_FMT_YAF16BE]        = { 1, 0 },
240
    [AV_PIX_FMT_YUVA422P12BE]   = { 1, 1 },
241
    [AV_PIX_FMT_YUVA422P12LE]   = { 1, 1 },
242
    [AV_PIX_FMT_YUVA444P12BE]   = { 1, 1 },
243
    [AV_PIX_FMT_YUVA444P12LE]   = { 1, 1 },
244
    [AV_PIX_FMT_NV24]           = { 1, 1 },
245
    [AV_PIX_FMT_NV42]           = { 1, 1 },
246
    [AV_PIX_FMT_Y210LE]         = { 1, 1 },
247
    [AV_PIX_FMT_Y212LE]         = { 1, 1 },
248
    [AV_PIX_FMT_Y216LE]         = { 1, 1 },
249
    [AV_PIX_FMT_X2RGB10LE]      = { 1, 1 },
250
    [AV_PIX_FMT_X2BGR10LE]      = { 1, 1 },
251
    [AV_PIX_FMT_NV20BE]         = { 1, 1 },
252
    [AV_PIX_FMT_NV20LE]         = { 1, 1 },
253
    [AV_PIX_FMT_P210BE]         = { 1, 1 },
254
    [AV_PIX_FMT_P210LE]         = { 1, 1 },
255
    [AV_PIX_FMT_P212BE]         = { 1, 1 },
256
    [AV_PIX_FMT_P212LE]         = { 1, 1 },
257
    [AV_PIX_FMT_P410BE]         = { 1, 1 },
258
    [AV_PIX_FMT_P410LE]         = { 1, 1 },
259
    [AV_PIX_FMT_P412BE]         = { 1, 1 },
260
    [AV_PIX_FMT_P412LE]         = { 1, 1 },
261
    [AV_PIX_FMT_P216BE]         = { 1, 1 },
262
    [AV_PIX_FMT_P216LE]         = { 1, 1 },
263
    [AV_PIX_FMT_P416BE]         = { 1, 1 },
264
    [AV_PIX_FMT_P416LE]         = { 1, 1 },
265
    [AV_PIX_FMT_NV16]           = { 1, 1 },
266
    [AV_PIX_FMT_VUYA]           = { 1, 1 },
267
    [AV_PIX_FMT_VUYX]           = { 1, 1 },
268
    [AV_PIX_FMT_RGBAF16BE]      = { 1, 0 },
269
    [AV_PIX_FMT_RGBAF16LE]      = { 1, 0 },
270
    [AV_PIX_FMT_RGBF16BE]       = { 1, 0 },
271
    [AV_PIX_FMT_RGBF16LE]       = { 1, 0 },
272
    [AV_PIX_FMT_RGBF32BE]       = { 1, 0 },
273
    [AV_PIX_FMT_RGBF32LE]       = { 1, 0 },
274
    [AV_PIX_FMT_XV30LE]         = { 1, 1 },
275
    [AV_PIX_FMT_XV36LE]         = { 1, 1 },
276
    [AV_PIX_FMT_XV36BE]         = { 1, 1 },
277
    [AV_PIX_FMT_XV48LE]         = { 1, 1 },
278
    [AV_PIX_FMT_XV48BE]         = { 1, 1 },
279
    [AV_PIX_FMT_AYUV]           = { 1, 1 },
280
    [AV_PIX_FMT_UYVA]           = { 1, 1 },
281
    [AV_PIX_FMT_VYU444]         = { 1, 1 },
282
    [AV_PIX_FMT_V30XLE]         = { 1, 1 },
283
};
284
285
int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
286
0
{
287
0
    return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
288
0
    legacy_format_entries[pix_fmt].is_supported_in : 0;
289
0
}
290
291
int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
292
0
{
293
0
    return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
294
0
    legacy_format_entries[pix_fmt].is_supported_out : 0;
295
0
}
296
297
int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt)
298
0
{
299
0
    return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
300
0
    legacy_format_entries[pix_fmt].is_supported_endianness : 0;
301
0
}
302
303
/**
304
 * This function also sanitizes and strips the input data, removing irrelevant
305
 * fields for certain formats.
306
 */
307
SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field)
308
0
{
309
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
310
0
    const AVColorPrimariesDesc *primaries;
311
0
    AVFrameSideData *sd;
312
313
0
    SwsFormat fmt = {
314
0
        .width  = frame->width,
315
0
        .height = frame->height,
316
0
        .format = frame->format,
317
0
        .range  = frame->color_range,
318
0
        .csp    = frame->colorspace,
319
0
        .loc    = frame->chroma_location,
320
0
        .desc   = desc,
321
0
        .color = {
322
0
            .prim = frame->color_primaries,
323
0
            .trc  = frame->color_trc,
324
0
        },
325
0
    };
326
327
0
    av_assert1(fmt.width > 0);
328
0
    av_assert1(fmt.height > 0);
329
0
    av_assert1(fmt.format != AV_PIX_FMT_NONE);
330
0
    av_assert0(desc);
331
0
    if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_BAYER)) {
332
        /* RGB-like family */
333
0
        fmt.csp   = AVCOL_SPC_RGB;
334
0
        fmt.range = AVCOL_RANGE_JPEG;
335
0
    } else if (desc->flags & AV_PIX_FMT_FLAG_XYZ) {
336
0
        fmt.csp   = AVCOL_SPC_UNSPECIFIED;
337
0
        fmt.color = (SwsColor) {
338
0
            .prim = AVCOL_PRI_BT709, /* swscale currently hard-codes this XYZ matrix */
339
0
            .trc  = AVCOL_TRC_SMPTE428,
340
0
        };
341
0
    } else if (desc->nb_components < 3) {
342
        /* Grayscale formats */
343
0
        fmt.color.prim = AVCOL_PRI_UNSPECIFIED;
344
0
        fmt.csp        = AVCOL_SPC_UNSPECIFIED;
345
0
        if (desc->flags & AV_PIX_FMT_FLAG_FLOAT)
346
0
            fmt.range = AVCOL_RANGE_UNSPECIFIED;
347
0
        else
348
0
            fmt.range = AVCOL_RANGE_JPEG; // FIXME: this restriction should be lifted
349
0
    }
350
351
0
    switch (frame->format) {
352
0
    case AV_PIX_FMT_YUVJ420P:
353
0
    case AV_PIX_FMT_YUVJ411P:
354
0
    case AV_PIX_FMT_YUVJ422P:
355
0
    case AV_PIX_FMT_YUVJ444P:
356
0
    case AV_PIX_FMT_YUVJ440P:
357
0
        fmt.range = AVCOL_RANGE_JPEG;
358
0
        break;
359
0
    }
360
361
0
    if (!desc->log2_chroma_w && !desc->log2_chroma_h)
362
0
        fmt.loc = AVCHROMA_LOC_UNSPECIFIED;
363
364
0
    if (frame->flags & AV_FRAME_FLAG_INTERLACED) {
365
0
        fmt.height = (fmt.height + (field == FIELD_TOP)) >> 1;
366
0
        fmt.interlaced = 1;
367
0
    }
368
369
    /* Set luminance and gamut information */
370
0
    fmt.color.min_luma = av_make_q(0, 1);
371
0
    switch (fmt.color.trc) {
372
0
    case AVCOL_TRC_SMPTE2084:
373
0
        fmt.color.max_luma = av_make_q(10000, 1); break;
374
0
    case AVCOL_TRC_ARIB_STD_B67:
375
0
        fmt.color.max_luma = av_make_q( 1000, 1); break; /* HLG reference display */
376
0
    default:
377
0
        fmt.color.max_luma = av_make_q(  203, 1); break; /* SDR reference brightness */
378
0
    }
379
380
0
    primaries = av_csp_primaries_desc_from_id(fmt.color.prim);
381
0
    if (primaries)
382
0
        fmt.color.gamut = primaries->prim;
383
384
0
    if ((sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA))) {
385
0
        const AVMasteringDisplayMetadata *mdm = (const AVMasteringDisplayMetadata *) sd->data;
386
0
        if (mdm->has_luminance) {
387
0
            fmt.color.min_luma = mdm->min_luminance;
388
0
            fmt.color.max_luma = mdm->max_luminance;
389
0
        }
390
391
0
        if (mdm->has_primaries) {
392
            /* Ignore mastering display white point as it has no bearance on
393
             * the underlying content */
394
0
            fmt.color.gamut.r.x = mdm->display_primaries[0][0];
395
0
            fmt.color.gamut.r.y = mdm->display_primaries[0][1];
396
0
            fmt.color.gamut.g.x = mdm->display_primaries[1][0];
397
0
            fmt.color.gamut.g.y = mdm->display_primaries[1][1];
398
0
            fmt.color.gamut.b.x = mdm->display_primaries[2][0];
399
0
            fmt.color.gamut.b.y = mdm->display_primaries[2][1];
400
0
        }
401
0
    }
402
403
0
    if ((sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS))) {
404
0
        const AVDynamicHDRPlus *dhp = (const AVDynamicHDRPlus *) sd->data;
405
0
        const AVHDRPlusColorTransformParams *pars = &dhp->params[0];
406
0
        const AVRational nits = av_make_q(10000, 1);
407
0
        AVRational maxrgb = pars->maxscl[0];
408
409
0
        if (!dhp->num_windows || dhp->application_version > 1)
410
0
            goto skip_hdr10;
411
412
        /* Maximum of MaxSCL components */
413
0
        if (av_cmp_q(pars->maxscl[1], maxrgb) > 0)
414
0
            maxrgb = pars->maxscl[1];
415
0
        if (av_cmp_q(pars->maxscl[2], maxrgb) > 0)
416
0
            maxrgb = pars->maxscl[2];
417
418
0
        if (maxrgb.num > 0) {
419
            /* Estimate true luminance from MaxSCL */
420
0
            const AVLumaCoefficients *luma = av_csp_luma_coeffs_from_avcsp(fmt.csp);
421
0
            if (!luma)
422
0
                goto skip_hdr10;
423
0
            fmt.color.frame_peak = av_add_q(av_mul_q(luma->cr, pars->maxscl[0]),
424
0
                                   av_add_q(av_mul_q(luma->cg, pars->maxscl[1]),
425
0
                                            av_mul_q(luma->cb, pars->maxscl[2])));
426
            /* Scale the scene average brightness by the ratio between the
427
             * maximum luminance and the MaxRGB values */
428
0
            fmt.color.frame_avg = av_mul_q(pars->average_maxrgb,
429
0
                                           av_div_q(fmt.color.frame_peak, maxrgb));
430
0
        } else {
431
            /**
432
             * Calculate largest value from histogram to use as fallback for
433
             * clips with missing MaxSCL information. Note that this may end
434
             * up picking the "reserved" value at the 5% percentile, which in
435
             * practice appears to track the brightest pixel in the scene.
436
             */
437
0
            for (int i = 0; i < pars->num_distribution_maxrgb_percentiles; i++) {
438
0
                const AVRational pct = pars->distribution_maxrgb[i].percentile;
439
0
                if (av_cmp_q(pct, maxrgb) > 0)
440
0
                    maxrgb = pct;
441
0
                fmt.color.frame_peak = maxrgb;
442
0
                fmt.color.frame_avg  = pars->average_maxrgb;
443
0
            }
444
0
        }
445
446
        /* Rescale to nits */
447
0
        fmt.color.frame_peak = av_mul_q(nits, fmt.color.frame_peak);
448
0
        fmt.color.frame_avg  = av_mul_q(nits, fmt.color.frame_avg);
449
0
    }
450
0
skip_hdr10:
451
452
    /* PQ is always scaled down to absolute zero, so ignore mastering metadata */
453
0
    if (fmt.color.trc == AVCOL_TRC_SMPTE2084)
454
0
        fmt.color.min_luma = av_make_q(0, 1);
455
456
0
    return fmt;
457
0
}
458
459
static int infer_prim_ref(SwsColor *csp, const SwsColor *ref)
460
0
{
461
0
    if (csp->prim != AVCOL_PRI_UNSPECIFIED)
462
0
        return 0;
463
464
    /* Reuse the reference gamut only for "safe", similar primaries */
465
0
    switch (ref->prim) {
466
0
    case AVCOL_PRI_BT709:
467
0
    case AVCOL_PRI_BT470M:
468
0
    case AVCOL_PRI_BT470BG:
469
0
    case AVCOL_PRI_SMPTE170M:
470
0
    case AVCOL_PRI_SMPTE240M:
471
0
        csp->prim  = ref->prim;
472
0
        csp->gamut = ref->gamut;
473
0
        break;
474
0
    default:
475
0
        csp->prim  = AVCOL_PRI_BT709;
476
0
        csp->gamut = av_csp_primaries_desc_from_id(csp->prim)->prim;
477
0
        break;
478
0
    }
479
480
0
    return 1;
481
0
}
482
483
static int infer_trc_ref(SwsColor *csp, const SwsColor *ref)
484
0
{
485
0
    if (csp->trc != AVCOL_TRC_UNSPECIFIED)
486
0
        return 0;
487
488
    /* Pick a suitable SDR transfer function, to try and minimize conversions */
489
0
    switch (ref->trc) {
490
0
    case AVCOL_TRC_UNSPECIFIED:
491
    /* HDR curves, never default to these */
492
0
    case AVCOL_TRC_SMPTE2084:
493
0
    case AVCOL_TRC_ARIB_STD_B67:
494
0
        csp->trc = AVCOL_TRC_BT709;
495
0
        csp->min_luma = av_make_q(0, 1);
496
0
        csp->max_luma = av_make_q(203, 1);
497
0
        break;
498
0
    default:
499
0
        csp->trc = ref->trc;
500
0
        csp->min_luma = ref->min_luma;
501
0
        csp->max_luma = ref->max_luma;
502
0
        break;
503
0
    }
504
505
0
    return 1;
506
0
}
507
508
bool ff_infer_colors(SwsColor *src, SwsColor *dst)
509
0
{
510
0
    int incomplete = 0;
511
512
0
    incomplete |= infer_prim_ref(dst, src);
513
0
    incomplete |= infer_prim_ref(src, dst);
514
0
    av_assert0(src->prim != AVCOL_PRI_UNSPECIFIED);
515
0
    av_assert0(dst->prim != AVCOL_PRI_UNSPECIFIED);
516
517
0
    incomplete |= infer_trc_ref(dst, src);
518
0
    incomplete |= infer_trc_ref(src, dst);
519
0
    av_assert0(src->trc != AVCOL_TRC_UNSPECIFIED);
520
0
    av_assert0(dst->trc != AVCOL_TRC_UNSPECIFIED);
521
522
0
    return incomplete;
523
0
}
524
525
int sws_test_format(enum AVPixelFormat format, int output)
526
0
{
527
0
    return output ? sws_isSupportedOutput(format) : sws_isSupportedInput(format);
528
0
}
529
530
int sws_test_colorspace(enum AVColorSpace csp, int output)
531
0
{
532
0
    switch (csp) {
533
0
    case AVCOL_SPC_UNSPECIFIED:
534
0
    case AVCOL_SPC_RGB:
535
0
    case AVCOL_SPC_BT709:
536
0
    case AVCOL_SPC_BT470BG:
537
0
    case AVCOL_SPC_SMPTE170M:
538
0
    case AVCOL_SPC_FCC:
539
0
    case AVCOL_SPC_SMPTE240M:
540
0
    case AVCOL_SPC_BT2020_NCL:
541
0
        return 1;
542
0
    default:
543
0
        return 0;
544
0
    }
545
0
}
546
547
int sws_test_primaries(enum AVColorPrimaries prim, int output)
548
0
{
549
0
    return ((prim > AVCOL_PRI_RESERVED0 && prim < AVCOL_PRI_NB) ||
550
0
            (prim >= AVCOL_PRI_EXT_BASE && prim < AVCOL_PRI_EXT_NB)) &&
551
0
           prim != AVCOL_PRI_RESERVED;
552
0
}
553
554
int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output)
555
0
{
556
0
    av_csp_eotf_function eotf = output ? av_csp_itu_eotf_inv(trc)
557
0
                                       : av_csp_itu_eotf(trc);
558
0
    return trc == AVCOL_TRC_UNSPECIFIED || eotf != NULL;
559
0
}
560
561
static int test_range(enum AVColorRange range)
562
0
{
563
0
    return (unsigned)range < AVCOL_RANGE_NB;
564
0
}
565
566
static int test_loc(enum AVChromaLocation loc)
567
0
{
568
0
    return (unsigned)loc < AVCHROMA_LOC_NB;
569
0
}
570
571
int ff_test_fmt(const SwsFormat *fmt, int output)
572
0
{
573
0
    return fmt->width > 0 && fmt->height > 0            &&
574
0
           sws_test_format    (fmt->format,     output) &&
575
0
           sws_test_colorspace(fmt->csp,        output) &&
576
0
           sws_test_primaries (fmt->color.prim, output) &&
577
0
           sws_test_transfer  (fmt->color.trc,  output) &&
578
0
           test_range         (fmt->range)              &&
579
0
           test_loc           (fmt->loc);
580
0
}
581
582
int sws_test_frame(const AVFrame *frame, int output)
583
0
{
584
0
    for (int field = 0; field < 2; field++) {
585
0
        const SwsFormat fmt = ff_fmt_from_frame(frame, field);
586
0
        if (!ff_test_fmt(&fmt, output))
587
0
            return 0;
588
0
        if (!fmt.interlaced)
589
0
            break;
590
0
    }
591
592
0
    return 1;
593
0
}
594
595
int sws_is_noop(const AVFrame *dst, const AVFrame *src)
596
0
{
597
0
    for (int field = 0; field < 2; field++) {
598
0
        SwsFormat dst_fmt = ff_fmt_from_frame(dst, field);
599
0
        SwsFormat src_fmt = ff_fmt_from_frame(src, field);
600
0
        if (!ff_fmt_equal(&dst_fmt, &src_fmt))
601
0
            return 0;
602
0
        if (!dst_fmt.interlaced)
603
0
            break;
604
0
    }
605
606
0
    return 1;
607
0
}
608
609
#if CONFIG_UNSTABLE
610
611
/* Returns the type suitable for a pixel after fully decoding/unpacking it */
612
static SwsPixelType fmt_pixel_type(enum AVPixelFormat fmt)
613
0
{
614
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
615
0
    const int bits = FFALIGN(desc->comp[0].depth, 8);
616
0
    if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
617
0
        switch (bits) {
618
0
        case 32: return SWS_PIXEL_F32;
619
        /* TODO: no support for 16-bit float yet */
620
0
        }
621
0
    } else {
622
0
        switch (bits) {
623
0
        case  8: return SWS_PIXEL_U8;
624
0
        case 16: return SWS_PIXEL_U16;
625
        /* TODO: AVRational cannot represent UINT32_MAX */
626
0
        }
627
0
    }
628
629
0
    return SWS_PIXEL_NONE;
630
0
}
631
632
/* A regular format is defined as any format that contains only a single
633
 * component per elementary data type (i.e. no sub-byte pack/unpack needed),
634
 * and whose components map 1:1 onto elementary data units */
635
static int is_regular_fmt(enum AVPixelFormat fmt)
636
0
{
637
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
638
0
    if (desc->flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_BAYER))
639
0
        return 0; /* no 1:1 correspondence between components and data units */
640
0
    if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM))
641
0
        return 0; /* bitstream formats are packed by definition */
642
0
    if ((desc->flags & AV_PIX_FMT_FLAG_PLANAR) || desc->nb_components == 1)
643
0
        return 1; /* planar formats are regular by definition */
644
645
0
    const int step = desc->comp[0].step;
646
0
    int total_bits = 0;
647
648
0
    for (int i = 0; i < desc->nb_components; i++) {
649
0
        if (desc->comp[i].shift || desc->comp[i].step != step)
650
0
            return 0; /* irregular/packed format */
651
0
        total_bits += desc->comp[i].depth;
652
0
    }
653
654
    /* Exclude formats with missing components like RGB0, 0RGB, etc. */
655
0
    return total_bits == step * 8;
656
0
}
657
658
typedef struct FmtInfo {
659
    SwsReadWriteOp rw;
660
    SwsSwizzleOp   swizzle;
661
    SwsPackOp      pack;
662
    int            shift;
663
} FmtInfo;
664
665
0
#define BITSTREAM_FMT(SWIZ, FRAC, PACKED, ...) (FmtInfo) {      \
666
0
    .rw = { .elems = 1, .frac = FRAC, .packed = PACKED },       \
667
0
    .swizzle = SWIZ,                                            \
668
0
    __VA_ARGS__                                                 \
669
0
}
670
671
0
#define SUBPACKED_FMT(SWIZ, ...) (FmtInfo) {                    \
672
0
    .rw = { .elems = 1, .packed = true },                       \
673
0
    .swizzle = SWIZ,                                            \
674
0
    .pack.pattern = {__VA_ARGS__},                              \
675
0
}
676
677
0
#define PACKED_FMT(SWIZ, N, ...) (FmtInfo) {                    \
678
0
    .rw = { .elems = N, .packed = (N) > 1 },                    \
679
0
    .swizzle = SWIZ,                                            \
680
0
    __VA_ARGS__                                                 \
681
0
}
682
683
#define RGBA SWS_SWIZZLE(0, 1, 2, 3)
684
#define BGRA SWS_SWIZZLE(2, 1, 0, 3)
685
#define ARGB SWS_SWIZZLE(3, 0, 1, 2)
686
#define ABGR SWS_SWIZZLE(3, 2, 1, 0)
687
#define AVYU SWS_SWIZZLE(3, 2, 0, 1)
688
#define VYUA SWS_SWIZZLE(2, 0, 1, 3)
689
#define UYVA SWS_SWIZZLE(1, 0, 2, 3)
690
#define VUYA BGRA
691
692
static FmtInfo fmt_info_irregular(enum AVPixelFormat fmt)
693
0
{
694
0
    switch (fmt) {
695
    /* Bitstream formats */
696
0
    case AV_PIX_FMT_MONOWHITE:
697
0
    case AV_PIX_FMT_MONOBLACK:
698
0
        return BITSTREAM_FMT(RGBA, 3, false);
699
0
    case AV_PIX_FMT_RGB4: return BITSTREAM_FMT(RGBA, 1, true, .pack = {{ 1, 2, 1 }});
700
0
    case AV_PIX_FMT_BGR4: return BITSTREAM_FMT(BGRA, 1, true, .pack = {{ 1, 2, 1 }});
701
702
    /* Sub-packed 8-bit aligned formats */
703
0
    case AV_PIX_FMT_RGB4_BYTE:  return SUBPACKED_FMT(RGBA, 1, 2, 1);
704
0
    case AV_PIX_FMT_BGR4_BYTE:  return SUBPACKED_FMT(BGRA, 1, 2, 1);
705
0
    case AV_PIX_FMT_RGB8:       return SUBPACKED_FMT(RGBA, 3, 3, 2);
706
0
    case AV_PIX_FMT_BGR8:       return SUBPACKED_FMT(BGRA, 2, 3, 3);
707
708
    /* Sub-packed 16-bit aligned formats */
709
0
    case AV_PIX_FMT_RGB565LE:
710
0
    case AV_PIX_FMT_RGB565BE:
711
0
        return SUBPACKED_FMT(RGBA, 5, 6, 5);
712
0
    case AV_PIX_FMT_BGR565LE:
713
0
    case AV_PIX_FMT_BGR565BE:
714
0
        return SUBPACKED_FMT(BGRA, 5, 6, 5);
715
0
    case AV_PIX_FMT_RGB555LE:
716
0
    case AV_PIX_FMT_RGB555BE:
717
0
        return SUBPACKED_FMT(RGBA, 5, 5, 5);
718
0
    case AV_PIX_FMT_BGR555LE:
719
0
    case AV_PIX_FMT_BGR555BE:
720
0
        return SUBPACKED_FMT(BGRA, 5, 5, 5);
721
0
    case AV_PIX_FMT_RGB444LE:
722
0
    case AV_PIX_FMT_RGB444BE:
723
0
        return SUBPACKED_FMT(RGBA, 4, 4, 4);
724
0
    case AV_PIX_FMT_BGR444LE:
725
0
    case AV_PIX_FMT_BGR444BE:
726
0
        return SUBPACKED_FMT(BGRA, 4, 4, 4);
727
728
    /* Sub-packed 32-bit aligned formats */
729
0
    case AV_PIX_FMT_X2RGB10LE:
730
0
    case AV_PIX_FMT_X2RGB10BE:
731
0
        return SUBPACKED_FMT(ARGB, 2, 10, 10, 10);
732
0
    case AV_PIX_FMT_X2BGR10LE:
733
0
    case AV_PIX_FMT_X2BGR10BE:
734
0
        return SUBPACKED_FMT(ABGR, 2, 10, 10, 10);
735
0
    case AV_PIX_FMT_XV30LE:
736
0
    case AV_PIX_FMT_XV30BE:
737
0
        return SUBPACKED_FMT(AVYU, 2, 10, 10, 10);
738
0
    case AV_PIX_FMT_V30XLE:
739
0
    case AV_PIX_FMT_V30XBE:
740
0
        return SUBPACKED_FMT(VYUA, 10, 10, 10, 2);
741
742
    /* 3-component formats with extra padding */
743
0
    case AV_PIX_FMT_RGB0:   return PACKED_FMT(RGBA, 4);
744
0
    case AV_PIX_FMT_BGR0:   return PACKED_FMT(BGRA, 4);
745
0
    case AV_PIX_FMT_0RGB:   return PACKED_FMT(ARGB, 4);
746
0
    case AV_PIX_FMT_0BGR:   return PACKED_FMT(ABGR, 4);
747
0
    case AV_PIX_FMT_VUYX:   return PACKED_FMT(VUYA, 4);
748
0
    case AV_PIX_FMT_XV36LE:
749
0
    case AV_PIX_FMT_XV36BE:
750
0
        return PACKED_FMT(UYVA, 4, .shift = 4);
751
0
    case AV_PIX_FMT_XV48LE:
752
0
    case AV_PIX_FMT_XV48BE:
753
0
        return PACKED_FMT(UYVA, 4);
754
0
    }
755
756
0
    return (FmtInfo) {0};
757
0
}
758
759
struct comp {
760
    int index;
761
    int plane;
762
    int offset;
763
};
764
765
/* Compare by (plane, offset) */
766
0
static int cmp_comp(const void *a, const void *b) {
767
0
    const struct comp *ca = a;
768
0
    const struct comp *cb = b;
769
0
    if (ca->plane != cb->plane)
770
0
        return ca->plane - cb->plane;
771
0
    return ca->offset - cb->offset;
772
0
}
773
774
static int fmt_analyze_regular(const AVPixFmtDescriptor *desc, SwsReadWriteOp *rw_op,
775
                               SwsSwizzleOp *swizzle, int *shift)
776
0
{
777
0
    if (desc->nb_components == 2) {
778
        /* YA formats */
779
0
        *swizzle = SWS_SWIZZLE(0, 3, 1, 2);
780
0
    } else {
781
        /* Sort by increasing component order */
782
0
        struct comp sorted[4] = { {0}, {1}, {2}, {3} };
783
0
        for (int i = 0; i < desc->nb_components; i++) {
784
0
            sorted[i].plane  = desc->comp[i].plane;
785
0
            sorted[i].offset = desc->comp[i].offset;
786
0
        }
787
788
0
        qsort(sorted, desc->nb_components, sizeof(struct comp), cmp_comp);
789
790
0
        SwsSwizzleOp swiz = SWS_SWIZZLE(0, 1, 2, 3);
791
0
        for (int i = 0; i < desc->nb_components; i++)
792
0
            swiz.in[i] = sorted[i].index;
793
0
        *swizzle = swiz;
794
0
    }
795
796
0
    *shift = desc->comp[0].shift;
797
0
    *rw_op = (SwsReadWriteOp) {
798
0
        .elems  = desc->nb_components,
799
0
        .packed = desc->nb_components > 1 && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR),
800
0
    };
801
0
    return 0;
802
0
}
803
804
static int fmt_analyze(enum AVPixelFormat fmt, SwsReadWriteOp *rw_op,
805
                       SwsPackOp *pack_op, SwsSwizzleOp *swizzle, int *shift,
806
                       SwsPixelType *pixel_type, SwsPixelType *raw_type)
807
0
{
808
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
809
0
    if (!desc)
810
0
        return AVERROR(EINVAL);
811
812
    /* No support for subsampled formats at the moment */
813
0
    if (desc->log2_chroma_w || desc->log2_chroma_h)
814
0
        return AVERROR(ENOTSUP);
815
816
    /* No support for semi-planar formats at the moment */
817
0
    if (desc->flags & AV_PIX_FMT_FLAG_PLANAR &&
818
0
        av_pix_fmt_count_planes(fmt) < desc->nb_components)
819
0
        return AVERROR(ENOTSUP);
820
821
0
    *pixel_type = *raw_type = fmt_pixel_type(fmt);
822
0
    if (!*pixel_type)
823
0
        return AVERROR(ENOTSUP);
824
825
0
    if (is_regular_fmt(fmt)) {
826
0
        *pack_op = (SwsPackOp) {0};
827
0
        return fmt_analyze_regular(desc, rw_op, swizzle, shift);
828
0
    }
829
830
0
    FmtInfo info = fmt_info_irregular(fmt);
831
0
    if (!info.rw.elems)
832
0
        return AVERROR(ENOTSUP);
833
834
0
    *rw_op   = info.rw;
835
0
    *pack_op = info.pack;
836
0
    *swizzle = info.swizzle;
837
0
    *shift   = info.shift;
838
839
0
    if (info.pack.pattern[0]) {
840
0
        const int sum = info.pack.pattern[0] + info.pack.pattern[1] +
841
0
                        info.pack.pattern[2] + info.pack.pattern[3];
842
0
        if (sum > 16)
843
0
            *raw_type = SWS_PIXEL_U32;
844
0
        else if (sum > 8)
845
0
            *raw_type = SWS_PIXEL_U16;
846
0
        else
847
0
            *raw_type = SWS_PIXEL_U8;
848
0
    }
849
850
0
    return 0;
851
0
}
852
853
0
static SwsSwizzleOp swizzle_inv(SwsSwizzleOp swiz) {
854
    /* Input[x] =: Output[swizzle.x] */
855
0
    unsigned out[4];
856
0
    out[swiz.x] = 0;
857
0
    out[swiz.y] = 1;
858
0
    out[swiz.z] = 2;
859
0
    out[swiz.w] = 3;
860
0
    return (SwsSwizzleOp) {{ .x = out[0], out[1], out[2], out[3] }};
861
0
}
862
863
/**
864
 * This initializes all absent components explicitly to zero. There is no
865
 * need to worry about the correct neutral value as fmt_decode() will
866
 * implicitly ignore and overwrite absent components in any case. This function
867
 * is just to ensure that we don't operate on undefined memory. In most cases,
868
 * it will end up getting pushed towards the output or optimized away entirely
869
 * by the optimization pass.
870
 */
871
static SwsConst fmt_clear(enum AVPixelFormat fmt)
872
0
{
873
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
874
0
    const bool has_chroma = desc->nb_components >= 3;
875
0
    const bool has_alpha  = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
876
877
0
    SwsConst c = {0};
878
0
    if (!has_chroma)
879
0
        c.q4[1] = c.q4[2] = Q0;
880
0
    if (!has_alpha)
881
0
        c.q4[3] = Q0;
882
883
0
    return c;
884
0
}
885
886
#if HAVE_BIGENDIAN
887
#  define NATIVE_ENDIAN_FLAG AV_PIX_FMT_FLAG_BE
888
#else
889
0
#  define NATIVE_ENDIAN_FLAG 0
890
#endif
891
892
int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
893
0
{
894
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
895
0
    SwsPixelType pixel_type, raw_type;
896
0
    SwsReadWriteOp rw_op;
897
0
    SwsSwizzleOp swizzle;
898
0
    SwsPackOp unpack;
899
0
    SwsComps comps = {0};
900
0
    int shift;
901
902
0
    RET(fmt_analyze(fmt, &rw_op, &unpack, &swizzle, &shift,
903
0
                    &pixel_type, &raw_type));
904
905
0
    swizzle = swizzle_inv(swizzle);
906
907
    /* Set baseline pixel content flags */
908
0
    const int integer = ff_sws_pixel_type_is_int(raw_type);
909
0
    const int swapped = (desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG;
910
0
    for (int i = 0; i < rw_op.elems; i++) {
911
0
        comps.flags[i] = (integer ? SWS_COMP_EXACT   : 0) |
912
0
                         (swapped ? SWS_COMP_SWAPPED : 0);
913
0
    }
914
915
    /* Generate value range information for simple unpacked formats */
916
0
    if (integer && !unpack.pattern[0]) {
917
        /* YA formats have desc->comp[] in the order {Y, A} instead of the
918
         * canonical order {Y, U, V, A} */
919
0
        const int is_ya = desc->nb_components == 2;
920
0
        for (int c = 0; c < desc->nb_components; c++) {
921
0
            const int bits   = desc->comp[c].depth + shift;
922
0
            const int idx    = swizzle.in[is_ya ? 3 * c : c];
923
0
            comps.min[idx]   = Q0;
924
0
            if (bits < 32) /* FIXME: AVRational is limited to INT_MAX */
925
0
                comps.max[idx] = Q((1ULL << bits) - 1);
926
0
        }
927
0
    }
928
929
    /* TODO: handle subsampled or semipacked input formats */
930
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
931
0
        .op    = SWS_OP_READ,
932
0
        .type  = raw_type,
933
0
        .rw    = rw_op,
934
0
        .comps = comps,
935
0
    }));
936
937
0
    if (swapped) {
938
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
939
0
            .op   = SWS_OP_SWAP_BYTES,
940
0
            .type = raw_type,
941
0
        }));
942
0
    }
943
944
0
    if (unpack.pattern[0]) {
945
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
946
0
            .op   = SWS_OP_UNPACK,
947
0
            .type = raw_type,
948
0
            .pack = unpack,
949
0
        }));
950
951
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
952
0
            .op   = SWS_OP_CONVERT,
953
0
            .type = raw_type,
954
0
            .convert.to = pixel_type,
955
0
        }));
956
0
    }
957
958
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
959
0
        .op      = SWS_OP_SWIZZLE,
960
0
        .type    = pixel_type,
961
0
        .swizzle = swizzle,
962
0
    }));
963
964
0
    if (shift) {
965
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
966
0
            .op   = SWS_OP_RSHIFT,
967
0
            .type = pixel_type,
968
0
            .c.u  = shift,
969
0
        }));
970
0
    }
971
972
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
973
0
        .op   = SWS_OP_CLEAR,
974
0
        .type = pixel_type,
975
0
        .c    = fmt_clear(fmt),
976
0
    }));
977
978
0
    return 0;
979
0
}
980
981
int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
982
0
{
983
0
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
984
0
    SwsPixelType pixel_type, raw_type;
985
0
    SwsReadWriteOp rw_op;
986
0
    SwsSwizzleOp swizzle;
987
0
    SwsPackOp pack;
988
0
    int shift;
989
990
0
    RET(fmt_analyze(fmt, &rw_op, &pack, &swizzle, &shift,
991
0
                    &pixel_type, &raw_type));
992
993
0
    if (shift) {
994
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
995
0
            .op   = SWS_OP_LSHIFT,
996
0
            .type = pixel_type,
997
0
            .c.u  = shift,
998
0
        }));
999
0
    }
1000
1001
0
    if (rw_op.elems > desc->nb_components) {
1002
        /* Format writes unused alpha channel, clear it explicitly for sanity */
1003
0
        av_assert1(!(desc->flags & AV_PIX_FMT_FLAG_ALPHA));
1004
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1005
0
            .op   = SWS_OP_CLEAR,
1006
0
            .type = pixel_type,
1007
0
            .c.q4[3] = Q0,
1008
0
        }));
1009
0
    }
1010
1011
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
1012
0
        .op      = SWS_OP_SWIZZLE,
1013
0
        .type    = pixel_type,
1014
0
        .swizzle = swizzle,
1015
0
    }));
1016
1017
0
    if (pack.pattern[0]) {
1018
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1019
0
            .op   = SWS_OP_CONVERT,
1020
0
            .type = pixel_type,
1021
0
            .convert.to = raw_type,
1022
0
        }));
1023
1024
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1025
0
            .op   = SWS_OP_PACK,
1026
0
            .type = raw_type,
1027
0
            .pack = pack,
1028
0
        }));
1029
0
    }
1030
1031
0
    if ((desc->flags & AV_PIX_FMT_FLAG_BE) != NATIVE_ENDIAN_FLAG) {
1032
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1033
0
            .op   = SWS_OP_SWAP_BYTES,
1034
0
            .type = raw_type,
1035
0
        }));
1036
0
    }
1037
1038
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
1039
0
        .op   = SWS_OP_WRITE,
1040
0
        .type = raw_type,
1041
0
        .rw   = rw_op,
1042
0
    }));
1043
1044
0
    return 0;
1045
0
}
1046
1047
static inline AVRational av_neg_q(AVRational x)
1048
0
{
1049
0
    return (AVRational) { -x.num, x.den };
1050
0
}
1051
1052
static SwsLinearOp fmt_encode_range(const SwsFormat fmt, bool *incomplete)
1053
0
{
1054
0
    SwsLinearOp c = { .m = {
1055
0
        { Q1, Q0, Q0, Q0, Q0 },
1056
0
        { Q0, Q1, Q0, Q0, Q0 },
1057
0
        { Q0, Q0, Q1, Q0, Q0 },
1058
0
        { Q0, Q0, Q0, Q1, Q0 },
1059
0
    }};
1060
1061
0
    const int depth0 = fmt.desc->comp[0].depth;
1062
0
    const int depth1 = fmt.desc->comp[1].depth;
1063
0
    const int depth2 = fmt.desc->comp[2].depth;
1064
0
    const int depth3 = fmt.desc->comp[3].depth;
1065
1066
0
    if (fmt.desc->flags & AV_PIX_FMT_FLAG_FLOAT)
1067
0
        return c; /* floats are directly output as-is */
1068
1069
0
    if (fmt.csp == AVCOL_SPC_RGB || (fmt.desc->flags & AV_PIX_FMT_FLAG_XYZ)) {
1070
0
        c.m[0][0] = Q((1 << depth0) - 1);
1071
0
        c.m[1][1] = Q((1 << depth1) - 1);
1072
0
        c.m[2][2] = Q((1 << depth2) - 1);
1073
0
    } else if (fmt.range == AVCOL_RANGE_JPEG) {
1074
        /* Full range YUV */
1075
0
        c.m[0][0] = Q((1 << depth0) - 1);
1076
0
        if (fmt.desc->nb_components >= 3) {
1077
            /* This follows the ITU-R convention, which is slightly different
1078
             * from the JFIF convention. */
1079
0
            c.m[1][1] = Q((1 << depth1) - 1);
1080
0
            c.m[2][2] = Q((1 << depth2) - 1);
1081
0
            c.m[1][4] = Q(1 << (depth1 - 1));
1082
0
            c.m[2][4] = Q(1 << (depth2 - 1));
1083
0
        }
1084
0
    } else {
1085
        /* Limited range YUV */
1086
0
        if (fmt.range == AVCOL_RANGE_UNSPECIFIED)
1087
0
            *incomplete = true;
1088
0
        c.m[0][0] = Q(219 << (depth0 - 8));
1089
0
        c.m[0][4] = Q( 16 << (depth0 - 8));
1090
0
        if (fmt.desc->nb_components >= 3) {
1091
0
            c.m[1][1] = Q(224 << (depth1 - 8));
1092
0
            c.m[2][2] = Q(224 << (depth2 - 8));
1093
0
            c.m[1][4] = Q(128 << (depth1 - 8));
1094
0
            c.m[2][4] = Q(128 << (depth2 - 8));
1095
0
        }
1096
0
    }
1097
1098
0
    if (fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
1099
0
        const bool is_ya = fmt.desc->nb_components == 2;
1100
0
        c.m[3][3] = Q((1 << (is_ya ? depth1 : depth3)) - 1);
1101
0
    }
1102
1103
0
    if (fmt.format == AV_PIX_FMT_MONOWHITE) {
1104
        /* This format is inverted, 0 = white, 1 = black */
1105
0
        c.m[0][4] = av_add_q(c.m[0][4], c.m[0][0]);
1106
0
        c.m[0][0] = av_neg_q(c.m[0][0]);
1107
0
    }
1108
1109
0
    c.mask = ff_sws_linear_mask(c);
1110
0
    return c;
1111
0
}
1112
1113
static SwsLinearOp fmt_decode_range(const SwsFormat fmt, bool *incomplete)
1114
0
{
1115
0
    SwsLinearOp c = fmt_encode_range(fmt, incomplete);
1116
1117
    /* Invert main diagonal + offset: x = s * y + k  ==>  y = (x - k) / s */
1118
0
    for (int i = 0; i < 4; i++) {
1119
0
        av_assert1(c.m[i][i].num);
1120
0
        c.m[i][i] = av_inv_q(c.m[i][i]);
1121
0
        c.m[i][4] = av_mul_q(c.m[i][4], av_neg_q(c.m[i][i]));
1122
0
    }
1123
1124
    /* Explicitly initialize alpha for sanity */
1125
0
    if (!(fmt.desc->flags & AV_PIX_FMT_FLAG_ALPHA))
1126
0
        c.m[3][4] = Q1;
1127
1128
0
    c.mask = ff_sws_linear_mask(c);
1129
0
    return c;
1130
0
}
1131
1132
static AVRational *generate_bayer_matrix(const int size_log2)
1133
0
{
1134
0
    const int size = 1 << size_log2;
1135
0
    const int num_entries = size * size;
1136
0
    AVRational *m = av_refstruct_allocz(sizeof(*m) * num_entries);
1137
0
    av_assert1(size_log2 < 16);
1138
0
    if (!m)
1139
0
        return NULL;
1140
1141
    /* Start with a 1x1 matrix */
1142
0
    m[0] = Q0;
1143
1144
    /* Generate three copies of the current, appropriately scaled and offset */
1145
0
    for (int sz = 1; sz < size; sz <<= 1) {
1146
0
        const int den = 4 * sz * sz;
1147
0
        for (int y = 0; y < sz; y++) {
1148
0
            for (int x = 0; x < sz; x++) {
1149
0
                const AVRational cur = m[y * size + x];
1150
0
                m[(y + sz) * size + x + sz] = av_add_q(cur, av_make_q(1, den));
1151
0
                m[(y     ) * size + x + sz] = av_add_q(cur, av_make_q(2, den));
1152
0
                m[(y + sz) * size + x     ] = av_add_q(cur, av_make_q(3, den));
1153
0
            }
1154
0
        }
1155
0
    }
1156
1157
    /**
1158
     * To correctly round, we need to evenly distribute the result on [0, 1),
1159
     * giving an average value of 1/2.
1160
     *
1161
     * After the above construction, we have a matrix with average value:
1162
     *   [ 0/N + 1/N + 2/N + ... (N-1)/N ] / N = (N-1)/(2N)
1163
     * where N = size * size is the total number of entries.
1164
     *
1165
     * To make the average value equal to 1/2 = N/(2N), add a bias of 1/(2N).
1166
     */
1167
0
    for (int i = 0; i < num_entries; i++)
1168
0
        m[i] = av_add_q(m[i], av_make_q(1, 2 * num_entries));
1169
1170
0
    return m;
1171
0
}
1172
1173
static bool trc_is_hdr(enum AVColorTransferCharacteristic trc)
1174
0
{
1175
0
    static_assert(AVCOL_TRC_NB == 19, "Update this list when adding TRCs");
1176
0
    static_assert(AVCOL_TRC_EXT_NB == 257, "Update this list when adding TRCs");
1177
0
    switch (trc) {
1178
0
    case AVCOL_TRC_LOG:
1179
0
    case AVCOL_TRC_LOG_SQRT:
1180
0
    case AVCOL_TRC_V_LOG:
1181
0
    case AVCOL_TRC_SMPTEST2084:
1182
0
    case AVCOL_TRC_ARIB_STD_B67:
1183
0
        return true;
1184
0
    default:
1185
0
        return false;
1186
0
    }
1187
0
}
1188
1189
static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
1190
                      const SwsPixelType type,
1191
                      const SwsFormat src, const SwsFormat dst)
1192
0
{
1193
0
    SwsDither mode = ctx->dither;
1194
0
    SwsDitherOp dither;
1195
0
    const int bpc = dst.desc->comp[0].depth;
1196
1197
0
    if (mode == SWS_DITHER_AUTO) {
1198
        /* Visual threshold of perception: 12 bits for SDR, 14 bits for HDR */
1199
0
        const int jnd_bits = trc_is_hdr(dst.color.trc) ? 14 : 12;
1200
0
        mode = bpc >= jnd_bits ? SWS_DITHER_NONE : SWS_DITHER_BAYER;
1201
0
    }
1202
1203
0
    switch (mode) {
1204
0
    case SWS_DITHER_NONE:
1205
0
        if (ctx->flags & SWS_ACCURATE_RND) {
1206
            /* Add constant 0.5 for correct rounding */
1207
0
            AVRational *bias = av_refstruct_allocz(sizeof(*bias));
1208
0
            if (!bias)
1209
0
                return AVERROR(ENOMEM);
1210
0
            *bias = (AVRational) {1, 2};
1211
0
            return ff_sws_op_list_append(ops, &(SwsOp) {
1212
0
                .op   = SWS_OP_DITHER,
1213
0
                .type = type,
1214
0
                .dither.matrix = bias,
1215
0
            });
1216
0
        } else {
1217
0
            return 0; /* No-op */
1218
0
        }
1219
0
    case SWS_DITHER_BAYER:
1220
        /* Hardcode 16x16 matrix for now; in theory we could adjust this
1221
         * based on the expected level of precision in the output, since lower
1222
         * bit depth outputs can suffice with smaller dither matrices; however
1223
         * in practice we probably want to use error diffusion for such low bit
1224
         * depths anyway */
1225
0
        dither.size_log2 = 4;
1226
0
        dither.matrix = generate_bayer_matrix(dither.size_log2);
1227
0
        if (!dither.matrix)
1228
0
            return AVERROR(ENOMEM);
1229
1230
        /* Brute-forced offsets; minimizes quantization error across a 16x16
1231
         * bayer dither pattern for standard RGBA and YUVA pixel formats */
1232
0
        const int offsets_16x16[4] = {0, 3, 2, 5};
1233
0
        for (int i = 0; i < 4; i++)
1234
0
            dither.y_offset[i] = offsets_16x16[i];
1235
1236
0
        if (src.desc->nb_components < 3 && bpc >= 8) {
1237
            /**
1238
             * For high-bit-depth sources without chroma, use same matrix
1239
             * offset for all color channels. This prevents introducing color
1240
             * noise in grayscale images; and also allows optimizing the dither
1241
             * operation. Skipped for low bit depth (<8 bpc) as the loss in
1242
             * PSNR, from the inability to diffuse error among all three
1243
             * channels, can be substantial.
1244
             *
1245
             * This shifts: { X, Y, Z, W } -> { X, X, X, Y }
1246
             */
1247
0
            dither.y_offset[3] = dither.y_offset[1];
1248
0
            dither.y_offset[1] = dither.y_offset[2] = dither.y_offset[0];
1249
0
        }
1250
1251
0
        return ff_sws_op_list_append(ops, &(SwsOp) {
1252
0
            .op     = SWS_OP_DITHER,
1253
0
            .type   = type,
1254
0
            .dither = dither,
1255
0
        });
1256
0
    case SWS_DITHER_ED:
1257
0
    case SWS_DITHER_A_DITHER:
1258
0
    case SWS_DITHER_X_DITHER:
1259
0
        return AVERROR(ENOTSUP);
1260
1261
0
    case SWS_DITHER_NB:
1262
0
        break;
1263
0
    }
1264
1265
0
    av_unreachable("Invalid dither mode");
1266
0
    return AVERROR(EINVAL);
1267
0
}
1268
1269
static inline SwsLinearOp
1270
linear_mat3(const AVRational m00, const AVRational m01, const AVRational m02,
1271
            const AVRational m10, const AVRational m11, const AVRational m12,
1272
            const AVRational m20, const AVRational m21, const AVRational m22)
1273
0
{
1274
0
    SwsLinearOp c = {{
1275
0
        { m00, m01, m02, Q0, Q0 },
1276
0
        { m10, m11, m12, Q0, Q0 },
1277
0
        { m20, m21, m22, Q0, Q0 },
1278
0
        {  Q0,  Q0,  Q0, Q1, Q0 },
1279
0
    }};
1280
1281
0
    c.mask = ff_sws_linear_mask(c);
1282
0
    return c;
1283
0
}
1284
1285
int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type,
1286
                         SwsOpList *ops, const SwsFormat fmt, bool *incomplete)
1287
0
{
1288
0
    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(fmt.csp);
1289
1290
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
1291
0
        .op         = SWS_OP_CONVERT,
1292
0
        .type       = fmt_pixel_type(fmt.format),
1293
0
        .convert.to = type,
1294
0
    }));
1295
1296
    /* Decode pixel format into standardized range */
1297
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
1298
0
        .type = type,
1299
0
        .op   = SWS_OP_LINEAR,
1300
0
        .lin  = fmt_decode_range(fmt, incomplete),
1301
0
    }));
1302
1303
    /* Final step, decode colorspace */
1304
0
    switch (fmt.csp) {
1305
0
    case AVCOL_SPC_RGB:
1306
0
        return 0;
1307
0
    case AVCOL_SPC_UNSPECIFIED:
1308
0
        c = av_csp_luma_coeffs_from_avcsp(AVCOL_SPC_BT470BG);
1309
0
        *incomplete = true;
1310
        /* fall through */
1311
0
    case AVCOL_SPC_FCC:
1312
0
    case AVCOL_SPC_BT470BG:
1313
0
    case AVCOL_SPC_SMPTE170M:
1314
0
    case AVCOL_SPC_BT709:
1315
0
    case AVCOL_SPC_SMPTE240M:
1316
0
    case AVCOL_SPC_BT2020_NCL: {
1317
0
        AVRational crg = av_sub_q(Q0, av_div_q(c->cr, c->cg));
1318
0
        AVRational cbg = av_sub_q(Q0, av_div_q(c->cb, c->cg));
1319
0
        AVRational m02 = av_mul_q(Q(2), av_sub_q(Q1, c->cr));
1320
0
        AVRational m21 = av_mul_q(Q(2), av_sub_q(Q1, c->cb));
1321
0
        AVRational m11 = av_mul_q(cbg, m21);
1322
0
        AVRational m12 = av_mul_q(crg, m02);
1323
1324
0
        return ff_sws_op_list_append(ops, &(SwsOp) {
1325
0
            .type = type,
1326
0
            .op   = SWS_OP_LINEAR,
1327
0
            .lin  = linear_mat3(
1328
0
                Q1,  Q0, m02,
1329
0
                Q1, m11, m12,
1330
0
                Q1, m21,  Q0
1331
0
            ),
1332
0
        });
1333
0
    }
1334
1335
0
    case AVCOL_SPC_YCGCO:
1336
0
        return ff_sws_op_list_append(ops, &(SwsOp) {
1337
0
            .type = type,
1338
0
            .op   = SWS_OP_LINEAR,
1339
0
            .lin  = linear_mat3(
1340
0
                Q1, Q(-1), Q( 1),
1341
0
                Q1, Q( 1), Q( 0),
1342
0
                Q1, Q(-1), Q(-1)
1343
0
            ),
1344
0
        });
1345
1346
0
    case AVCOL_SPC_BT2020_CL:
1347
0
    case AVCOL_SPC_SMPTE2085:
1348
0
    case AVCOL_SPC_CHROMA_DERIVED_NCL:
1349
0
    case AVCOL_SPC_CHROMA_DERIVED_CL:
1350
0
    case AVCOL_SPC_ICTCP:
1351
0
    case AVCOL_SPC_IPT_C2:
1352
0
    case AVCOL_SPC_YCGCO_RE:
1353
0
    case AVCOL_SPC_YCGCO_RO:
1354
0
        return AVERROR(ENOTSUP);
1355
1356
0
    case AVCOL_SPC_RESERVED:
1357
0
        return AVERROR(EINVAL);
1358
1359
0
    case AVCOL_SPC_NB:
1360
0
        break;
1361
0
    }
1362
1363
0
    av_unreachable("Corrupt AVColorSpace value?");
1364
0
    return AVERROR(EINVAL);
1365
0
}
1366
1367
int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type,
1368
                         SwsOpList *ops, const SwsFormat src,
1369
                         const SwsFormat dst, bool *incomplete)
1370
0
{
1371
0
    const AVLumaCoefficients *c = av_csp_luma_coeffs_from_avcsp(dst.csp);
1372
1373
0
    switch (dst.csp) {
1374
0
    case AVCOL_SPC_RGB:
1375
0
        break;
1376
0
    case AVCOL_SPC_UNSPECIFIED:
1377
0
        c = av_csp_luma_coeffs_from_avcsp(AVCOL_SPC_BT470BG);
1378
0
        *incomplete = true;
1379
        /* fall through */
1380
0
    case AVCOL_SPC_FCC:
1381
0
    case AVCOL_SPC_BT470BG:
1382
0
    case AVCOL_SPC_SMPTE170M:
1383
0
    case AVCOL_SPC_BT709:
1384
0
    case AVCOL_SPC_SMPTE240M:
1385
0
    case AVCOL_SPC_BT2020_NCL: {
1386
0
        AVRational cb1 = av_sub_q(c->cb, Q1);
1387
0
        AVRational cr1 = av_sub_q(c->cr, Q1);
1388
0
        AVRational m20 = av_make_q(1,2);
1389
0
        AVRational m10 = av_mul_q(m20, av_div_q(c->cr, cb1));
1390
0
        AVRational m11 = av_mul_q(m20, av_div_q(c->cg, cb1));
1391
0
        AVRational m21 = av_mul_q(m20, av_div_q(c->cg, cr1));
1392
0
        AVRational m22 = av_mul_q(m20, av_div_q(c->cb, cr1));
1393
1394
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1395
0
            .type = type,
1396
0
            .op   = SWS_OP_LINEAR,
1397
0
            .lin  = linear_mat3(
1398
0
                c->cr, c->cg, c->cb,
1399
0
                m10,     m11,   m20,
1400
0
                m20,     m21,   m22
1401
0
            ),
1402
0
        }));
1403
0
        break;
1404
0
    }
1405
1406
0
    case AVCOL_SPC_YCGCO:
1407
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1408
0
            .type = type,
1409
0
            .op   = SWS_OP_LINEAR,
1410
0
            .lin  = linear_mat3(
1411
0
                av_make_q( 1, 4), av_make_q(1, 2), av_make_q( 1, 4),
1412
0
                av_make_q( 1, 2), av_make_q(0, 1), av_make_q(-1, 2),
1413
0
                av_make_q(-1, 4), av_make_q(1, 2), av_make_q(-1, 4)
1414
0
            ),
1415
0
        }));
1416
0
        break;
1417
1418
0
    case AVCOL_SPC_BT2020_CL:
1419
0
    case AVCOL_SPC_SMPTE2085:
1420
0
    case AVCOL_SPC_CHROMA_DERIVED_NCL:
1421
0
    case AVCOL_SPC_CHROMA_DERIVED_CL:
1422
0
    case AVCOL_SPC_ICTCP:
1423
0
    case AVCOL_SPC_IPT_C2:
1424
0
    case AVCOL_SPC_YCGCO_RE:
1425
0
    case AVCOL_SPC_YCGCO_RO:
1426
0
        return AVERROR(ENOTSUP);
1427
1428
0
    case AVCOL_SPC_RESERVED:
1429
0
    case AVCOL_SPC_NB:
1430
0
        return AVERROR(EINVAL);
1431
0
    }
1432
1433
0
    RET(ff_sws_op_list_append(ops, &(SwsOp) {
1434
0
        .type = type,
1435
0
        .op   = SWS_OP_LINEAR,
1436
0
        .lin  = fmt_encode_range(dst, incomplete),
1437
0
    }));
1438
1439
0
    if (!(dst.desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
1440
0
        SwsConst range = {0};
1441
1442
0
        const bool is_ya = dst.desc->nb_components == 2;
1443
0
        for (int i = 0; i < dst.desc->nb_components; i++) {
1444
            /* Clamp to legal pixel range */
1445
0
            const int idx = i * (is_ya ? 3 : 1);
1446
0
            range.q4[idx] = Q((1 << dst.desc->comp[i].depth) - 1);
1447
0
        }
1448
1449
0
        RET(fmt_dither(ctx, ops, type, src, dst));
1450
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1451
0
            .op   = SWS_OP_MAX,
1452
0
            .type = type,
1453
0
            .c.q4 = { Q0, Q0, Q0, Q0 },
1454
0
        }));
1455
1456
0
        RET(ff_sws_op_list_append(ops, &(SwsOp) {
1457
0
            .op   = SWS_OP_MIN,
1458
0
            .type = type,
1459
0
            .c    = range,
1460
0
        }));
1461
0
    }
1462
1463
0
    return ff_sws_op_list_append(ops, &(SwsOp) {
1464
0
        .type       = type,
1465
0
        .op         = SWS_OP_CONVERT,
1466
0
        .convert.to = fmt_pixel_type(dst.format),
1467
0
    });
1468
0
}
1469
1470
#endif /* CONFIG_UNSTABLE */