FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/tests/floatimg_cmp.c
Date: 2025-07-28 20:30:09
Exec Total Coverage
Lines: 92 151 60.9%
Functions: 1 1 100.0%
Branches: 58 102 56.9%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 #include <inttypes.h>
24 #include <float.h>
25
26 #include "libavutil/avutil.h"
27 #include "libavutil/imgutils.h"
28 #include "libavutil/intfloat.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/parseutils.h"
33 #include "libavutil/pixdesc.h"
34
35 #include "libswscale/swscale.h"
36
37 #define DEFAULT_W 96
38 #define DEFAULT_H 96
39
40 static const enum AVPixelFormat pix_fmts[] = {
41 AV_PIX_FMT_YUV444P16LE,
42 AV_PIX_FMT_YUV444P,
43 AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUV444P10LE,
44 AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P14LE,
45 AV_PIX_FMT_YUV444P10MSBLE, AV_PIX_FMT_YUV444P12MSBLE,
46 AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
47 AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
48 AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
49 AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
50 AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
51 AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
52 AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
53 AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
54 AV_PIX_FMT_GBRP9LE,
55 AV_PIX_FMT_GBRP10LE, AV_PIX_FMT_GBRAP10LE,
56 AV_PIX_FMT_GBRP10MSBLE, AV_PIX_FMT_GBRP12MSBLE,
57 AV_PIX_FMT_GBRP12LE, AV_PIX_FMT_GBRAP12LE,
58 AV_PIX_FMT_GBRP14LE,
59 AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRAP16LE
60 };
61
62 const char *usage = "floatimg_cmp -pixel_format <pix_fmt> -size <image_size> -ref <testfile>\n";
63
64 1 int main(int argc, char **argv)
65 {
66 1 enum AVPixelFormat inFormat = AV_PIX_FMT_NONE;
67 1 enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE;
68 const AVPixFmtDescriptor *desc;
69 uint8_t *ptr;
70 uint32_t *in, *out;
71
72 1 uint8_t *rgbIn[4] = {NULL, NULL, NULL, NULL};
73 1 uint8_t *rgbOut[4] = {NULL, NULL, NULL, NULL};
74 int rgbStride[4];
75
76 1 uint8_t *dst[4] = {NULL, NULL, NULL, NULL};
77 int dstStride[4];
78
79 int i, x, y, p, size, count;
80 1 int res = -1;
81 1 int w = -1;
82 1 int h = -1;
83 union av_intfloat32 v0, v1;
84
85 double sum;
86 float minimum, maximum, diff;
87
88 1 SwsContext *sws = NULL;
89 AVLFG rand;
90 1 FILE *fp = NULL;
91
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (i = 1; i < argc; i += 2) {
93 if (argv[i][0] != '-' || i + 1 == argc)
94 goto bad_option;
95 if (!strcmp(argv[i], "-ref")) {
96 fp = fopen(argv[i + 1], "rb");
97 if (!fp) {
98 fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
99 goto end;
100 }
101 } else if (!strcmp(argv[i], "-size")) {
102 res = av_parse_video_size(&w, &h, argv[i + 1]);
103 if (res < 0) {
104 fprintf(stderr, "invalid video size %s\n", argv[i + 1]);
105 goto end;
106 }
107 } else if (!strcmp(argv[i], "-pixel_format")) {
108 inFormat = av_get_pix_fmt(argv[i + 1]);
109 if (inFormat == AV_PIX_FMT_NONE) {
110 fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
111 goto end;
112 }
113 } else {
114 bad_option:
115 fprintf(stderr, "%s", usage);
116 fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]);
117 goto end;
118 };
119 }
120
121
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!fp) {
122 1 inFormat = AV_PIX_FMT_GBRPF32LE;
123 1 w = DEFAULT_W;
124 1 h = DEFAULT_H;
125 }
126
127
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (w <= 0 || h <= 0) {
128 fprintf(stderr, "%s", usage);
129 fprintf(stderr, "invalid -video_size\n");
130 goto end;
131 }
132
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (inFormat == AV_PIX_FMT_NONE) {
134 fprintf(stderr, "%s", usage);
135 fprintf(stderr, "invalid input pixel format\n");
136 goto end;
137 }
138
139 1 desc = av_pix_fmt_desc_get(inFormat);
140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!(desc->flags & AV_PIX_FMT_FLAG_FLOAT)) {
141 fprintf(stderr, "input pixel format not floating point.\n");
142 goto end;
143 }
144
145 1 res = av_image_fill_linesizes(rgbStride, inFormat, w);
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (res < 0) {
147 fprintf(stderr, "av_image_fill_linesizes failed\n");
148 goto end;
149 }
150
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (p = 0; p < 4; p++) {
151 4 rgbStride[p] = FFALIGN(rgbStride[p], 16);
152
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (rgbStride[p]) {
153 3 rgbIn[p] = av_mallocz(rgbStride[p] * h + 16);
154 3 rgbOut[p] = av_mallocz(rgbStride[p] * h + 16);
155 }
156
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
4 if (rgbStride[p] && (!rgbIn[p] || !rgbOut[p])) {
157 goto end;
158 }
159 }
160
161
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
35 for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) {
162 34 dstFormat = pix_fmts[i];
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (fp) {
164 fseek(fp, 0, SEEK_SET);
165 for (p = 0; p < 4; p++) {
166 if (!rgbStride[p])
167 continue;
168
169 ptr = rgbIn[p];
170 for (y = 0; y < h; y++) {
171 size = fread(ptr, 1, w*4, fp);
172 if (size != w*4) {
173 fprintf(stderr, "read error: %d\n", size);
174 goto end;
175 }
176 ptr += rgbStride[p];
177 }
178 }
179 } else {
180 // fill src with random values between 0.0 - 1.0
181 34 av_lfg_init(&rand, 1);
182
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 34 times.
170 for (p = 0; p < 4; p++) {
183
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 102 times.
136 if (!rgbStride[p])
184 34 continue;
185
186
2/2
✓ Branch 0 taken 9792 times.
✓ Branch 1 taken 102 times.
9894 for (y = 0; y < h; y++) {
187 9792 in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]);
188
2/2
✓ Branch 0 taken 940032 times.
✓ Branch 1 taken 9792 times.
949824 for (x = 0; x < w; x++) {
189 940032 v0.f = (float)av_lfg_get(&rand)/(float)(UINT32_MAX);
190 940032 *in++ = AV_RL32(&v0.i);
191 }
192 }
193 }
194 }
195
196 // setup intermediate image
197
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 34 times.
170 for (p = 0; p < 4; p++) {
198 136 av_freep(&dst[p]);
199 }
200
201 34 res = av_image_fill_linesizes(dstStride, dstFormat, w);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (res < 0) {
203 fprintf(stderr, "av_image_fill_linesizes failed\n");
204 goto end;
205 }
206
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 34 times.
170 for (p = 0; p < 4; p++) {
207 136 dstStride[p] = FFALIGN(dstStride[p], 16);
208
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 58 times.
136 if (dstStride[p]) {
209 78 dst[p] = av_mallocz(dstStride[p] * h + 16);
210 }
211
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
136 if (dstStride[p] && !dst[p]) {
212 goto end;
213 }
214 }
215
216 // srcFormat -> dstFormat
217 34 sws = sws_getContext(w, h, inFormat, w, h,
218 dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (!sws) {
220 fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat) );
221 goto end;
222 }
223
224 34 res = sws_scale(sws, (const uint8_t *const *)rgbIn, rgbStride, 0, h, dst, dstStride);
225
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
34 if (res < 0 || res != h) {
226 fprintf(stderr, "sws_scale failed\n");
227 res = -1;
228 goto end;
229 }
230 34 sws_freeContext(sws);
231
232 // dstFormat -> srcFormat
233 34 sws = sws_getContext(w, h, dstFormat, w, h,
234 inFormat, SWS_BILINEAR, NULL, NULL, NULL);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if(!sws) {
236 fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) );
237 goto end;
238 }
239
240 34 res = sws_scale(sws, (const uint8_t *const *)dst, dstStride, 0, h, rgbOut, rgbStride);
241
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
34 if (res < 0 || res != h) {
242 fprintf(stderr, "sws_scale failed\n");
243 res = -1;
244 goto end;
245 }
246 34 sws_freeContext(sws);
247 34 sws = NULL;
248
249 34 minimum = FLT_MAX;
250 34 maximum = -FLT_MAX;
251 34 count = 0;
252 34 sum = 0.0;
253
254
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 34 times.
170 for (p = 0; p < 4; p++) {
255
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 102 times.
136 if (!rgbStride[p])
256 34 continue;
257
258
2/2
✓ Branch 0 taken 9792 times.
✓ Branch 1 taken 102 times.
9894 for (y = 0; y < h; y++) {
259 9792 in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]);
260 9792 out = (uint32_t*)(rgbOut[p] + y * rgbStride[p]);
261
2/2
✓ Branch 0 taken 940032 times.
✓ Branch 1 taken 9792 times.
949824 for (x = 0; x < w; x++) {
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 940032 times.
940032 if (desc->flags & AV_PIX_FMT_FLAG_BE) {
263 v0.i = AV_RB32(in);
264 v1.i = AV_RB32(out);
265 } else {
266 940032 v0.i = AV_RL32(in);
267 940032 v1.i = AV_RL32(out);
268 }
269
270 940032 diff = fabsf(v0.f - v1.f);
271 940032 sum += diff;
272
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 939672 times.
940032 minimum = FFMIN(minimum, diff);
273
2/2
✓ Branch 0 taken 939510 times.
✓ Branch 1 taken 522 times.
940032 maximum = FFMAX(maximum, diff);
274
275 940032 count++;
276 940032 in++;
277 940032 out++;
278 }
279 }
280 }
281
282 34 fprintf(stdout, "%s -> %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) );
283 34 fprintf(stdout, "avg diff: %f\nmin diff: %f\nmax diff: %f\n", sum / count, minimum, maximum);
284 34 res = 0;
285 }
286
287 1 end:
288 1 sws_freeContext(sws);
289
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (p = 0; p < 4; p++) {
290 4 av_freep(&rgbIn[p]);
291 4 av_freep(&rgbOut[p]);
292 4 av_freep(&dst[p]);
293 }
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (fp)
295 fclose(fp);
296
297 1 return res;
298 }
299