FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/tests/sws_ops.c
Date: 2026-04-21 03:24:50
Exec Total Coverage
Lines: 27 111 24.3%
Functions: 3 6 50.0%
Branches: 8 62 12.9%

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/avstring.h"
23 #include "libavutil/mem.h"
24 #include "libavutil/pixdesc.h"
25 #include "libavutil/tree.h"
26 #include "libswscale/ops.h"
27 #include "libswscale/format.h"
28
29 #ifdef _WIN32
30 #include <io.h>
31 #include <fcntl.h>
32 #endif
33
34 17424 static int print_ops(SwsContext *const ctx, void *opaque, SwsOpList *ops)
35 {
36 17424 av_log(opaque, AV_LOG_INFO, "%s -> %s:\n",
37 av_get_pix_fmt_name(ops->src.format),
38 av_get_pix_fmt_name(ops->dst.format));
39
40
2/2
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 17296 times.
17424 if (ff_sws_op_list_is_noop(ops))
41 128 av_log(opaque, AV_LOG_INFO, " (no-op)\n");
42 else
43 17296 ff_sws_op_list_print(opaque, AV_LOG_INFO, AV_LOG_INFO, ops);
44
45 17424 return 0;
46 }
47
48 static int cmp_str(const void *a, const void *b)
49 {
50 return strcmp(a, b);
51 }
52
53 static int register_op(SwsContext *ctx, void *opaque, SwsOp *op)
54 {
55 struct AVTreeNode **root = opaque;
56 AVBPrint bp;
57 char *desc;
58
59 /* Strip irrelevant constant data from some operations */
60 switch (op->op) {
61 case SWS_OP_LINEAR:
62 for (int i = 0; i < 4; i++) {
63 for (int j = 0; j < 5; j++)
64 op->lin.m[i][j] = (AVRational) { 0, 1 };
65 }
66 break;
67 case SWS_OP_SCALE:
68 op->scale.factor = (AVRational) { 0, 1 };
69 break;
70 case SWS_OP_MIN:
71 case SWS_OP_MAX:
72 for (int i = 0; i < 4; i++)
73 op->clamp.limit[i] = (AVRational) { 0, 1 };
74 break;
75 case SWS_OP_CLEAR:
76 for (int i = 0; i < 4; i++)
77 op->clear.value[i] = (AVRational) { 0, SWS_COMP_TEST(op->clear.mask, i) };
78 break;
79 case SWS_OP_DITHER:
80 /* Strip arbitrary offset */
81 for (int i = 0; i < 4; i++)
82 op->dither.y_offset[i] = op->dither.y_offset[i] >= 0 ? 0 : -1;
83 break;
84 }
85
86 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
87 ff_sws_op_desc(&bp, op);
88 int ret = av_bprint_finalize(&bp, &desc);
89 if (ret < 0)
90 return ret;
91
92 struct AVTreeNode *node = av_tree_node_alloc();
93 if (!node) {
94 av_free(desc);
95 return AVERROR(ENOMEM);
96 }
97
98 av_tree_insert(root, desc, cmp_str, &node);
99 if (node) {
100 av_free(node);
101 av_free(desc);
102 }
103 return ret;
104 }
105
106 static int print_and_free_summary(void *opaque, void *key)
107 {
108 char *desc = key;
109 av_log(opaque, AV_LOG_INFO, "%s\n", desc);
110 av_free(desc);
111 return 0;
112 }
113
114 291694 static void log_stdout(void *avcl, int level, const char *fmt, va_list vl)
115 {
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 291694 times.
291694 if (level != AV_LOG_INFO) {
117 av_log_default_callback(avcl, level, fmt, vl);
118
1/2
✓ Branch 1 taken 291694 times.
✗ Branch 2 not taken.
291694 } else if (av_log_get_level() >= AV_LOG_INFO) {
119 291694 vfprintf(stdout, fmt, vl);
120 }
121 291694 }
122
123 1 int main(int argc, char **argv)
124 {
125 1 enum AVPixelFormat src_fmt = AV_PIX_FMT_NONE;
126 1 enum AVPixelFormat dst_fmt = AV_PIX_FMT_NONE;
127 1 bool summarize = false;
128 1 int ret = 1;
129
130 #ifdef _WIN32
131 _setmode(_fileno(stdout), _O_BINARY);
132 #endif
133
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (int i = 1; i < argc; i++) {
135 if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
136 fprintf(stderr,
137 "sws_ops [options...]\n"
138 " -help\n"
139 " This text\n"
140 " -dst <pixfmt>\n"
141 " Only test the specified destination pixel format\n"
142 " -src <pixfmt>\n"
143 " Only test the specified source pixel format\n"
144 " -v <level>\n"
145 " Enable log verbosity at given level\n"
146 " -summarize\n"
147 " Summarize operation types, instead of printing op lists\n"
148 );
149 return 0;
150 }
151 if (!strcmp(argv[i], "-src")) {
152 if (i + 1 >= argc)
153 goto bad_option;
154 src_fmt = av_get_pix_fmt(argv[i + 1]);
155 if (src_fmt == AV_PIX_FMT_NONE) {
156 fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
157 goto error;
158 }
159 i++;
160 } else if (!strcmp(argv[i], "-dst")) {
161 if (i + 1 >= argc)
162 goto bad_option;
163 dst_fmt = av_get_pix_fmt(argv[i + 1]);
164 if (dst_fmt == AV_PIX_FMT_NONE) {
165 fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
166 goto error;
167 }
168 i++;
169 } else if (!strcmp(argv[i], "-v")) {
170 if (i + 1 >= argc)
171 goto bad_option;
172 av_log_set_level(atoi(argv[i + 1]));
173 i++;
174 } else if (!strcmp(argv[i], "-summarize")) {
175 summarize = true;
176 } else {
177 bad_option:
178 fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]);
179 goto error;
180 }
181 }
182
183 1 SwsContext *ctx = sws_alloc_context();
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ctx)
185 goto fail;
186
187 1 av_log_set_callback(log_stdout);
188
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (summarize) {
190 struct AVTreeNode *root = NULL;
191 ret = ff_sws_enum_ops(ctx, &root, src_fmt, dst_fmt, register_op);
192 if (ret < 0)
193 goto fail;
194 av_tree_enumerate(root, NULL, NULL, print_and_free_summary);
195 av_tree_destroy(root);
196 } else {
197 1 ret = ff_sws_enum_op_lists(ctx, NULL, src_fmt, dst_fmt, print_ops);
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
199 goto fail;
200 }
201
202 1 ret = 0;
203 1 fail:
204 1 sws_free_context(&ctx);
205 1 return ret;
206
207 error:
208 return AVERROR(EINVAL);
209 }
210