Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo 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 : : * libplacebo 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 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 libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #pragma once
19 : :
20 : : #include "common.h"
21 : :
22 : : #include <libplacebo/log.h>
23 : : #include <libplacebo/colorspace.h>
24 : : #include <libplacebo/shaders/film_grain.h>
25 : :
26 : : #include <stdio.h>
27 : : #include <stdlib.h>
28 : : #include <math.h>
29 : : #include <time.h>
30 : :
31 : : #ifdef PL_HAVE_WIN32
32 : : #include <io.h>
33 : : #define isatty _isatty
34 : : #define fileno _fileno
35 : : #else
36 : : #include <unistd.h>
37 : : #endif
38 : :
39 : 71527 : static void pl_log_timestamp(void *stream, enum pl_log_level level, const char *msg)
40 : : {
41 : : static char letter[] = {
42 : : [PL_LOG_FATAL] = 'f',
43 : : [PL_LOG_ERR] = 'e',
44 : : [PL_LOG_WARN] = 'w',
45 : : [PL_LOG_INFO] = 'i',
46 : : [PL_LOG_DEBUG] = 'd',
47 : : [PL_LOG_TRACE] = 't',
48 : : };
49 : :
50 : : // Log time relative to the first message
51 : : static pl_clock_t base = 0;
52 [ + + ]: 71527 : if (!base)
53 : 11 : base = pl_clock_now();
54 : :
55 : 71527 : double secs = pl_clock_diff(pl_clock_now(), base);
56 : 71527 : printf("[%2.3f][%c] %s\n", secs, letter[level], msg);
57 : :
58 [ + + ]: 71527 : if (level <= PL_LOG_WARN) {
59 : : // duplicate warnings/errors to stderr
60 : 197 : fprintf(stderr, "[%2.3f][%c] %s\n", secs, letter[level], msg);
61 : 197 : fflush(stderr);
62 : : }
63 : 71527 : }
64 : :
65 : 11 : static inline pl_log pl_test_logger(void)
66 : : {
67 : 11 : setbuf(stdout, NULL);
68 : 11 : setbuf(stderr, NULL);
69 : :
70 [ + - ]: 22 : return pl_log_create(PL_API_VER, pl_log_params(
71 : : .log_cb = isatty(fileno(stdout)) ? pl_log_color : pl_log_timestamp,
72 : : .log_level = PL_LOG_DEBUG,
73 : : ));
74 : : }
75 : :
76 : : #define RANDOM (rand() / (float) RAND_MAX)
77 : : #define RANDOM_U8 ((uint8_t) (256.0 * rand() / (RAND_MAX + 1.0)))
78 : : #define SKIP 77
79 : :
80 : 381808 : static inline uint16_t random_f16(void)
81 : : {
82 : : union { uint16_t u; uint8_t b[2]; } x;
83 : : do {
84 [ + + ]: 1182615 : for (int i = 0; i < PL_ARRAY_SIZE(x.b); i++)
85 : 788410 : x.b[i] = RANDOM_U8;
86 [ + + ]: 394205 : } while ((x.u & 0x7C00) == 0x7C00); /* infinity or nan */
87 : :
88 : 381808 : return x.u;
89 : : }
90 : :
91 : 218400 : static inline float random_f32(void)
92 : : {
93 : : union { float f; uint8_t b[4]; } x;
94 : : do {
95 [ + + ]: 1096065 : for (int i = 0; i < PL_ARRAY_SIZE(x.b); i++)
96 : 876852 : x.b[i] = RANDOM_U8;
97 [ + + - + ]: 219213 : } while (isnan(x.f) || isinf(x.f));
98 : :
99 : 218400 : return x.f;
100 : : }
101 : :
102 : 43680 : static inline double random_f64(void)
103 : : {
104 : : union { double f; uint8_t b[8]; } x;
105 : : do {
106 [ + + ]: 393300 : for (int i = 0; i < PL_ARRAY_SIZE(x.b); i++)
107 : 349600 : x.b[i] = RANDOM_U8;
108 [ + + - + ]: 43700 : } while (isnan(x.f) || isinf(x.f));
109 : :
110 : 43680 : return x.f;
111 : : }
112 : :
113 : : #define RANDOM_F16 random_f16()
114 : : #define RANDOM_F32 random_f32()
115 : : #define RANDOM_F64 random_f64()
116 : :
117 : : // Helpers for performing various checks
118 : : #define REQUIRE(cond) do \
119 : : { \
120 : : if (!(cond)) { \
121 : : fprintf(stderr, "=== FAILED: '"#cond"' at "__FILE__":%d\n\n", __LINE__);\
122 : : exit(1); \
123 : : } \
124 : : } while (0)
125 : :
126 : : #define REQUIRE_CMP(a, op, b, fmt) do \
127 : : { \
128 : : __typeof__(a) _va = (a), _vb = (b); \
129 : : \
130 : : if (!(_va op _vb)) { \
131 : : fprintf(stderr, "=== FAILED: '"#a" "#op" "#b"' at "__FILE__":%d\n" \
132 : : " %-31s = %"fmt"\n" \
133 : : " %-31s = %"fmt"\n\n", \
134 : : __LINE__, #a, _va, #b, _vb); \
135 : : exit(1); \
136 : : } \
137 : : } while (0)
138 : :
139 : : #define REQUIRE_FEQ(a, b, epsilon) do \
140 : : { \
141 : : float _va = (a); \
142 : : float _vb = (b); \
143 : : float _delta = (epsilon) * fmax(1.0, fabs(_va)); \
144 : : \
145 : : if (fabs(_va - _vb) > _delta) { \
146 : : fprintf(stderr, "=== FAILED: '"#a" ≈ "#b"' at "__FILE__":%d\n" \
147 : : " %-31s = %f\n" \
148 : : " %-31s = %f\n" \
149 : : " %-31s = %f\n\n", \
150 : : __LINE__, #a, _va, #b, _vb, \
151 : : "epsilon "#epsilon" -> max delta", _delta); \
152 : : exit(1); \
153 : : } \
154 : : } while (0)
155 : :
156 : : #define REQUIRE_STREQ(a, b) do \
157 : : { \
158 : : const char *_a = (a); \
159 : : const char *_b = (b); \
160 : : if (strcmp(_a, _b) != 0) { \
161 : : fprintf(stderr, "=== FAILED: !strcmp("#a", "#b") at "__FILE__":%d\n" \
162 : : " %-31s = %s\n" \
163 : : " %-31s = %s\n\n", \
164 : : __LINE__, #a, _a, #b, _b); \
165 : : exit(1); \
166 : : } \
167 : : } while (0)
168 : :
169 : 0 : static inline void log_array(const uint8_t *a, const uint8_t *ref, size_t off, size_t size)
170 : : {
171 : : const int width = 16;
172 : : unsigned errors = 0;
173 [ # # ]: 0 : for (size_t n = 0; n < size; n++) {
174 : : const char *prefix = "", *suffix = "";
175 : : bool newline = false;
176 : 0 : int idx = n % width;
177 [ # # ]: 0 : if (a[n + off] != ref[n + off]) {
178 : : prefix = "\033[31;1m";
179 : : suffix = "\033[0m";
180 : 0 : errors |= 1 << idx;
181 : : }
182 [ # # # # ]: 0 : if (n + 1 == size || idx == width - 1)
183 : : newline = true;
184 : 0 : fprintf(stderr, "%s%02"PRIx8"%s%c", prefix, a[n + off], suffix, newline ? '\n' : ' ');
185 [ # # ]: 0 : if (newline && errors) {
186 [ # # ]: 0 : for (int i = 0; i <= idx; i++) {
187 [ # # ]: 0 : const char mark = errors & (1 << i) ? '^' : ' ';
188 [ # # ]: 0 : fprintf(stderr, "%c%c%c", mark, mark, i == idx ? '\n' : ' ');
189 : : }
190 : : errors = 0;
191 : : }
192 : : }
193 : 0 : }
194 : :
195 : 705 : static inline void require_memeq(const void *aptr, const void *bptr, size_t size,
196 : : const char *astr, const char *bstr,
197 : : const char *sizestr, const char *file, int line)
198 : : {
199 : : const uint8_t *a = aptr, *b = bptr;
200 [ + + ]: 6182514 : for (size_t i = 0; i < size; i++) {
201 [ + - ]: 6181809 : if (a[i] == b[i])
202 : : continue;
203 : :
204 : 0 : fprintf(stderr, "=== FAILED: memcmp(%s, %s, %s) == 0 at %s:%d\n"
205 : : "at position %zu: 0x%02"PRIx8" != 0x%02"PRIx8"\n\n",
206 : : astr, bstr, sizestr, file, line, i, a[i], b[i]);
207 : :
208 : 0 : size_t start = i >= 256 ? i - 256 : 0;
209 : 0 : size_t end = PL_MIN(size, i + 256);
210 : 0 : fprintf(stderr, "%zu bytes of '%s' at offset %zu:\n", end - start, astr, start);
211 : 0 : log_array(a, b, start, end - start);
212 : 0 : fprintf(stderr, "\n%zu bytes of '%s' at offset %zu:\n", end - start, bstr, start);
213 : 0 : log_array(b, a, start, end - start);
214 : 0 : exit(1);
215 : : }
216 : 705 : }
217 : :
218 : : #define REQUIRE_MEMEQ(a, b, size) require_memeq(a, b, size, #a, #b, #size, __FILE__, __LINE__)
219 : :
220 : : #define REQUIRE_HANDLE(shmem, type) \
221 : : switch (type) { \
222 : : case PL_HANDLE_FD: \
223 : : case PL_HANDLE_DMA_BUF: \
224 : : REQUIRE(shmem.handle.fd > -1); \
225 : : break; \
226 : : case PL_HANDLE_WIN32: \
227 : : case PL_HANDLE_WIN32_KMT: \
228 : : /* INVALID_HANDLE_VALUE = (-1) */ \
229 : : REQUIRE(shmem.handle.handle != (void *)(intptr_t) (-1)); \
230 : : /* fallthrough */ \
231 : : case PL_HANDLE_MTL_TEX: \
232 : : case PL_HANDLE_IOSURFACE: \
233 : : REQUIRE(shmem.handle.handle); \
234 : : break; \
235 : : case PL_HANDLE_HOST_PTR: \
236 : : REQUIRE(shmem.handle.ptr); \
237 : : break; \
238 : : }
239 : :
240 : : static const struct pl_av1_grain_data av1_grain_data = {
241 : : .num_points_y = 6,
242 : : .points_y = {{0, 4}, {27, 33}, {54, 55}, {67, 61}, {108, 71}, {255, 72}},
243 : : .chroma_scaling_from_luma = false,
244 : : .num_points_uv = {2, 2},
245 : : .points_uv = {{{0, 64}, {255, 64}}, {{0, 64}, {255, 64}}},
246 : : .scaling_shift = 11,
247 : : .ar_coeff_lag = 3,
248 : : .ar_coeffs_y = {4, 1, 3, 0, 1, -3, 8, -3, 7, -23, 1, -25,
249 : : 0, -10, 6, -17, -4, 53, 36, 5, -5, -17, 8, 66},
250 : : .ar_coeffs_uv = {
251 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252 : : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127},
253 : : {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254 : : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127},
255 : : },
256 : : .ar_coeff_shift = 7,
257 : : .grain_scale_shift = 0,
258 : : .uv_mult = {0, 0},
259 : : .uv_mult_luma = {64, 64},
260 : : .uv_offset = {0, 0},
261 : : };
262 : :
263 : : static const uint8_t h274_lower_bound = 10;
264 : : static const uint8_t h274_upper_bound = 250;
265 : : static const int16_t h274_values[6] = {16, 12, 14};
266 : :
267 : : static const struct pl_h274_grain_data h274_grain_data = {
268 : : .model_id = 0,
269 : : .blending_mode_id = 0,
270 : : .log2_scale_factor = 2,
271 : : .component_model_present = {true},
272 : : .num_intensity_intervals = {1},
273 : : .num_model_values = {3},
274 : : .intensity_interval_lower_bound = {&h274_lower_bound},
275 : : .intensity_interval_upper_bound = {&h274_upper_bound},
276 : : .comp_model_value = {&h274_values},
277 : : };
278 : :
279 : : static const struct pl_dovi_metadata dovi_meta = {
280 : : .nonlinear = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}},
281 : : .linear = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}},
282 : : .comp = {
283 : : {
284 : : .num_pivots = 9,
285 : : .pivots = {0.0615835786, 0.129032254, 0.353861183,
286 : : 0.604105592, 0.854349971, 0.890518069,
287 : : 0.906158328, 0.913978517, 0.92082113},
288 : : .method = {0, 0, 0, 0, 0, 0, 0, 0},
289 : : .poly_coeffs = {
290 : : {-0.0488376617, 1.99335372, -2.41716385},
291 : : {-0.0141925812, 1.61829138, -1.53397191},
292 : : { 0.157061458, 0.63640213, -0.11302495},
293 : : {0.25272119, 0.246226311, 0.27281332},
294 : : {0.951621532, -1.35507894, 1.18898678},
295 : : {6.41251612, -13.6188488, 8.07336903},
296 : : {13.467535, -29.1869125, 16.6612244},
297 : : {28.2321472, -61.8516273, 34.7264938}
298 : : },
299 : : }, {
300 : : .num_pivots = 2,
301 : : .pivots = {0.0, 1.0},
302 : : .method = {1},
303 : : .mmr_order = {3},
304 : : .mmr_constant = {-0.500733018},
305 : : .mmr_coeffs = {{
306 : : {1.08411026, 3.80807829, 0.0881733894, -3.23097038, -0.409078479, -1.31310081, 2.71297002},
307 : : {-0.241833091, -3.57880807, -0.108109117, 3.13198471, 0.869203091, 1.96561158, -9.30871677},
308 : : {-0.177356839, 1.48970401, 0.0908923149, -0.510447979, -0.687603354, -0.934977889, 12.3544884},
309 : : }},
310 : : }, {
311 : : .num_pivots = 2,
312 : : .pivots = {0.0, 1.0},
313 : : .method = {1},
314 : : .mmr_order = {3},
315 : : .mmr_constant = {-1.23833287},
316 : : .mmr_coeffs = {{
317 : : {3.52909589, 0.383154511, 5.50820637, -1.02094889, -6.36386824, 0.194121242, 0.64683497},
318 : : {-2.57899785, -0.626081586, -6.05729723, 2.29143763, 9.14653015, -0.0507702827, -4.17724133},
319 : : {0.705404401, 0.341412306, 2.98387456, -1.71712542, -4.91501331, 0.1465137, 6.38665438},
320 : : }},
321 : : },
322 : : },
323 : : };
324 : :
325 : : static const uint8_t sRGB_v2_nano_icc[] = {
326 : : 0x00, 0x00, 0x01, 0x9a, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
327 : : 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
328 : : 0x07, 0xe2, 0x00, 0x03, 0x00, 0x14, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x1d,
329 : : 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
330 : : 0x73, 0x61, 0x77, 0x73, 0x63, 0x74, 0x72, 0x6c, 0x00, 0x00, 0x00, 0x00,
331 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
332 : : 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x68, 0x61, 0x6e, 0x64,
333 : : 0xeb, 0x77, 0x1f, 0x3c, 0xaa, 0x53, 0x51, 0x02, 0xe9, 0x3e, 0x28, 0x6c,
334 : : 0x91, 0x46, 0xae, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
337 : : 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x5f,
338 : : 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x14,
339 : : 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x14,
340 : : 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x14,
341 : : 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x14,
342 : : 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x34,
343 : : 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x34,
344 : : 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x34,
345 : : 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x0a,
346 : : 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
347 : : 0x6e, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 : : 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
349 : : 0x00, 0x00, 0xf3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xc9,
350 : : 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
351 : : 0x00, 0x00, 0x38, 0xf2, 0x00, 0x00, 0x03, 0x8f, 0x58, 0x59, 0x5a, 0x20,
352 : : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x96, 0x00, 0x00, 0xb7, 0x89,
353 : : 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
354 : : 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x85, 0x00, 0x00, 0xb6, 0xc4,
355 : : 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
356 : : 0x00, 0x00, 0x01, 0x07, 0x02, 0xb5, 0x05, 0x6b, 0x09, 0x36, 0x0e, 0x50,
357 : : 0x14, 0xb1, 0x1c, 0x80, 0x25, 0xc8, 0x30, 0xa1, 0x3d, 0x19, 0x4b, 0x40,
358 : : 0x5b, 0x27, 0x6c, 0xdb, 0x80, 0x6b, 0x95, 0xe3, 0xad, 0x50, 0xc6, 0xc2,
359 : : 0xe2, 0x31, 0xff, 0xff, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00,
360 : : 0x30, 0x00
361 : : };
362 : :
363 : : #define TEST_PROFILE(arr) ((struct pl_icc_profile) { \
364 : : .data = (arr), \
365 : : .len = PL_ARRAY_SIZE(arr), \
366 : : .signature = (uintptr_t) (arr), \
367 : : })
|