FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/utils.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 890 1505 59.1%
Functions: 35 58 60.3%
Branches: 697 1300 53.6%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2024 Niklas Haas
3 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config.h"
23
24 #define _DEFAULT_SOURCE
25 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
26 #define _DARWIN_C_SOURCE // needed for MAP_ANON
27 #include <inttypes.h>
28 #include <math.h>
29 #include <stdio.h>
30 #include <string.h>
31 #if HAVE_MMAP
32 #include <sys/mman.h>
33 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
34 #define MAP_ANONYMOUS MAP_ANON
35 #endif
36 #endif
37 #if HAVE_VIRTUALALLOC
38 #include <windows.h>
39 #endif
40
41 #include "libavutil/attributes.h"
42 #include "libavutil/avassert.h"
43 #include "libavutil/cpu.h"
44 #include "libavutil/csp.h"
45 #include "libavutil/emms.h"
46 #include "libavutil/hdr_dynamic_metadata.h"
47 #include "libavutil/imgutils.h"
48 #include "libavutil/intreadwrite.h"
49 #include "libavutil/libm.h"
50 #include "libavutil/mastering_display_metadata.h"
51 #include "libavutil/mathematics.h"
52 #include "libavutil/mem.h"
53 #include "libavutil/opt.h"
54 #include "libavutil/pixdesc.h"
55 #include "libavutil/slicethread.h"
56 #include "libavutil/thread.h"
57 #include "libavutil/aarch64/cpu.h"
58 #include "libavutil/ppc/cpu.h"
59 #include "libavutil/x86/asm.h"
60 #include "libavutil/x86/cpu.h"
61 #include "libavutil/loongarch/cpu.h"
62
63 #include "rgb2rgb.h"
64 #include "swscale.h"
65 #include "swscale_internal.h"
66 #include "utils.h"
67 #include "graph.h"
68
69 typedef struct FormatEntry {
70 uint8_t is_supported_in :1;
71 uint8_t is_supported_out :1;
72 uint8_t is_supported_endianness :1;
73 } FormatEntry;
74
75 static const FormatEntry format_entries[] = {
76 [AV_PIX_FMT_YUV420P] = { 1, 1 },
77 [AV_PIX_FMT_YUYV422] = { 1, 1 },
78 [AV_PIX_FMT_RGB24] = { 1, 1 },
79 [AV_PIX_FMT_BGR24] = { 1, 1 },
80 [AV_PIX_FMT_YUV422P] = { 1, 1 },
81 [AV_PIX_FMT_YUV444P] = { 1, 1 },
82 [AV_PIX_FMT_YUV410P] = { 1, 1 },
83 [AV_PIX_FMT_YUV411P] = { 1, 1 },
84 [AV_PIX_FMT_GRAY8] = { 1, 1 },
85 [AV_PIX_FMT_MONOWHITE] = { 1, 1 },
86 [AV_PIX_FMT_MONOBLACK] = { 1, 1 },
87 [AV_PIX_FMT_PAL8] = { 1, 0 },
88 [AV_PIX_FMT_YUVJ420P] = { 1, 1 },
89 [AV_PIX_FMT_YUVJ411P] = { 1, 1 },
90 [AV_PIX_FMT_YUVJ422P] = { 1, 1 },
91 [AV_PIX_FMT_YUVJ444P] = { 1, 1 },
92 [AV_PIX_FMT_YVYU422] = { 1, 1 },
93 [AV_PIX_FMT_UYVY422] = { 1, 1 },
94 [AV_PIX_FMT_UYYVYY411] = { 0, 0 },
95 [AV_PIX_FMT_BGR8] = { 1, 1 },
96 [AV_PIX_FMT_BGR4] = { 0, 1 },
97 [AV_PIX_FMT_BGR4_BYTE] = { 1, 1 },
98 [AV_PIX_FMT_RGB8] = { 1, 1 },
99 [AV_PIX_FMT_RGB4] = { 0, 1 },
100 [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 },
101 [AV_PIX_FMT_NV12] = { 1, 1 },
102 [AV_PIX_FMT_NV21] = { 1, 1 },
103 [AV_PIX_FMT_ARGB] = { 1, 1 },
104 [AV_PIX_FMT_RGBA] = { 1, 1 },
105 [AV_PIX_FMT_ABGR] = { 1, 1 },
106 [AV_PIX_FMT_BGRA] = { 1, 1 },
107 [AV_PIX_FMT_0RGB] = { 1, 1 },
108 [AV_PIX_FMT_RGB0] = { 1, 1 },
109 [AV_PIX_FMT_0BGR] = { 1, 1 },
110 [AV_PIX_FMT_BGR0] = { 1, 1 },
111 [AV_PIX_FMT_GRAY9BE] = { 1, 1 },
112 [AV_PIX_FMT_GRAY9LE] = { 1, 1 },
113 [AV_PIX_FMT_GRAY10BE] = { 1, 1 },
114 [AV_PIX_FMT_GRAY10LE] = { 1, 1 },
115 [AV_PIX_FMT_GRAY12BE] = { 1, 1 },
116 [AV_PIX_FMT_GRAY12LE] = { 1, 1 },
117 [AV_PIX_FMT_GRAY14BE] = { 1, 1 },
118 [AV_PIX_FMT_GRAY14LE] = { 1, 1 },
119 [AV_PIX_FMT_GRAY16BE] = { 1, 1 },
120 [AV_PIX_FMT_GRAY16LE] = { 1, 1 },
121 [AV_PIX_FMT_YUV440P] = { 1, 1 },
122 [AV_PIX_FMT_YUVJ440P] = { 1, 1 },
123 [AV_PIX_FMT_YUV440P10LE] = { 1, 1 },
124 [AV_PIX_FMT_YUV440P10BE] = { 1, 1 },
125 [AV_PIX_FMT_YUV440P12LE] = { 1, 1 },
126 [AV_PIX_FMT_YUV440P12BE] = { 1, 1 },
127 [AV_PIX_FMT_YUVA420P] = { 1, 1 },
128 [AV_PIX_FMT_YUVA422P] = { 1, 1 },
129 [AV_PIX_FMT_YUVA444P] = { 1, 1 },
130 [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 },
131 [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 },
132 [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 },
133 [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 },
134 [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 },
135 [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 },
136 [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 },
137 [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 },
138 [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 },
139 [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 },
140 [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 },
141 [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 },
142 [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 },
143 [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 },
144 [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 },
145 [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 },
146 [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 },
147 [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 },
148 [AV_PIX_FMT_RGB48BE] = { 1, 1 },
149 [AV_PIX_FMT_RGB48LE] = { 1, 1 },
150 [AV_PIX_FMT_RGBA64BE] = { 1, 1, 1 },
151 [AV_PIX_FMT_RGBA64LE] = { 1, 1, 1 },
152 [AV_PIX_FMT_RGB565BE] = { 1, 1 },
153 [AV_PIX_FMT_RGB565LE] = { 1, 1 },
154 [AV_PIX_FMT_RGB555BE] = { 1, 1 },
155 [AV_PIX_FMT_RGB555LE] = { 1, 1 },
156 [AV_PIX_FMT_BGR565BE] = { 1, 1 },
157 [AV_PIX_FMT_BGR565LE] = { 1, 1 },
158 [AV_PIX_FMT_BGR555BE] = { 1, 1 },
159 [AV_PIX_FMT_BGR555LE] = { 1, 1 },
160 [AV_PIX_FMT_YUV420P16LE] = { 1, 1 },
161 [AV_PIX_FMT_YUV420P16BE] = { 1, 1 },
162 [AV_PIX_FMT_YUV422P16LE] = { 1, 1 },
163 [AV_PIX_FMT_YUV422P16BE] = { 1, 1 },
164 [AV_PIX_FMT_YUV444P16LE] = { 1, 1 },
165 [AV_PIX_FMT_YUV444P16BE] = { 1, 1 },
166 [AV_PIX_FMT_RGB444LE] = { 1, 1 },
167 [AV_PIX_FMT_RGB444BE] = { 1, 1 },
168 [AV_PIX_FMT_BGR444LE] = { 1, 1 },
169 [AV_PIX_FMT_BGR444BE] = { 1, 1 },
170 [AV_PIX_FMT_YA8] = { 1, 1 },
171 [AV_PIX_FMT_YA16BE] = { 1, 1 },
172 [AV_PIX_FMT_YA16LE] = { 1, 1 },
173 [AV_PIX_FMT_BGR48BE] = { 1, 1 },
174 [AV_PIX_FMT_BGR48LE] = { 1, 1 },
175 [AV_PIX_FMT_BGRA64BE] = { 1, 1, 1 },
176 [AV_PIX_FMT_BGRA64LE] = { 1, 1, 1 },
177 [AV_PIX_FMT_YUV420P9BE] = { 1, 1 },
178 [AV_PIX_FMT_YUV420P9LE] = { 1, 1 },
179 [AV_PIX_FMT_YUV420P10BE] = { 1, 1 },
180 [AV_PIX_FMT_YUV420P10LE] = { 1, 1 },
181 [AV_PIX_FMT_YUV420P12BE] = { 1, 1 },
182 [AV_PIX_FMT_YUV420P12LE] = { 1, 1 },
183 [AV_PIX_FMT_YUV420P14BE] = { 1, 1 },
184 [AV_PIX_FMT_YUV420P14LE] = { 1, 1 },
185 [AV_PIX_FMT_YUV422P9BE] = { 1, 1 },
186 [AV_PIX_FMT_YUV422P9LE] = { 1, 1 },
187 [AV_PIX_FMT_YUV422P10BE] = { 1, 1 },
188 [AV_PIX_FMT_YUV422P10LE] = { 1, 1 },
189 [AV_PIX_FMT_YUV422P12BE] = { 1, 1 },
190 [AV_PIX_FMT_YUV422P12LE] = { 1, 1 },
191 [AV_PIX_FMT_YUV422P14BE] = { 1, 1 },
192 [AV_PIX_FMT_YUV422P14LE] = { 1, 1 },
193 [AV_PIX_FMT_YUV444P9BE] = { 1, 1 },
194 [AV_PIX_FMT_YUV444P9LE] = { 1, 1 },
195 [AV_PIX_FMT_YUV444P10BE] = { 1, 1 },
196 [AV_PIX_FMT_YUV444P10LE] = { 1, 1 },
197 [AV_PIX_FMT_YUV444P12BE] = { 1, 1 },
198 [AV_PIX_FMT_YUV444P12LE] = { 1, 1 },
199 [AV_PIX_FMT_YUV444P14BE] = { 1, 1 },
200 [AV_PIX_FMT_YUV444P14LE] = { 1, 1 },
201 [AV_PIX_FMT_GBRP] = { 1, 1 },
202 [AV_PIX_FMT_GBRP9LE] = { 1, 1 },
203 [AV_PIX_FMT_GBRP9BE] = { 1, 1 },
204 [AV_PIX_FMT_GBRP10LE] = { 1, 1 },
205 [AV_PIX_FMT_GBRP10BE] = { 1, 1 },
206 [AV_PIX_FMT_GBRAP10LE] = { 1, 1 },
207 [AV_PIX_FMT_GBRAP10BE] = { 1, 1 },
208 [AV_PIX_FMT_GBRP12LE] = { 1, 1 },
209 [AV_PIX_FMT_GBRP12BE] = { 1, 1 },
210 [AV_PIX_FMT_GBRAP12LE] = { 1, 1 },
211 [AV_PIX_FMT_GBRAP12BE] = { 1, 1 },
212 [AV_PIX_FMT_GBRP14LE] = { 1, 1 },
213 [AV_PIX_FMT_GBRP14BE] = { 1, 1 },
214 [AV_PIX_FMT_GBRAP14LE] = { 1, 1 },
215 [AV_PIX_FMT_GBRAP14BE] = { 1, 1 },
216 [AV_PIX_FMT_GBRP16LE] = { 1, 1 },
217 [AV_PIX_FMT_GBRP16BE] = { 1, 1 },
218 [AV_PIX_FMT_GBRPF32LE] = { 1, 1 },
219 [AV_PIX_FMT_GBRPF32BE] = { 1, 1 },
220 [AV_PIX_FMT_GBRAPF32LE] = { 1, 1 },
221 [AV_PIX_FMT_GBRAPF32BE] = { 1, 1 },
222 [AV_PIX_FMT_GBRAP] = { 1, 1 },
223 [AV_PIX_FMT_GBRAP16LE] = { 1, 1 },
224 [AV_PIX_FMT_GBRAP16BE] = { 1, 1 },
225 [AV_PIX_FMT_BAYER_BGGR8] = { 1, 0 },
226 [AV_PIX_FMT_BAYER_RGGB8] = { 1, 0 },
227 [AV_PIX_FMT_BAYER_GBRG8] = { 1, 0 },
228 [AV_PIX_FMT_BAYER_GRBG8] = { 1, 0 },
229 [AV_PIX_FMT_BAYER_BGGR16LE] = { 1, 0 },
230 [AV_PIX_FMT_BAYER_BGGR16BE] = { 1, 0 },
231 [AV_PIX_FMT_BAYER_RGGB16LE] = { 1, 0 },
232 [AV_PIX_FMT_BAYER_RGGB16BE] = { 1, 0 },
233 [AV_PIX_FMT_BAYER_GBRG16LE] = { 1, 0 },
234 [AV_PIX_FMT_BAYER_GBRG16BE] = { 1, 0 },
235 [AV_PIX_FMT_BAYER_GRBG16LE] = { 1, 0 },
236 [AV_PIX_FMT_BAYER_GRBG16BE] = { 1, 0 },
237 [AV_PIX_FMT_XYZ12BE] = { 1, 1, 1 },
238 [AV_PIX_FMT_XYZ12LE] = { 1, 1, 1 },
239 [AV_PIX_FMT_AYUV64LE] = { 1, 1},
240 [AV_PIX_FMT_AYUV64BE] = { 1, 1 },
241 [AV_PIX_FMT_P010LE] = { 1, 1 },
242 [AV_PIX_FMT_P010BE] = { 1, 1 },
243 [AV_PIX_FMT_P012LE] = { 1, 1 },
244 [AV_PIX_FMT_P012BE] = { 1, 1 },
245 [AV_PIX_FMT_P016LE] = { 1, 1 },
246 [AV_PIX_FMT_P016BE] = { 1, 1 },
247 [AV_PIX_FMT_GRAYF32LE] = { 1, 1 },
248 [AV_PIX_FMT_GRAYF32BE] = { 1, 1 },
249 [AV_PIX_FMT_YUVA422P12BE] = { 1, 1 },
250 [AV_PIX_FMT_YUVA422P12LE] = { 1, 1 },
251 [AV_PIX_FMT_YUVA444P12BE] = { 1, 1 },
252 [AV_PIX_FMT_YUVA444P12LE] = { 1, 1 },
253 [AV_PIX_FMT_NV24] = { 1, 1 },
254 [AV_PIX_FMT_NV42] = { 1, 1 },
255 [AV_PIX_FMT_Y210LE] = { 1, 1 },
256 [AV_PIX_FMT_Y212LE] = { 1, 1 },
257 [AV_PIX_FMT_Y216LE] = { 1, 1 },
258 [AV_PIX_FMT_X2RGB10LE] = { 1, 1 },
259 [AV_PIX_FMT_X2BGR10LE] = { 1, 1 },
260 [AV_PIX_FMT_P210BE] = { 1, 1 },
261 [AV_PIX_FMT_P210LE] = { 1, 1 },
262 [AV_PIX_FMT_P212BE] = { 1, 1 },
263 [AV_PIX_FMT_P212LE] = { 1, 1 },
264 [AV_PIX_FMT_P410BE] = { 1, 1 },
265 [AV_PIX_FMT_P410LE] = { 1, 1 },
266 [AV_PIX_FMT_P412BE] = { 1, 1 },
267 [AV_PIX_FMT_P412LE] = { 1, 1 },
268 [AV_PIX_FMT_P216BE] = { 1, 1 },
269 [AV_PIX_FMT_P216LE] = { 1, 1 },
270 [AV_PIX_FMT_P416BE] = { 1, 1 },
271 [AV_PIX_FMT_P416LE] = { 1, 1 },
272 [AV_PIX_FMT_NV16] = { 1, 1 },
273 [AV_PIX_FMT_VUYA] = { 1, 1 },
274 [AV_PIX_FMT_VUYX] = { 1, 1 },
275 [AV_PIX_FMT_RGBAF16BE] = { 1, 0 },
276 [AV_PIX_FMT_RGBAF16LE] = { 1, 0 },
277 [AV_PIX_FMT_RGBF16BE] = { 1, 0 },
278 [AV_PIX_FMT_RGBF16LE] = { 1, 0 },
279 [AV_PIX_FMT_RGBF32BE] = { 1, 0 },
280 [AV_PIX_FMT_RGBF32LE] = { 1, 0 },
281 [AV_PIX_FMT_XV30LE] = { 1, 1 },
282 [AV_PIX_FMT_XV36LE] = { 1, 1 },
283 [AV_PIX_FMT_XV36BE] = { 1, 1 },
284 [AV_PIX_FMT_XV48LE] = { 1, 1 },
285 [AV_PIX_FMT_XV48BE] = { 1, 1 },
286 [AV_PIX_FMT_AYUV] = { 1, 1 },
287 [AV_PIX_FMT_UYVA] = { 1, 1 },
288 [AV_PIX_FMT_VYU444] = { 1, 1 },
289 [AV_PIX_FMT_V30XLE] = { 1, 1 },
290 };
291
292 /**
293 * Allocate and return an SwsContext without performing initialization.
294 */
295 3145 static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcFormat,
296 int dstW, int dstH, enum AVPixelFormat dstFormat,
297 int flags, const double *param)
298 {
299 3145 SwsContext *sws = sws_alloc_context();
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3145 times.
3145 if (!sws)
301 return NULL;
302
303 3145 sws->flags = flags;
304 3145 sws->src_w = srcW;
305 3145 sws->src_h = srcH;
306 3145 sws->dst_w = dstW;
307 3145 sws->dst_h = dstH;
308 3145 sws->src_format = srcFormat;
309 3145 sws->dst_format = dstFormat;
310
311
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3143 times.
3145 if (param) {
312 2 sws->scaler_params[0] = param[0];
313 2 sws->scaler_params[1] = param[1];
314 }
315
316 3145 return sws;
317 }
318
319 41832 int ff_shuffle_filter_coefficients(SwsInternal *c, int *filterPos,
320 int filterSize, int16_t *filter,
321 int dstW)
322 {
323 #if ARCH_X86_64
324 int i, j, k;
325 41832 int cpu_flags = av_get_cpu_flags();
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41832 times.
41832 if (!filter)
327 return 0;
328
4/6
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 41442 times.
✓ Branch 2 taken 390 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 390 times.
✗ Branch 5 not taken.
41832 if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) {
329
4/4
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 180 times.
✓ Branch 3 taken 86 times.
390 if ((c->srcBpc == 8) && (c->dstBpc <= 14)) {
330 180 int16_t *filterCopy = NULL;
331
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 150 times.
180 if (filterSize > 4) {
332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (!FF_ALLOC_TYPED_ARRAY(filterCopy, dstW * filterSize))
333 return AVERROR(ENOMEM);
334 30 memcpy(filterCopy, filter, dstW * filterSize * sizeof(int16_t));
335 }
336 // Do not swap filterPos for pixels which won't be processed by
337 // the main loop.
338
2/2
✓ Branch 0 taken 13356 times.
✓ Branch 1 taken 180 times.
13536 for (i = 0; i + 16 <= dstW; i += 16) {
339 13356 FFSWAP(int, filterPos[i + 2], filterPos[i + 4]);
340 13356 FFSWAP(int, filterPos[i + 3], filterPos[i + 5]);
341 13356 FFSWAP(int, filterPos[i + 10], filterPos[i + 12]);
342 13356 FFSWAP(int, filterPos[i + 11], filterPos[i + 13]);
343 }
344
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 150 times.
180 if (filterSize > 4) {
345 // 16 pixels are processed at a time.
346
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 30 times.
360 for (i = 0; i + 16 <= dstW; i += 16) {
347 // 4 filter coeffs are processed at a time.
348
2/2
✓ Branch 0 taken 1782 times.
✓ Branch 1 taken 330 times.
2112 for (k = 0; k + 4 <= filterSize; k += 4) {
349
2/2
✓ Branch 0 taken 28512 times.
✓ Branch 1 taken 1782 times.
30294 for (j = 0; j < 16; ++j) {
350 28512 int from = (i + j) * filterSize + k;
351 28512 int to = i * filterSize + j * 4 + k * 16;
352 28512 memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t));
353 }
354 }
355 }
356 // 4 pixels are processed at a time in the tail.
357
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 30 times.
50 for (; i < dstW; i += 4) {
358 // 4 filter coeffs are processed at a time.
359 20 int rem = dstW - i >= 4 ? 4 : dstW - i;
360
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 20 times.
128 for (k = 0; k + 4 <= filterSize; k += 4) {
361
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 108 times.
540 for (j = 0; j < rem; ++j) {
362 432 int from = (i + j) * filterSize + k;
363 432 int to = i * filterSize + j * 4 + k * 4;
364 432 memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t));
365 }
366 }
367 }
368 }
369 180 av_free(filterCopy);
370 }
371 }
372 #endif
373 41832 return 0;
374 }
375
376 1525746 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
377 {
378 1525746 return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
379
1/2
✓ Branch 0 taken 1525746 times.
✗ Branch 1 not taken.
1525746 format_entries[pix_fmt].is_supported_in : 0;
380 }
381
382 1525746 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
383 {
384 1525746 return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
385
1/2
✓ Branch 0 taken 1525746 times.
✗ Branch 1 not taken.
1525746 format_entries[pix_fmt].is_supported_out : 0;
386 }
387
388 24536 int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt)
389 {
390 24536 return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
391
1/2
✓ Branch 0 taken 24536 times.
✗ Branch 1 not taken.
24536 format_entries[pix_fmt].is_supported_endianness : 0;
392 }
393
394 static double getSplineCoeff(double a, double b, double c, double d,
395 double dist)
396 {
397 if (dist <= 1.0)
398 return ((d * dist + c) * dist + b) * dist + a;
399 else
400 return getSplineCoeff(0.0,
401 b + 2.0 * c + 3.0 * d,
402 c + 3.0 * d,
403 -b - 3.0 * c - 6.0 * d,
404 dist - 1.0);
405 }
406
407 163584 static av_cold int get_local_pos(SwsInternal *s, int chr_subsample, int pos, int dir)
408 {
409
3/4
✓ Branch 0 taken 163584 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61074 times.
✓ Branch 3 taken 102510 times.
163584 if (pos == -1 || pos <= -513) {
410 61074 pos = (128 << chr_subsample) - 128;
411 }
412 163584 pos += 128; // relative to ideal left edge
413 163584 return pos >> chr_subsample;
414 }
415
416 typedef struct {
417 int flag; ///< flag associated to the algorithm
418 const char *description; ///< human-readable description
419 int size_factor; ///< size factor used when initing the filters
420 } ScaleAlgorithm;
421
422 static const ScaleAlgorithm scale_algorithms[] = {
423 { SWS_AREA, "area averaging", 1 /* downscale only, for upscale it is bilinear */ },
424 { SWS_BICUBIC, "bicubic", 4 },
425 { SWS_BICUBLIN, "luma bicubic / chroma bilinear", -1 },
426 { SWS_BILINEAR, "bilinear", 2 },
427 { SWS_FAST_BILINEAR, "fast bilinear", -1 },
428 { SWS_GAUSS, "Gaussian", 8 /* infinite ;) */ },
429 { SWS_LANCZOS, "Lanczos", -1 /* custom */ },
430 { SWS_POINT, "nearest neighbor / point", -1 },
431 { SWS_SINC, "sinc", 20 /* infinite ;) */ },
432 { SWS_SPLINE, "bicubic spline", 20 /* infinite :)*/ },
433 { SWS_X, "experimental", 8 },
434 };
435
436 81792 static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos,
437 int *outFilterSize, int xInc, int srcW,
438 int dstW, int filterAlign, int one,
439 int flags, int cpu_flags,
440 SwsVector *srcFilter, SwsVector *dstFilter,
441 double param[2], int srcPos, int dstPos)
442 {
443 int i;
444 int filterSize;
445 int filter2Size;
446 int minFilterSize;
447 81792 int64_t *filter = NULL;
448 81792 int64_t *filter2 = NULL;
449 81792 const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8));
450 81792 int ret = -1;
451
452 81792 emms_c(); // FIXME should not be required but IS (even for non-MMX versions)
453
454 // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81792 times.
81792 if (!FF_ALLOC_TYPED_ARRAY(*filterPos, dstW + 3))
456 goto nomem;
457
458
6/8
✓ Branch 0 taken 70287 times.
✓ Branch 1 taken 11505 times.
✓ Branch 2 taken 63082 times.
✓ Branch 3 taken 7205 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11505 times.
✓ Branch 6 taken 63082 times.
✗ Branch 7 not taken.
144874 if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled
459 int i;
460 63082 filterSize = 1;
461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63082 times.
63082 if (!FF_ALLOCZ_TYPED_ARRAY(filter, dstW * filterSize))
462 goto nomem;
463
464
2/2
✓ Branch 0 taken 24038817 times.
✓ Branch 1 taken 63082 times.
24101899 for (i = 0; i < dstW; i++) {
465 24038817 filter[i * filterSize] = fone;
466 24038817 (*filterPos)[i] = i;
467 }
468
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 18418 times.
18710 } else if (flags & SWS_POINT) { // lame looking point sampling mode
469 int i;
470 int64_t xDstInSrc;
471 292 filterSize = 1;
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
292 if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize))
473 goto nomem;
474
475 292 xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7);
476
2/2
✓ Branch 0 taken 85885 times.
✓ Branch 1 taken 292 times.
86177 for (i = 0; i < dstW; i++) {
477 85885 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
478
479 85885 (*filterPos)[i] = xx;
480 85885 filter[i] = fone;
481 85885 xDstInSrc += xInc;
482 }
483
4/4
✓ Branch 0 taken 11345 times.
✓ Branch 1 taken 7073 times.
✓ Branch 2 taken 11257 times.
✓ Branch 3 taken 88 times.
18418 } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) ||
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18330 times.
18418 (flags & SWS_FAST_BILINEAR)) { // bilinear upscale
485 int i;
486 int64_t xDstInSrc;
487 88 filterSize = 2;
488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize))
489 goto nomem;
490
491 88 xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7);
492
2/2
✓ Branch 0 taken 157236 times.
✓ Branch 1 taken 88 times.
157324 for (i = 0; i < dstW; i++) {
493 157236 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
494 int j;
495
496 157236 (*filterPos)[i] = xx;
497 // bilinear upscale / linear interpolate / area averaging
498
2/2
✓ Branch 0 taken 314472 times.
✓ Branch 1 taken 157236 times.
471708 for (j = 0; j < filterSize; j++) {
499 314472 int64_t coeff = fone - FFABS((int64_t)xx * (1 << 16) - xDstInSrc) * (fone >> 16);
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 314472 times.
314472 if (coeff < 0)
501 coeff = 0;
502 314472 filter[i * filterSize + j] = coeff;
503 314472 xx++;
504 }
505 157236 xDstInSrc += xInc;
506 }
507 } else {
508 int64_t xDstInSrc;
509 18330 int sizeFactor = -1;
510
511
1/2
✓ Branch 0 taken 37240 times.
✗ Branch 1 not taken.
37240 for (i = 0; i < FF_ARRAY_ELEMS(scale_algorithms); i++) {
512
3/4
✓ Branch 0 taken 18330 times.
✓ Branch 1 taken 18910 times.
✓ Branch 2 taken 18330 times.
✗ Branch 3 not taken.
37240 if (flags & scale_algorithms[i].flag && scale_algorithms[i].size_factor > 0) {
513 18330 sizeFactor = scale_algorithms[i].size_factor;
514 18330 break;
515 }
516 }
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18330 times.
18330 if (flags & SWS_LANCZOS)
518 sizeFactor = param[0] != SWS_PARAM_DEFAULT ? ceil(2 * param[0]) : 6;
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18330 times.
18330 av_assert0(sizeFactor > 0);
520
521
2/2
✓ Branch 0 taken 11257 times.
✓ Branch 1 taken 7073 times.
18330 if (xInc <= 1 << 16)
522 11257 filterSize = 1 + sizeFactor; // upscale
523 else
524 7073 filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
525
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18330 times.
18330 filterSize = FFMIN(filterSize, srcW - 2);
527 18330 filterSize = FFMAX(filterSize, 1);
528
529
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18330 times.
18330 if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize))
530 goto nomem;
531 18330 xDstInSrc = ((dstPos*(int64_t)xInc)>>7) - ((srcPos*0x10000LL)>>7);
532
2/2
✓ Branch 0 taken 6947128 times.
✓ Branch 1 taken 18330 times.
6965458 for (i = 0; i < dstW; i++) {
533 6947128 int xx = (xDstInSrc - (filterSize - 2) * (1LL<<16)) / (1 << 17);
534 int j;
535 6947128 (*filterPos)[i] = xx;
536
2/2
✓ Branch 0 taken 39591876 times.
✓ Branch 1 taken 6947128 times.
46539004 for (j = 0; j < filterSize; j++) {
537 39591876 int64_t d = (FFABS(((int64_t)xx * (1 << 17)) - xDstInSrc)) << 13;
538 double floatd;
539 int64_t coeff;
540
541
2/2
✓ Branch 0 taken 10170321 times.
✓ Branch 1 taken 29421555 times.
39591876 if (xInc > 1 << 16)
542 10170321 d = d * dstW / srcW;
543 39591876 floatd = d * (1.0 / (1 << 30));
544
545
2/2
✓ Branch 0 taken 38902449 times.
✓ Branch 1 taken 689427 times.
39591876 if (flags & SWS_BICUBIC) {
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38902449 times.
38902449 int64_t B = (param[0] != SWS_PARAM_DEFAULT ? param[0] : 0) * (1 << 24);
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38902449 times.
38902449 int64_t C = (param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6) * (1 << 24);
548
549
2/2
✓ Branch 0 taken 7024377 times.
✓ Branch 1 taken 31878072 times.
38902449 if (d >= 1LL << 31) {
550 7024377 coeff = 0.0;
551 } else {
552 31878072 int64_t dd = (d * d) >> 30;
553 31878072 int64_t ddd = (dd * d) >> 30;
554
555
2/2
✓ Branch 0 taken 15949876 times.
✓ Branch 1 taken 15928196 times.
31878072 if (d < 1LL << 30)
556 15949876 coeff = (12 * (1 << 24) - 9 * B - 6 * C) * ddd +
557 15949876 (-18 * (1 << 24) + 12 * B + 6 * C) * dd +
558 15949876 (6 * (1 << 24) - 2 * B) * (1 << 30);
559 else
560 15928196 coeff = (-B - 6 * C) * ddd +
561 15928196 (6 * B + 30 * C) * dd +
562 15928196 (-12 * B - 48 * C) * d +
563 15928196 (8 * B + 24 * C) * (1 << 30);
564 }
565 38902449 coeff /= (1LL<<54)/fone;
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 689427 times.
689427 } else if (flags & SWS_X) {
567 double A = param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
568 double c;
569
570 if (floatd < 1.0)
571 c = cos(floatd * M_PI);
572 else
573 c = -1.0;
574 if (c < 0.0)
575 c = -pow(-c, A);
576 else
577 c = pow(c, A);
578 coeff = (c * 0.5 + 0.5) * fone;
579
2/2
✓ Branch 0 taken 288927 times.
✓ Branch 1 taken 400500 times.
689427 } else if (flags & SWS_AREA) {
580 288927 int64_t d2 = d - (1 << 29);
581
2/2
✓ Branch 0 taken 218924 times.
✓ Branch 1 taken 70003 times.
288927 if (d2 * xInc < -(1LL << (29 + 16)))
582 218924 coeff = 1.0 * (1LL << (30 + 16));
583
2/2
✓ Branch 0 taken 60908 times.
✓ Branch 1 taken 9095 times.
70003 else if (d2 * xInc < (1LL << (29 + 16)))
584 60908 coeff = -d2 * xInc + (1LL << (29 + 16));
585 else
586 9095 coeff = 0.0;
587 288927 coeff *= fone >> (30 + 16);
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400500 times.
400500 } else if (flags & SWS_GAUSS) {
589 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
590 coeff = exp2(-p * floatd * floatd) * fone;
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400500 times.
400500 } else if (flags & SWS_SINC) {
592 coeff = (d ? sin(floatd * M_PI) / (floatd * M_PI) : 1.0) * fone;
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400500 times.
400500 } else if (flags & SWS_LANCZOS) {
594 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
595 coeff = (d ? sin(floatd * M_PI) * sin(floatd * M_PI / p) /
596 (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
597 if (floatd > p)
598 coeff = 0;
599
1/2
✓ Branch 0 taken 400500 times.
✗ Branch 1 not taken.
400500 } else if (flags & SWS_BILINEAR) {
600 400500 coeff = (1 << 30) - d;
601
2/2
✓ Branch 0 taken 48380 times.
✓ Branch 1 taken 352120 times.
400500 if (coeff < 0)
602 48380 coeff = 0;
603 400500 coeff *= fone >> 30;
604 } else if (flags & SWS_SPLINE) {
605 double p = -2.196152422706632;
606 coeff = getSplineCoeff(1.0, 0.0, p, -p - 1.0, floatd) * fone;
607 } else {
608 av_assert0(0);
609 }
610
611 39591876 filter[i * filterSize + j] = coeff;
612 39591876 xx++;
613 }
614 6947128 xDstInSrc += 2LL * xInc;
615 }
616 }
617
618 /* apply src & dst Filter to filter -> filter2
619 * av_free(filter);
620 */
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 av_assert0(filterSize > 0);
622 81792 filter2Size = filterSize;
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 if (srcFilter)
624 filter2Size += srcFilter->length - 1;
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 if (dstFilter)
626 filter2Size += dstFilter->length - 1;
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 av_assert0(filter2Size > 0);
628
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81792 times.
81792 if (!FF_ALLOCZ_TYPED_ARRAY(filter2, dstW * filter2Size))
629 goto nomem;
630
2/2
✓ Branch 0 taken 31229066 times.
✓ Branch 1 taken 81792 times.
31310858 for (i = 0; i < dstW; i++) {
631 int j, k;
632
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31229066 times.
31229066 if (srcFilter) {
634 for (k = 0; k < srcFilter->length; k++) {
635 for (j = 0; j < filterSize; j++)
636 filter2[i * filter2Size + k + j] +=
637 srcFilter->coeff[k] * filter[i * filterSize + j];
638 }
639 } else {
640
2/2
✓ Branch 0 taken 64031050 times.
✓ Branch 1 taken 31229066 times.
95260116 for (j = 0; j < filterSize; j++)
641 64031050 filter2[i * filter2Size + j] = filter[i * filterSize + j];
642 }
643 // FIXME dstFilter
644
645 31229066 (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
646 }
647 81792 av_freep(&filter);
648
649 /* try to reduce the filter-size (step1 find size and shift left) */
650 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
651 81792 minFilterSize = 0;
652
2/2
✓ Branch 0 taken 31229066 times.
✓ Branch 1 taken 81792 times.
31310858 for (i = dstW - 1; i >= 0; i--) {
653 31229066 int min = filter2Size;
654 int j;
655 31229066 int64_t cutOff = 0.0;
656
657 /* get rid of near zero elements on the left by shifting left */
658
1/2
✓ Branch 0 taken 34345111 times.
✗ Branch 1 not taken.
34345111 for (j = 0; j < filter2Size; j++) {
659 int k;
660 34345111 cutOff += FFABS(filter2[i * filter2Size]);
661
662
2/2
✓ Branch 0 taken 31226245 times.
✓ Branch 1 taken 3118866 times.
34345111 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
663 31226245 break;
664
665 /* preserve monotonicity because the core can't handle the
666 * filter otherwise */
667
4/4
✓ Branch 0 taken 3106288 times.
✓ Branch 1 taken 12578 times.
✓ Branch 2 taken 2821 times.
✓ Branch 3 taken 3103467 times.
3118866 if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
668 2821 break;
669
670 // move filter coefficients left
671
2/2
✓ Branch 0 taken 13317541 times.
✓ Branch 1 taken 3116045 times.
16433586 for (k = 1; k < filter2Size; k++)
672 13317541 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
673 3116045 filter2[i * filter2Size + k - 1] = 0;
674 3116045 (*filterPos)[i]++;
675 }
676
677 31229066 cutOff = 0;
678 /* count near zeros on the right */
679
2/2
✓ Branch 0 taken 14250542 times.
✓ Branch 1 taken 24125624 times.
38376166 for (j = filter2Size - 1; j > 0; j--) {
680 14250542 cutOff += FFABS(filter2[i * filter2Size + j]);
681
682
2/2
✓ Branch 0 taken 7103442 times.
✓ Branch 1 taken 7147100 times.
14250542 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
683 7103442 break;
684 7147100 min--;
685 }
686
687
2/2
✓ Branch 0 taken 82480 times.
✓ Branch 1 taken 31146586 times.
31229066 if (min > minFilterSize)
688 82480 minFilterSize = min;
689 }
690
691 if (PPC_ALTIVEC(cpu_flags)) {
692 // we can handle the special case 4, so we don't want to go the full 8
693 if (minFilterSize < 5)
694 filterAlign = 4;
695
696 /* We really don't want to waste our time doing useless computation, so
697 * fall back on the scalar C code for very small filters.
698 * Vectorizing is worth it only if you have a decent-sized vector. */
699 if (minFilterSize < 3)
700 filterAlign = 1;
701 }
702
703
2/2
✓ Branch 0 taken 4904 times.
✓ Branch 1 taken 76888 times.
81792 if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX || have_neon(cpu_flags)) {
704 // special case for unscaled vertical filtering
705
4/4
✓ Branch 0 taken 3733 times.
✓ Branch 1 taken 1171 times.
✓ Branch 2 taken 1285 times.
✓ Branch 3 taken 2448 times.
4904 if (minFilterSize == 1 && filterAlign == 2)
706 1285 filterAlign = 1;
707 }
708
709 if (have_lasx(cpu_flags) || have_lsx(cpu_flags)) {
710 int reNum = minFilterSize & (0x07);
711
712 if (minFilterSize < 5)
713 filterAlign = 4;
714 if (reNum < 3)
715 filterAlign = 1;
716 }
717
718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 av_assert0(minFilterSize > 0);
719 81792 filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 av_assert0(filterSize > 0);
721 81792 filter = av_malloc_array(dstW, filterSize * sizeof(*filter));
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 if (!filter)
723 goto nomem;
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 if (filterSize >= MAX_FILTER_SIZE * 16 /
725
2/2
✓ Branch 0 taken 79148 times.
✓ Branch 1 taken 2644 times.
81792 ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16)) {
726 ret = RETCODE_USE_CASCADE;
727 goto fail;
728 }
729 81792 *outFilterSize = filterSize;
730
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81792 times.
81792 if (flags & SWS_PRINT_INFO)
732 av_log(NULL, AV_LOG_VERBOSE,
733 "SwScaler: reducing / aligning filtersize %d -> %d\n",
734 filter2Size, filterSize);
735 /* try to reduce the filter-size (step2 reduce it) */
736
2/2
✓ Branch 0 taken 31229066 times.
✓ Branch 1 taken 81792 times.
31310858 for (i = 0; i < dstW; i++) {
737 int j;
738
739
2/2
✓ Branch 0 taken 67115407 times.
✓ Branch 1 taken 31229066 times.
98344473 for (j = 0; j < filterSize; j++) {
740
2/2
✓ Branch 0 taken 10091970 times.
✓ Branch 1 taken 57023437 times.
67115407 if (j >= filter2Size)
741 10091970 filter[i * filterSize + j] = 0;
742 else
743 57023437 filter[i * filterSize + j] = filter2[i * filter2Size + j];
744
4/4
✓ Branch 0 taken 65602291 times.
✓ Branch 1 taken 1513116 times.
✓ Branch 2 taken 10056960 times.
✓ Branch 3 taken 55545331 times.
67115407 if ((flags & SWS_BITEXACT) && j >= minFilterSize)
745 10056960 filter[i * filterSize + j] = 0;
746 }
747 }
748
749 // FIXME try to align filterPos if possible
750
751 // fix borders
752
2/2
✓ Branch 0 taken 31229066 times.
✓ Branch 1 taken 81792 times.
31310858 for (i = 0; i < dstW; i++) {
753 int j;
754
2/2
✓ Branch 0 taken 39307 times.
✓ Branch 1 taken 31189759 times.
31229066 if ((*filterPos)[i] < 0) {
755 // move filter coefficients left to compensate for filterPos
756
2/2
✓ Branch 0 taken 184594 times.
✓ Branch 1 taken 39307 times.
223901 for (j = 1; j < filterSize; j++) {
757 184594 int left = FFMAX(j + (*filterPos)[i], 0);
758 184594 filter[i * filterSize + left] += filter[i * filterSize + j];
759 184594 filter[i * filterSize + j] = 0;
760 }
761 39307 (*filterPos)[i]= 0;
762 }
763
764
2/2
✓ Branch 0 taken 60110 times.
✓ Branch 1 taken 31168956 times.
31229066 if ((*filterPos)[i] + filterSize > srcW) {
765 60110 int shift = (*filterPos)[i] + FFMIN(filterSize - srcW, 0);
766 60110 int64_t acc = 0;
767
768
2/2
✓ Branch 0 taken 309525 times.
✓ Branch 1 taken 60110 times.
369635 for (j = filterSize - 1; j >= 0; j--) {
769
2/2
✓ Branch 0 taken 98407 times.
✓ Branch 1 taken 211118 times.
309525 if ((*filterPos)[i] + j >= srcW) {
770 98407 acc += filter[i * filterSize + j];
771 98407 filter[i * filterSize + j] = 0;
772 }
773 }
774
2/2
✓ Branch 0 taken 309525 times.
✓ Branch 1 taken 60110 times.
369635 for (j = filterSize - 1; j >= 0; j--) {
775
2/2
✓ Branch 0 taken 98407 times.
✓ Branch 1 taken 211118 times.
309525 if (j < shift) {
776 98407 filter[i * filterSize + j] = 0;
777 } else {
778 211118 filter[i * filterSize + j] = filter[i * filterSize + j - shift];
779 }
780 }
781
782 60110 (*filterPos)[i]-= shift;
783 60110 filter[i * filterSize + srcW - 1 - (*filterPos)[i]] += acc;
784 }
785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31229066 times.
31229066 av_assert0((*filterPos)[i] >= 0);
786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31229066 times.
31229066 av_assert0((*filterPos)[i] < srcW);
787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31229066 times.
31229066 if ((*filterPos)[i] + filterSize > srcW) {
788 for (j = 0; j < filterSize; j++) {
789 av_assert0((*filterPos)[i] + j < srcW || !filter[i * filterSize + j]);
790 }
791 }
792 }
793
794 // Note the +1 is for the MMX scaler which reads over the end
795 /* align at 16 for AltiVec (needed by hScale_altivec_real) */
796
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81792 times.
81792 if (!FF_ALLOCZ_TYPED_ARRAY(*outFilter, *outFilterSize * (dstW + 3)))
797 goto nomem;
798
799 /* normalize & store in outFilter */
800
2/2
✓ Branch 0 taken 31229066 times.
✓ Branch 1 taken 81792 times.
31310858 for (i = 0; i < dstW; i++) {
801 int j;
802 31229066 int64_t error = 0;
803 31229066 int64_t sum = 0;
804
805
2/2
✓ Branch 0 taken 67115407 times.
✓ Branch 1 taken 31229066 times.
98344473 for (j = 0; j < filterSize; j++) {
806 67115407 sum += filter[i * filterSize + j];
807 }
808 31229066 sum = (sum + one / 2) / one;
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31229066 times.
31229066 if (!sum) {
810 av_log(NULL, AV_LOG_WARNING, "SwScaler: zero vector in scaling\n");
811 sum = 1;
812 }
813
2/2
✓ Branch 0 taken 67115407 times.
✓ Branch 1 taken 31229066 times.
98344473 for (j = 0; j < *outFilterSize; j++) {
814 67115407 int64_t v = filter[i * filterSize + j] + error;
815
2/2
✓ Branch 0 taken 51272445 times.
✓ Branch 1 taken 15842962 times.
67115407 int intV = ROUNDED_DIV(v, sum);
816 67115407 (*outFilter)[i * (*outFilterSize) + j] = intV;
817 67115407 error = v - intV * sum;
818 }
819 }
820
821 81792 (*filterPos)[dstW + 0] =
822 81792 (*filterPos)[dstW + 1] =
823 81792 (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1]; /* the MMX/SSE scaler will
824 * read over the end */
825
2/2
✓ Branch 0 taken 181965 times.
✓ Branch 1 taken 81792 times.
263757 for (i = 0; i < *outFilterSize; i++) {
826 181965 int k = (dstW - 1) * (*outFilterSize) + i;
827 181965 (*outFilter)[k + 1 * (*outFilterSize)] =
828 181965 (*outFilter)[k + 2 * (*outFilterSize)] =
829 181965 (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
830 }
831
832 81792 ret = 0;
833 81792 goto done;
834 nomem:
835 ret = AVERROR(ENOMEM);
836 fail:
837 if(ret < 0)
838 av_log(NULL, ret == RETCODE_USE_CASCADE ? AV_LOG_DEBUG : AV_LOG_ERROR, "sws: initFilter failed\n");
839 done:
840 81792 av_free(filter);
841 81792 av_free(filter2);
842 81792 return ret;
843 }
844
845 17100 static void fill_rgb2yuv_table(SwsInternal *c, const int table[4], int dstRange)
846 {
847 int64_t W, V, Z, Cy, Cu, Cv;
848 17100 int64_t vr = table[0];
849 17100 int64_t ub = table[1];
850 17100 int64_t ug = -table[2];
851 17100 int64_t vg = -table[3];
852 17100 int64_t ONE = 65536;
853 17100 int64_t cy = ONE;
854 17100 uint8_t *p = (uint8_t*)c->input_rgb2yuv_table;
855 int i;
856 static const int8_t map[] = {
857 BY_IDX, GY_IDX, -1 , BY_IDX, BY_IDX, GY_IDX, -1 , BY_IDX,
858 RY_IDX, -1 , GY_IDX, RY_IDX, RY_IDX, -1 , GY_IDX, RY_IDX,
859 RY_IDX, GY_IDX, -1 , RY_IDX, RY_IDX, GY_IDX, -1 , RY_IDX,
860 BY_IDX, -1 , GY_IDX, BY_IDX, BY_IDX, -1 , GY_IDX, BY_IDX,
861 BU_IDX, GU_IDX, -1 , BU_IDX, BU_IDX, GU_IDX, -1 , BU_IDX,
862 RU_IDX, -1 , GU_IDX, RU_IDX, RU_IDX, -1 , GU_IDX, RU_IDX,
863 RU_IDX, GU_IDX, -1 , RU_IDX, RU_IDX, GU_IDX, -1 , RU_IDX,
864 BU_IDX, -1 , GU_IDX, BU_IDX, BU_IDX, -1 , GU_IDX, BU_IDX,
865 BV_IDX, GV_IDX, -1 , BV_IDX, BV_IDX, GV_IDX, -1 , BV_IDX,
866 RV_IDX, -1 , GV_IDX, RV_IDX, RV_IDX, -1 , GV_IDX, RV_IDX,
867 RV_IDX, GV_IDX, -1 , RV_IDX, RV_IDX, GV_IDX, -1 , RV_IDX,
868 BV_IDX, -1 , GV_IDX, BV_IDX, BV_IDX, -1 , GV_IDX, BV_IDX,
869 RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX,
870 BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX,
871 GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 ,
872 -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX,
873 RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX,
874 BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX,
875 GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 ,
876 -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX,
877 RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX,
878 BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX,
879 GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 ,
880 -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, //23
881 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //24
882 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //25
883 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //26
884 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //27
885 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //28
886 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //29
887 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //30
888 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //31
889 BY_IDX, GY_IDX, RY_IDX, -1 , -1 , -1 , -1 , -1 , //32
890 BU_IDX, GU_IDX, RU_IDX, -1 , -1 , -1 , -1 , -1 , //33
891 BV_IDX, GV_IDX, RV_IDX, -1 , -1 , -1 , -1 , -1 , //34
892 };
893
894 17100 dstRange = 0; //FIXME range = 1 is handled elsewhere
895
896
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 if (!dstRange) {
897 17100 cy = cy * 255 / 219;
898 } else {
899 vr = vr * 224 / 255;
900 ub = ub * 224 / 255;
901 ug = ug * 224 / 255;
902 vg = vg * 224 / 255;
903 }
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 W = ROUNDED_DIV(ONE*ONE*ug, ub);
905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 V = ROUNDED_DIV(ONE*ONE*vg, vr);
906 17100 Z = ONE*ONE-W-V;
907
908
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 Cy = ROUNDED_DIV(cy*Z, ONE);
909
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 Cu = ROUNDED_DIV(ub*Z, ONE);
910
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 Cv = ROUNDED_DIV(vr*Z, ONE);
911
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 c->input_rgb2yuv_table[RY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cy);
913 17100 c->input_rgb2yuv_table[GY_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cy);
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 c->input_rgb2yuv_table[BY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cy);
915
916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 c->input_rgb2yuv_table[RU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cu);
917 17100 c->input_rgb2yuv_table[GU_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cu);
918
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 c->input_rgb2yuv_table[BU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(Z+W) , Cu);
919
920
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 c->input_rgb2yuv_table[RV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(V+Z) , Cv);
921 17100 c->input_rgb2yuv_table[GV_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cv);
922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17100 times.
17100 c->input_rgb2yuv_table[BV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cv);
923
924
1/2
✓ Branch 0 taken 17100 times.
✗ Branch 1 not taken.
17100 if(/*!dstRange && */!memcmp(table, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], sizeof(ff_yuv2rgb_coeffs[SWS_CS_DEFAULT]))) {
925 17100 c->input_rgb2yuv_table[BY_IDX] = ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
926 17100 c->input_rgb2yuv_table[BV_IDX] = (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
927 17100 c->input_rgb2yuv_table[BU_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
928 17100 c->input_rgb2yuv_table[GY_IDX] = ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
929 17100 c->input_rgb2yuv_table[GV_IDX] = (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
930 17100 c->input_rgb2yuv_table[GU_IDX] = (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
931 17100 c->input_rgb2yuv_table[RY_IDX] = ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
932 17100 c->input_rgb2yuv_table[RV_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
933 17100 c->input_rgb2yuv_table[RU_IDX] = (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
934 }
935
2/2
✓ Branch 0 taken 4788000 times.
✓ Branch 1 taken 17100 times.
4805100 for(i=0; i<FF_ARRAY_ELEMS(map); i++)
936
2/2
✓ Branch 0 taken 2616300 times.
✓ Branch 1 taken 2171700 times.
4788000 AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
937 17100 }
938
939 132 static int fill_xyztables(SwsInternal *c)
940 {
941 int i;
942 132 double xyzgamma = XYZ_GAMMA;
943 132 double rgbgamma = 1.0 / RGB_GAMMA;
944 132 double xyzgammainv = 1.0 / XYZ_GAMMA;
945 132 double rgbgammainv = RGB_GAMMA;
946 static const int16_t xyz2rgb_matrix[3][4] = {
947 {13270, -6295, -2041},
948 {-3969, 7682, 170},
949 { 228, -835, 4329} };
950 static const int16_t rgb2xyz_matrix[3][4] = {
951 {1689, 1464, 739},
952 { 871, 2929, 296},
953 { 79, 488, 3891} };
954 #if !CONFIG_SMALL
955 static uint16_t xyzgamma_tab[4096], rgbgammainv_tab[4096];
956 static uint16_t rgbgamma_tab[65536], xyzgammainv_tab[65536];
957 #endif
958
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 44 times.
132 if (c->xyzgamma)
959 88 return 0;
960
961 44 memcpy(c->xyz2rgb_matrix, xyz2rgb_matrix, sizeof(c->xyz2rgb_matrix));
962 44 memcpy(c->rgb2xyz_matrix, rgb2xyz_matrix, sizeof(c->rgb2xyz_matrix));
963
964 #if CONFIG_SMALL
965 c->xyzgamma = av_malloc(sizeof(uint16_t) * 2 * (4096 + 65536));
966 if (!c->xyzgamma)
967 return AVERROR(ENOMEM);
968 c->rgbgammainv = c->xyzgamma + 4096;
969 c->rgbgamma = c->rgbgammainv + 4096;
970 c->xyzgammainv = c->rgbgamma + 65536;
971 #else
972 44 c->xyzgamma = xyzgamma_tab;
973 44 c->rgbgamma = rgbgamma_tab;
974 44 c->xyzgammainv = xyzgammainv_tab;
975 44 c->rgbgammainv = rgbgammainv_tab;
976
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 34 times.
44 if (xyzgamma_tab[4095])
977 10 return 0;
978 #endif
979
980 /* set input gamma vectors */
981
2/2
✓ Branch 0 taken 139264 times.
✓ Branch 1 taken 34 times.
139298 for (i = 0; i < 4096; i++) {
982 139264 c->xyzgamma[i] = lrint(pow(i / 4095.0, xyzgamma) * 65535.0);
983 139264 c->rgbgammainv[i] = lrint(pow(i / 4095.0, rgbgammainv) * 65535.0);
984 }
985
986 /* set output gamma vectors */
987
2/2
✓ Branch 0 taken 2228224 times.
✓ Branch 1 taken 34 times.
2228258 for (i = 0; i < 65536; i++) {
988 2228224 c->rgbgamma[i] = lrint(pow(i / 65535.0, rgbgamma) * 4095.0);
989 2228224 c->xyzgammainv[i] = lrint(pow(i / 65535.0, xyzgammainv) * 4095.0);
990 }
991 34 return 0;
992 }
993
994 17696 static int handle_jpeg(enum AVPixelFormat *format)
995 {
996
7/7
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 369 times.
✓ Branch 6 taken 17081 times.
17696 switch (*format) {
997 89 case AV_PIX_FMT_YUVJ420P:
998 89 *format = AV_PIX_FMT_YUV420P;
999 89 return 1;
1000 16 case AV_PIX_FMT_YUVJ411P:
1001 16 *format = AV_PIX_FMT_YUV411P;
1002 16 return 1;
1003 47 case AV_PIX_FMT_YUVJ422P:
1004 47 *format = AV_PIX_FMT_YUV422P;
1005 47 return 1;
1006 56 case AV_PIX_FMT_YUVJ444P:
1007 56 *format = AV_PIX_FMT_YUV444P;
1008 56 return 1;
1009 38 case AV_PIX_FMT_YUVJ440P:
1010 38 *format = AV_PIX_FMT_YUV440P;
1011 38 return 1;
1012 369 case AV_PIX_FMT_GRAY8:
1013 case AV_PIX_FMT_YA8:
1014 case AV_PIX_FMT_GRAY9LE:
1015 case AV_PIX_FMT_GRAY9BE:
1016 case AV_PIX_FMT_GRAY10LE:
1017 case AV_PIX_FMT_GRAY10BE:
1018 case AV_PIX_FMT_GRAY12LE:
1019 case AV_PIX_FMT_GRAY12BE:
1020 case AV_PIX_FMT_GRAY14LE:
1021 case AV_PIX_FMT_GRAY14BE:
1022 case AV_PIX_FMT_GRAY16LE:
1023 case AV_PIX_FMT_GRAY16BE:
1024 case AV_PIX_FMT_YA16BE:
1025 case AV_PIX_FMT_YA16LE:
1026 369 return 1;
1027 17081 default:
1028 17081 return 0;
1029 }
1030 }
1031
1032 146348 static int handle_0alpha(enum AVPixelFormat *format)
1033 {
1034
5/5
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 146240 times.
146348 switch (*format) {
1035 19 case AV_PIX_FMT_0BGR : *format = AV_PIX_FMT_ABGR ; return 1;
1036 51 case AV_PIX_FMT_BGR0 : *format = AV_PIX_FMT_BGRA ; return 4;
1037 19 case AV_PIX_FMT_0RGB : *format = AV_PIX_FMT_ARGB ; return 1;
1038 19 case AV_PIX_FMT_RGB0 : *format = AV_PIX_FMT_RGBA ; return 4;
1039 146240 default: return 0;
1040 }
1041 }
1042
1043 146348 static int handle_xyz(enum AVPixelFormat *format)
1044 {
1045
3/3
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 146302 times.
146348 switch (*format) {
1046 14 case AV_PIX_FMT_XYZ12BE : *format = AV_PIX_FMT_RGB48BE; return 1;
1047 32 case AV_PIX_FMT_XYZ12LE : *format = AV_PIX_FMT_RGB48LE; return 1;
1048 146302 default: return 0;
1049 }
1050 }
1051
1052 73174 static int handle_formats(SwsContext *sws)
1053 {
1054 73174 SwsInternal *c = sws_internal(sws);
1055 73174 c->src0Alpha |= handle_0alpha(&sws->src_format);
1056 73174 c->dst0Alpha |= handle_0alpha(&sws->dst_format);
1057 73174 c->srcXYZ |= handle_xyz(&sws->src_format);
1058 73174 c->dstXYZ |= handle_xyz(&sws->dst_format);
1059
4/4
✓ Branch 0 taken 73141 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 73042 times.
73174 if (c->srcXYZ || c->dstXYZ)
1060 132 return fill_xyztables(c);
1061 else
1062 73042 return 0;
1063 }
1064
1065 106356 static int range_override_needed(enum AVPixelFormat format)
1066 {
1067
4/4
✓ Branch 1 taken 44418 times.
✓ Branch 2 taken 61938 times.
✓ Branch 4 taken 40989 times.
✓ Branch 5 taken 3429 times.
106356 return !isYUV(format) && !isGray(format);
1068 }
1069
1070 47670 int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4],
1071 int srcRange, const int table[4], int dstRange,
1072 int brightness, int contrast, int saturation)
1073 {
1074 47670 SwsInternal *c = sws_internal(sws);
1075 const AVPixFmtDescriptor *desc_dst;
1076 const AVPixFmtDescriptor *desc_src;
1077 47670 int ret, need_reinit = 0;
1078
1079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47670 times.
47670 if (c->nb_slice_ctx) {
1080 int parent_ret = 0;
1081 for (int i = 0; i < c->nb_slice_ctx; i++) {
1082 int ret = sws_setColorspaceDetails(c->slice_ctx[i], inv_table,
1083 srcRange, table, dstRange,
1084 brightness, contrast, saturation);
1085 if (ret < 0)
1086 parent_ret = ret;
1087 }
1088
1089 return parent_ret;
1090 }
1091
1092 47670 ret = handle_formats(sws);
1093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47670 times.
47670 if (ret < 0)
1094 return ret;
1095 47670 desc_dst = av_pix_fmt_desc_get(sws->dst_format);
1096 47670 desc_src = av_pix_fmt_desc_get(sws->src_format);
1097
1098
2/2
✓ Branch 1 taken 21675 times.
✓ Branch 2 taken 25995 times.
47670 if(range_override_needed(sws->dst_format))
1099 21675 dstRange = 0;
1100
2/2
✓ Branch 1 taken 16402 times.
✓ Branch 2 taken 31268 times.
47670 if(range_override_needed(sws->src_format))
1101 16402 srcRange = 0;
1102
1103
2/2
✓ Branch 0 taken 46676 times.
✓ Branch 1 taken 994 times.
47670 if (sws->src_range != srcRange ||
1104
2/2
✓ Branch 0 taken 45178 times.
✓ Branch 1 taken 1498 times.
46676 sws->dst_range != dstRange ||
1105
1/2
✓ Branch 0 taken 45178 times.
✗ Branch 1 not taken.
45178 c->brightness != brightness ||
1106
2/2
✓ Branch 0 taken 22166 times.
✓ Branch 1 taken 23012 times.
45178 c->contrast != contrast ||
1107
1/2
✓ Branch 0 taken 22166 times.
✗ Branch 1 not taken.
22166 c->saturation != saturation ||
1108
2/2
✓ Branch 0 taken 22024 times.
✓ Branch 1 taken 142 times.
22166 memcmp(c->srcColorspaceTable, inv_table, sizeof(int) * 4) ||
1109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22024 times.
22024 memcmp(c->dstColorspaceTable, table, sizeof(int) * 4)
1110 )
1111 25646 need_reinit = 1;
1112
1113 47670 memmove(c->srcColorspaceTable, inv_table, sizeof(int) * 4);
1114 47670 memmove(c->dstColorspaceTable, table, sizeof(int) * 4);
1115
1116
1117
1118 47670 c->brightness = brightness;
1119 47670 c->contrast = contrast;
1120 47670 c->saturation = saturation;
1121 47670 sws->src_range = srcRange;
1122 47670 sws->dst_range = dstRange;
1123
1124
2/2
✓ Branch 0 taken 25646 times.
✓ Branch 1 taken 22024 times.
47670 if (need_reinit)
1125 25646 ff_sws_init_range_convert(c);
1126
1127 47670 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
1128 47670 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
1129
1130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47670 times.
47670 if (c->cascaded_context[c->cascaded_mainindex])
1131 return sws_setColorspaceDetails(c->cascaded_context[c->cascaded_mainindex],inv_table, srcRange,table, dstRange, brightness, contrast, saturation);
1132
1133
2/2
✓ Branch 0 taken 22024 times.
✓ Branch 1 taken 25646 times.
47670 if (!need_reinit)
1134 22024 return 0;
1135
1136
8/8
✓ Branch 1 taken 13227 times.
✓ Branch 2 taken 12419 times.
✓ Branch 4 taken 869 times.
✓ Branch 5 taken 12358 times.
✓ Branch 7 taken 4999 times.
✓ Branch 8 taken 8289 times.
✓ Branch 10 taken 257 times.
✓ Branch 11 taken 4742 times.
25646 if ((isYUV(sws->dst_format) || isGray(sws->dst_format)) && (isYUV(sws->src_format) || isGray(sws->src_format))) {
1137
1/2
✓ Branch 0 taken 8546 times.
✗ Branch 1 not taken.
8546 if (!c->cascaded_context[0] &&
1138
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8545 times.
8546 memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4) &&
1139
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 sws->src_w && sws->src_h && sws->dst_w && sws->dst_h) {
1140 enum AVPixelFormat tmp_format;
1141 int tmp_width, tmp_height;
1142 1 int srcW = sws->src_w;
1143 1 int srcH = sws->src_h;
1144 1 int dstW = sws->dst_w;
1145 1 int dstH = sws->dst_h;
1146 int ret;
1147 1 av_log(c, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n");
1148
1149
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (isNBPS(sws->dst_format) || is16BPS(sws->dst_format)) {
1150 if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) {
1151 tmp_format = AV_PIX_FMT_BGRA64;
1152 } else {
1153 tmp_format = AV_PIX_FMT_BGR48;
1154 }
1155 } else {
1156
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) {
1157 tmp_format = AV_PIX_FMT_BGRA;
1158 } else {
1159 1 tmp_format = AV_PIX_FMT_BGR24;
1160 }
1161 }
1162
1163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (srcW*srcH > dstW*dstH) {
1164 tmp_width = dstW;
1165 tmp_height = dstH;
1166 } else {
1167 1 tmp_width = srcW;
1168 1 tmp_height = srcH;
1169 }
1170
1171 1 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
1172 tmp_width, tmp_height, tmp_format, 64);
1173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1174 return ret;
1175
1176 2 c->cascaded_context[0] = alloc_set_opts(srcW, srcH, sws->src_format,
1177 tmp_width, tmp_height, tmp_format,
1178 1 sws->flags, sws->scaler_params);
1179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!c->cascaded_context[0])
1180 return -1;
1181
1182 1 c->cascaded_context[0]->alpha_blend = sws->alpha_blend;
1183 1 ret = sws_init_context(c->cascaded_context[0], NULL , NULL);
1184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1185 return ret;
1186 //we set both src and dst depending on that the RGB side will be ignored
1187 1 sws_setColorspaceDetails(c->cascaded_context[0], inv_table,
1188 srcRange, table, dstRange,
1189 brightness, contrast, saturation);
1190
1191 2 c->cascaded_context[1] = alloc_set_opts(tmp_width, tmp_height, tmp_format,
1192 1 dstW, dstH, sws->dst_format,
1193 1 sws->flags, sws->scaler_params);
1194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!c->cascaded_context[1])
1195 return -1;
1196 1 c->cascaded_context[1]->src_range = srcRange;
1197 1 c->cascaded_context[1]->dst_range = dstRange;
1198 1 ret = sws_init_context(c->cascaded_context[1], NULL , NULL);
1199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1200 return ret;
1201 1 sws_setColorspaceDetails(c->cascaded_context[1], inv_table,
1202 srcRange, table, dstRange,
1203 0, 1 << 16, 1 << 16);
1204 1 return 0;
1205 }
1206 //We do not support this combination currently, we need to cascade more contexts to compensate
1207
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8545 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8545 if (c->cascaded_context[0] && memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4))
1208 return -1; //AVERROR_PATCHWELCOME;
1209 8545 return 0;
1210 }
1211
1212
4/4
✓ Branch 1 taken 12778 times.
✓ Branch 2 taken 4322 times.
✓ Branch 4 taken 12358 times.
✓ Branch 5 taken 420 times.
17100 if (!isYUV(sws->dst_format) && !isGray(sws->dst_format)) {
1213 12358 ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
1214 contrast, saturation);
1215 // FIXME factorize
1216
1217 #if ARCH_PPC
1218 ff_yuv2rgb_init_tables_ppc(c, inv_table, brightness,
1219 contrast, saturation);
1220 #endif
1221 }
1222
1223 17100 fill_rgb2yuv_table(c, table, dstRange);
1224
1225 17100 return 0;
1226 }
1227
1228 5508 int sws_getColorspaceDetails(SwsContext *sws, int **inv_table,
1229 int *srcRange, int **table, int *dstRange,
1230 int *brightness, int *contrast, int *saturation)
1231 {
1232 5508 SwsInternal *c = sws_internal(sws);
1233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 if (!c)
1234 return -1;
1235
1236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 if (c->nb_slice_ctx) {
1237 return sws_getColorspaceDetails(c->slice_ctx[0], inv_table, srcRange,
1238 table, dstRange, brightness, contrast,
1239 saturation);
1240 }
1241
1242 5508 *inv_table = c->srcColorspaceTable;
1243 5508 *table = c->dstColorspaceTable;
1244
2/2
✓ Branch 1 taken 4514 times.
✓ Branch 2 taken 994 times.
5508 *srcRange = range_override_needed(sws->src_format) ? 1 : sws->src_range;
1245
2/2
✓ Branch 1 taken 3590 times.
✓ Branch 2 taken 1918 times.
5508 *dstRange = range_override_needed(sws->dst_format) ? 1 : sws->dst_range;
1246 5508 *brightness = c->brightness;
1247 5508 *contrast = c->contrast;
1248 5508 *saturation = c->saturation;
1249
1250 5508 return 0;
1251 }
1252
1253 35410 SwsContext *sws_alloc_context(void)
1254 {
1255 35410 SwsInternal *c = (SwsInternal *) av_mallocz(sizeof(SwsInternal));
1256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35410 times.
35410 if (!c)
1257 return NULL;
1258
1259 35410 c->opts.av_class = &ff_sws_context_class;
1260 35410 av_opt_set_defaults(c);
1261 35410 atomic_init(&c->stride_unaligned_warned, 0);
1262 35410 atomic_init(&c->data_unaligned_warned, 0);
1263
1264 35410 return &c->opts;
1265 }
1266
1267 static uint16_t * alloc_gamma_tbl(double e)
1268 {
1269 int i = 0;
1270 uint16_t * tbl;
1271 tbl = (uint16_t*)av_malloc(sizeof(uint16_t) * 1 << 16);
1272 if (!tbl)
1273 return NULL;
1274
1275 for (i = 0; i < 65536; ++i) {
1276 tbl[i] = pow(i / 65535.0, e) * 65535.0;
1277 }
1278 return tbl;
1279 }
1280
1281 1455 static enum AVPixelFormat alphaless_fmt(enum AVPixelFormat fmt)
1282 {
1283
19/42
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 190 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 364 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 51 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 10 times.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 20 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 10 times.
✓ Branch 40 taken 4 times.
✓ Branch 41 taken 742 times.
1455 switch(fmt) {
1284 12 case AV_PIX_FMT_ARGB: return AV_PIX_FMT_RGB24;
1285 12 case AV_PIX_FMT_RGBA: return AV_PIX_FMT_RGB24;
1286 2 case AV_PIX_FMT_ABGR: return AV_PIX_FMT_BGR24;
1287 190 case AV_PIX_FMT_BGRA: return AV_PIX_FMT_BGR24;
1288 20 case AV_PIX_FMT_YA8: return AV_PIX_FMT_GRAY8;
1289
1290 364 case AV_PIX_FMT_YUVA420P: return AV_PIX_FMT_YUV420P;
1291 3 case AV_PIX_FMT_YUVA422P: return AV_PIX_FMT_YUV422P;
1292 case AV_PIX_FMT_YUVA444P: return AV_PIX_FMT_YUV444P;
1293
1294 51 case AV_PIX_FMT_GBRAP: return AV_PIX_FMT_GBRP;
1295
1296 1 case AV_PIX_FMT_GBRAP10LE: return AV_PIX_FMT_GBRP10;
1297 case AV_PIX_FMT_GBRAP10BE: return AV_PIX_FMT_GBRP10;
1298
1299 1 case AV_PIX_FMT_GBRAP12LE: return AV_PIX_FMT_GBRP12;
1300 case AV_PIX_FMT_GBRAP12BE: return AV_PIX_FMT_GBRP12;
1301
1302 case AV_PIX_FMT_GBRAP14LE: return AV_PIX_FMT_GBRP14;
1303 case AV_PIX_FMT_GBRAP14BE: return AV_PIX_FMT_GBRP14;
1304
1305 1 case AV_PIX_FMT_GBRAP16LE: return AV_PIX_FMT_GBRP16;
1306 10 case AV_PIX_FMT_GBRAP16BE: return AV_PIX_FMT_GBRP16;
1307
1308 1 case AV_PIX_FMT_RGBA64LE: return AV_PIX_FMT_RGB48;
1309 10 case AV_PIX_FMT_RGBA64BE: return AV_PIX_FMT_RGB48;
1310 1 case AV_PIX_FMT_BGRA64LE: return AV_PIX_FMT_BGR48;
1311 case AV_PIX_FMT_BGRA64BE: return AV_PIX_FMT_BGR48;
1312
1313 20 case AV_PIX_FMT_YA16BE: return AV_PIX_FMT_GRAY16;
1314 case AV_PIX_FMT_YA16LE: return AV_PIX_FMT_GRAY16;
1315
1316 case AV_PIX_FMT_YUVA420P9BE: return AV_PIX_FMT_YUV420P9;
1317 case AV_PIX_FMT_YUVA422P9BE: return AV_PIX_FMT_YUV422P9;
1318 case AV_PIX_FMT_YUVA444P9BE: return AV_PIX_FMT_YUV444P9;
1319 case AV_PIX_FMT_YUVA420P9LE: return AV_PIX_FMT_YUV420P9;
1320 case AV_PIX_FMT_YUVA422P9LE: return AV_PIX_FMT_YUV422P9;
1321 case AV_PIX_FMT_YUVA444P9LE: return AV_PIX_FMT_YUV444P9;
1322 case AV_PIX_FMT_YUVA420P10BE: return AV_PIX_FMT_YUV420P10;
1323 case AV_PIX_FMT_YUVA422P10BE: return AV_PIX_FMT_YUV422P10;
1324 case AV_PIX_FMT_YUVA444P10BE: return AV_PIX_FMT_YUV444P10;
1325 case AV_PIX_FMT_YUVA420P10LE: return AV_PIX_FMT_YUV420P10;
1326 case AV_PIX_FMT_YUVA422P10LE: return AV_PIX_FMT_YUV422P10;
1327 case AV_PIX_FMT_YUVA444P10LE: return AV_PIX_FMT_YUV444P10;
1328 case AV_PIX_FMT_YUVA420P16BE: return AV_PIX_FMT_YUV420P16;
1329 case AV_PIX_FMT_YUVA422P16BE: return AV_PIX_FMT_YUV422P16;
1330 case AV_PIX_FMT_YUVA444P16BE: return AV_PIX_FMT_YUV444P16;
1331 case AV_PIX_FMT_YUVA420P16LE: return AV_PIX_FMT_YUV420P16;
1332 10 case AV_PIX_FMT_YUVA422P16LE: return AV_PIX_FMT_YUV422P16;
1333 4 case AV_PIX_FMT_YUVA444P16LE: return AV_PIX_FMT_YUV444P16;
1334
1335 // case AV_PIX_FMT_AYUV64LE:
1336 // case AV_PIX_FMT_AYUV64BE:
1337 // case AV_PIX_FMT_PAL8:
1338 742 default: return AV_PIX_FMT_NONE;
1339 }
1340 }
1341
1342 25504 av_cold int ff_sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter,
1343 SwsFilter *dstFilter)
1344 {
1345 int i;
1346 int usesVFilter, usesHFilter;
1347 int unscaled;
1348 25504 SwsInternal *c = sws_internal(sws);
1349 25504 SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
1350 25504 int srcW = sws->src_w;
1351 25504 int srcH = sws->src_h;
1352 25504 int dstW = sws->dst_w;
1353 25504 int dstH = sws->dst_h;
1354 25504 int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 66, 16);
1355 int flags, cpu_flags;
1356 enum AVPixelFormat srcFormat, dstFormat;
1357 const AVPixFmtDescriptor *desc_src;
1358 const AVPixFmtDescriptor *desc_dst;
1359 25504 int ret = 0;
1360 enum AVPixelFormat tmpFmt;
1361 static const float float_mult = 1.0f / 255.0f;
1362
1363 25504 cpu_flags = av_get_cpu_flags();
1364 25504 flags = sws->flags;
1365 25504 emms_c();
1366
1367
4/4
✓ Branch 0 taken 24635 times.
✓ Branch 1 taken 869 times.
✓ Branch 2 taken 24536 times.
✓ Branch 3 taken 99 times.
25504 unscaled = (srcW == dstW && srcH == dstH);
1368
1369
3/6
✓ Branch 0 taken 25504 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25504 times.
✗ Branch 5 not taken.
25504 if (!c->contrast && !c->saturation && !c->dstFormatBpp)
1370 25504 sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], sws->src_range,
1371 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
1372 sws->dst_range, 0, 1 << 16, 1 << 16);
1373
1374 25504 ret = handle_formats(sws);
1375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
25504 if (ret < 0)
1376 return ret;
1377 25504 srcFormat = sws->src_format;
1378 25504 dstFormat = sws->dst_format;
1379 25504 desc_src = av_pix_fmt_desc_get(srcFormat);
1380 25504 desc_dst = av_pix_fmt_desc_get(dstFormat);
1381
1382 // If the source has no alpha then disable alpha blendaway
1383
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 25474 times.
25504 if (c->src0Alpha)
1384 30 sws->alpha_blend = SWS_ALPHA_BLEND_NONE;
1385
1386
5/6
✓ Branch 0 taken 24536 times.
✓ Branch 1 taken 968 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 24523 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
25517 if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) &&
1387 13 av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) {
1388
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
25504 if (!sws_isSupportedInput(srcFormat)) {
1389 av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
1390 av_get_pix_fmt_name(srcFormat));
1391 return AVERROR(EINVAL);
1392 }
1393
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
25504 if (!sws_isSupportedOutput(dstFormat)) {
1394 av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
1395 av_get_pix_fmt_name(dstFormat));
1396 return AVERROR(EINVAL);
1397 }
1398 }
1399 av_assert2(desc_src && desc_dst);
1400
1401 25504 i = flags & (SWS_POINT |
1402 SWS_AREA |
1403 SWS_BILINEAR |
1404 SWS_FAST_BILINEAR |
1405 SWS_BICUBIC |
1406 SWS_X |
1407 SWS_GAUSS |
1408 SWS_LANCZOS |
1409 SWS_SINC |
1410 SWS_SPLINE |
1411 SWS_BICUBLIN);
1412
1413 /* provide a default scaler if not set by caller */
1414
2/2
✓ Branch 0 taken 3084 times.
✓ Branch 1 taken 22420 times.
25504 if (!i) {
1415
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3082 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3084 if (dstW < srcW && dstH < srcH)
1416 flags |= SWS_BICUBIC;
1417
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3084 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3084 else if (dstW > srcW && dstH > srcH)
1418 flags |= SWS_BICUBIC;
1419 else
1420 3084 flags |= SWS_BICUBIC;
1421 3084 sws->flags = flags;
1422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22420 times.
22420 } else if (i & (i - 1)) {
1423 av_log(c, AV_LOG_ERROR,
1424 "Exactly one scaler algorithm must be chosen, got %X\n", i);
1425 return AVERROR(EINVAL);
1426 }
1427 /* sanity check */
1428
4/8
✓ Branch 0 taken 25504 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25504 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 25504 times.
25504 if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
1429 /* FIXME check if these are enough and try to lower them after
1430 * fixing the relevant parts of the code */
1431 av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
1432 srcW, srcH, dstW, dstH);
1433 return AVERROR(EINVAL);
1434 }
1435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
25504 if (flags & SWS_FAST_BILINEAR) {
1436 if (srcW < 8 || dstW < 8) {
1437 flags ^= SWS_FAST_BILINEAR | SWS_BILINEAR;
1438 sws->flags = flags;
1439 }
1440 }
1441
1442
1/2
✓ Branch 0 taken 25504 times.
✗ Branch 1 not taken.
25504 if (!dstFilter)
1443 25504 dstFilter = &dummyFilter;
1444
1/2
✓ Branch 0 taken 25504 times.
✗ Branch 1 not taken.
25504 if (!srcFilter)
1445 25504 srcFilter = &dummyFilter;
1446
1447 25504 c->lumXInc = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
1448 25504 c->lumYInc = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
1449 25504 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
1450 25504 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
1451 25504 c->vRounder = 4 * 0x0001000100010001ULL;
1452
1453 usesVFilter = (srcFilter->lumV && srcFilter->lumV->length > 1) ||
1454
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25504 (srcFilter->chrV && srcFilter->chrV->length > 1) ||
1455
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25504 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
76512 (dstFilter->lumV && dstFilter->lumV->length > 1) ||
1456
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25504 (dstFilter->chrV && dstFilter->chrV->length > 1);
1457 usesHFilter = (srcFilter->lumH && srcFilter->lumH->length > 1) ||
1458
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25504 (srcFilter->chrH && srcFilter->chrH->length > 1) ||
1459
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25504 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
76512 (dstFilter->lumH && dstFilter->lumH->length > 1) ||
1460
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25504 (dstFilter->chrH && dstFilter->chrH->length > 1);
1461
1462 25504 av_pix_fmt_get_chroma_sub_sample(srcFormat, &c->chrSrcHSubSample, &c->chrSrcVSubSample);
1463 25504 av_pix_fmt_get_chroma_sub_sample(dstFormat, &c->chrDstHSubSample, &c->chrDstVSubSample);
1464
1465 25504 c->dst_slice_align = 1 << c->chrDstVSubSample;
1466
1467
4/4
✓ Branch 1 taken 12347 times.
✓ Branch 2 taken 13157 times.
✓ Branch 3 taken 6213 times.
✓ Branch 4 taken 6134 times.
25504 if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
1468
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 6176 times.
6213 if (dstW&1) {
1469 37 av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
1470 37 flags |= SWS_FULL_CHR_H_INT;
1471 37 sws->flags = flags;
1472 }
1473
1474
2/2
✓ Branch 0 taken 1126 times.
✓ Branch 1 taken 5087 times.
6213 if ( c->chrSrcHSubSample == 0
1475
2/2
✓ Branch 0 taken 988 times.
✓ Branch 1 taken 138 times.
1126 && c->chrSrcVSubSample == 0
1476
1/2
✓ Branch 0 taken 988 times.
✗ Branch 1 not taken.
988 && sws->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER
1477
1/2
✓ Branch 0 taken 988 times.
✗ Branch 1 not taken.
988 && !(sws->flags & SWS_FAST_BILINEAR)
1478 ) {
1479 988 av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n");
1480 988 flags |= SWS_FULL_CHR_H_INT;
1481 988 sws->flags = flags;
1482 }
1483 }
1484
1485
2/2
✓ Branch 0 taken 17914 times.
✓ Branch 1 taken 7590 times.
25504 if (sws->dither == SWS_DITHER_AUTO) {
1486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17914 times.
17914 if (flags & SWS_ERROR_DIFFUSION)
1487 sws->dither = SWS_DITHER_ED;
1488 }
1489
1490
4/4
✓ Branch 0 taken 25451 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 25397 times.
✓ Branch 3 taken 54 times.
25504 if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
1491
2/2
✓ Branch 0 taken 25327 times.
✓ Branch 1 taken 70 times.
25397 dstFormat == AV_PIX_FMT_RGB4_BYTE ||
1492
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 25271 times.
25327 dstFormat == AV_PIX_FMT_BGR8 ||
1493 dstFormat == AV_PIX_FMT_RGB8) {
1494
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 if (sws->dither == SWS_DITHER_AUTO)
1495
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 222 times.
233 sws->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER;
1496
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 11 times.
233 if (!(flags & SWS_FULL_CHR_H_INT)) {
1497
4/8
✓ Branch 0 taken 222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 222 times.
222 if (sws->dither == SWS_DITHER_ED || sws->dither == SWS_DITHER_A_DITHER || sws->dither == SWS_DITHER_X_DITHER || sws->dither == SWS_DITHER_NONE) {
1498 av_log(c, AV_LOG_DEBUG,
1499 "Desired dithering only supported in full chroma interpolation for destination format '%s'\n",
1500 av_get_pix_fmt_name(dstFormat));
1501 flags |= SWS_FULL_CHR_H_INT;
1502 sws->flags = flags;
1503 }
1504 }
1505
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 222 times.
233 if (flags & SWS_FULL_CHR_H_INT) {
1506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (sws->dither == SWS_DITHER_BAYER) {
1507 av_log(c, AV_LOG_DEBUG,
1508 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
1509 av_get_pix_fmt_name(dstFormat));
1510 sws->dither = SWS_DITHER_ED;
1511 }
1512 }
1513 }
1514
2/2
✓ Branch 1 taken 4234 times.
✓ Branch 2 taken 21270 times.
25504 if (isPlanarRGB(dstFormat)) {
1515
2/2
✓ Branch 0 taken 641 times.
✓ Branch 1 taken 3593 times.
4234 if (!(flags & SWS_FULL_CHR_H_INT)) {
1516 641 av_log(c, AV_LOG_DEBUG,
1517 "%s output is not supported with half chroma resolution, switching to full\n",
1518 av_get_pix_fmt_name(dstFormat));
1519 641 flags |= SWS_FULL_CHR_H_INT;
1520 641 sws->flags = flags;
1521 }
1522 }
1523
1524 /* reuse chroma for 2 pixels RGB/BGR unless user wants full
1525 * chroma interpolation */
1526
3/4
✓ Branch 0 taken 7767 times.
✓ Branch 1 taken 17737 times.
✓ Branch 2 taken 7767 times.
✗ Branch 3 not taken.
33271 if (flags & SWS_FULL_CHR_H_INT &&
1527
2/2
✓ Branch 1 taken 3533 times.
✓ Branch 2 taken 4234 times.
15534 isAnyRGB(dstFormat) &&
1528
2/2
✓ Branch 1 taken 3531 times.
✓ Branch 2 taken 2 times.
11300 !isPlanarRGB(dstFormat) &&
1529
2/2
✓ Branch 0 taken 3530 times.
✓ Branch 1 taken 1 times.
3531 dstFormat != AV_PIX_FMT_RGBA64LE &&
1530
2/2
✓ Branch 0 taken 3528 times.
✓ Branch 1 taken 2 times.
3530 dstFormat != AV_PIX_FMT_RGBA64BE &&
1531
2/2
✓ Branch 0 taken 3527 times.
✓ Branch 1 taken 1 times.
3528 dstFormat != AV_PIX_FMT_BGRA64LE &&
1532
2/2
✓ Branch 0 taken 2883 times.
✓ Branch 1 taken 644 times.
3527 dstFormat != AV_PIX_FMT_BGRA64BE &&
1533
2/2
✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 3 times.
2883 dstFormat != AV_PIX_FMT_RGB48LE &&
1534
2/2
✓ Branch 0 taken 2878 times.
✓ Branch 1 taken 2 times.
2880 dstFormat != AV_PIX_FMT_RGB48BE &&
1535
2/2
✓ Branch 0 taken 2877 times.
✓ Branch 1 taken 1 times.
2878 dstFormat != AV_PIX_FMT_BGR48LE &&
1536
2/2
✓ Branch 0 taken 2824 times.
✓ Branch 1 taken 53 times.
2877 dstFormat != AV_PIX_FMT_BGR48BE &&
1537
2/2
✓ Branch 0 taken 2810 times.
✓ Branch 1 taken 14 times.
2824 dstFormat != AV_PIX_FMT_RGBA &&
1538
2/2
✓ Branch 0 taken 2300 times.
✓ Branch 1 taken 510 times.
2810 dstFormat != AV_PIX_FMT_ARGB &&
1539
2/2
✓ Branch 0 taken 2296 times.
✓ Branch 1 taken 4 times.
2300 dstFormat != AV_PIX_FMT_BGRA &&
1540
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 1679 times.
2296 dstFormat != AV_PIX_FMT_ABGR &&
1541
2/2
✓ Branch 0 taken 507 times.
✓ Branch 1 taken 110 times.
617 dstFormat != AV_PIX_FMT_RGB24 &&
1542
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 2 times.
507 dstFormat != AV_PIX_FMT_BGR24 &&
1543
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 2 times.
505 dstFormat != AV_PIX_FMT_BGR4_BYTE &&
1544
2/2
✓ Branch 0 taken 499 times.
✓ Branch 1 taken 4 times.
503 dstFormat != AV_PIX_FMT_RGB4_BYTE &&
1545
2/2
✓ Branch 0 taken 496 times.
✓ Branch 1 taken 3 times.
499 dstFormat != AV_PIX_FMT_BGR8 &&
1546
2/2
✓ Branch 0 taken 415 times.
✓ Branch 1 taken 81 times.
496 dstFormat != AV_PIX_FMT_RGB8 &&
1547
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 81 times.
415 dstFormat != AV_PIX_FMT_X2RGB10LE &&
1548 dstFormat != AV_PIX_FMT_X2BGR10LE
1549 ) {
1550 334 av_log(c, AV_LOG_WARNING,
1551 "full chroma interpolation for destination format '%s' not yet implemented\n",
1552 av_get_pix_fmt_name(dstFormat));
1553 334 flags &= ~SWS_FULL_CHR_H_INT;
1554 334 sws->flags = flags;
1555 }
1556
4/4
✓ Branch 1 taken 12347 times.
✓ Branch 2 taken 13157 times.
✓ Branch 3 taken 4914 times.
✓ Branch 4 taken 7433 times.
25504 if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
1557 4914 c->chrDstHSubSample = 1;
1558
1559 // drop some chroma lines if the user wants it
1560 25504 c->vChrDrop = (flags & SWS_SRC_V_CHR_DROP_MASK) >>
1561 SWS_SRC_V_CHR_DROP_SHIFT;
1562 25504 c->chrSrcVSubSample += c->vChrDrop;
1563
1564 /* drop every other pixel for chroma calculation unless user
1565 * wants full chroma */
1566
7/8
✓ Branch 1 taken 7408 times.
✓ Branch 2 taken 18096 times.
✓ Branch 3 taken 7174 times.
✓ Branch 4 taken 234 times.
✓ Branch 5 taken 7174 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7173 times.
✓ Branch 8 taken 1 times.
25504 if (isAnyRGB(srcFormat) && !(srcW & 1) && !(flags & SWS_FULL_CHR_H_INP) &&
1567
3/4
✓ Branch 0 taken 7172 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7172 times.
✗ Branch 3 not taken.
7173 srcFormat != AV_PIX_FMT_RGB8 && srcFormat != AV_PIX_FMT_BGR8 &&
1568
3/4
✓ Branch 0 taken 7172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7171 times.
✓ Branch 3 taken 1 times.
7172 srcFormat != AV_PIX_FMT_RGB4 && srcFormat != AV_PIX_FMT_BGR4 &&
1569
4/4
✓ Branch 0 taken 7170 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7169 times.
✓ Branch 3 taken 1 times.
7171 srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
1570
4/4
✓ Branch 0 taken 7167 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7086 times.
✓ Branch 3 taken 81 times.
7169 srcFormat != AV_PIX_FMT_GBRP9BE && srcFormat != AV_PIX_FMT_GBRP9LE &&
1571
4/4
✓ Branch 0 taken 6099 times.
✓ Branch 1 taken 987 times.
✓ Branch 2 taken 6098 times.
✓ Branch 3 taken 1 times.
7086 srcFormat != AV_PIX_FMT_GBRP10BE && srcFormat != AV_PIX_FMT_GBRP10LE &&
1572
4/4
✓ Branch 0 taken 6096 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6015 times.
✓ Branch 3 taken 81 times.
6098 srcFormat != AV_PIX_FMT_GBRAP10BE && srcFormat != AV_PIX_FMT_GBRAP10LE &&
1573
4/4
✓ Branch 0 taken 5043 times.
✓ Branch 1 taken 972 times.
✓ Branch 2 taken 5042 times.
✓ Branch 3 taken 1 times.
6015 srcFormat != AV_PIX_FMT_GBRP12BE && srcFormat != AV_PIX_FMT_GBRP12LE &&
1574
4/4
✓ Branch 0 taken 5040 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5039 times.
✓ Branch 3 taken 1 times.
5042 srcFormat != AV_PIX_FMT_GBRAP12BE && srcFormat != AV_PIX_FMT_GBRAP12LE &&
1575
4/4
✓ Branch 0 taken 5038 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5037 times.
✓ Branch 3 taken 1 times.
5039 srcFormat != AV_PIX_FMT_GBRAP14BE && srcFormat != AV_PIX_FMT_GBRAP14LE &&
1576
4/4
✓ Branch 0 taken 5035 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4924 times.
✓ Branch 3 taken 111 times.
5037 srcFormat != AV_PIX_FMT_GBRP14BE && srcFormat != AV_PIX_FMT_GBRP14LE &&
1577
4/4
✓ Branch 0 taken 4636 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 4625 times.
✓ Branch 3 taken 11 times.
4924 srcFormat != AV_PIX_FMT_GBRP16BE && srcFormat != AV_PIX_FMT_GBRP16LE &&
1578
4/4
✓ Branch 0 taken 4621 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4620 times.
✓ Branch 3 taken 1 times.
4625 srcFormat != AV_PIX_FMT_GBRAP16BE && srcFormat != AV_PIX_FMT_GBRAP16LE &&
1579
4/4
✓ Branch 0 taken 4588 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 4587 times.
✓ Branch 3 taken 1 times.
4620 srcFormat != AV_PIX_FMT_GBRPF32BE && srcFormat != AV_PIX_FMT_GBRPF32LE &&
1580
2/2
✓ Branch 0 taken 4586 times.
✓ Branch 1 taken 1 times.
4587 srcFormat != AV_PIX_FMT_GBRAPF32BE && srcFormat != AV_PIX_FMT_GBRAPF32LE &&
1581
2/2
✓ Branch 0 taken 3092 times.
✓ Branch 1 taken 1494 times.
4586 ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||
1582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3092 times.
3092 (flags & SWS_FAST_BILINEAR)))
1583 1494 c->chrSrcHSubSample = 1;
1584
1585 // Note the AV_CEIL_RSHIFT is so that we always round toward +inf.
1586 25504 c->chrSrcW = AV_CEIL_RSHIFT(srcW, c->chrSrcHSubSample);
1587 25504 c->chrSrcH = AV_CEIL_RSHIFT(srcH, c->chrSrcVSubSample);
1588 25504 c->chrDstW = AV_CEIL_RSHIFT(dstW, c->chrDstHSubSample);
1589 25504 c->chrDstH = AV_CEIL_RSHIFT(dstH, c->chrDstVSubSample);
1590
1591
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
25504 if (!FF_ALLOCZ_TYPED_ARRAY(c->formatConvBuffer, FFALIGN(srcW * 2 + 78, 16) * 2))
1592 goto nomem;
1593
1594 25504 c->srcBpc = desc_src->comp[0].depth;
1595
2/2
✓ Branch 0 taken 515 times.
✓ Branch 1 taken 24989 times.
25504 if (c->srcBpc < 8)
1596 515 c->srcBpc = 8;
1597 25504 c->dstBpc = desc_dst->comp[0].depth;
1598
2/2
✓ Branch 0 taken 1944 times.
✓ Branch 1 taken 23560 times.
25504 if (c->dstBpc < 8)
1599 1944 c->dstBpc = 8;
1600
4/4
✓ Branch 1 taken 18096 times.
✓ Branch 2 taken 7408 times.
✓ Branch 3 taken 827 times.
✓ Branch 4 taken 17269 times.
25504 if (isAnyRGB(srcFormat) || srcFormat == AV_PIX_FMT_PAL8)
1601 8235 c->srcBpc = 16;
1602
2/2
✓ Branch 0 taken 4357 times.
✓ Branch 1 taken 21147 times.
25504 if (c->dstBpc == 16)
1603 4357 dst_stride <<= 1;
1604
1605
6/6
✓ Branch 0 taken 2854 times.
✓ Branch 1 taken 22650 times.
✓ Branch 2 taken 2762 times.
✓ Branch 3 taken 92 times.
✓ Branch 4 taken 2497 times.
✓ Branch 5 taken 265 times.
25504 if (INLINE_MMXEXT(cpu_flags) && c->srcBpc == 8 && c->dstBpc <= 14) {
1606
2/2
✓ Branch 0 taken 1562 times.
✓ Branch 1 taken 935 times.
2497 c->canMMXEXTBeUsed = dstW >= srcW && (dstW & 31) == 0 &&
1607
3/4
✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1518 times.
✓ Branch 3 taken 44 times.
6512 c->chrDstW >= c->chrSrcW &&
1608
1/2
✓ Branch 0 taken 1518 times.
✗ Branch 1 not taken.
1518 (srcW & 15) == 0;
1609
7/8
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 1518 times.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 891 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 165 times.
✓ Branch 7 taken 726 times.
2497 if (!c->canMMXEXTBeUsed && dstW >= srcW && c->chrDstW >= c->chrSrcW && (srcW & 15) == 0
1610
1611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 165 times.
165 && (flags & SWS_FAST_BILINEAR)) {
1612 if (flags & SWS_PRINT_INFO)
1613 av_log(c, AV_LOG_INFO,
1614 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
1615 }
1616
4/8
✓ Branch 0 taken 2497 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2497 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2497 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2497 times.
2497 if (usesHFilter || isNBPS(sws->src_format) || is16BPS(sws->src_format) || isAnyRGB(sws->src_format))
1617 c->canMMXEXTBeUsed = 0;
1618 } else
1619 23007 c->canMMXEXTBeUsed = 0;
1620
1621 25504 c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;
1622 25504 c->chrYInc = (((int64_t)c->chrSrcH << 16) + (c->chrDstH >> 1)) / c->chrDstH;
1623
1624 /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
1625 * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
1626 * correct scaling.
1627 * n-2 is the last chrominance sample available.
1628 * This is not perfect, but no one should notice the difference, the more
1629 * correct variant would be like the vertical one, but that would require
1630 * some special code for the first and last pixel */
1631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25504 times.
25504 if (flags & SWS_FAST_BILINEAR) {
1632 if (c->canMMXEXTBeUsed) {
1633 c->lumXInc += 20;
1634 c->chrXInc += 20;
1635 }
1636 // we don't use the x86 asm scaler if MMX is available
1637 else if (INLINE_MMX(cpu_flags) && c->dstBpc <= 14) {
1638 c->lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
1639 c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
1640 }
1641 }
1642
1643 // hardcoded for now
1644 25504 c->gamma_value = 2.2;
1645 25504 tmpFmt = AV_PIX_FMT_RGBA64LE;
1646
1647
3/8
✓ Branch 0 taken 968 times.
✓ Branch 1 taken 24536 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 968 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
25504 if (!unscaled && sws->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) {
1648 SwsInternal *c2;
1649 c->cascaded_context[0] = NULL;
1650
1651 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
1652 srcW, srcH, tmpFmt, 64);
1653 if (ret < 0)
1654 return ret;
1655
1656 c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
1657 srcW, srcH, tmpFmt,
1658 flags, NULL, NULL,
1659 sws->scaler_params);
1660 if (!c->cascaded_context[0]) {
1661 return AVERROR(ENOMEM);
1662 }
1663
1664 c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt,
1665 dstW, dstH, tmpFmt,
1666 flags, srcFilter, dstFilter,
1667 sws->scaler_params);
1668
1669 if (!c->cascaded_context[1])
1670 return AVERROR(ENOMEM);
1671
1672 c2 = sws_internal(c->cascaded_context[1]);
1673 c2->is_internal_gamma = 1;
1674 c2->gamma = alloc_gamma_tbl( c->gamma_value);
1675 c2->inv_gamma = alloc_gamma_tbl(1.f/c->gamma_value);
1676 if (!c2->gamma || !c2->inv_gamma)
1677 return AVERROR(ENOMEM);
1678
1679 // is_internal_flag is set after creating the context
1680 // to properly create the gamma convert FilterDescriptor
1681 // we have to re-initialize it
1682 ff_free_filters(c2);
1683 if ((ret = ff_init_filters(c2)) < 0) {
1684 sws_freeContext(c->cascaded_context[1]);
1685 c->cascaded_context[1] = NULL;
1686 return ret;
1687 }
1688
1689 c->cascaded_context[2] = NULL;
1690 if (dstFormat != tmpFmt) {
1691 ret = av_image_alloc(c->cascaded_tmp[1], c->cascaded_tmpStride[1],
1692 dstW, dstH, tmpFmt, 64);
1693 if (ret < 0)
1694 return ret;
1695
1696 c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt,
1697 dstW, dstH, dstFormat,
1698 flags, NULL, NULL,
1699 sws->scaler_params);
1700 if (!c->cascaded_context[2])
1701 return AVERROR(ENOMEM);
1702 }
1703 return 0;
1704 }
1705
1706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25504 times.
25504 if (isBayer(srcFormat)) {
1707 if (!unscaled ||
1708 (dstFormat != AV_PIX_FMT_RGB24 && dstFormat != AV_PIX_FMT_YUV420P &&
1709 dstFormat != AV_PIX_FMT_RGB48)) {
1710 enum AVPixelFormat tmpFormat = isBayer16BPS(srcFormat) ? AV_PIX_FMT_RGB48 : AV_PIX_FMT_RGB24;
1711
1712 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
1713 srcW, srcH, tmpFormat, 64);
1714 if (ret < 0)
1715 return ret;
1716
1717 c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
1718 srcW, srcH, tmpFormat,
1719 flags, srcFilter, NULL,
1720 sws->scaler_params);
1721 if (!c->cascaded_context[0])
1722 return AVERROR(ENOMEM);
1723
1724 c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat,
1725 dstW, dstH, dstFormat,
1726 flags, NULL, dstFilter,
1727 sws->scaler_params);
1728 if (!c->cascaded_context[1])
1729 return AVERROR(ENOMEM);
1730 return 0;
1731 }
1732 }
1733
1734
6/6
✓ Branch 0 taken 24536 times.
✓ Branch 1 taken 968 times.
✓ Branch 2 taken 9499 times.
✓ Branch 3 taken 15037 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 9482 times.
25504 if (unscaled && c->srcBpc == 8 && dstFormat == AV_PIX_FMT_GRAYF32){
1735
2/2
✓ Branch 0 taken 4352 times.
✓ Branch 1 taken 17 times.
4369 for (i = 0; i < 256; ++i){
1736 4352 c->uint2float_lut[i] = (float)i * float_mult;
1737 }
1738 }
1739
1740 // float will be converted to uint16_t
1741
6/6
✓ Branch 0 taken 25503 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25501 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
25504 if ((srcFormat == AV_PIX_FMT_GRAYF32BE || srcFormat == AV_PIX_FMT_GRAYF32LE) &&
1742
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 (!unscaled || unscaled && dstFormat != srcFormat && (srcFormat != AV_PIX_FMT_GRAYF32 ||
1743 dstFormat != AV_PIX_FMT_GRAY8))){
1744 3 c->srcBpc = 16;
1745 }
1746
1747
4/4
✓ Branch 1 taken 2245 times.
✓ Branch 2 taken 23259 times.
✓ Branch 4 taken 1455 times.
✓ Branch 5 taken 790 times.
25504 if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) {
1748 1455 enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat);
1749
1750
3/4
✓ Branch 0 taken 713 times.
✓ Branch 1 taken 742 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 713 times.
1455 if (tmpFormat != AV_PIX_FMT_NONE && sws->alpha_blend != SWS_ALPHA_BLEND_NONE) {
1751 if (!unscaled ||
1752 dstFormat != tmpFormat ||
1753 usesHFilter || usesVFilter ||
1754 sws->src_range != sws->dst_range
1755 ) {
1756 c->cascaded_mainindex = 1;
1757 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
1758 srcW, srcH, tmpFormat, 64);
1759 if (ret < 0)
1760 return ret;
1761
1762 c->cascaded_context[0] = alloc_set_opts(srcW, srcH, srcFormat,
1763 srcW, srcH, tmpFormat,
1764 flags, sws->scaler_params);
1765 if (!c->cascaded_context[0])
1766 return AVERROR(EINVAL);
1767 c->cascaded_context[0]->alpha_blend = sws->alpha_blend;
1768 ret = sws_init_context(c->cascaded_context[0], NULL , NULL);
1769 if (ret < 0)
1770 return ret;
1771
1772 c->cascaded_context[1] = alloc_set_opts(srcW, srcH, tmpFormat,
1773 dstW, dstH, dstFormat,
1774 flags, sws->scaler_params);
1775 if (!c->cascaded_context[1])
1776 return AVERROR(EINVAL);
1777
1778 c->cascaded_context[1]->src_range = sws->src_range;
1779 c->cascaded_context[1]->dst_range = sws->dst_range;
1780 ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter);
1781 if (ret < 0)
1782 return ret;
1783
1784 return 0;
1785 }
1786 }
1787 }
1788
1789 /* alpha blend special case, note this has been split via cascaded contexts if its scaled */
1790
4/6
✓ Branch 0 taken 24536 times.
✓ Branch 1 taken 968 times.
✓ Branch 2 taken 24536 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24536 times.
✗ Branch 5 not taken.
25504 if (unscaled && !usesHFilter && !usesVFilter &&
1791
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24536 sws->alpha_blend != SWS_ALPHA_BLEND_NONE &&
1792 isALPHA(srcFormat) &&
1793 (sws->src_range == sws->dst_range || isAnyRGB(dstFormat)) &&
1794 alphaless_fmt(srcFormat) == dstFormat
1795 ) {
1796 c->convert_unscaled = ff_sws_alphablendaway;
1797
1798 if (flags & SWS_PRINT_INFO)
1799 av_log(c, AV_LOG_INFO,
1800 "using alpha blendaway %s -> %s special converter\n",
1801 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
1802 return 0;
1803 }
1804
1805 /* unscaled special cases */
1806
4/6
✓ Branch 0 taken 24536 times.
✓ Branch 1 taken 968 times.
✓ Branch 2 taken 24536 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24536 times.
✗ Branch 5 not taken.
25504 if (unscaled && !usesHFilter && !usesVFilter &&
1807
5/6
✓ Branch 0 taken 2395 times.
✓ Branch 1 taken 22141 times.
✓ Branch 3 taken 1738 times.
✓ Branch 4 taken 657 times.
✓ Branch 5 taken 1738 times.
✗ Branch 6 not taken.
26274 (sws->src_range == sws->dst_range || isAnyRGB(dstFormat) ||
1808
2/4
✓ Branch 2 taken 1738 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1738 times.
3476 isFloat(srcFormat) || isFloat(dstFormat) || isBayer(srcFormat))){
1809
1810 22798 ff_get_unscaled_swscale(c);
1811
1812
2/2
✓ Branch 0 taken 5056 times.
✓ Branch 1 taken 17742 times.
22798 if (c->convert_unscaled) {
1813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5056 times.
5056 if (flags & SWS_PRINT_INFO)
1814 av_log(c, AV_LOG_INFO,
1815 "using unscaled %s -> %s special converter\n",
1816 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
1817 5056 return 0;
1818 }
1819 }
1820
1821 #if HAVE_MMAP && HAVE_MPROTECT && defined(MAP_ANONYMOUS)
1822 #define USE_MMAP 1
1823 #else
1824 #define USE_MMAP 0
1825 #endif
1826
1827 /* precalculate horizontal scaler filter coefficients */
1828 {
1829 #if HAVE_MMXEXT_INLINE
1830 // can't downscale !!!
1831
3/4
✓ Branch 0 taken 792 times.
✓ Branch 1 taken 19656 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 792 times.
20448 if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
1832 c->lumMmxextFilterCodeSize = ff_init_hscaler_mmxext(dstW, c->lumXInc, NULL,
1833 NULL, NULL, 8);
1834 c->chrMmxextFilterCodeSize = ff_init_hscaler_mmxext(c->chrDstW, c->chrXInc,
1835 NULL, NULL, NULL, 4);
1836
1837 #if USE_MMAP
1838 c->lumMmxextFilterCode = mmap(NULL, c->lumMmxextFilterCodeSize,
1839 PROT_READ | PROT_WRITE,
1840 MAP_PRIVATE | MAP_ANONYMOUS,
1841 -1, 0);
1842 c->chrMmxextFilterCode = mmap(NULL, c->chrMmxextFilterCodeSize,
1843 PROT_READ | PROT_WRITE,
1844 MAP_PRIVATE | MAP_ANONYMOUS,
1845 -1, 0);
1846 #elif HAVE_VIRTUALALLOC
1847 c->lumMmxextFilterCode = VirtualAlloc(NULL,
1848 c->lumMmxextFilterCodeSize,
1849 MEM_COMMIT,
1850 PAGE_EXECUTE_READWRITE);
1851 c->chrMmxextFilterCode = VirtualAlloc(NULL,
1852 c->chrMmxextFilterCodeSize,
1853 MEM_COMMIT,
1854 PAGE_EXECUTE_READWRITE);
1855 #else
1856 c->lumMmxextFilterCode = av_malloc(c->lumMmxextFilterCodeSize);
1857 c->chrMmxextFilterCode = av_malloc(c->chrMmxextFilterCodeSize);
1858 #endif
1859
1860 #ifdef MAP_ANONYMOUS
1861 if (c->lumMmxextFilterCode == MAP_FAILED || c->chrMmxextFilterCode == MAP_FAILED)
1862 #else
1863 if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
1864 #endif
1865 {
1866 av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
1867 return AVERROR(ENOMEM);
1868 }
1869
1870 if (!FF_ALLOCZ_TYPED_ARRAY(c->hLumFilter, dstW / 8 + 8) ||
1871 !FF_ALLOCZ_TYPED_ARRAY(c->hChrFilter, c->chrDstW / 4 + 8) ||
1872 !FF_ALLOCZ_TYPED_ARRAY(c->hLumFilterPos, dstW / 2 / 8 + 8) ||
1873 !FF_ALLOCZ_TYPED_ARRAY(c->hChrFilterPos, c->chrDstW / 2 / 4 + 8))
1874 goto nomem;
1875
1876 ff_init_hscaler_mmxext( dstW, c->lumXInc, c->lumMmxextFilterCode,
1877 c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
1878 ff_init_hscaler_mmxext(c->chrDstW, c->chrXInc, c->chrMmxextFilterCode,
1879 c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
1880
1881 #if USE_MMAP
1882 if ( mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1
1883 || mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1) {
1884 av_log(c, AV_LOG_ERROR, "mprotect failed, cannot use fast bilinear scaler\n");
1885 ret = AVERROR(EINVAL);
1886 goto fail;
1887 }
1888 #endif
1889 } else
1890 #endif /* HAVE_MMXEXT_INLINE */
1891 {
1892
2/2
✓ Branch 0 taken 1226 times.
✓ Branch 1 taken 19222 times.
20448 const int filterAlign = X86_MMX(cpu_flags) ? 4 :
1893 PPC_ALTIVEC(cpu_flags) ? 8 :
1894 have_neon(cpu_flags) ? 4 :
1895 have_lsx(cpu_flags) ? 8 :
1896 have_lasx(cpu_flags) ? 8 : 1;
1897
1898
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 20448 times.
40896 if ((ret = initFilter(&c->hLumFilter, &c->hLumFilterPos,
1899 &c->hLumFilterSize, c->lumXInc,
1900 srcW, dstW, filterAlign, 1 << 14,
1901 20448 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
1902 cpu_flags, srcFilter->lumH, dstFilter->lumH,
1903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 sws->scaler_params,
1904 get_local_pos(c, 0, 0, 0),
1905 get_local_pos(c, 0, 0, 0))) < 0)
1906 goto fail;
1907
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20448 times.
20448 if (ff_shuffle_filter_coefficients(c, c->hLumFilterPos, c->hLumFilterSize, c->hLumFilter, dstW) < 0)
1908 goto nomem;
1909
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 20448 times.
40896 if ((ret = initFilter(&c->hChrFilter, &c->hChrFilterPos,
1910 &c->hChrFilterSize, c->chrXInc,
1911 c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
1912 20448 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
1913 cpu_flags, srcFilter->chrH, dstFilter->chrH,
1914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 sws->scaler_params,
1915 get_local_pos(c, c->chrSrcHSubSample, sws->src_h_chr_pos, 0),
1916 get_local_pos(c, c->chrDstHSubSample, sws->dst_h_chr_pos, 0))) < 0)
1917 goto fail;
1918
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20448 times.
20448 if (ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW) < 0)
1919 goto nomem;
1920 }
1921 } // initialize horizontal stuff
1922
1923 /* precalculate vertical scaler filter coefficients */
1924 {
1925
2/2
✓ Branch 0 taken 1226 times.
✓ Branch 1 taken 19222 times.
20448 const int filterAlign = X86_MMX(cpu_flags) ? 2 :
1926 PPC_ALTIVEC(cpu_flags) ? 8 :
1927 have_neon(cpu_flags) ? 2 : 1;
1928
1929
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 20448 times.
40896 if ((ret = initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
1930 c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
1931 20448 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
1932 cpu_flags, srcFilter->lumV, dstFilter->lumV,
1933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 sws->scaler_params,
1934 get_local_pos(c, 0, 0, 1),
1935 get_local_pos(c, 0, 0, 1))) < 0)
1936 goto fail;
1937
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 20448 times.
40896 if ((ret = initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
1938 c->chrYInc, c->chrSrcH, c->chrDstH,
1939 filterAlign, (1 << 12),
1940 20448 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
1941 cpu_flags, srcFilter->chrV, dstFilter->chrV,
1942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 sws->scaler_params,
1943 get_local_pos(c, c->chrSrcVSubSample, sws->src_v_chr_pos, 1),
1944 get_local_pos(c, c->chrDstVSubSample, sws->dst_v_chr_pos, 1))) < 0)
1945
1946 goto fail;
1947
1948 #if HAVE_ALTIVEC
1949 if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * sws->dst_h) ||
1950 !FF_ALLOC_TYPED_ARRAY(c->vCCoeffsBank, c->vChrFilterSize * c->chrDstH))
1951 goto nomem;
1952
1953 for (i = 0; i < c->vLumFilterSize * sws->dst_h; i++) {
1954 int j;
1955 short *p = (short *)&c->vYCoeffsBank[i];
1956 for (j = 0; j < 8; j++)
1957 p[j] = c->vLumFilter[i];
1958 }
1959
1960 for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {
1961 int j;
1962 short *p = (short *)&c->vCCoeffsBank[i];
1963 for (j = 0; j < 8; j++)
1964 p[j] = c->vChrFilter[i];
1965 }
1966 #endif
1967 }
1968
1969
2/2
✓ Branch 0 taken 81792 times.
✓ Branch 1 taken 20448 times.
102240 for (i = 0; i < 4; i++)
1970
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81792 times.
81792 if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], sws->dst_w + 3))
1971 goto nomem;
1972
1973
4/4
✓ Branch 1 taken 475 times.
✓ Branch 2 taken 19973 times.
✓ Branch 4 taken 234 times.
✓ Branch 5 taken 241 times.
20448 c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(sws->src_format) && isALPHA(sws->dst_format)) ? 1 : 0;
1974
1975 // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
1976 20448 c->uv_off = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
1977 20448 c->uv_offx2 = dst_stride + 16;
1978
1979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 av_assert0(c->chrDstH <= dstH);
1980
1981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20448 times.
20448 if (flags & SWS_PRINT_INFO) {
1982 const char *scaler = NULL, *cpucaps;
1983
1984 for (i = 0; i < FF_ARRAY_ELEMS(scale_algorithms); i++) {
1985 if (flags & scale_algorithms[i].flag) {
1986 scaler = scale_algorithms[i].description;
1987 break;
1988 }
1989 }
1990 if (!scaler)
1991 scaler = "ehh flags invalid?!";
1992 av_log(c, AV_LOG_INFO, "%s scaler, from %s to %s%s ",
1993 scaler,
1994 av_get_pix_fmt_name(srcFormat),
1995 dstFormat == AV_PIX_FMT_BGR555 || dstFormat == AV_PIX_FMT_BGR565 ||
1996 dstFormat == AV_PIX_FMT_RGB444BE || dstFormat == AV_PIX_FMT_RGB444LE ||
1997 dstFormat == AV_PIX_FMT_BGR444BE || dstFormat == AV_PIX_FMT_BGR444LE ?
1998 "dithered " : "",
1999 av_get_pix_fmt_name(dstFormat));
2000
2001 if (INLINE_MMXEXT(cpu_flags))
2002 cpucaps = "MMXEXT";
2003 else if (INLINE_MMX(cpu_flags))
2004 cpucaps = "MMX";
2005 else if (PPC_ALTIVEC(cpu_flags))
2006 cpucaps = "AltiVec";
2007 else
2008 cpucaps = "C";
2009
2010 av_log(c, AV_LOG_INFO, "using %s\n", cpucaps);
2011
2012 av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
2013 av_log(c, AV_LOG_DEBUG,
2014 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
2015 sws->src_w, sws->src_h, sws->dst_w, sws->dst_h, c->lumXInc, c->lumYInc);
2016 av_log(c, AV_LOG_DEBUG,
2017 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
2018 c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
2019 c->chrXInc, c->chrYInc);
2020 }
2021
2022 20448 ff_sws_init_scale(c);
2023
2024 20448 return ff_init_filters(c);
2025 nomem:
2026 ret = AVERROR(ENOMEM);
2027 fail: // FIXME replace things by appropriate error codes
2028 if (ret == RETCODE_USE_CASCADE) {
2029 int tmpW = sqrt(srcW * (int64_t)dstW);
2030 int tmpH = sqrt(srcH * (int64_t)dstH);
2031 enum AVPixelFormat tmpFormat = AV_PIX_FMT_YUV420P;
2032
2033 if (isALPHA(srcFormat))
2034 tmpFormat = AV_PIX_FMT_YUVA420P;
2035
2036 if (srcW*(int64_t)srcH <= 4LL*dstW*dstH)
2037 return AVERROR(EINVAL);
2038
2039 ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0],
2040 tmpW, tmpH, tmpFormat, 64);
2041 if (ret < 0)
2042 return ret;
2043
2044 c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
2045 tmpW, tmpH, tmpFormat,
2046 flags, srcFilter, NULL,
2047 sws->scaler_params);
2048 if (!c->cascaded_context[0])
2049 return AVERROR(ENOMEM);
2050
2051 c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat,
2052 dstW, dstH, dstFormat,
2053 flags, NULL, dstFilter,
2054 sws->scaler_params);
2055 if (!c->cascaded_context[1])
2056 return AVERROR(ENOMEM);
2057 return 0;
2058 }
2059 return ret;
2060 }
2061
2062 static int context_init_threaded(SwsContext *sws,
2063 SwsFilter *src_filter, SwsFilter *dst_filter)
2064 {
2065 SwsInternal *c = sws_internal(sws);
2066 int ret;
2067
2068 ret = avpriv_slicethread_create(&c->slicethread, (void*) sws,
2069 ff_sws_slice_worker, NULL, sws->threads);
2070 if (ret == AVERROR(ENOSYS)) {
2071 sws->threads = 1;
2072 return 0;
2073 } else if (ret < 0)
2074 return ret;
2075
2076 sws->threads = ret;
2077
2078 c->slice_ctx = av_calloc(sws->threads, sizeof(*c->slice_ctx));
2079 c->slice_err = av_calloc(sws->threads, sizeof(*c->slice_err));
2080 if (!c->slice_ctx || !c->slice_err)
2081 return AVERROR(ENOMEM);
2082
2083 for (int i = 0; i < sws->threads; i++) {
2084 SwsContext *slice;
2085 slice = c->slice_ctx[i] = sws_alloc_context();
2086 if (!slice)
2087 return AVERROR(ENOMEM);
2088 sws_internal(slice)->parent = sws;
2089 c->nb_slice_ctx++;
2090
2091 ret = av_opt_copy(slice, sws);
2092 if (ret < 0)
2093 return ret;
2094 slice->threads = 1;
2095
2096 ret = ff_sws_init_single_context(slice, src_filter, dst_filter);
2097 if (ret < 0)
2098 return ret;
2099
2100 if (slice->dither == SWS_DITHER_ED) {
2101 av_log(c, AV_LOG_VERBOSE,
2102 "Error-diffusion dither is in use, scaling will be single-threaded.");
2103 break;
2104 }
2105 }
2106
2107 return 0;
2108 }
2109
2110 8848 av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter,
2111 SwsFilter *dstFilter)
2112 {
2113 8848 SwsInternal *c = sws_internal(sws);
2114 static AVOnce rgb2rgb_once = AV_ONCE_INIT;
2115 enum AVPixelFormat src_format, dst_format;
2116 int ret;
2117
2118 8848 c->frame_src = av_frame_alloc();
2119 8848 c->frame_dst = av_frame_alloc();
2120
2/4
✓ Branch 0 taken 8848 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8848 times.
8848 if (!c->frame_src || !c->frame_dst)
2121 return AVERROR(ENOMEM);
2122
2123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8848 times.
8848 if (ff_thread_once(&rgb2rgb_once, ff_sws_rgb2rgb_init) != 0)
2124 return AVERROR_UNKNOWN;
2125
2126 8848 src_format = sws->src_format;
2127 8848 dst_format = sws->dst_format;
2128 8848 sws->src_range |= handle_jpeg(&sws->src_format);
2129 8848 sws->dst_range |= handle_jpeg(&sws->dst_format);
2130
2131
4/4
✓ Branch 0 taken 8768 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 161 times.
✓ Branch 3 taken 8607 times.
8848 if (src_format != sws->src_format || dst_format != sws->dst_format)
2132 241 av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
2133
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8848 times.
8848 if (sws->threads != 1) {
2135 ret = context_init_threaded(sws, srcFilter, dstFilter);
2136 if (ret < 0 || sws->threads > 1)
2137 return ret;
2138 // threading disabled in this build, init as single-threaded
2139 }
2140
2141 8848 return ff_sws_init_single_context(sws, srcFilter, dstFilter);
2142 }
2143
2144 3143 SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
2145 int dstW, int dstH, enum AVPixelFormat dstFormat,
2146 int flags, SwsFilter *srcFilter,
2147 SwsFilter *dstFilter, const double *param)
2148 {
2149 SwsContext *sws;
2150
2151 3143 sws = alloc_set_opts(srcW, srcH, srcFormat,
2152 dstW, dstH, dstFormat,
2153 flags, param);
2154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3143 times.
3143 if (!sws)
2155 return NULL;
2156
2157
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3143 times.
3143 if (sws_init_context(sws, srcFilter, dstFilter) < 0) {
2158 sws_freeContext(sws);
2159 return NULL;
2160 }
2161
2162 3143 return sws;
2163 }
2164
2165 static int isnan_vec(SwsVector *a)
2166 {
2167 int i;
2168 for (i=0; i<a->length; i++)
2169 if (isnan(a->coeff[i]))
2170 return 1;
2171 return 0;
2172 }
2173
2174 static void makenan_vec(SwsVector *a)
2175 {
2176 int i;
2177 for (i=0; i<a->length; i++)
2178 a->coeff[i] = NAN;
2179 }
2180
2181 SwsVector *sws_allocVec(int length)
2182 {
2183 SwsVector *vec;
2184
2185 if(length <= 0 || length > INT_MAX/ sizeof(double))
2186 return NULL;
2187
2188 vec = av_malloc(sizeof(SwsVector));
2189 if (!vec)
2190 return NULL;
2191 vec->length = length;
2192 vec->coeff = av_malloc(sizeof(double) * length);
2193 if (!vec->coeff)
2194 av_freep(&vec);
2195 return vec;
2196 }
2197
2198 SwsVector *sws_getGaussianVec(double variance, double quality)
2199 {
2200 const int length = (int)(variance * quality + 0.5) | 1;
2201 int i;
2202 double middle = (length - 1) * 0.5;
2203 SwsVector *vec;
2204
2205 if(variance < 0 || quality < 0)
2206 return NULL;
2207
2208 vec = sws_allocVec(length);
2209
2210 if (!vec)
2211 return NULL;
2212
2213 for (i = 0; i < length; i++) {
2214 double dist = i - middle;
2215 vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
2216 sqrt(2 * variance * M_PI);
2217 }
2218
2219 sws_normalizeVec(vec, 1.0);
2220
2221 return vec;
2222 }
2223
2224 /**
2225 * Allocate and return a vector with length coefficients, all
2226 * with the same value c.
2227 */
2228 static
2229 SwsVector *sws_getConstVec(double c, int length)
2230 {
2231 int i;
2232 SwsVector *vec = sws_allocVec(length);
2233
2234 if (!vec)
2235 return NULL;
2236
2237 for (i = 0; i < length; i++)
2238 vec->coeff[i] = c;
2239
2240 return vec;
2241 }
2242
2243 /**
2244 * Allocate and return a vector with just one coefficient, with
2245 * value 1.0.
2246 */
2247 static
2248 SwsVector *sws_getIdentityVec(void)
2249 {
2250 return sws_getConstVec(1.0, 1);
2251 }
2252
2253 static double sws_dcVec(SwsVector *a)
2254 {
2255 int i;
2256 double sum = 0;
2257
2258 for (i = 0; i < a->length; i++)
2259 sum += a->coeff[i];
2260
2261 return sum;
2262 }
2263
2264 void sws_scaleVec(SwsVector *a, double scalar)
2265 {
2266 int i;
2267
2268 for (i = 0; i < a->length; i++)
2269 a->coeff[i] *= scalar;
2270 }
2271
2272 void sws_normalizeVec(SwsVector *a, double height)
2273 {
2274 sws_scaleVec(a, height / sws_dcVec(a));
2275 }
2276
2277 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
2278 {
2279 int length = FFMAX(a->length, b->length);
2280 int i;
2281 SwsVector *vec = sws_getConstVec(0.0, length);
2282
2283 if (!vec)
2284 return NULL;
2285
2286 for (i = 0; i < a->length; i++)
2287 vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
2288 for (i = 0; i < b->length; i++)
2289 vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
2290
2291 return vec;
2292 }
2293
2294 /* shift left / or right if "shift" is negative */
2295 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
2296 {
2297 int length = a->length + FFABS(shift) * 2;
2298 int i;
2299 SwsVector *vec = sws_getConstVec(0.0, length);
2300
2301 if (!vec)
2302 return NULL;
2303
2304 for (i = 0; i < a->length; i++) {
2305 vec->coeff[i + (length - 1) / 2 -
2306 (a->length - 1) / 2 - shift] = a->coeff[i];
2307 }
2308
2309 return vec;
2310 }
2311
2312 static
2313 void sws_shiftVec(SwsVector *a, int shift)
2314 {
2315 SwsVector *shifted = sws_getShiftedVec(a, shift);
2316 if (!shifted) {
2317 makenan_vec(a);
2318 return;
2319 }
2320 av_free(a->coeff);
2321 a->coeff = shifted->coeff;
2322 a->length = shifted->length;
2323 av_free(shifted);
2324 }
2325
2326 static
2327 void sws_addVec(SwsVector *a, SwsVector *b)
2328 {
2329 SwsVector *sum = sws_sumVec(a, b);
2330 if (!sum) {
2331 makenan_vec(a);
2332 return;
2333 }
2334 av_free(a->coeff);
2335 a->coeff = sum->coeff;
2336 a->length = sum->length;
2337 av_free(sum);
2338 }
2339
2340 /**
2341 * Print with av_log() a textual representation of the vector a
2342 * if log_level <= av_log_level.
2343 */
2344 static
2345 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
2346 {
2347 int i;
2348 double max = 0;
2349 double min = 0;
2350 double range;
2351
2352 for (i = 0; i < a->length; i++)
2353 if (a->coeff[i] > max)
2354 max = a->coeff[i];
2355
2356 for (i = 0; i < a->length; i++)
2357 if (a->coeff[i] < min)
2358 min = a->coeff[i];
2359
2360 range = max - min;
2361
2362 for (i = 0; i < a->length; i++) {
2363 int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
2364 av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
2365 for (; x > 0; x--)
2366 av_log(log_ctx, log_level, " ");
2367 av_log(log_ctx, log_level, "|\n");
2368 }
2369 }
2370
2371 void sws_freeVec(SwsVector *a)
2372 {
2373 if (!a)
2374 return;
2375 av_freep(&a->coeff);
2376 a->length = 0;
2377 av_free(a);
2378 }
2379
2380 void sws_freeFilter(SwsFilter *filter)
2381 {
2382 if (!filter)
2383 return;
2384
2385 sws_freeVec(filter->lumH);
2386 sws_freeVec(filter->lumV);
2387 sws_freeVec(filter->chrH);
2388 sws_freeVec(filter->chrV);
2389 av_free(filter);
2390 }
2391
2392 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
2393 float lumaSharpen, float chromaSharpen,
2394 float chromaHShift, float chromaVShift,
2395 int verbose)
2396 {
2397 SwsFilter *filter = av_malloc(sizeof(SwsFilter));
2398 if (!filter)
2399 return NULL;
2400
2401 if (lumaGBlur != 0.0) {
2402 filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
2403 filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
2404 } else {
2405 filter->lumH = sws_getIdentityVec();
2406 filter->lumV = sws_getIdentityVec();
2407 }
2408
2409 if (chromaGBlur != 0.0) {
2410 filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
2411 filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
2412 } else {
2413 filter->chrH = sws_getIdentityVec();
2414 filter->chrV = sws_getIdentityVec();
2415 }
2416
2417 if (!filter->lumH || !filter->lumV || !filter->chrH || !filter->chrV)
2418 goto fail;
2419
2420 if (chromaSharpen != 0.0) {
2421 SwsVector *id = sws_getIdentityVec();
2422 if (!id)
2423 goto fail;
2424 sws_scaleVec(filter->chrH, -chromaSharpen);
2425 sws_scaleVec(filter->chrV, -chromaSharpen);
2426 sws_addVec(filter->chrH, id);
2427 sws_addVec(filter->chrV, id);
2428 sws_freeVec(id);
2429 }
2430
2431 if (lumaSharpen != 0.0) {
2432 SwsVector *id = sws_getIdentityVec();
2433 if (!id)
2434 goto fail;
2435 sws_scaleVec(filter->lumH, -lumaSharpen);
2436 sws_scaleVec(filter->lumV, -lumaSharpen);
2437 sws_addVec(filter->lumH, id);
2438 sws_addVec(filter->lumV, id);
2439 sws_freeVec(id);
2440 }
2441
2442 if (chromaHShift != 0.0)
2443 sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
2444
2445 if (chromaVShift != 0.0)
2446 sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
2447
2448 sws_normalizeVec(filter->chrH, 1.0);
2449 sws_normalizeVec(filter->chrV, 1.0);
2450 sws_normalizeVec(filter->lumH, 1.0);
2451 sws_normalizeVec(filter->lumV, 1.0);
2452
2453 if (isnan_vec(filter->chrH) ||
2454 isnan_vec(filter->chrV) ||
2455 isnan_vec(filter->lumH) ||
2456 isnan_vec(filter->lumV))
2457 goto fail;
2458
2459 if (verbose)
2460 sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
2461 if (verbose)
2462 sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
2463
2464 return filter;
2465
2466 fail:
2467 sws_freeVec(filter->lumH);
2468 sws_freeVec(filter->lumV);
2469 sws_freeVec(filter->chrH);
2470 sws_freeVec(filter->chrV);
2471 av_freep(&filter);
2472 return NULL;
2473 }
2474
2475 141641 void sws_freeContext(SwsContext *sws)
2476 {
2477 141641 SwsInternal *c = sws_internal(sws);
2478 int i;
2479
2/2
✓ Branch 0 taken 106231 times.
✓ Branch 1 taken 35410 times.
141641 if (!c)
2480 106231 return;
2481
2482
2/2
✓ Branch 0 taken 70820 times.
✓ Branch 1 taken 35410 times.
106230 for (i = 0; i < FF_ARRAY_ELEMS(c->graph); i++)
2483 70820 ff_sws_graph_free(&c->graph[i]);
2484
2485
2/2
✓ Branch 0 taken 16656 times.
✓ Branch 1 taken 35410 times.
52066 for (i = 0; i < c->nb_slice_ctx; i++)
2486 16656 sws_freeContext(c->slice_ctx[i]);
2487 35410 av_freep(&c->slice_ctx);
2488 35410 av_freep(&c->slice_err);
2489
2490 35410 avpriv_slicethread_free(&c->slicethread);
2491
2492
2/2
✓ Branch 0 taken 141640 times.
✓ Branch 1 taken 35410 times.
177050 for (i = 0; i < 4; i++)
2493 141640 av_freep(&c->dither_error[i]);
2494
2495 35410 av_frame_free(&c->frame_src);
2496 35410 av_frame_free(&c->frame_dst);
2497
2498 35410 av_freep(&c->src_ranges.ranges);
2499
2500 35410 av_freep(&c->vLumFilter);
2501 35410 av_freep(&c->vChrFilter);
2502 35410 av_freep(&c->hLumFilter);
2503 35410 av_freep(&c->hChrFilter);
2504 #if HAVE_ALTIVEC
2505 av_freep(&c->vYCoeffsBank);
2506 av_freep(&c->vCCoeffsBank);
2507 #endif
2508
2509 35410 av_freep(&c->vLumFilterPos);
2510 35410 av_freep(&c->vChrFilterPos);
2511 35410 av_freep(&c->hLumFilterPos);
2512 35410 av_freep(&c->hChrFilterPos);
2513
2514 #if HAVE_MMX_INLINE
2515 #if USE_MMAP
2516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35410 times.
35410 if (c->lumMmxextFilterCode)
2517 munmap(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize);
2518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35410 times.
35410 if (c->chrMmxextFilterCode)
2519 munmap(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize);
2520 #elif HAVE_VIRTUALALLOC
2521 if (c->lumMmxextFilterCode)
2522 VirtualFree(c->lumMmxextFilterCode, 0, MEM_RELEASE);
2523 if (c->chrMmxextFilterCode)
2524 VirtualFree(c->chrMmxextFilterCode, 0, MEM_RELEASE);
2525 #else
2526 av_free(c->lumMmxextFilterCode);
2527 av_free(c->chrMmxextFilterCode);
2528 #endif
2529 35410 c->lumMmxextFilterCode = NULL;
2530 35410 c->chrMmxextFilterCode = NULL;
2531 #endif /* HAVE_MMX_INLINE */
2532
2533 35410 av_freep(&c->yuvTable);
2534 35410 av_freep(&c->formatConvBuffer);
2535
2536 35410 sws_freeContext(c->cascaded_context[0]);
2537 35410 sws_freeContext(c->cascaded_context[1]);
2538 35410 sws_freeContext(c->cascaded_context[2]);
2539 35410 memset(c->cascaded_context, 0, sizeof(c->cascaded_context));
2540 35410 av_freep(&c->cascaded_tmp[0][0]);
2541 35410 av_freep(&c->cascaded_tmp[1][0]);
2542
2543 35410 av_freep(&c->gamma);
2544 35410 av_freep(&c->inv_gamma);
2545 #if CONFIG_SMALL
2546 av_freep(&c->xyzgamma);
2547 #endif
2548
2549 35410 av_freep(&c->rgb0_scratch);
2550 35410 av_freep(&c->xyz_scratch);
2551
2552 35410 ff_free_filters(c);
2553
2554 35410 av_free(c);
2555 }
2556
2557 15416 void sws_free_context(SwsContext **pctx)
2558 {
2559 15416 SwsContext *ctx = *pctx;
2560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15416 times.
15416 if (!ctx)
2561 return;
2562
2563 15416 sws_freeContext(ctx);
2564 15416 *pctx = NULL;
2565 }
2566
2567 SwsContext *sws_getCachedContext(SwsContext *prev, int srcW,
2568 int srcH, enum AVPixelFormat srcFormat,
2569 int dstW, int dstH,
2570 enum AVPixelFormat dstFormat, int flags,
2571 SwsFilter *srcFilter,
2572 SwsFilter *dstFilter,
2573 const double *param)
2574 {
2575 SwsContext *sws;
2576 static const double default_param[2] = { SWS_PARAM_DEFAULT,
2577 SWS_PARAM_DEFAULT };
2578
2579 if (!param)
2580 param = default_param;
2581
2582 if (prev && (prev->src_w == srcW &&
2583 prev->src_h == srcH &&
2584 prev->src_format == srcFormat &&
2585 prev->dst_w == dstW &&
2586 prev->dst_h == dstH &&
2587 prev->dst_format == dstFormat &&
2588 prev->flags == flags &&
2589 prev->scaler_params[0] == param[0] &&
2590 prev->scaler_params[1] == param[1])) {
2591 return prev;
2592 }
2593
2594 if (!(sws = sws_alloc_context())) {
2595 sws_free_context(&prev);
2596 return NULL;
2597 }
2598
2599 if (prev) {
2600 av_opt_copy(sws, prev);
2601 sws_free_context(&prev);
2602 }
2603
2604 sws->src_w = srcW;
2605 sws->src_h = srcH;
2606 sws->src_format = srcFormat;
2607 sws->dst_w = dstW;
2608 sws->dst_h = dstH;
2609 sws->dst_format = dstFormat;
2610 sws->flags = flags;
2611 sws->scaler_params[0] = param[0];
2612 sws->scaler_params[1] = param[1];
2613
2614 if (sws_init_context(sws, srcFilter, dstFilter) < 0)
2615 sws_free_context(&sws);
2616
2617 return sws;
2618 }
2619
2620 int ff_range_add(RangeList *rl, unsigned int start, unsigned int len)
2621 {
2622 Range *tmp;
2623 unsigned int idx;
2624
2625 /* find the first existing range after the new one */
2626 for (idx = 0; idx < rl->nb_ranges; idx++)
2627 if (rl->ranges[idx].start > start)
2628 break;
2629
2630 /* check for overlap */
2631 if (idx > 0) {
2632 Range *prev = &rl->ranges[idx - 1];
2633 if (prev->start + prev->len > start)
2634 return AVERROR(EINVAL);
2635 }
2636 if (idx < rl->nb_ranges) {
2637 Range *next = &rl->ranges[idx];
2638 if (start + len > next->start)
2639 return AVERROR(EINVAL);
2640 }
2641
2642 tmp = av_fast_realloc(rl->ranges, &rl->ranges_allocated,
2643 (rl->nb_ranges + 1) * sizeof(*rl->ranges));
2644 if (!tmp)
2645 return AVERROR(ENOMEM);
2646 rl->ranges = tmp;
2647
2648 memmove(rl->ranges + idx + 1, rl->ranges + idx,
2649 sizeof(*rl->ranges) * (rl->nb_ranges - idx));
2650 rl->ranges[idx].start = start;
2651 rl->ranges[idx].len = len;
2652 rl->nb_ranges++;
2653
2654 /* merge ranges */
2655 if (idx > 0) {
2656 Range *prev = &rl->ranges[idx - 1];
2657 Range *cur = &rl->ranges[idx];
2658 if (prev->start + prev->len == cur->start) {
2659 prev->len += cur->len;
2660 memmove(rl->ranges + idx - 1, rl->ranges + idx,
2661 sizeof(*rl->ranges) * (rl->nb_ranges - idx));
2662 rl->nb_ranges--;
2663 idx--;
2664 }
2665 }
2666 if (idx < rl->nb_ranges - 1) {
2667 Range *cur = &rl->ranges[idx];
2668 Range *next = &rl->ranges[idx + 1];
2669 if (cur->start + cur->len == next->start) {
2670 cur->len += next->len;
2671 memmove(rl->ranges + idx, rl->ranges + idx + 1,
2672 sizeof(*rl->ranges) * (rl->nb_ranges - idx - 1));
2673 rl->nb_ranges--;
2674 }
2675 }
2676
2677 return 0;
2678 }
2679
2680 /**
2681 * This function also sanitizes and strips the input data, removing irrelevant
2682 * fields for certain formats.
2683 */
2684 346532 SwsFormat ff_fmt_from_frame(const AVFrame *frame, int field)
2685 {
2686 346532 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
2687 const AVColorPrimariesDesc *primaries;
2688 AVFrameSideData *sd;
2689
2690 346532 SwsFormat fmt = {
2691 346532 .width = frame->width,
2692 346532 .height = frame->height,
2693 346532 .format = frame->format,
2694 346532 .range = frame->color_range,
2695 346532 .csp = frame->colorspace,
2696 346532 .loc = frame->chroma_location,
2697 .desc = desc,
2698 .color = {
2699 346532 .prim = frame->color_primaries,
2700 346532 .trc = frame->color_trc,
2701 },
2702 };
2703
2704 av_assert1(fmt.width > 0);
2705 av_assert1(fmt.height > 0);
2706 av_assert1(fmt.format != AV_PIX_FMT_NONE);
2707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 346532 times.
346532 av_assert0(desc);
2708
2/2
✓ Branch 0 taken 117144 times.
✓ Branch 1 taken 229388 times.
346532 if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_BAYER)) {
2709 /* RGB-like family */
2710 117144 fmt.csp = AVCOL_SPC_RGB;
2711 117144 fmt.range = AVCOL_RANGE_JPEG;
2712
2/2
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 228458 times.
229388 } else if (desc->flags & AV_PIX_FMT_FLAG_XYZ) {
2713 930 fmt.csp = AVCOL_SPC_UNSPECIFIED;
2714 930 fmt.color = (SwsColor) {
2715 .prim = AVCOL_PRI_BT709, /* swscale currently hard-codes this XYZ matrix */
2716 .trc = AVCOL_TRC_SMPTE428,
2717 };
2718
2/2
✓ Branch 0 taken 11972 times.
✓ Branch 1 taken 216486 times.
228458 } else if (desc->nb_components < 3) {
2719 /* Grayscale formats */
2720 11972 fmt.color.prim = AVCOL_PRI_UNSPECIFIED;
2721 11972 fmt.csp = AVCOL_SPC_UNSPECIFIED;
2722
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 11672 times.
11972 if (desc->flags & AV_PIX_FMT_FLAG_FLOAT)
2723 300 fmt.range = AVCOL_RANGE_UNSPECIFIED;
2724 else
2725 11672 fmt.range = AVCOL_RANGE_JPEG; // FIXME: this restriction should be lifted
2726 }
2727
2728
2/2
✓ Branch 0 taken 9710 times.
✓ Branch 1 taken 336822 times.
346532 switch (frame->format) {
2729 9710 case AV_PIX_FMT_YUVJ420P:
2730 case AV_PIX_FMT_YUVJ411P:
2731 case AV_PIX_FMT_YUVJ422P:
2732 case AV_PIX_FMT_YUVJ444P:
2733 case AV_PIX_FMT_YUVJ440P:
2734 9710 fmt.range = AVCOL_RANGE_JPEG;
2735 9710 break;
2736 }
2737
2738
4/4
✓ Branch 0 taken 202092 times.
✓ Branch 1 taken 144440 times.
✓ Branch 2 taken 196544 times.
✓ Branch 3 taken 5548 times.
346532 if (!desc->log2_chroma_w && !desc->log2_chroma_h)
2739 196544 fmt.loc = AVCHROMA_LOC_UNSPECIFIED;
2740
2741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 346532 times.
346532 if (frame->flags & AV_FRAME_FLAG_INTERLACED) {
2742 fmt.height = (fmt.height + (field == FIELD_TOP)) >> 1;
2743 fmt.interlaced = 1;
2744 }
2745
2746 /* Set luminance and gamut information */
2747 346532 fmt.color.min_luma = av_make_q(0, 1);
2748
3/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 346470 times.
346532 switch (fmt.color.trc) {
2749 4 case AVCOL_TRC_SMPTE2084:
2750 4 fmt.color.max_luma = av_make_q(10000, 1); break;
2751 58 case AVCOL_TRC_ARIB_STD_B67:
2752 58 fmt.color.max_luma = av_make_q( 1000, 1); break; /* HLG reference display */
2753 346470 default:
2754 346470 fmt.color.max_luma = av_make_q( 203, 1); break; /* SDR reference brightness */
2755 }
2756
2757 346532 primaries = av_csp_primaries_desc_from_id(fmt.color.prim);
2758
2/2
✓ Branch 0 taken 1678 times.
✓ Branch 1 taken 344854 times.
346532 if (primaries)
2759 1678 fmt.color.gamut = primaries->prim;
2760
2761
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 346528 times.
346532 if ((sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA))) {
2762 4 const AVMasteringDisplayMetadata *mdm = (const AVMasteringDisplayMetadata *) sd->data;
2763
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mdm->has_luminance) {
2764 4 fmt.color.min_luma = mdm->min_luminance;
2765 4 fmt.color.max_luma = mdm->max_luminance;
2766 }
2767
2768
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (mdm->has_primaries) {
2769 /* Ignore mastering display white point as it has no bearance on
2770 * the underlying content */
2771 4 fmt.color.gamut.r.x = mdm->display_primaries[0][0];
2772 4 fmt.color.gamut.r.y = mdm->display_primaries[0][1];
2773 4 fmt.color.gamut.g.x = mdm->display_primaries[1][0];
2774 4 fmt.color.gamut.g.y = mdm->display_primaries[1][1];
2775 4 fmt.color.gamut.b.x = mdm->display_primaries[2][0];
2776 4 fmt.color.gamut.b.y = mdm->display_primaries[2][1];
2777 }
2778 }
2779
2780
2/2
✓ Branch 1 taken 346528 times.
✓ Branch 2 taken 4 times.
346532 if ((sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS))) {
2781 4 const AVDynamicHDRPlus *dhp = (const AVDynamicHDRPlus *) sd->data;
2782 4 const AVHDRPlusColorTransformParams *pars = &dhp->params[0];
2783 4 const AVRational nits = av_make_q(10000, 1);
2784 4 AVRational maxrgb = pars->maxscl[0];
2785
2786
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)
2787 goto skip_hdr10;
2788
2789 /* Maximum of MaxSCL components */
2790
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (av_cmp_q(pars->maxscl[1], maxrgb) > 0)
2791 maxrgb = pars->maxscl[1];
2792
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (av_cmp_q(pars->maxscl[2], maxrgb) > 0)
2793 maxrgb = pars->maxscl[2];
2794
2795
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (maxrgb.num > 0) {
2796 /* Estimate true luminance from MaxSCL */
2797 4 const AVLumaCoefficients *luma = av_csp_luma_coeffs_from_avcsp(fmt.csp);
2798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!luma)
2799 goto skip_hdr10;
2800 4 fmt.color.frame_peak = av_add_q(av_mul_q(luma->cr, pars->maxscl[0]),
2801 av_add_q(av_mul_q(luma->cg, pars->maxscl[1]),
2802 av_mul_q(luma->cb, pars->maxscl[2])));
2803 /* Scale the scene average brightness by the ratio between the
2804 * maximum luminance and the MaxRGB values */
2805 4 fmt.color.frame_avg = av_mul_q(pars->average_maxrgb,
2806 av_div_q(fmt.color.frame_peak, maxrgb));
2807 } else {
2808 /**
2809 * Calculate largest value from histogram to use as fallback for
2810 * clips with missing MaxSCL information. Note that this may end
2811 * up picking the "reserved" value at the 5% percentile, which in
2812 * practice appears to track the brightest pixel in the scene.
2813 */
2814 for (int i = 0; i < pars->num_distribution_maxrgb_percentiles; i++) {
2815 const AVRational pct = pars->distribution_maxrgb[i].percentile;
2816 if (av_cmp_q(pct, maxrgb) > 0)
2817 maxrgb = pct;
2818 fmt.color.frame_peak = maxrgb;
2819 fmt.color.frame_avg = pars->average_maxrgb;
2820 }
2821 }
2822
2823 /* Rescale to nits */
2824 4 fmt.color.frame_peak = av_mul_q(nits, fmt.color.frame_peak);
2825 4 fmt.color.frame_avg = av_mul_q(nits, fmt.color.frame_avg);
2826 }
2827 346528 skip_hdr10:
2828
2829 /* PQ is always scaled down to absolute zero, so ignore mastering metadata */
2830
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 346528 times.
346532 if (fmt.color.trc == AVCOL_TRC_SMPTE2084)
2831 4 fmt.color.min_luma = av_make_q(0, 1);
2832
2833 346532 return fmt;
2834 }
2835
2836 11016 static int infer_prim_ref(SwsColor *csp, const SwsColor *ref)
2837 {
2838
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 10878 times.
11016 if (csp->prim != AVCOL_PRI_UNSPECIFIED)
2839 138 return 0;
2840
2841 /* Re-use the reference gamut only for "safe", similar primaries */
2842
2/2
✓ Branch 0 taken 5460 times.
✓ Branch 1 taken 5418 times.
10878 switch (ref->prim) {
2843 5460 case AVCOL_PRI_BT709:
2844 case AVCOL_PRI_BT470M:
2845 case AVCOL_PRI_BT470BG:
2846 case AVCOL_PRI_SMPTE170M:
2847 case AVCOL_PRI_SMPTE240M:
2848 5460 csp->prim = ref->prim;
2849 5460 csp->gamut = ref->gamut;
2850 5460 break;
2851 5418 default:
2852 5418 csp->prim = AVCOL_PRI_BT709;
2853 5418 csp->gamut = av_csp_primaries_desc_from_id(csp->prim)->prim;
2854 5418 break;
2855 }
2856
2857 10878 return 1;
2858 }
2859
2860 11016 static int infer_trc_ref(SwsColor *csp, const SwsColor *ref)
2861 {
2862
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 10816 times.
11016 if (csp->trc != AVCOL_TRC_UNSPECIFIED)
2863 200 return 0;
2864
2865 /* Pick a suitable SDR transfer function, to try and minimize conversions */
2866
2/2
✓ Branch 0 taken 5387 times.
✓ Branch 1 taken 5429 times.
10816 switch (ref->trc) {
2867 5387 case AVCOL_TRC_UNSPECIFIED:
2868 /* HDR curves, never default to these */
2869 case AVCOL_TRC_SMPTE2084:
2870 case AVCOL_TRC_ARIB_STD_B67:
2871 5387 csp->trc = AVCOL_TRC_BT709;
2872 5387 csp->min_luma = av_make_q(0, 1);
2873 5387 csp->max_luma = av_make_q(203, 1);
2874 5387 break;
2875 5429 default:
2876 5429 csp->trc = ref->trc;
2877 5429 csp->min_luma = ref->min_luma;
2878 5429 csp->max_luma = ref->max_luma;
2879 5429 break;
2880 }
2881
2882 10816 return 1;
2883 }
2884
2885 5508 int ff_infer_colors(SwsColor *src, SwsColor *dst)
2886 {
2887 5508 int incomplete = 0;
2888
2889 5508 incomplete |= infer_prim_ref(dst, src);
2890 5508 incomplete |= infer_prim_ref(src, dst);
2891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 av_assert0(src->prim != AVCOL_PRI_UNSPECIFIED);
2892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 av_assert0(dst->prim != AVCOL_PRI_UNSPECIFIED);
2893
2894 5508 incomplete |= infer_trc_ref(dst, src);
2895 5508 incomplete |= infer_trc_ref(src, dst);
2896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 av_assert0(src->trc != AVCOL_TRC_UNSPECIFIED);
2897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5508 times.
5508 av_assert0(dst->trc != AVCOL_TRC_UNSPECIFIED);
2898
2899 5508 return incomplete;
2900 }
2901
2902 2999998 int sws_test_format(enum AVPixelFormat format, int output)
2903 {
2904
2/2
✓ Branch 0 taken 1499999 times.
✓ Branch 1 taken 1499999 times.
2999998 return output ? sws_isSupportedOutput(format) : sws_isSupportedInput(format);
2905 }
2906
2907 376522 int sws_test_colorspace(enum AVColorSpace csp, int output)
2908 {
2909
2/2
✓ Branch 0 taken 271672 times.
✓ Branch 1 taken 104850 times.
376522 switch (csp) {
2910 271672 case AVCOL_SPC_UNSPECIFIED:
2911 case AVCOL_SPC_RGB:
2912 case AVCOL_SPC_BT709:
2913 case AVCOL_SPC_BT470BG:
2914 case AVCOL_SPC_SMPTE170M:
2915 case AVCOL_SPC_FCC:
2916 case AVCOL_SPC_SMPTE240M:
2917 case AVCOL_SPC_BT2020_NCL:
2918 271672 return 1;
2919 104850 default:
2920 104850 return 0;
2921 }
2922 }
2923
2924 168562 int sws_test_primaries(enum AVColorPrimaries prim, int output)
2925 {
2926
3/6
✓ Branch 0 taken 168562 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168562 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 168562 times.
✗ Branch 5 not taken.
168562 return prim > AVCOL_PRI_RESERVED0 && prim < AVCOL_PRI_NB &&
2927 prim != AVCOL_PRI_RESERVED;
2928 }
2929
2930 168562 int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output)
2931 {
2932 84281 av_csp_eotf_function eotf = output ? av_csp_itu_eotf_inv(trc)
2933
2/2
✓ Branch 0 taken 84281 times.
✓ Branch 1 taken 84281 times.
168562 : av_csp_itu_eotf(trc);
2934
3/4
✓ Branch 0 taken 947 times.
✓ Branch 1 taken 167615 times.
✓ Branch 2 taken 947 times.
✗ Branch 3 not taken.
168562 return trc == AVCOL_TRC_UNSPECIFIED || eotf != NULL;
2935 }
2936
2937 168562 static int test_range(enum AVColorRange range)
2938 {
2939 168562 return range >= 0 && range < AVCOL_RANGE_NB;
2940 }
2941
2942 168562 static int test_loc(enum AVChromaLocation loc)
2943 {
2944 168562 return loc >= 0 && loc < AVCHROMA_LOC_NB;
2945 }
2946
2947 168562 int ff_test_fmt(const SwsFormat *fmt, int output)
2948 {
2949
2/4
✓ Branch 0 taken 168562 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168562 times.
✗ Branch 3 not taken.
337124 return fmt->width > 0 && fmt->height > 0 &&
2950
1/2
✓ Branch 1 taken 168562 times.
✗ Branch 2 not taken.
337124 sws_test_format (fmt->format, output) &&
2951
1/2
✓ Branch 1 taken 168562 times.
✗ Branch 2 not taken.
337124 sws_test_colorspace(fmt->csp, output) &&
2952
1/2
✓ Branch 1 taken 168562 times.
✗ Branch 2 not taken.
337124 sws_test_primaries (fmt->color.prim, output) &&
2953
1/2
✓ Branch 1 taken 168562 times.
✗ Branch 2 not taken.
337124 sws_test_transfer (fmt->color.trc, output) &&
2954
2/4
✓ Branch 0 taken 168562 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 168562 times.
✗ Branch 4 not taken.
505686 test_range (fmt->range) &&
2955 168562 test_loc (fmt->loc);
2956 }
2957
2958 int sws_test_frame(const AVFrame *frame, int output)
2959 {
2960 for (int field = 0; field < 2; field++) {
2961 const SwsFormat fmt = ff_fmt_from_frame(frame, field);
2962 if (!ff_test_fmt(&fmt, output))
2963 return 0;
2964 if (!fmt.interlaced)
2965 break;
2966 }
2967
2968 return 1;
2969 }
2970
2971 88985 int sws_is_noop(const AVFrame *dst, const AVFrame *src)
2972 {
2973
1/2
✓ Branch 0 taken 88985 times.
✗ Branch 1 not taken.
88985 for (int field = 0; field < 2; field++) {
2974 88985 SwsFormat dst_fmt = ff_fmt_from_frame(dst, field);
2975 88985 SwsFormat src_fmt = ff_fmt_from_frame(src, field);
2976
2/2
✓ Branch 1 taken 84281 times.
✓ Branch 2 taken 4704 times.
88985 if (!ff_fmt_equal(&dst_fmt, &src_fmt))
2977 84281 return 0;
2978
1/2
✓ Branch 0 taken 4704 times.
✗ Branch 1 not taken.
4704 if (!dst_fmt.interlaced)
2979 4704 break;
2980 }
2981
2982 4704 return 1;
2983 }
2984