FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/format.c
Date: 2025-10-10 03:51:19
Exec Total Coverage
Lines: 156 504 31.0%
Functions: 15 34 44.1%
Branches: 76 299 25.4%

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