FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/ops_chain.c
Date: 2026-07-21 08:37:06
Exec Total Coverage
Lines: 72 80 90.0%
Functions: 6 6 100.0%
Branches: 42 52 80.8%

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/avassert.h"
22 #include "libavutil/mem.h"
23 #include "libavutil/rational.h"
24
25 #include "ops_chain.h"
26
27 99130 SwsOpChain *ff_sws_op_chain_alloc(void)
28 {
29 99130 return av_mallocz(sizeof(SwsOpChain));
30 }
31
32 99130 void ff_sws_op_chain_free_cb(void *ptr)
33 {
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99130 times.
99130 if (!ptr)
35 return;
36
37 99130 SwsOpChain *chain = ptr;
38
2/2
✓ Branch 0 taken 571178 times.
✓ Branch 1 taken 99130 times.
670308 for (int i = 0; i < chain->num_impl + 1; i++) {
39
2/2
✓ Branch 0 taken 104882 times.
✓ Branch 1 taken 466296 times.
571178 if (chain->free[i])
40 104882 chain->free[i](&chain->impl[i].priv);
41 }
42
43 99130 av_free(chain);
44 }
45
46 472048 int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func,
47 void (*free)(SwsOpPriv *), const SwsOpPriv *priv)
48 {
49 472048 const int idx = chain->num_impl;
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 472048 times.
472048 if (idx == SWS_MAX_OPS)
51 return AVERROR(EINVAL);
52
53 av_assert1(func);
54 472048 chain->impl[idx].cont = func;
55 472048 chain->impl[idx + 1].priv = *priv;
56 472048 chain->free[idx + 1] = free;
57 472048 chain->num_impl++;
58 472048 return 0;
59 }
60
61 #define q2pixel(type, q) ((q).den ? (type) (q).num / (q).den : 0)
62
63 #if ARCH_AARCH64
64 int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
65 {
66 const SwsOp *op = params->op;
67 const AVRational64 factor = op->scale.factor;
68 switch (op->type) {
69 case SWS_PIXEL_U8: out->priv.u8[0] = q2pixel(uint8_t, factor); break;
70 case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, factor); break;
71 case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, factor); break;
72 case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float, factor); break;
73 default: return AVERROR(EINVAL);
74 }
75
76 return 0;
77 }
78
79 int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out)
80 {
81 const SwsOp *op = params->op;
82 for (int i = 0; i < 4; i++) {
83 const AVRational64 limit = op->clamp.limit[i];
84 switch (op->type) {
85 case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, limit); break;
86 case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, limit); break;
87 case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, limit); break;
88 case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, limit); break;
89 default: return AVERROR(EINVAL);
90 }
91 }
92
93 return 0;
94 }
95
96 int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out)
97 {
98 const SwsOp *op = params->op;
99 for (int i = 0; i < 4; i++) {
100 const AVRational64 value = op->clear.value[i];
101 if (!value.den)
102 continue;
103 switch (op->type) {
104 case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, value); break;
105 case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, value); break;
106 case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, value); break;
107 case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, value); break;
108 default: return AVERROR(EINVAL);
109 }
110 }
111
112 return 0;
113 }
114 #endif
115
116 483280 int ff_sws_uop_lookup(SwsContext *ctx, const SwsUOpTable *const tables[],
117 int num_tables, const SwsUOp *uop, const int block_size,
118 SwsOpChain *chain)
119 {
120 483280 const unsigned cpu_flags = av_get_cpu_flags();
121 483280 const SwsUOpEntry *match = NULL;
122 int ret;
123
124 483280 SwsImplParams params = {
125 .ctx = ctx,
126 .uop = uop
127 };
128
129
4/4
✓ Branch 0 taken 2576277 times.
✓ Branch 1 taken 472048 times.
✓ Branch 2 taken 2565045 times.
✓ Branch 3 taken 11232 times.
3048325 for (int n = 0; !match && n < num_tables; n++) {
130 2565045 const SwsUOpTable *table = params.table = tables[n];
131
3/4
✓ Branch 0 taken 2565045 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1231323 times.
✓ Branch 3 taken 1333722 times.
2565045 if (table->block_size && table->block_size != block_size ||
132
2/2
✓ Branch 0 taken 4284 times.
✓ Branch 1 taken 1227039 times.
1231323 table->cpu_flags & ~cpu_flags)
133 1338006 continue;
134
135
2/2
✓ Branch 0 taken 93058020 times.
✓ Branch 1 taken 754991 times.
93813011 for (int i = 0; table->entries[i]; i++) {
136 93058020 const SwsUOpEntry *entry = table->entries[i];
137 93058020 const SwsUOp entry_uop = {
138 93058020 .uop = entry->uop,
139 93058020 .type = entry->type,
140 93058020 .mask = entry->mask,
141 .par = entry->par,
142 };
143
144
2/2
✓ Branch 1 taken 92584282 times.
✓ Branch 2 taken 473738 times.
93058020 if (ff_sws_uop_cmp(uop, &entry_uop) != 0)
145 92585972 continue;
146
4/4
✓ Branch 0 taken 19294 times.
✓ Branch 1 taken 454444 times.
✓ Branch 3 taken 1690 times.
✓ Branch 4 taken 17604 times.
473738 if (entry->check && !entry->check(&params))
147 1690 continue;
148
149 472048 match = entry;
150 472048 break;
151 }
152 }
153
154
2/2
✓ Branch 0 taken 11232 times.
✓ Branch 1 taken 472048 times.
483280 if (!match) {
155 char name[64];
156 11232 ff_sws_uop_name(uop, name);
157 11232 av_log(ctx, AV_LOG_DEBUG, "No implementation found for: %s\n", name);
158 11232 return AVERROR(ENOTSUP);
159 }
160
161 472048 SwsImplResult res = {0};
162
2/2
✓ Branch 0 taken 211232 times.
✓ Branch 1 taken 260816 times.
472048 if (match->setup) {
163 211232 ret = match->setup(&params, &res);
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 211232 times.
211232 if (ret < 0)
165 return ret;
166 }
167
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 472048 times.
472048 ret = ff_sws_op_chain_append(chain, res.func ? res.func : match->func,
169 res.free, &res.priv);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 472048 times.
472048 if (ret < 0) {
171 if (res.free)
172 res.free(&res.priv);
173 return ret;
174 }
175
176
2/2
✓ Branch 0 taken 1888192 times.
✓ Branch 1 taken 472048 times.
2360240 for (int i = 0; i < 4; i++) {
177 1888192 chain->over_read[i] = FFMAX(chain->over_read[i], res.over_read[i]);
178 1888192 chain->over_write[i] = FFMAX(chain->over_write[i], res.over_write[i]);
179 }
180
181 472048 chain->cpu_flags |= params.table->cpu_flags;
182 472048 return 0;
183 }
184
185 1571 int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
186 {
187 1571 const SwsUOp *uop = params->uop;
188 1571 const SwsPixel scalar = uop->data.scalar;
189
4/5
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 1476 times.
✗ Branch 4 not taken.
1571 switch (uop->type) {
190 14 case SWS_PIXEL_U8: out->priv.u8[0] = scalar.u8; break;
191 28 case SWS_PIXEL_U16: out->priv.u16[0] = scalar.u16; break;
192 53 case SWS_PIXEL_U32: out->priv.u32[0] = scalar.u32; break;
193 1476 case SWS_PIXEL_F32: out->priv.f32[0] = scalar.f32; break;
194 default: return AVERROR(EINVAL);
195 }
196
197 1571 return 0;
198 }
199
200 64290 int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
201 {
202 64290 const SwsUOp *uop = params->uop;
203
2/2
✓ Branch 0 taken 257160 times.
✓ Branch 1 taken 64290 times.
321450 for (int i = 0; i < 4; i++) {
204 257160 const SwsPixel vi = uop->data.vec4[i];
205
4/5
✓ Branch 0 taken 1336 times.
✓ Branch 1 taken 11772 times.
✓ Branch 2 taken 12224 times.
✓ Branch 3 taken 231828 times.
✗ Branch 4 not taken.
257160 switch (uop->type) {
206 1336 case SWS_PIXEL_U8: out->priv.u8[i] = vi.u8; break;
207 11772 case SWS_PIXEL_U16: out->priv.u16[i] = vi.u16; break;
208 12224 case SWS_PIXEL_U32: out->priv.u32[i] = vi.u32; break;
209 231828 case SWS_PIXEL_F32: out->priv.f32[i] = vi.f32; break;
210 default: return AVERROR(EINVAL);
211 }
212 }
213
214 64290 return 0;
215 }
216