FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/ops.c
Date: 2026-07-19 01:11:25
Exec Total Coverage
Lines: 579 624 92.8%
Functions: 30 30 100.0%
Branches: 378 427 88.5%

Line Branch Exec Source
1 /**
2 * Copyright (C) 2025 Niklas Haas
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "libavutil/attributes.h"
22 #include "libavutil/avassert.h"
23 #include "libavutil/avstring.h"
24 #include "libavutil/bprint.h"
25 #include "libavutil/bswap.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/rational.h"
28 #include "libavutil/refstruct.h"
29
30 #include "format.h"
31 #include "ops.h"
32 #include "ops_internal.h"
33
34 extern const SwsOpBackend backend_c;
35 extern const SwsOpBackend backend_murder;
36 extern const SwsOpBackend backend_aarch64;
37 extern const SwsOpBackend backend_x86;
38 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
39 extern const SwsOpBackend backend_spirv;
40 #endif
41
42 const SwsOpBackend * const ff_sws_op_backends[] = {
43 &backend_murder,
44 #if ARCH_AARCH64 && HAVE_NEON
45 &backend_aarch64,
46 #elif ARCH_X86_64 && HAVE_X86ASM
47 &backend_x86,
48 #endif
49 &backend_c,
50 #if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
51 &backend_spirv,
52 #endif
53 NULL
54 };
55
56 8475390 const char *ff_sws_pixel_type_name(SwsPixelType type)
57 {
58
4/7
✓ Branch 0 taken 1231168 times.
✓ Branch 1 taken 2848144 times.
✓ Branch 2 taken 473324 times.
✓ Branch 3 taken 3922754 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8475390 switch (type) {
59 1231168 case SWS_PIXEL_U8: return "u8";
60 2848144 case SWS_PIXEL_U16: return "u16";
61 473324 case SWS_PIXEL_U32: return "u32";
62 3922754 case SWS_PIXEL_F32: return "f32";
63 case SWS_PIXEL_NONE: return "none";
64 case SWS_PIXEL_TYPE_NB: break;
65 }
66
67 av_unreachable("Invalid pixel type!");
68 return "ERR";
69 }
70
71 5710970 const char *ff_sws_op_type_name(SwsOpType op)
72 {
73
17/20
✓ Branch 0 taken 950240 times.
✓ Branch 1 taken 1011795 times.
✓ Branch 2 taken 436338 times.
✓ Branch 3 taken 384271 times.
✓ Branch 4 taken 113862 times.
✓ Branch 5 taken 109553 times.
✓ Branch 6 taken 46067 times.
✓ Branch 7 taken 42141 times.
✓ Branch 8 taken 234527 times.
✓ Branch 9 taken 761491 times.
✓ Branch 10 taken 360522 times.
✓ Branch 11 taken 203911 times.
✓ Branch 12 taken 161112 times.
✓ Branch 13 taken 462620 times.
✓ Branch 14 taken 362588 times.
✓ Branch 15 taken 33753 times.
✓ Branch 16 taken 36179 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
5710970 switch (op) {
74 950240 case SWS_OP_READ: return "SWS_OP_READ";
75 1011795 case SWS_OP_WRITE: return "SWS_OP_WRITE";
76 436338 case SWS_OP_SWAP_BYTES: return "SWS_OP_SWAP_BYTES";
77 384271 case SWS_OP_SWIZZLE: return "SWS_OP_SWIZZLE";
78 113862 case SWS_OP_UNPACK: return "SWS_OP_UNPACK";
79 109553 case SWS_OP_PACK: return "SWS_OP_PACK";
80 46067 case SWS_OP_LSHIFT: return "SWS_OP_LSHIFT";
81 42141 case SWS_OP_RSHIFT: return "SWS_OP_RSHIFT";
82 234527 case SWS_OP_CLEAR: return "SWS_OP_CLEAR";
83 761491 case SWS_OP_CONVERT: return "SWS_OP_CONVERT";
84 360522 case SWS_OP_MIN: return "SWS_OP_MIN";
85 203911 case SWS_OP_MAX: return "SWS_OP_MAX";
86 161112 case SWS_OP_SCALE: return "SWS_OP_SCALE";
87 462620 case SWS_OP_LINEAR: return "SWS_OP_LINEAR";
88 362588 case SWS_OP_DITHER: return "SWS_OP_DITHER";
89 33753 case SWS_OP_FILTER_H: return "SWS_OP_FILTER_H";
90 36179 case SWS_OP_FILTER_V: return "SWS_OP_FILTER_V";
91 case SWS_OP_INVALID: return "SWS_OP_INVALID";
92 case SWS_OP_TYPE_NB: break;
93 }
94
95 av_unreachable("Invalid operation type!");
96 return "ERR";
97 }
98
99 12596416 SwsCompMask ff_sws_comp_mask_q4(const AVRational64 q[4])
100 {
101 12596416 SwsCompMask mask = 0;
102
2/2
✓ Branch 0 taken 50385664 times.
✓ Branch 1 taken 12596416 times.
62982080 for (int i = 0; i < 4; i++) {
103
2/2
✓ Branch 0 taken 32343715 times.
✓ Branch 1 taken 18041949 times.
50385664 if (q[i].den)
104 32343715 mask |= SWS_COMP(i);
105 }
106 12596416 return mask;
107 }
108
109 150376 void ff_sws_comp_mask_swizzle(SwsCompMask *mask, const SwsSwizzleOp *swiz)
110 {
111 150376 const SwsCompMask orig = *mask;
112 150376 SwsCompMask res = 0;
113
2/2
✓ Branch 0 taken 601504 times.
✓ Branch 1 taken 150376 times.
751880 for (int i = 0; i < 4; i++) {
114 601504 const int src = swiz->in[i];
115
2/2
✓ Branch 0 taken 234151 times.
✓ Branch 1 taken 367353 times.
601504 if (SWS_COMP_TEST(orig, src))
116 234151 res |= SWS_COMP(i);
117 }
118
119 150376 *mask = res;
120 150376 }
121
122 58105413 SwsCompMask ff_sws_comp_mask_needed(const SwsOp *op)
123 {
124 58105413 SwsCompMask mask = 0;
125
2/2
✓ Branch 0 taken 232421652 times.
✓ Branch 1 taken 58105413 times.
290527065 for (int i = 0; i < 4; i++) {
126
2/2
✓ Branch 0 taken 147134799 times.
✓ Branch 1 taken 85286853 times.
232421652 if (SWS_OP_NEEDED(op, i))
127 147134799 mask |= SWS_COMP(i);
128 }
129 58105413 return mask;
130 }
131
132 5136119 int ff_sws_rw_op_planes(const SwsOp *op)
133 {
134 av_assert2(op->op == SWS_OP_READ || op->op == SWS_OP_WRITE);
135
3/4
✓ Branch 0 taken 3689758 times.
✓ Branch 1 taken 1436329 times.
✓ Branch 2 taken 10032 times.
✗ Branch 3 not taken.
5136119 switch (op->rw.mode) {
136 3689758 case SWS_RW_PLANAR: return op->rw.elems;
137 1436329 case SWS_RW_PACKED: return 1;
138 10032 case SWS_RW_PALETTE: return 2;
139 }
140
141 av_unreachable("Invalid read/write mode!");
142 return 0;
143 }
144
145 /* biased towards `a` */
146 59225604 static AVRational64 av_min_q64(AVRational64 a, AVRational64 b)
147 {
148
2/2
✓ Branch 1 taken 14957601 times.
✓ Branch 2 taken 44268003 times.
59225604 return av_cmp_q64(a, b) == 1 ? b : a;
149 }
150
151 47031556 static AVRational64 av_max_q64(AVRational64 a, AVRational64 b)
152 {
153
2/2
✓ Branch 1 taken 7592420 times.
✓ Branch 2 taken 39439136 times.
47031556 return av_cmp_q64(a, b) == -1 ? b : a;
154 }
155
156 142725832 void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
157 {
158 uint64_t mask[4];
159 int shift[4];
160
161
12/16
✓ Branch 0 taken 40479498 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3346490 times.
✓ Branch 3 taken 40358 times.
✓ Branch 4 taken 11375336 times.
✓ Branch 5 taken 1438802 times.
✓ Branch 6 taken 1292864 times.
✓ Branch 7 taken 26027642 times.
✓ Branch 8 taken 28360756 times.
✓ Branch 9 taken 81272 times.
✓ Branch 10 taken 14806401 times.
✓ Branch 11 taken 11757889 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3718524 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
142725832 switch (op->op) {
162 40479498 case SWS_OP_READ:
163 case SWS_OP_WRITE:
164 40479498 return;
165 case SWS_OP_UNPACK: {
166 av_assert1(ff_sws_pixel_type_is_int(op->type));
167 ff_sws_pack_op_decode(op, mask, shift);
168 unsigned val = x[0].num;
169 for (int i = 0; i < 4; i++)
170 x[i] = Q((val >> shift[i]) & mask[i]);
171 return;
172 }
173 3346490 case SWS_OP_PACK: {
174 av_assert1(ff_sws_pixel_type_is_int(op->type));
175 3346490 ff_sws_pack_op_decode(op, mask, shift);
176 3346490 unsigned val = 0;
177
2/2
✓ Branch 0 taken 13385960 times.
✓ Branch 1 taken 3346490 times.
16732450 for (int i = 0; i < 4; i++)
178 13385960 val |= (x[i].num & mask[i]) << shift[i];
179 3346490 x[0] = Q(val);
180 3346490 return;
181 }
182 40358 case SWS_OP_SWAP_BYTES:
183
1/3
✓ Branch 0 taken 40358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
40358 switch (op->type) {
184 40358 case SWS_PIXEL_U16:
185
2/2
✓ Branch 0 taken 161432 times.
✓ Branch 1 taken 40358 times.
201790 for (int i = 0; i < 4; i++) {
186 av_assert2(x[i].num >= 0 && x[i].num <= UINT16_MAX);
187 161432 x[i].num = av_bswap16(x[i].num);
188 }
189 40358 return;
190 case SWS_PIXEL_U32:
191 for (int i = 0; i < 4; i++) {
192 av_assert2(x[i].num >= 0 && x[i].num <= UINT32_MAX);
193 x[i].num = av_bswap32(x[i].num);
194 }
195 return;
196 }
197 av_unreachable("Invalid pixel type for SWS_OP_SWAP_BYTES!");
198 return;
199 11375336 case SWS_OP_CLEAR:
200
2/2
✓ Branch 0 taken 45501344 times.
✓ Branch 1 taken 11375336 times.
56876680 for (int i = 0; i < 4; i++) {
201
2/2
✓ Branch 0 taken 13728902 times.
✓ Branch 1 taken 31772442 times.
45501344 if (SWS_COMP_TEST(op->clear.mask, i))
202 13728902 x[i] = op->clear.value[i];
203 }
204 11375336 return;
205 1438802 case SWS_OP_LSHIFT: {
206 av_assert1(ff_sws_pixel_type_is_int(op->type));
207 1438802 AVRational64 mult = Q(1 << op->shift.amount);
208
2/2
✓ Branch 0 taken 5755208 times.
✓ Branch 1 taken 1438802 times.
7194010 for (int i = 0; i < 4; i++)
209
2/2
✓ Branch 0 taken 4901500 times.
✓ Branch 1 taken 853708 times.
5755208 x[i] = x[i].den ? av_mul_q64(x[i], mult) : x[i];
210 1438802 return;
211 }
212 1292864 case SWS_OP_RSHIFT: {
213 av_assert1(ff_sws_pixel_type_is_int(op->type));
214
2/2
✓ Branch 0 taken 5171456 times.
✓ Branch 1 taken 1292864 times.
6464320 for (int i = 0; i < 4; i++)
215
2/2
✓ Branch 0 taken 3735268 times.
✓ Branch 1 taken 1436188 times.
5171456 x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->shift.amount) : x[i];
216 1292864 return;
217 }
218 26027642 case SWS_OP_SWIZZLE: {
219 26027642 const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] };
220
2/2
✓ Branch 0 taken 104110568 times.
✓ Branch 1 taken 26027642 times.
130138210 for (int i = 0; i < 4; i++)
221 104110568 x[i] = orig[op->swizzle.in[i]];
222 26027642 return;
223 }
224 28360756 case SWS_OP_CONVERT:
225
2/2
✓ Branch 0 taken 22324884 times.
✓ Branch 1 taken 6035872 times.
28360756 if (ff_sws_pixel_type_is_int(op->convert.to)) {
226 22324884 const AVRational64 scale = ff_sws_pixel_expand(op->type, op->convert.to);
227
2/2
✓ Branch 0 taken 89299536 times.
✓ Branch 1 taken 22324884 times.
111624420 for (int i = 0; i < 4; i++) {
228
2/2
✓ Branch 0 taken 78411146 times.
✓ Branch 1 taken 10888390 times.
89299536 x[i] = x[i].den ? Q(x[i].num / x[i].den) : x[i];
229
2/2
✓ Branch 0 taken 35064 times.
✓ Branch 1 taken 89264472 times.
89299536 if (op->convert.expand)
230 35064 x[i] = av_mul_q64(x[i], scale);
231 }
232 }
233 28360756 return;
234 81272 case SWS_OP_DITHER:
235 av_assert1(!ff_sws_pixel_type_is_int(op->type));
236
2/2
✓ Branch 0 taken 325088 times.
✓ Branch 1 taken 81272 times.
406360 for (int i = 0; i < 4; i++) {
237
3/4
✓ Branch 0 taken 207319 times.
✓ Branch 1 taken 117769 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 207319 times.
325088 if (op->dither.y_offset[i] >= 0 && x[i].den)
238 x[i] = av_add_q64(x[i], av_make_q64(1, 2));
239 }
240 81272 return;
241 14806401 case SWS_OP_MIN:
242
2/2
✓ Branch 0 taken 59225604 times.
✓ Branch 1 taken 14806401 times.
74032005 for (int i = 0; i < 4; i++)
243 59225604 x[i] = av_min_q64(x[i], op->clamp.limit[i]);
244 14806401 return;
245 11757889 case SWS_OP_MAX:
246
2/2
✓ Branch 0 taken 47031556 times.
✓ Branch 1 taken 11757889 times.
58789445 for (int i = 0; i < 4; i++)
247 47031556 x[i] = av_max_q64(x[i], op->clamp.limit[i]);
248 11757889 return;
249 case SWS_OP_LINEAR: {
250 av_assert1(!ff_sws_pixel_type_is_int(op->type));
251 const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] };
252 for (int i = 0; i < 4; i++) {
253 AVRational64 sum = op->lin.m[i][4];
254 for (int j = 0; j < 4; j++)
255 sum = av_add_q64(sum, av_mul_q64(orig[j], op->lin.m[i][j]));
256 x[i] = sum;
257 }
258 return;
259 }
260 3718524 case SWS_OP_SCALE:
261
2/2
✓ Branch 0 taken 14874096 times.
✓ Branch 1 taken 3718524 times.
18592620 for (int i = 0; i < 4; i++)
262
2/2
✓ Branch 0 taken 9556028 times.
✓ Branch 1 taken 5318068 times.
14874096 x[i] = x[i].den ? av_mul_q64(x[i], op->scale.factor) : x[i];
263 3718524 return;
264 case SWS_OP_FILTER_H:
265 case SWS_OP_FILTER_V:
266 /* Filters have normalized energy by definition, so they don't
267 * conceptually modify individual components */
268 return;
269 }
270
271 av_unreachable("Invalid operation type!");
272 }
273
274 enum {
275 SWS_COMP_IDENTITY = SWS_COMP_ZERO | SWS_COMP_EXACT |
276 SWS_COMP_COPY | SWS_COMP_CONST,
277
278 SWS_COMP_DIRTY = ~(SWS_COMP_COPY | SWS_COMP_CONST),
279 };
280
281 /* merge_comp_flags() forms a monoid with SWS_COMP_IDENTITY as the null element */
282 79178167 static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
283 {
284 79178167 const SwsCompFlags flags_or = SWS_COMP_GARBAGE;
285 79178167 const SwsCompFlags flags_and = SWS_COMP_IDENTITY;
286 79178167 return ((a & b) & flags_and) | ((a | b) & flags_or);
287 }
288
289 10046931 static void apply_filter_weights(SwsComps *comps, const SwsComps *prev,
290 const SwsFilterWeights *weights)
291 {
292 10046931 const AVRational64 posw = { weights->sum_positive, SWS_FILTER_SCALE };
293 10046931 const AVRational64 negw = { weights->sum_negative, SWS_FILTER_SCALE };
294
2/2
✓ Branch 0 taken 40187724 times.
✓ Branch 1 taken 10046931 times.
50234655 for (int i = 0; i < 4; i++) {
295 40187724 comps->flags[i] = prev->flags[i] & SWS_COMP_DIRTY;
296 /* Only point sampling preserves exactness */
297
2/2
✓ Branch 0 taken 39709328 times.
✓ Branch 1 taken 478396 times.
40187724 if (weights->filter_size != 1)
298 39709328 comps->flags[i] &= ~SWS_COMP_EXACT;
299 /* Update min/max assuming extremes */
300 40187724 comps->min[i] = av_add_q64(av_mul_q64(prev->min[i], posw),
301 av_mul_q64(prev->max[i], negw));
302 40187724 comps->max[i] = av_add_q64(av_mul_q64(prev->min[i], negw),
303 av_mul_q64(prev->max[i], posw));
304 }
305 10046931 }
306
307 /* Infer + propagate known information about components */
308 10398027 void ff_sws_op_list_update_comps(SwsOpList *ops)
309 {
310 10398027 SwsComps prev = { .flags = {
311 SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE,
312 }};
313
314 /* Forwards pass, propagates knowledge about the incoming pixel values */
315
2/2
✓ Branch 0 taken 106447314 times.
✓ Branch 1 taken 10398027 times.
116845341 for (int n = 0; n < ops->num_ops; n++) {
316 106447314 SwsOp *op = &ops->ops[n];
317
318
2/2
✓ Branch 0 taken 35346933 times.
✓ Branch 1 taken 71100381 times.
106447314 switch (op->op) {
319 35346933 case SWS_OP_LINEAR:
320 case SWS_OP_DITHER:
321 case SWS_OP_SWAP_BYTES:
322 case SWS_OP_UNPACK:
323 case SWS_OP_FILTER_H:
324 case SWS_OP_FILTER_V:
325 35346933 break; /* special cases, handled below */
326 71100381 default:
327 71100381 memcpy(op->comps.min, prev.min, sizeof(prev.min));
328 71100381 memcpy(op->comps.max, prev.max, sizeof(prev.max));
329 71100381 ff_sws_apply_op_q(op, op->comps.min);
330 71100381 ff_sws_apply_op_q(op, op->comps.max);
331 71100381 break;
332 }
333
334
14/15
✓ Branch 0 taken 9841722 times.
✓ Branch 1 taken 6946824 times.
✓ Branch 2 taken 10398027 times.
✓ Branch 3 taken 1364257 times.
✓ Branch 4 taken 13226904 times.
✓ Branch 5 taken 6272779 times.
✓ Branch 6 taken 1670322 times.
✓ Branch 7 taken 1673245 times.
✓ Branch 8 taken 5687668 times.
✓ Branch 9 taken 12938633 times.
✓ Branch 10 taken 14110663 times.
✓ Branch 11 taken 12322820 times.
✓ Branch 12 taken 1859262 times.
✓ Branch 13 taken 8134188 times.
✗ Branch 14 not taken.
106447314 switch (op->op) {
335 9841722 case SWS_OP_READ:
336 /* Active components are taken from the user-provided values,
337 * other components are explicitly stripped */
338
2/2
✓ Branch 0 taken 24713971 times.
✓ Branch 1 taken 9841722 times.
34555693 for (int i = 0; i < op->rw.elems; i++) {
339 24713971 int idx = 0;
340
3/4
✓ Branch 0 taken 194372 times.
✓ Branch 1 taken 9545719 times.
✓ Branch 2 taken 14973880 times.
✗ Branch 3 not taken.
24713971 switch (op->rw.mode) {
341 194372 case SWS_RW_PALETTE: idx = i; break;
342 9545719 case SWS_RW_PACKED: idx = i; break;
343 14973880 case SWS_RW_PLANAR: idx = ops->plane_src[i]; break;
344 }
345
346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24713971 times.
24713971 av_assert0(!(ops->comps_src.flags[idx] & SWS_COMP_GARBAGE));
347 24713971 op->comps.flags[i] = ops->comps_src.flags[idx] & SWS_COMP_DIRTY;
348 24713971 op->comps.min[i] = ops->comps_src.min[idx];
349 24713971 op->comps.max[i] = ops->comps_src.max[idx];
350
351 /**
352 * Don't mark packed or fractional reads as a copy, because the
353 * read operation implicitly unpacks the data into separate
354 * components. The only case in which op lists involving such
355 * reads can be refcopies is in the case of a true noop, which
356 * is already covered by the no-op check.
357 */
358
4/4
✓ Branch 0 taken 14973880 times.
✓ Branch 1 taken 9740091 times.
✓ Branch 2 taken 14818110 times.
✓ Branch 3 taken 155770 times.
24713971 if (op->rw.mode == SWS_RW_PLANAR && !op->rw.frac)
359 14818110 op->comps.flags[i] |= SWS_COMP_COPY;
360 }
361
362
2/2
✓ Branch 0 taken 1912743 times.
✓ Branch 1 taken 7928979 times.
9841722 if (op->rw.filter.op) {
363 1912743 const SwsComps prev = op->comps;
364 1912743 apply_filter_weights(&op->comps, &prev, op->rw.filter.kernel);
365 }
366 9841722 break;
367 6946824 case SWS_OP_SWAP_BYTES:
368
2/2
✓ Branch 0 taken 27787296 times.
✓ Branch 1 taken 6946824 times.
34734120 for (int i = 0; i < 4; i++) {
369 27787296 op->comps.flags[i] = (prev.flags[i] ^ SWS_COMP_SWAPPED) & SWS_COMP_DIRTY;
370 27787296 op->comps.min[i] = prev.min[i];
371 27787296 op->comps.max[i] = prev.max[i];
372 }
373 6946824 break;
374 10398027 case SWS_OP_WRITE:
375
2/2
✓ Branch 0 taken 27038627 times.
✓ Branch 1 taken 10398027 times.
37436654 for (int i = 0; i < op->rw.elems; i++)
376 av_assert1(!(prev.flags[i] & SWS_COMP_GARBAGE));
377
2/2
✓ Branch 0 taken 41592108 times.
✓ Branch 1 taken 10398027 times.
51990135 for (int i = 0; i < 4; i++)
378 41592108 op->comps.flags[i] = prev.flags[i];
379 10398027 break;
380 1364257 case SWS_OP_LSHIFT:
381 case SWS_OP_RSHIFT:
382
2/2
✓ Branch 0 taken 5457028 times.
✓ Branch 1 taken 1364257 times.
6821285 for (int i = 0; i < 4; i++)
383 5457028 op->comps.flags[i] = prev.flags[i] & SWS_COMP_DIRTY;
384 1364257 break;
385 13226904 case SWS_OP_MIN:
386 case SWS_OP_MAX: {
387
2/2
✓ Branch 0 taken 7368672 times.
✓ Branch 1 taken 5858232 times.
13226904 AVRational64 *bound = op->op == SWS_OP_MIN ? op->comps.max : op->comps.min;
388
2/2
✓ Branch 0 taken 52907616 times.
✓ Branch 1 taken 13226904 times.
66134520 for (int i = 0; i < 4; i++) {
389 52907616 op->comps.flags[i] = prev.flags[i];
390
2/2
✓ Branch 0 taken 45913400 times.
✓ Branch 1 taken 6994216 times.
52907616 if (op->clamp.limit[i].den)
391 45913400 op->comps.flags[i] &= SWS_COMP_DIRTY;
392
2/2
✓ Branch 0 taken 12787253 times.
✓ Branch 1 taken 40120363 times.
52907616 if (!bound[i].den) /* reset undefined bounds to known range */
393 12787253 bound[i] = op->clamp.limit[i];
394 }
395 13226904 break;
396 }
397 6272779 case SWS_OP_DITHER:
398
2/2
✓ Branch 0 taken 25091116 times.
✓ Branch 1 taken 6272779 times.
31363895 for (int i = 0; i < 4; i++) {
399 25091116 op->comps.flags[i] = prev.flags[i];
400 25091116 op->comps.min[i] = prev.min[i];
401 25091116 op->comps.max[i] = prev.max[i];
402
2/2
✓ Branch 0 taken 4350453 times.
✓ Branch 1 taken 20740663 times.
25091116 if (op->dither.y_offset[i] < 0)
403 4350453 continue;
404 /* Strip zero flag because of the nonzero dithering offset */
405 20740663 op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
406 20740663 op->comps.min[i] = av_add_q64(op->comps.min[i], op->dither.min);
407 20740663 op->comps.max[i] = av_add_q64(op->comps.max[i], op->dither.max);
408 }
409 6272779 break;
410 1670322 case SWS_OP_UNPACK:
411
2/2
✓ Branch 0 taken 6681288 times.
✓ Branch 1 taken 1670322 times.
8351610 for (int i = 0; i < 4; i++) {
412 6681288 const int pattern = op->pack.pattern[i];
413
2/2
✓ Branch 0 taken 5603384 times.
✓ Branch 1 taken 1077904 times.
6681288 if (pattern) {
414 av_assert1(pattern < 32);
415 5603384 op->comps.flags[i] = prev.flags[0] & SWS_COMP_DIRTY;
416 5603384 op->comps.min[i] = Q(0);
417 5603384 op->comps.max[i] = Q((1ULL << pattern) - 1);
418 } else
419 1077904 op->comps.flags[i] = SWS_COMP_GARBAGE;
420 }
421 1670322 break;
422 1673245 case SWS_OP_PACK: {
423 1673245 SwsCompFlags flags = SWS_COMP_IDENTITY;
424
2/2
✓ Branch 0 taken 6692980 times.
✓ Branch 1 taken 1673245 times.
8366225 for (int i = 0; i < 4; i++) {
425
2/2
✓ Branch 0 taken 5618458 times.
✓ Branch 1 taken 1074522 times.
6692980 if (op->pack.pattern[i])
426 5618458 flags = merge_comp_flags(flags, prev.flags[i]);
427
2/2
✓ Branch 0 taken 5019735 times.
✓ Branch 1 taken 1673245 times.
6692980 if (i > 0) /* clear remaining comps for sanity */
428 5019735 op->comps.flags[i] = SWS_COMP_GARBAGE;
429 }
430 1673245 op->comps.flags[0] = flags & SWS_COMP_DIRTY;
431 1673245 break;
432 }
433 5687668 case SWS_OP_CLEAR:
434
2/2
✓ Branch 0 taken 22750672 times.
✓ Branch 1 taken 5687668 times.
28438340 for (int i = 0; i < 4; i++) {
435
2/2
✓ Branch 0 taken 6864451 times.
✓ Branch 1 taken 15886221 times.
22750672 if (SWS_COMP_TEST(op->clear.mask, i)) {
436 6864451 op->comps.flags[i] = SWS_COMP_CONST;
437
2/2
✓ Branch 0 taken 3829462 times.
✓ Branch 1 taken 3034989 times.
6864451 if (op->clear.value[i].num == 0)
438 3829462 op->comps.flags[i] |= SWS_COMP_ZERO;
439
1/2
✓ Branch 0 taken 6864451 times.
✗ Branch 1 not taken.
6864451 if (op->clear.value[i].den == 1)
440 6864451 op->comps.flags[i] |= SWS_COMP_EXACT;
441 } else {
442 15886221 op->comps.flags[i] = prev.flags[i];
443 }
444 }
445 5687668 break;
446 12938633 case SWS_OP_SWIZZLE:
447
2/2
✓ Branch 0 taken 51754532 times.
✓ Branch 1 taken 12938633 times.
64693165 for (int i = 0; i < 4; i++)
448 51754532 op->comps.flags[i] = prev.flags[op->swizzle.in[i]];
449 12938633 break;
450 14110663 case SWS_OP_CONVERT:
451
2/2
✓ Branch 0 taken 56442652 times.
✓ Branch 1 taken 14110663 times.
70553315 for (int i = 0; i < 4; i++) {
452 56442652 op->comps.flags[i] = prev.flags[i];
453
4/4
✓ Branch 0 taken 20213105 times.
✓ Branch 1 taken 36229547 times.
✓ Branch 2 taken 14283 times.
✓ Branch 3 taken 20198822 times.
56442652 if (!(prev.flags[i] & SWS_COMP_EXACT) || op->convert.expand)
454 36243830 op->comps.flags[i] &= SWS_COMP_DIRTY;
455
2/2
✓ Branch 0 taken 44370908 times.
✓ Branch 1 taken 12071744 times.
56442652 if (ff_sws_pixel_type_is_int(op->convert.to))
456 44370908 op->comps.flags[i] |= SWS_COMP_EXACT;
457 }
458 14110663 break;
459 12322820 case SWS_OP_LINEAR:
460
2/2
✓ Branch 0 taken 49291280 times.
✓ Branch 1 taken 12322820 times.
61614100 for (int i = 0; i < 4; i++) {
461 49291280 SwsCompFlags flags = SWS_COMP_IDENTITY;
462 49291280 AVRational64 min = Q(0), max = Q(0);
463 49291280 bool first = true;
464
2/2
✓ Branch 0 taken 197165120 times.
✓ Branch 1 taken 49291280 times.
246456400 for (int j = 0; j < 4; j++) {
465 197165120 const AVRational64 k = op->lin.m[i][j];
466 197165120 AVRational64 mink = av_mul_q64(prev.min[j], k);
467 197165120 AVRational64 maxk = av_mul_q64(prev.max[j], k);
468
2/2
✓ Branch 0 taken 73559709 times.
✓ Branch 1 taken 123605411 times.
197165120 if (k.num) {
469 73559709 flags = merge_comp_flags(flags, prev.flags[j]);
470
2/2
✓ Branch 0 taken 44425886 times.
✓ Branch 1 taken 29133823 times.
73559709 if (k.den != 1) /* fractional coefficient */
471 44425886 flags &= ~SWS_COMP_EXACT;
472
2/2
✓ Branch 0 taken 14268142 times.
✓ Branch 1 taken 59291567 times.
73559709 if (k.num < 0)
473 14268142 FFSWAP(AVRational64, mink, maxk);
474 73559709 min = av_add_q64(min, mink);
475 73559709 max = av_add_q64(max, maxk);
476
4/4
✓ Branch 0 taken 49291280 times.
✓ Branch 1 taken 24268429 times.
✓ Branch 3 taken 29788880 times.
✓ Branch 4 taken 19502400 times.
73559709 if (!first || av_cmp_q64(k, Q(1)))
477 54057309 flags &= SWS_COMP_DIRTY;
478 73559709 first = false;
479 }
480 }
481
2/2
✓ Branch 0 taken 14954269 times.
✓ Branch 1 taken 34337011 times.
49291280 if (op->lin.m[i][4].num) { /* nonzero offset */
482 14954269 flags &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
483
2/2
✓ Branch 0 taken 5859776 times.
✓ Branch 1 taken 9094493 times.
14954269 if (op->lin.m[i][4].den != 1) /* fractional offset */
484 5859776 flags &= ~SWS_COMP_EXACT;
485 14954269 min = av_add_q64(min, op->lin.m[i][4]);
486 14954269 max = av_add_q64(max, op->lin.m[i][4]);
487 }
488 49291280 op->comps.flags[i] = flags;
489 49291280 op->comps.min[i] = min;
490 49291280 op->comps.max[i] = max;
491 }
492 12322820 break;
493 1859262 case SWS_OP_SCALE:
494
2/2
✓ Branch 0 taken 7437048 times.
✓ Branch 1 taken 1859262 times.
9296310 for (int i = 0; i < 4; i++) {
495 7437048 op->comps.flags[i] = prev.flags[i] & SWS_COMP_DIRTY;
496
2/2
✓ Branch 0 taken 5383948 times.
✓ Branch 1 taken 2053100 times.
7437048 if (op->scale.factor.den != 1) /* fractional scale */
497 5383948 op->comps.flags[i] &= ~SWS_COMP_EXACT;
498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7437048 times.
7437048 if (op->scale.factor.num < 0)
499 FFSWAP(AVRational64, op->comps.min[i], op->comps.max[i]);
500 }
501 1859262 break;
502 8134188 case SWS_OP_FILTER_H:
503 case SWS_OP_FILTER_V: {
504 8134188 apply_filter_weights(&op->comps, &prev, op->filter.kernel);
505 8134188 break;
506 }
507
508 case SWS_OP_INVALID:
509 case SWS_OP_TYPE_NB:
510 av_unreachable("Invalid operation type!");
511 }
512
513 106447314 prev = op->comps;
514 }
515
516 /* Backwards pass, solves for component dependencies */
517 10398027 bool need_out[4] = { false, false, false, false };
518
2/2
✓ Branch 0 taken 106447314 times.
✓ Branch 1 taken 10398027 times.
116845341 for (int n = ops->num_ops - 1; n >= 0; n--) {
519 106447314 SwsOp *op = &ops->ops[n];
520 106447314 bool need_in[4] = { false, false, false, false };
521
522
2/2
✓ Branch 0 taken 425789256 times.
✓ Branch 1 taken 106447314 times.
532236570 for (int i = 0; i < 4; i++) {
523
2/2
✓ Branch 0 taken 158546780 times.
✓ Branch 1 taken 267242476 times.
425789256 if (!need_out[i])
524 158546780 op->comps.flags[i] = SWS_COMP_GARBAGE;
525 }
526
527
7/8
✓ Branch 0 taken 20239749 times.
✓ Branch 1 taken 51914877 times.
✓ Branch 2 taken 1670322 times.
✓ Branch 3 taken 1673245 times.
✓ Branch 4 taken 5687668 times.
✓ Branch 5 taken 12938633 times.
✓ Branch 6 taken 12322820 times.
✗ Branch 7 not taken.
106447314 switch (op->op) {
528 20239749 case SWS_OP_READ:
529 case SWS_OP_WRITE:
530
2/2
✓ Branch 0 taken 51752598 times.
✓ Branch 1 taken 20239749 times.
71992347 for (int i = 0; i < op->rw.elems; i++)
531 51752598 need_in[i] = op->op == SWS_OP_WRITE;
532
2/2
✓ Branch 0 taken 29206398 times.
✓ Branch 1 taken 20239749 times.
49446147 for (int i = op->rw.elems; i < 4; i++)
533 29206398 need_in[i] = need_out[i];
534 20239749 break;
535 51914877 case SWS_OP_SWAP_BYTES:
536 case SWS_OP_LSHIFT:
537 case SWS_OP_RSHIFT:
538 case SWS_OP_CONVERT:
539 case SWS_OP_DITHER:
540 case SWS_OP_MIN:
541 case SWS_OP_MAX:
542 case SWS_OP_SCALE:
543 case SWS_OP_FILTER_H:
544 case SWS_OP_FILTER_V:
545
2/2
✓ Branch 0 taken 207659508 times.
✓ Branch 1 taken 51914877 times.
259574385 for (int i = 0; i < 4; i++)
546 207659508 need_in[i] = need_out[i];
547 51914877 break;
548 1670322 case SWS_OP_UNPACK:
549
4/4
✓ Branch 0 taken 6681288 times.
✓ Branch 1 taken 592418 times.
✓ Branch 2 taken 5603384 times.
✓ Branch 3 taken 1077904 times.
7273706 for (int i = 0; i < 4 && op->pack.pattern[i]; i++)
550 5603384 need_in[0] |= need_out[i];
551 1670322 break;
552 1673245 case SWS_OP_PACK:
553
4/4
✓ Branch 0 taken 6692980 times.
✓ Branch 1 taken 598723 times.
✓ Branch 2 taken 5618458 times.
✓ Branch 3 taken 1074522 times.
7291703 for (int i = 0; i < 4 && op->pack.pattern[i]; i++)
554 5618458 need_in[i] = need_out[0];
555 1673245 break;
556 5687668 case SWS_OP_CLEAR:
557
2/2
✓ Branch 0 taken 22750672 times.
✓ Branch 1 taken 5687668 times.
28438340 for (int i = 0; i < 4; i++) {
558
2/2
✓ Branch 0 taken 15886221 times.
✓ Branch 1 taken 6864451 times.
22750672 if (!SWS_COMP_TEST(op->clear.mask, i))
559 15886221 need_in[i] = need_out[i];
560 }
561 5687668 break;
562 12938633 case SWS_OP_SWIZZLE:
563
2/2
✓ Branch 0 taken 51754532 times.
✓ Branch 1 taken 12938633 times.
64693165 for (int i = 0; i < 4; i++)
564 51754532 need_in[op->swizzle.in[i]] |= need_out[i];
565 12938633 break;
566 12322820 case SWS_OP_LINEAR:
567
2/2
✓ Branch 0 taken 49291280 times.
✓ Branch 1 taken 12322820 times.
61614100 for (int i = 0; i < 4; i++) {
568
2/2
✓ Branch 0 taken 197165120 times.
✓ Branch 1 taken 49291280 times.
246456400 for (int j = 0; j < 4; j++) {
569
2/2
✓ Branch 0 taken 73559709 times.
✓ Branch 1 taken 123605411 times.
197165120 if (op->lin.m[i][j].num)
570 73559709 need_in[j] |= need_out[i];
571 }
572 }
573 12322820 break;
574 }
575
576 106447314 memcpy(need_out, need_in, sizeof(need_in));
577 }
578 10398027 }
579
580 23764119 static void op_uninit(SwsOp *op)
581 {
582
4/4
✓ Branch 0 taken 2834716 times.
✓ Branch 1 taken 1423844 times.
✓ Branch 2 taken 1663506 times.
✓ Branch 3 taken 17842053 times.
23764119 switch (op->op) {
583 2834716 case SWS_OP_READ:
584 2834716 av_refstruct_unref(&op->rw.filter.kernel);
585 2834716 break;
586 1423844 case SWS_OP_DITHER:
587 1423844 av_refstruct_unref(&op->dither.matrix);
588 1423844 break;
589 1663506 case SWS_OP_FILTER_H:
590 case SWS_OP_FILTER_V:
591 1663506 av_refstruct_unref(&op->filter.kernel);
592 1663506 break;
593 }
594
595 23764119 *op = (SwsOp) {0};
596 23764119 }
597
598 791925 SwsOpList *ff_sws_op_list_alloc(void)
599 {
600 791925 SwsOpList *ops = av_mallocz(sizeof(SwsOpList));
601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 791925 times.
791925 if (!ops)
602 return NULL;
603
604
2/2
✓ Branch 0 taken 3167700 times.
✓ Branch 1 taken 791925 times.
3959625 for (int i = 0; i < 4; i++)
605 3167700 ops->plane_src[i] = ops->plane_dst[i] = i;
606 791925 ff_fmt_clear(&ops->src);
607 791925 ff_fmt_clear(&ops->dst);
608 791925 return ops;
609 }
610
611 4095336 void ff_sws_op_list_free(SwsOpList **p_ops)
612 {
613 4095336 SwsOpList *ops = *p_ops;
614
2/2
✓ Branch 0 taken 1303987 times.
✓ Branch 1 taken 2791349 times.
4095336 if (!ops)
615 1303987 return;
616
617
2/2
✓ Branch 0 taken 16793513 times.
✓ Branch 1 taken 2791349 times.
19584862 for (int i = 0; i < ops->num_ops; i++)
618 16793513 op_uninit(&ops->ops[i]);
619
620 2791349 av_freep(&ops->ops);
621 2791349 av_free(ops);
622 2791349 *p_ops = NULL;
623 }
624
625 1999424 SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops)
626 {
627 1999424 SwsOpList *copy = av_malloc(sizeof(*copy));
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1999424 times.
1999424 if (!copy)
629 return NULL;
630
631 1999424 int num = ops->num_ops;
632
1/2
✓ Branch 0 taken 1999424 times.
✗ Branch 1 not taken.
1999424 if (num)
633 1999424 num = 1 << av_ceil_log2(num);
634
635 1999424 *copy = *ops;
636 1999424 copy->ops = av_memdup(ops->ops, num * sizeof(ops->ops[0]));
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1999424 times.
1999424 if (!copy->ops) {
638 av_free(copy);
639 return NULL;
640 }
641
642
2/2
✓ Branch 0 taken 14543316 times.
✓ Branch 1 taken 1999424 times.
16542740 for (int i = 0; i < copy->num_ops; i++) {
643 14543316 const SwsOp *op = &copy->ops[i];
644
4/4
✓ Branch 0 taken 1940117 times.
✓ Branch 1 taken 1056240 times.
✓ Branch 2 taken 1204224 times.
✓ Branch 3 taken 10342735 times.
14543316 switch (op->op) {
645 1940117 case SWS_OP_READ:
646
2/2
✓ Branch 0 taken 727583 times.
✓ Branch 1 taken 1212534 times.
1940117 if (op->rw.filter.kernel)
647 727583 av_refstruct_ref(op->rw.filter.kernel);
648 1940117 break;
649 1056240 case SWS_OP_DITHER:
650 1056240 av_refstruct_ref(op->dither.matrix);
651 1056240 break;
652 1204224 case SWS_OP_FILTER_H:
653 case SWS_OP_FILTER_V:
654 1204224 av_refstruct_ref(op->filter.kernel);
655 1204224 break;
656 }
657 }
658
659 1999424 return copy;
660 }
661
662 1209139 const SwsOp *ff_sws_op_list_input(const SwsOpList *ops)
663 {
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1209139 times.
1209139 if (!ops->num_ops)
665 return NULL;
666
667 1209139 const SwsOp *read = &ops->ops[0];
668
2/2
✓ Branch 0 taken 1200199 times.
✓ Branch 1 taken 8940 times.
1209139 return read->op == SWS_OP_READ ? read : NULL;
669 }
670
671 2461596 const SwsOp *ff_sws_op_list_output(const SwsOpList *ops)
672 {
673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2461596 times.
2461596 if (!ops->num_ops)
674 return NULL;
675
676 2461596 const SwsOp *write = &ops->ops[ops->num_ops - 1];
677
1/2
✓ Branch 0 taken 2461596 times.
✗ Branch 1 not taken.
2461596 return write->op == SWS_OP_WRITE ? write : NULL;
678 }
679
680 4727205 void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
681 {
682 4727205 const int end = ops->num_ops - count;
683 av_assert2(index >= 0 && count >= 0 && index + count <= ops->num_ops);
684
2/2
✓ Branch 0 taken 6970606 times.
✓ Branch 1 taken 4727205 times.
11697811 for (int i = 0; i < count; i++)
685 6970606 op_uninit(&ops->ops[index + i]);
686
2/2
✓ Branch 0 taken 30456679 times.
✓ Branch 1 taken 4727205 times.
35183884 for (int i = index; i < end; i++)
687 30456679 ops->ops[i] = ops->ops[i + count];
688 4727205 ops->num_ops = end;
689 4727205 }
690
691 9220803 int ff_sws_op_list_insert_at(SwsOpList *ops, int index, SwsOp *op)
692 {
693 9220803 void *ret = av_dynarray2_add((void **) &ops->ops, &ops->num_ops, sizeof(*op), NULL);
694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9220803 times.
9220803 if (!ret) {
695 op_uninit(op);
696 return AVERROR(ENOMEM);
697 }
698
699
2/2
✓ Branch 0 taken 4477821 times.
✓ Branch 1 taken 9220803 times.
13698624 for (int i = ops->num_ops - 1; i > index; i--)
700 4477821 ops->ops[i] = ops->ops[i - 1];
701 9220803 ops->ops[index] = *op;
702 9220803 return 0;
703 }
704
705 8537539 int ff_sws_op_list_append(SwsOpList *ops, SwsOp *op)
706 {
707 8537539 return ff_sws_op_list_insert_at(ops, ops->num_ops, op);
708 }
709
710 803499 bool ff_sws_op_list_is_noop(const SwsOpList *ops)
711 {
712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 803499 times.
803499 if (!ops->num_ops)
713 return true;
714
715 803499 const SwsOp *read = ff_sws_op_list_input(ops);
716 803499 const SwsOp *write = ff_sws_op_list_output(ops);
717
4/6
✓ Branch 0 taken 803499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 803499 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 153325 times.
✓ Branch 5 taken 650174 times.
803499 if (!read || !write || ops->num_ops > 2 ||
718
2/2
✓ Branch 0 taken 62774 times.
✓ Branch 1 taken 90551 times.
153325 read->type != write->type ||
719
2/2
✓ Branch 0 taken 15124 times.
✓ Branch 1 taken 47650 times.
62774 read->rw.mode != write->rw.mode ||
720
2/2
✓ Branch 0 taken 15044 times.
✓ Branch 1 taken 80 times.
15124 read->rw.elems != write->rw.elems ||
721
2/2
✓ Branch 0 taken 10734 times.
✓ Branch 1 taken 4310 times.
15044 read->rw.frac != write->rw.frac ||
722
3/4
✓ Branch 0 taken 789 times.
✓ Branch 1 taken 9945 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
10734 read->rw.filter.op || write->rw.filter.op)
723 802710 return false;
724
725 /**
726 * Note that this check is unlikely to ever be hit in practice, since it
727 * would imply the existence of planar formats with different plane orders
728 * between them, e.g. rgbap <-> gbrap, which doesn't currently exist.
729 * However, the check is cheap and lets me sleep at night.
730 */
731 789 const int num_planes = ff_sws_rw_op_planes(read);
732
2/2
✓ Branch 0 taken 1729 times.
✓ Branch 1 taken 789 times.
2518 for (int i = 0; i < num_planes; i++) {
733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1729 times.
1729 if (ops->plane_src[i] != ops->plane_dst[i])
734 return false;
735 }
736
737 789 return true;
738 }
739
740 19515 int ff_sws_op_list_max_size(const SwsOpList *ops)
741 {
742 19515 int max_size = 0;
743
2/2
✓ Branch 0 taken 144570 times.
✓ Branch 1 taken 19515 times.
164085 for (int i = 0; i < ops->num_ops; i++) {
744 144570 const int size = ff_sws_pixel_type_size(ops->ops[i].type);
745 144570 max_size = FFMAX(max_size, size);
746 }
747
748 19515 return max_size;
749 }
750
751 3043385 uint32_t ff_sws_linear_mask(const SwsLinearOp *c)
752 {
753 3043385 uint32_t mask = 0;
754
2/2
✓ Branch 0 taken 12173540 times.
✓ Branch 1 taken 3043385 times.
15216925 for (int i = 0; i < 4; i++) {
755
2/2
✓ Branch 0 taken 60867700 times.
✓ Branch 1 taken 12173540 times.
73041240 for (int j = 0; j < 5; j++) {
756
2/2
✓ Branch 1 taken 18629252 times.
✓ Branch 2 taken 42238448 times.
60867700 if (av_cmp_q64(c->m[i][j], Q(i == j)))
757 18629252 mask |= SWS_MASK(i, j);
758 }
759 }
760 3043385 return mask;
761 }
762
763 22843880 static char describe_comp_flags(SwsCompFlags flags)
764 {
765
2/2
✓ Branch 0 taken 9630064 times.
✓ Branch 1 taken 13213816 times.
22843880 if (flags & SWS_COMP_GARBAGE)
766 9630064 return 'X';
767
2/2
✓ Branch 0 taken 35275 times.
✓ Branch 1 taken 13178541 times.
13213816 else if (flags & SWS_COMP_ZERO)
768 35275 return '0';
769
2/2
✓ Branch 0 taken 1073972 times.
✓ Branch 1 taken 12104569 times.
13178541 else if (flags & SWS_COMP_SWAPPED)
770 1073972 return 'z';
771
2/2
✓ Branch 0 taken 189802 times.
✓ Branch 1 taken 11914767 times.
12104569 else if (flags & SWS_COMP_CONST)
772 189802 return '$';
773
2/2
✓ Branch 0 taken 231774 times.
✓ Branch 1 taken 11682993 times.
11914767 else if (flags & SWS_COMP_COPY)
774 231774 return '=';
775
2/2
✓ Branch 0 taken 4035799 times.
✓ Branch 1 taken 7647194 times.
11682993 else if (flags & SWS_COMP_EXACT)
776 4035799 return '+';
777 else
778 7647194 return '.';
779 }
780
781 30724583 static void print_q(AVBPrint *bp, const AVRational64 q)
782 {
783
2/2
✓ Branch 0 taken 135212 times.
✓ Branch 1 taken 30589371 times.
30724583 if (!q.den) {
784
2/4
✓ Branch 0 taken 135212 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 135212 times.
135212 av_bprintf(bp, "%s", q.num > 0 ? "inf" : q.num < 0 ? "-inf" : "nan");
785
2/2
✓ Branch 0 taken 24824246 times.
✓ Branch 1 taken 5765125 times.
30589371 } else if (q.den == 1) {
786 24824246 av_bprintf(bp, "%"PRId64, q.num);
787
7/8
✓ Branch 0 taken 3152941 times.
✓ Branch 1 taken 2612184 times.
✓ Branch 2 taken 1733677 times.
✓ Branch 3 taken 1419264 times.
✓ Branch 4 taken 1357916 times.
✓ Branch 5 taken 375761 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1357916 times.
5765125 } else if (q.num > 1000 || q.num < -1000 || q.den > 1000 || q.den < -1000) {
788 4407209 av_bprintf(bp, "%f", av_q2d_64(q));
789 } else {
790 1357916 av_bprintf(bp, "%"PRId64"/%"PRId64, q.num, q.den);
791 }
792 30724583 }
793
794 8210984 static void print_q4(AVBPrint *bp, const AVRational64 q4[4], SwsCompMask mask)
795 {
796 8210984 av_bprintf(bp, "{");
797
2/2
✓ Branch 0 taken 32843936 times.
✓ Branch 1 taken 8210984 times.
41054920 for (int i = 0; i < 4; i++) {
798
2/2
✓ Branch 0 taken 24632952 times.
✓ Branch 1 taken 8210984 times.
32843936 if (i)
799 24632952 av_bprintf(bp, " ");
800
2/2
✓ Branch 0 taken 11371753 times.
✓ Branch 1 taken 21472183 times.
32843936 if (!SWS_COMP_TEST(mask, i)) {
801 11371753 av_bprintf(bp, "_");
802 } else {
803 21472183 print_q(bp, q4[i]);
804 }
805 }
806 8210984 av_bprintf(bp, "}");
807 8210984 }
808
809 static const char *const rw_mode_names[] = {
810 [SWS_RW_PLANAR] = "planar",
811 [SWS_RW_PACKED] = "packed",
812 [SWS_RW_PALETTE] = "palette"
813 };
814
815 5710970 void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
816 {
817 5710970 const char *name = ff_sws_op_type_name(op->op);
818 5710970 const SwsCompMask mask = ff_sws_comp_mask_needed(op);
819
820
14/16
✓ Branch 0 taken 436338 times.
✓ Branch 1 taken 1962035 times.
✓ Branch 2 taken 46067 times.
✓ Branch 3 taken 42141 times.
✓ Branch 4 taken 223415 times.
✓ Branch 5 taken 234527 times.
✓ Branch 6 taken 384271 times.
✓ Branch 7 taken 761491 times.
✓ Branch 8 taken 362588 times.
✓ Branch 9 taken 360522 times.
✓ Branch 10 taken 203911 times.
✓ Branch 11 taken 462620 times.
✓ Branch 12 taken 161112 times.
✓ Branch 13 taken 69932 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
5710970 switch (op->op) {
821 436338 case SWS_OP_INVALID:
822 case SWS_OP_SWAP_BYTES:
823 436338 av_bprintf(bp, "%s", name);
824 436338 break;
825 1962035 case SWS_OP_READ:
826 case SWS_OP_WRITE:
827 1962035 av_bprintf(bp, "%-20s: %d elem(s) %s >> %d", name,
828 1962035 op->rw.elems, rw_mode_names[op->rw.mode],
829 1962035 op->rw.frac);
830
2/2
✓ Branch 0 taken 1496809 times.
✓ Branch 1 taken 465226 times.
1962035 if (!op->rw.filter.op)
831 1496809 break;
832 465226 const SwsFilterWeights *kernel = op->rw.filter.kernel;
833 465226 av_bprintf(bp, " + %d tap %s filter (%c)",
834 465226 kernel->filter_size, kernel->name,
835
2/2
✓ Branch 0 taken 234297 times.
✓ Branch 1 taken 230929 times.
465226 op->rw.filter.op == SWS_OP_FILTER_H ? 'H' : 'V');
836 465226 break;
837 46067 case SWS_OP_LSHIFT:
838 46067 av_bprintf(bp, "%-20s: << %u", name, op->shift.amount);
839 46067 break;
840 42141 case SWS_OP_RSHIFT:
841 42141 av_bprintf(bp, "%-20s: >> %u", name, op->shift.amount);
842 42141 break;
843 223415 case SWS_OP_PACK:
844 case SWS_OP_UNPACK:
845 223415 av_bprintf(bp, "%-20s: {%d %d %d %d}", name,
846 223415 op->pack.pattern[0], op->pack.pattern[1],
847 223415 op->pack.pattern[2], op->pack.pattern[3]);
848 223415 break;
849 234527 case SWS_OP_CLEAR:
850 234527 av_bprintf(bp, "%-20s: ", name);
851 234527 print_q4(bp, op->clear.value, mask & op->clear.mask);
852 234527 break;
853 384271 case SWS_OP_SWIZZLE:
854 384271 av_bprintf(bp, "%-20s: %d%d%d%d", name,
855 384271 op->swizzle.x, op->swizzle.y, op->swizzle.z, op->swizzle.w);
856 384271 break;
857 761491 case SWS_OP_CONVERT:
858 1522982 av_bprintf(bp, "%-20s: %s -> %s%s", name,
859 761491 ff_sws_pixel_type_name(op->type),
860 761491 ff_sws_pixel_type_name(op->convert.to),
861
2/2
✓ Branch 0 taken 1704 times.
✓ Branch 1 taken 759787 times.
761491 op->convert.expand ? " (expand)" : "");
862 761491 break;
863 362588 case SWS_OP_DITHER:
864 362588 av_bprintf(bp, "%-20s: %dx%d matrix + {%d %d %d %d}", name,
865 362588 1 << op->dither.size_log2, 1 << op->dither.size_log2,
866 362588 op->dither.y_offset[0], op->dither.y_offset[1],
867 362588 op->dither.y_offset[2], op->dither.y_offset[3]);
868 362588 break;
869 360522 case SWS_OP_MIN:
870 360522 av_bprintf(bp, "%-20s: x <= ", name);
871 360522 print_q4(bp, op->clamp.limit, mask & ff_sws_comp_mask_q4(op->clamp.limit));
872 360522 break;
873 203911 case SWS_OP_MAX:
874 203911 av_bprintf(bp, "%-20s: ", name);
875 203911 print_q4(bp, op->clamp.limit, mask & ff_sws_comp_mask_q4(op->clamp.limit));
876 203911 av_bprintf(bp, " <= x");
877 203911 break;
878 462620 case SWS_OP_LINEAR:
879 462620 av_bprintf(bp, "%-20s: [", name);
880
2/2
✓ Branch 0 taken 1850480 times.
✓ Branch 1 taken 462620 times.
2313100 for (int i = 0; i < 4; i++) {
881
2/2
✓ Branch 0 taken 1387860 times.
✓ Branch 1 taken 462620 times.
1850480 av_bprintf(bp, "%s[", i ? " " : "");
882
2/2
✓ Branch 0 taken 9252400 times.
✓ Branch 1 taken 1850480 times.
11102880 for (int j = 0; j < 5; j++) {
883
2/2
✓ Branch 0 taken 7401920 times.
✓ Branch 1 taken 1850480 times.
9252400 av_bprintf(bp, j ? " " : "");
884 9252400 print_q(bp, op->lin.m[i][j]);
885 }
886 1850480 av_bprintf(bp, "]");
887 }
888 462620 av_bprintf(bp, "]");
889 462620 break;
890 161112 case SWS_OP_SCALE:
891 161112 av_bprintf(bp, "%-20s: * %"PRId64, name, op->scale.factor.num);
892
2/2
✓ Branch 0 taken 119779 times.
✓ Branch 1 taken 41333 times.
161112 if (op->scale.factor.den != 1)
893 119779 av_bprintf(bp, "/%"PRId64, op->scale.factor.den);
894 161112 break;
895 69932 case SWS_OP_FILTER_H:
896 case SWS_OP_FILTER_V: {
897 69932 const SwsFilterWeights *kernel = op->filter.kernel;
898 69932 av_bprintf(bp, "%-20s: %d -> %d %s (%d taps)", name,
899 69932 kernel->src_size, kernel->dst_size,
900 69932 kernel->name, kernel->filter_size);
901 69932 break;
902 }
903 case SWS_OP_TYPE_NB:
904 break;
905 }
906 5710970 }
907
908 1962035 static void desc_plane_order(AVBPrint *bp, int nb_planes, const uint8_t *order)
909 {
910 1962035 bool inorder = true;
911
2/2
✓ Branch 0 taken 4264241 times.
✓ Branch 1 taken 1962035 times.
6226276 for (int i = 0; i < nb_planes; i++)
912 4264241 inorder &= order[i] == i;
913
2/2
✓ Branch 0 taken 1639176 times.
✓ Branch 1 taken 322859 times.
1962035 if (inorder)
914 1639176 return;
915
916 322859 av_bprintf(bp, ", via {");
917
2/2
✓ Branch 0 taken 891876 times.
✓ Branch 1 taken 322859 times.
1214735 for (int i = 0; i < nb_planes; i++)
918
2/2
✓ Branch 0 taken 569017 times.
✓ Branch 1 taken 322859 times.
891876 av_bprintf(bp, "%s%d", i ? ", " : "", order[i]);
919 322859 av_bprintf(bp, "}");
920 }
921
922 1011795 void ff_sws_op_list_print(void *log, int lev, int lev_extra,
923 const SwsOpList *ops)
924 {
925 AVBPrint bp;
926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1011795 times.
1011795 if (!ops->num_ops) {
927 av_log(log, lev, " (empty)\n");
928 return;
929 }
930
931 1011795 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
932
933
2/2
✓ Branch 0 taken 5710970 times.
✓ Branch 1 taken 1011795 times.
6722765 for (int i = 0; i < ops->num_ops; i++) {
934 5710970 const SwsOp *op = &ops->ops[i];
935 5710970 const SwsCompMask mask = ff_sws_comp_mask_needed(op);
936 5710970 av_bprint_clear(&bp);
937 5710970 av_bprintf(&bp, " [%3s %c%c%c%c] ",
938 5710970 ff_sws_pixel_type_name(op->type),
939 5710970 describe_comp_flags(op->comps.flags[0]),
940 5710970 describe_comp_flags(op->comps.flags[1]),
941 5710970 describe_comp_flags(op->comps.flags[2]),
942 5710970 describe_comp_flags(op->comps.flags[3]));
943
944 5710970 ff_sws_op_desc(&bp, op);
945
946
4/4
✓ Branch 0 taken 4760730 times.
✓ Branch 1 taken 950240 times.
✓ Branch 2 taken 1011795 times.
✓ Branch 3 taken 3748935 times.
5710970 if (op->op == SWS_OP_READ || op->op == SWS_OP_WRITE) {
947 1962035 const int planes = ff_sws_rw_op_planes(op);
948 1962035 desc_plane_order(&bp, planes,
949
2/2
✓ Branch 0 taken 950240 times.
✓ Branch 1 taken 1011795 times.
1962035 op->op == SWS_OP_READ ? ops->plane_src : ops->plane_dst);
950 }
951
952
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5710970 times.
5710970 av_assert0(av_bprint_is_complete(&bp));
953 5710970 av_log(log, lev, "%s\n", bp.str);
954
955 /* Only print value ranges if any are relevant */
956 5710970 SwsCompMask range_mask = ff_sws_comp_mask_q4(op->comps.min) |
957 5710970 ff_sws_comp_mask_q4(op->comps.max);
958
2/2
✓ Branch 0 taken 3706012 times.
✓ Branch 1 taken 2004958 times.
5710970 if (range_mask & mask) {
959 3706012 av_bprint_clear(&bp);
960 3706012 av_bprintf(&bp, " min: ");
961 3706012 print_q4(&bp, op->comps.min, mask);
962 3706012 av_bprintf(&bp, ", max: ");
963 3706012 print_q4(&bp, op->comps.max, mask);
964
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3706012 times.
3706012 av_assert0(av_bprint_is_complete(&bp));
965 3706012 av_log(log, lev_extra, "%s\n", bp.str);
966 }
967
968 }
969
970 1011795 av_log(log, lev, " ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)\n");
971 }
972