Coverage Report

Created: 2026-07-15 07:31

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