Coverage Report

Created: 2026-03-12 07:14

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