FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/vf_colorspace.c
Date: 2024-05-03 15:42:48
Exec Total Coverage
Lines: 165 169 97.6%
Functions: 5 5 100.0%
Branches: 78 90 86.7%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com>
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 <string.h>
22 #include "checkasm.h"
23 #include "libavfilter/colorspacedsp.h"
24 #include "libavutil/common.h"
25 #include "libavutil/internal.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/mem_internal.h"
28
29 #define W 64
30 #define H 64
31
32 #define randomize_buffers() \
33 do { \
34 unsigned mask = bpp_mask[idepth]; \
35 int n, m; \
36 int bpp = 1 + (!!idepth); \
37 int buf_size = W * H * bpp; \
38 for (m = 0; m < 3; m++) { \
39 int ss = m ? ss_w + ss_h : 0; \
40 int plane_sz = buf_size >> ss; \
41 for (n = 0; n < plane_sz; n += 4) { \
42 unsigned r = rnd() & mask; \
43 AV_WN32A(&src[m][n], r); \
44 } \
45 } \
46 } while (0)
47
48 static const char *format_string[] = {
49 "444", "422", "420"
50 };
51
52 static const unsigned bpp_mask[] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff };
53
54 13 static void check_yuv2yuv(void)
55 {
56 13 declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
57 uint8_t *src[3], ptrdiff_t src_stride[3],
58 int w, int h, const int16_t coeff[3][3][8],
59 const int16_t off[2][8]);
60 ColorSpaceDSPContext dsp;
61 int idepth, odepth, fmt, n;
62 13 LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
63 13 LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
64 13 LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
65 13 uint8_t *src[3] = { src_y, src_u, src_v };
66 13 LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
67 13 LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
68 13 LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
69 13 LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
70 13 LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
71 13 LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
72 13 uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
73 13 LOCAL_ALIGNED_32(int16_t, offset_buf, [16]);
74 13 LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
75 13 int16_t (*offset)[8] = (int16_t(*)[8]) offset_buf;
76 13 int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
77
78 13 ff_colorspacedsp_init(&dsp);
79
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 13 times.
117 for (n = 0; n < 8; n++) {
80 104 offset[0][n] = offset[1][n] = 16;
81
82 104 coeff[0][0][n] = (1 << 14) + (1 << 7) + 1;
83 104 coeff[0][1][n] = (1 << 7) - 1;
84 104 coeff[0][2][n] = -(1 << 8);
85 104 coeff[1][0][n] = coeff[2][0][n] = 0;
86 104 coeff[1][1][n] = (1 << 14) + (1 << 7);
87 104 coeff[1][2][n] = -(1 << 7);
88 104 coeff[2][2][n] = (1 << 14) - (1 << 6);
89 104 coeff[2][1][n] = 1 << 6;
90 }
91
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
52 for (idepth = 0; idepth < 3; idepth++) {
92
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 39 times.
156 for (odepth = 0; odepth < 3; odepth++) {
93
2/2
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 117 times.
468 for (fmt = 0; fmt < 3; fmt++) {
94
2/2
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 297 times.
351 if (check_func(dsp.yuv2yuv[idepth][odepth][fmt],
95 "ff_colorspacedsp_yuv2yuv_%sp%dto%d",
96 format_string[fmt],
97 idepth * 2 + 8, odepth * 2 + 8)) {
98 54 int ss_w = !!fmt, ss_h = fmt == 2;
99
4/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 18 times.
54 int y_src_stride = W << !!idepth, y_dst_stride = W << !!odepth;
100 54 int uv_src_stride = y_src_stride >> ss_w, uv_dst_stride = y_dst_stride >> ss_w;
101
102
8/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 54 times.
✓ Branch 5 taken 199680 times.
✓ Branch 6 taken 162 times.
✓ Branch 7 taken 162 times.
✓ Branch 8 taken 54 times.
199896 randomize_buffers();
103 54 call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
104 src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
105 W, H, coeff, offset);
106 54 call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
107 src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
108 W, H, coeff, offset);
109
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (memcmp(dst0[0], dst1[0], y_dst_stride * H) ||
110
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 memcmp(dst0[1], dst1[1], uv_dst_stride * H >> ss_h) ||
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 memcmp(dst0[2], dst1[2], uv_dst_stride * H >> ss_h)) {
112 fail();
113 }
114 }
115 }
116 }
117 }
118
119 13 report("yuv2yuv");
120 13 }
121
122 13 static void check_yuv2rgb(void)
123 {
124 13 declare_func(void, int16_t *dst[3], ptrdiff_t dst_stride,
125 uint8_t *src[3], ptrdiff_t src_stride[3],
126 int w, int h, const int16_t coeff[3][3][8],
127 const int16_t off[8]);
128 ColorSpaceDSPContext dsp;
129 int idepth, fmt, n;
130 13 LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
131 13 LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
132 13 LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
133 13 uint8_t *src[3] = { src_y, src_u, src_v };
134 13 LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
135 13 LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
136 13 LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
137 13 LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
138 13 LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
139 13 LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
140 13 int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
141 13 LOCAL_ALIGNED_32(int16_t, offset, [8]);
142 13 LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
143 13 int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
144
145 13 ff_colorspacedsp_init(&dsp);
146
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 13 times.
117 for (n = 0; n < 8; n++) {
147 104 offset[n] = 16;
148
149 104 coeff[0][0][n] = coeff[1][0][n] = coeff[2][0][n] = (1 << 14) | 1;
150 104 coeff[0][1][n] = coeff[2][2][n] = 0;
151 104 coeff[0][2][n] = 1 << 13;
152 104 coeff[1][1][n] = -(1 << 12);
153 104 coeff[1][2][n] = 1 << 12;
154 104 coeff[2][1][n] = 1 << 11;
155 }
156
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
52 for (idepth = 0; idepth < 3; idepth++) {
157
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 39 times.
156 for (fmt = 0; fmt < 3; fmt++) {
158
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 99 times.
117 if (check_func(dsp.yuv2rgb[idepth][fmt],
159 "ff_colorspacedsp_yuv2rgb_%sp%d",
160 format_string[fmt], idepth * 2 + 8)) {
161 18 int ss_w = !!fmt, ss_h = fmt == 2;
162
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 int y_src_stride = W << !!idepth;
163 18 int uv_src_stride = y_src_stride >> ss_w;
164
165
8/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 18 times.
✓ Branch 5 taken 66560 times.
✓ Branch 6 taken 54 times.
✓ Branch 7 taken 54 times.
✓ Branch 8 taken 18 times.
66632 randomize_buffers();
166 18 call_ref(dst0, W, src,
167 (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
168 W, H, coeff, offset);
169 18 call_new(dst1, W, src,
170 (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
171 W, H, coeff, offset);
172
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (memcmp(dst0[0], dst1[0], W * H * sizeof(int16_t)) ||
173
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 memcmp(dst0[1], dst1[1], W * H * sizeof(int16_t)) ||
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 memcmp(dst0[2], dst1[2], W * H * sizeof(int16_t))) {
175 fail();
176 }
177 }
178 }
179 }
180
181 13 report("yuv2rgb");
182 13 }
183
184 #undef randomize_buffers
185 #define randomize_buffers() \
186 do { \
187 int y, x, p; \
188 for (p = 0; p < 3; p++) { \
189 for (y = 0; y < H; y++) { \
190 for (x = 0; x < W; x++) { \
191 int r = rnd() & 0x7fff; \
192 r -= (32768 - 28672) >> 1; \
193 src[p][y * W + x] = r; \
194 } \
195 } \
196 } \
197 } while (0)
198
199 13 static void check_rgb2yuv(void)
200 {
201 13 declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
202 int16_t *src[3], ptrdiff_t src_stride,
203 int w, int h, const int16_t coeff[3][3][8],
204 const int16_t off[8]);
205 ColorSpaceDSPContext dsp;
206 int odepth, fmt, n;
207 13 LOCAL_ALIGNED_32(int16_t, src_y, [W * H * 2]);
208 13 LOCAL_ALIGNED_32(int16_t, src_u, [W * H * 2]);
209 13 LOCAL_ALIGNED_32(int16_t, src_v, [W * H * 2]);
210 13 int16_t *src[3] = { src_y, src_u, src_v };
211 13 LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
212 13 LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
213 13 LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
214 13 LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
215 13 LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
216 13 LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
217 13 uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
218 13 LOCAL_ALIGNED_32(int16_t, offset, [8]);
219 13 LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
220 13 int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
221
222 13 ff_colorspacedsp_init(&dsp);
223
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 13 times.
117 for (n = 0; n < 8; n++) {
224 104 offset[n] = 16;
225
226 // these somewhat resemble bt601/smpte170m coefficients
227 104 coeff[0][0][n] = lrint(0.3 * (1 << 14));
228 104 coeff[0][1][n] = lrint(0.6 * (1 << 14));
229 104 coeff[0][2][n] = lrint(0.1 * (1 << 14));
230 104 coeff[1][0][n] = lrint(-0.15 * (1 << 14));
231 104 coeff[1][1][n] = lrint(-0.35 * (1 << 14));
232 104 coeff[1][2][n] = lrint(0.5 * (1 << 14));
233 104 coeff[2][0][n] = lrint(0.5 * (1 << 14));
234 104 coeff[2][1][n] = lrint(-0.42 * (1 << 14));
235 104 coeff[2][2][n] = lrint(-0.08 * (1 << 14));
236 }
237
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13 times.
52 for (odepth = 0; odepth < 3; odepth++) {
238
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 39 times.
156 for (fmt = 0; fmt < 3; fmt++) {
239
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 99 times.
117 if (check_func(dsp.rgb2yuv[odepth][fmt],
240 "ff_colorspacedsp_rgb2yuv_%sp%d",
241 format_string[fmt], odepth * 2 + 8)) {
242 18 int ss_w = !!fmt, ss_h = fmt == 2;
243
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 int y_dst_stride = W << !!odepth;
244 18 int uv_dst_stride = y_dst_stride >> ss_w;
245
246
6/6
✓ Branch 1 taken 221184 times.
✓ Branch 2 taken 3456 times.
✓ Branch 3 taken 3456 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 18 times.
224712 randomize_buffers();
247 18 call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
248 src, W, W, H, coeff, offset);
249 18 call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
250 src, W, W, H, coeff, offset);
251
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (memcmp(dst0[0], dst1[0], H * y_dst_stride) ||
252
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 memcmp(dst0[1], dst1[1], H * uv_dst_stride >> ss_h) ||
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 memcmp(dst0[2], dst1[2], H * uv_dst_stride >> ss_h)) {
254 fail();
255 }
256 }
257 }
258 }
259
260 13 report("rgb2yuv");
261 13 }
262
263 13 static void check_multiply3x3(void)
264 {
265 13 declare_func(void, int16_t *data[3], ptrdiff_t stride,
266 int w, int h, const int16_t coeff[3][3][8]);
267 ColorSpaceDSPContext dsp;
268 13 LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
269 13 LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
270 13 LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
271 13 LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
272 13 LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
273 13 LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
274 13 int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
275 13 int16_t **src = dst0;
276 13 LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
277 13 int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
278 int n;
279
280 13 ff_colorspacedsp_init(&dsp);
281
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 13 times.
117 for (n = 0; n < 8; n++) {
282 104 coeff[0][0][n] = lrint(0.85 * (1 << 14));
283 104 coeff[0][1][n] = lrint(0.10 * (1 << 14));
284 104 coeff[0][2][n] = lrint(0.05 * (1 << 14));
285 104 coeff[1][0][n] = lrint(-0.1 * (1 << 14));
286 104 coeff[1][1][n] = lrint(0.95 * (1 << 14));
287 104 coeff[1][2][n] = lrint(0.15 * (1 << 14));
288 104 coeff[2][0][n] = lrint(-0.2 * (1 << 14));
289 104 coeff[2][1][n] = lrint(0.30 * (1 << 14));
290 104 coeff[2][2][n] = lrint(0.90 * (1 << 14));
291 }
292
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 11 times.
13 if (check_func(dsp.multiply3x3, "ff_colorspacedsp_multiply3x3")) {
293
6/6
✓ Branch 1 taken 24576 times.
✓ Branch 2 taken 384 times.
✓ Branch 3 taken 384 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
24968 randomize_buffers();
294 2 memcpy(dst1_y, dst0_y, W * H * sizeof(*dst1_y));
295 2 memcpy(dst1_u, dst0_u, W * H * sizeof(*dst1_u));
296 2 memcpy(dst1_v, dst0_v, W * H * sizeof(*dst1_v));
297 2 call_ref(dst0, W, W, H, coeff);
298 2 call_new(dst1, W, W, H, coeff);
299
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (memcmp(dst0[0], dst1[0], H * W * sizeof(*dst0_y)) ||
300
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 memcmp(dst0[1], dst1[1], H * W * sizeof(*dst0_u)) ||
301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 memcmp(dst0[2], dst1[2], H * W * sizeof(*dst0_v))) {
302 fail();
303 }
304 }
305
306 13 report("multiply3x3");
307 13 }
308
309 13 void checkasm_check_colorspace(void)
310 {
311 13 check_yuv2yuv();
312 13 check_yuv2rgb();
313 13 check_rgb2yuv();
314 13 check_multiply3x3();
315 13 }
316