FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/sw_yuv2rgb.c
Date: 2026-04-22 13:46:37
Exec Total Coverage
Lines: 103 116 88.8%
Functions: 5 5 100.0%
Branches: 66 86 76.7%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <string.h>
20
21 #include "libavutil/common.h"
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/mem_internal.h"
24 #include "libavutil/pixdesc.h"
25
26 #include "libswscale/swscale.h"
27 #include "libswscale/swscale_internal.h"
28
29 #include "checkasm.h"
30
31 #define randomize_buffers(buf, size) \
32 do { \
33 for (int j = 0; j < size; j += 4) \
34 AV_WN32(buf + j, rnd()); \
35 } while (0)
36
37 static const int dst_fmts[] = {
38 // AV_PIX_FMT_BGR48BE,
39 // AV_PIX_FMT_BGR48LE,
40 // AV_PIX_FMT_RGB48BE,
41 // AV_PIX_FMT_RGB48LE,
42 AV_PIX_FMT_ARGB,
43 AV_PIX_FMT_ABGR,
44 AV_PIX_FMT_RGBA,
45 AV_PIX_FMT_BGRA,
46 AV_PIX_FMT_RGB24,
47 AV_PIX_FMT_BGR24,
48 AV_PIX_FMT_RGB565,
49 AV_PIX_FMT_BGR565,
50 AV_PIX_FMT_RGB555,
51 AV_PIX_FMT_BGR555,
52 // AV_PIX_FMT_RGB444,
53 // AV_PIX_FMT_BGR444,
54 // AV_PIX_FMT_RGB8,
55 // AV_PIX_FMT_BGR8,
56 // AV_PIX_FMT_RGB4,
57 // AV_PIX_FMT_BGR4,
58 // AV_PIX_FMT_RGB4_BYTE,
59 // AV_PIX_FMT_BGR4_BYTE,
60 // AV_PIX_FMT_MONOBLACK,
61 AV_PIX_FMT_GBRP,
62 };
63
64 768 static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
65 {
66
2/2
✓ Branch 0 taken 1580544 times.
✓ Branch 1 taken 768 times.
1581312 for (size_t i = 0; i < n; i++) {
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1580544 times.
1580544 if (abs(ref[i] - test[i]) > accuracy)
68 return 1;
69 }
70 768 return 0;
71 }
72
73 144 static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
74 {
75 144 const uint16_t *ref16 = (const uint16_t *) ref;
76 144 const uint16_t *test16 = (const uint16_t *) test;
77
2/2
✓ Branch 0 taken 112896 times.
✓ Branch 1 taken 144 times.
113040 for (size_t i = 0; i < n; i++) {
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
79 return 1;
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(((ref16[i] >> 5) & 0x1f) - ((test16[i] >> 5) & 0x1f)) > accuracy)
81 return 1;
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(((ref16[i] >> 10) & 0x1f) - ((test16[i] >> 10) & 0x1f)) > accuracy)
83 return 1;
84 }
85 144 return 0;
86 }
87
88 144 static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
89 {
90 144 const uint16_t *ref16 = (const uint16_t *) ref;
91 144 const uint16_t *test16 = (const uint16_t *) test;
92
2/2
✓ Branch 0 taken 112896 times.
✓ Branch 1 taken 144 times.
113040 for (size_t i = 0; i < n; i++) {
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
94 return 1;
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(((ref16[i] >> 5) & 0x3f) - ((test16[i] >> 5) & 0x3f)) > accuracy)
96 return 1;
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112896 times.
112896 if (abs(((ref16[i] >> 11) & 0x1f) - ((test16[i] >> 11) & 0x1f)) > accuracy)
98 return 1;
99 }
100 144 return 0;
101 }
102
103 42 static void check_yuv2rgb(int src_pix_fmt)
104 {
105 42 const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
106 #define MAX_LINE_SIZE 1920
107 #define SRC_STRIDE_PAD 32
108 #define NUM_LINES 4
109 static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE};
110
111 42 declare_func(int, SwsInternal *c, const uint8_t *const src[],
112 const int srcStride[], int srcSliceY, int srcSliceH,
113 uint8_t *const dst[], const int dstStride[]);
114
115 42 LOCAL_ALIGNED_8(uint8_t, src_y, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
116 42 LOCAL_ALIGNED_8(uint8_t, src_u, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
117 42 LOCAL_ALIGNED_8(uint8_t, src_v, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
118 42 LOCAL_ALIGNED_8(uint8_t, src_a, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
119 42 const uint8_t *src[4] = { src_y, src_u, src_v, src_a };
120
121 42 LOCAL_ALIGNED_8(uint8_t, dst0_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
122 42 LOCAL_ALIGNED_8(uint8_t, dst0_1, [NUM_LINES * MAX_LINE_SIZE]);
123 42 LOCAL_ALIGNED_8(uint8_t, dst0_2, [NUM_LINES * MAX_LINE_SIZE]);
124 42 uint8_t *dst0[4] = { dst0_0, dst0_1, dst0_2 };
125
126 42 LOCAL_ALIGNED_8(uint8_t, dst1_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
127 42 LOCAL_ALIGNED_8(uint8_t, dst1_1, [NUM_LINES * MAX_LINE_SIZE]);
128 42 LOCAL_ALIGNED_8(uint8_t, dst1_2, [NUM_LINES * MAX_LINE_SIZE]);
129 42 uint8_t *dst1[4] = { dst1_0, dst1_1, dst1_2 };
130
131
2/2
✓ Branch 1 taken 81984 times.
✓ Branch 2 taken 42 times.
82026 randomize_buffers(src_y, (MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES);
132
2/2
✓ Branch 1 taken 81984 times.
✓ Branch 2 taken 42 times.
82026 randomize_buffers(src_u, (MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES);
133
2/2
✓ Branch 1 taken 81984 times.
✓ Branch 2 taken 42 times.
82026 randomize_buffers(src_v, (MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES);
134
2/2
✓ Branch 1 taken 81984 times.
✓ Branch 2 taken 42 times.
82026 randomize_buffers(src_a, (MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES);
135
136
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 42 times.
504 for (int dfi = 0; dfi < FF_ARRAY_ELEMS(dst_fmts); dfi++) {
137 462 int dst_pix_fmt = dst_fmts[dfi];
138 462 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
139 462 int sample_size = av_get_padded_bits_per_pixel(dst_desc) >> 3;
140
2/2
✓ Branch 0 taken 1848 times.
✓ Branch 1 taken 462 times.
2310 for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
141 SwsContext *sws;
142 SwsInternal *c;
143 int log_level;
144 1848 int width = input_sizes[isi];
145 1848 int srcSliceY = 0;
146 1848 int srcSliceH = NUM_LINES;
147 1848 int srcStride[4] = {
148 1848 width + SRC_STRIDE_PAD,
149 1848 (width >> src_desc->log2_chroma_w) + SRC_STRIDE_PAD,
150 1848 (width >> src_desc->log2_chroma_w) + SRC_STRIDE_PAD,
151 1848 width + SRC_STRIDE_PAD,
152 };
153 1848 int dstStride[4] = {
154 MAX_LINE_SIZE * 6,
155 MAX_LINE_SIZE,
156 MAX_LINE_SIZE,
157 };
158
159 // override log level to prevent spamming of the message
160 // "No accelerated colorspace conversion found from %s to %s"
161 1848 log_level = av_log_get_level();
162 1848 av_log_set_level(AV_LOG_ERROR);
163 1848 sws = sws_getContext(width, srcSliceH, src_pix_fmt,
164 width, srcSliceH, dst_pix_fmt,
165 0, NULL, NULL, NULL);
166 1848 av_log_set_level(log_level);
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1848 times.
1848 if (!sws)
168 fail();
169
170 1848 c = sws_internal(sws);
171
2/2
✓ Branch 3 taken 216 times.
✓ Branch 4 taken 1632 times.
1848 if (check_func(c->convert_unscaled, "%s_%s_%d", src_desc->name, dst_desc->name, width)) {
172 216 memset(dst0_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
173 216 memset(dst1_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
174
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 192 times.
216 if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
175 24 memset(dst0_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
176 24 memset(dst0_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
177 24 memset(dst1_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
178 24 memset(dst1_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
179 }
180
181 216 call_ref(c, src, srcStride, srcSliceY,
182 srcSliceH, dst0, dstStride);
183 216 call_new(c, src, srcStride, srcSliceY,
184 srcSliceH, dst1, dstStride);
185
186
4/4
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 12 times.
216 if (dst_pix_fmt == AV_PIX_FMT_ARGB ||
187
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 24 times.
192 dst_pix_fmt == AV_PIX_FMT_ABGR ||
188
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 24 times.
168 dst_pix_fmt == AV_PIX_FMT_RGBA ||
189
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 24 times.
144 dst_pix_fmt == AV_PIX_FMT_BGRA ||
190
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 96 times.
120 dst_pix_fmt == AV_PIX_FMT_RGB24 ||
191 dst_pix_fmt == AV_PIX_FMT_BGR24) {
192
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 120 times.
600 for (int row = 0; row < srcSliceH; row++)
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 480 times.
480 if (cmp_off_by_n(dst0_0 + row * dstStride[0],
194 480 dst1_0 + row * dstStride[0],
195 480 width * sample_size, 3))
196 fail();
197
4/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 60 times.
96 } else if (dst_pix_fmt == AV_PIX_FMT_RGB565 ||
198 dst_pix_fmt == AV_PIX_FMT_BGR565) {
199
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 36 times.
180 for (int row = 0; row < srcSliceH; row++)
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (cmp_565_by_n(dst0_0 + row * dstStride[0],
201 144 dst1_0 + row * dstStride[0],
202 width, 2))
203 fail();
204
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 24 times.
60 } else if (dst_pix_fmt == AV_PIX_FMT_RGB555 ||
205 dst_pix_fmt == AV_PIX_FMT_BGR555) {
206
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 36 times.
180 for (int row = 0; row < srcSliceH; row++)
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (cmp_555_by_n(dst0_0 + row * dstStride[0],
208 144 dst1_0 + row * dstStride[0],
209 width, 2))
210 fail();
211
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 } else if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
212
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 24 times.
96 for (int p = 0; p < 3; p++)
213
2/2
✓ Branch 0 taken 288 times.
✓ Branch 1 taken 72 times.
360 for (int row = 0; row < srcSliceH; row++)
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
288 if (cmp_off_by_n(dst0[p] + row * dstStride[p],
215 288 dst1[p] + row * dstStride[p],
216 width, 3))
217 fail();
218 } else {
219 fail();
220 }
221
222
1/8
✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
216 bench_new(c, src, srcStride, srcSliceY,
223 srcSliceH, dst0, dstStride);
224 }
225 1848 sws_freeContext(sws);
226 }
227 }
228 42 }
229
230 #undef NUM_LINES
231 #undef SRC_STRIDE_PAD
232 #undef MAX_LINE_SIZE
233
234 14 void checkasm_check_sw_yuv2rgb(void)
235 {
236 14 check_yuv2rgb(AV_PIX_FMT_YUV420P);
237 14 report("yuv420p");
238 14 check_yuv2rgb(AV_PIX_FMT_YUV422P);
239 14 report("yuv422p");
240 14 check_yuv2rgb(AV_PIX_FMT_YUVA420P);
241 14 report("yuva420p");
242 14 }
243