SDL

Форк
0
/
testyuv.c 
559 строк · 23.6 Кб
1
/*
2
  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
3

4
  This software is provided 'as-is', without any express or implied
5
  warranty.  In no event will the authors be held liable for any damages
6
  arising from the use of this software.
7

8
  Permission is granted to anyone to use this software for any purpose,
9
  including commercial applications, and to alter it and redistribute it
10
  freely.
11
*/
12
#include <SDL3/SDL.h>
13
#include <SDL3/SDL_main.h>
14
#include <SDL3/SDL_test.h>
15
#include "testyuv_cvt.h"
16
#include "testutils.h"
17

18
/* 422 (YUY2, etc) and P010 formats are the largest */
19
#define MAX_YUV_SURFACE_SIZE(W, H, P) ((H + 1) * ((W + 1) + P) * 4)
20

21
/* Return true if the YUV format is packed pixels */
22
static SDL_bool is_packed_yuv_format(Uint32 format)
23
{
24
    return format == SDL_PIXELFORMAT_YUY2 || format == SDL_PIXELFORMAT_UYVY || format == SDL_PIXELFORMAT_YVYU;
25
}
26

27
/* Create a surface with a good pattern for verifying YUV conversion */
28
static SDL_Surface *generate_test_pattern(int pattern_size)
29
{
30
    SDL_Surface *pattern = SDL_CreateSurface(pattern_size, pattern_size, SDL_PIXELFORMAT_RGB24);
31

32
    if (pattern) {
33
        int i, x, y;
34
        Uint8 *p, c;
35
        const int thickness = 2; /* Important so 2x2 blocks of color are the same, to avoid Cr/Cb interpolation over pixels */
36

37
        /* R, G, B in alternating horizontal bands */
38
        for (y = 0; y < pattern->h - (thickness - 1); y += thickness) {
39
            for (i = 0; i < thickness; ++i) {
40
                p = (Uint8 *)pattern->pixels + (y + i) * pattern->pitch + ((y / thickness) % 3);
41
                for (x = 0; x < pattern->w; ++x) {
42
                    *p = 0xFF;
43
                    p += 3;
44
                }
45
            }
46
        }
47

48
        /* Black and white in alternating vertical bands */
49
        c = 0xFF;
50
        for (x = 1 * thickness; x < pattern->w; x += 2 * thickness) {
51
            for (i = 0; i < thickness; ++i) {
52
                p = (Uint8 *)pattern->pixels + (x + i) * 3;
53
                for (y = 0; y < pattern->h; ++y) {
54
                    SDL_memset(p, c, 3);
55
                    p += pattern->pitch;
56
                }
57
            }
58
            if (c) {
59
                c = 0x00;
60
            } else {
61
                c = 0xFF;
62
            }
63
        }
64
    }
65
    return pattern;
66
}
67

68
static SDL_bool verify_yuv_data(Uint32 format, SDL_Colorspace colorspace, const Uint8 *yuv, int yuv_pitch, SDL_Surface *surface, int tolerance)
69
{
70
    const int size = (surface->h * surface->pitch);
71
    Uint8 *rgb;
72
    SDL_bool result = SDL_FALSE;
73

74
    rgb = (Uint8 *)SDL_malloc(size);
75
    if (!rgb) {
76
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory");
77
        return SDL_FALSE;
78
    }
79

80
    if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, format, colorspace, 0, yuv, yuv_pitch, surface->format, SDL_COLORSPACE_SRGB, 0, rgb, surface->pitch) == 0) {
81
        int x, y;
82
        result = SDL_TRUE;
83
        for (y = 0; y < surface->h; ++y) {
84
            const Uint8 *actual = rgb + y * surface->pitch;
85
            const Uint8 *expected = (const Uint8 *)surface->pixels + y * surface->pitch;
86
            for (x = 0; x < surface->w; ++x) {
87
                int deltaR = (int)actual[0] - expected[0];
88
                int deltaG = (int)actual[1] - expected[1];
89
                int deltaB = (int)actual[2] - expected[2];
90
                int distance = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB);
91
                if (distance > tolerance) {
92
                    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Pixel at %d,%d was 0x%.2x,0x%.2x,0x%.2x, expected 0x%.2x,0x%.2x,0x%.2x, distance = %d\n", x, y, actual[0], actual[1], actual[2], expected[0], expected[1], expected[2], distance);
93
                    result = SDL_FALSE;
94
                }
95
                actual += 3;
96
                expected += 3;
97
            }
98
        }
99
    } else {
100
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(format), SDL_GetPixelFormatName(surface->format), SDL_GetError());
101
    }
102
    SDL_free(rgb);
103

104
    return result;
105
}
106

107
static int run_automated_tests(int pattern_size, int extra_pitch)
108
{
109
    const Uint32 formats[] = {
110
        SDL_PIXELFORMAT_YV12,
111
        SDL_PIXELFORMAT_IYUV,
112
        SDL_PIXELFORMAT_NV12,
113
        SDL_PIXELFORMAT_NV21,
114
        SDL_PIXELFORMAT_YUY2,
115
        SDL_PIXELFORMAT_UYVY,
116
        SDL_PIXELFORMAT_YVYU
117
    };
118
    int i, j;
119
    SDL_Surface *pattern = generate_test_pattern(pattern_size);
120
    const int yuv_len = MAX_YUV_SURFACE_SIZE(pattern->w, pattern->h, extra_pitch);
121
    Uint8 *yuv1 = (Uint8 *)SDL_malloc(yuv_len);
122
    Uint8 *yuv2 = (Uint8 *)SDL_malloc(yuv_len);
123
    int yuv1_pitch, yuv2_pitch;
124
    YUV_CONVERSION_MODE mode;
125
    SDL_Colorspace colorspace;
126
    const int tight_tolerance = 20;
127
    const int loose_tolerance = 333;
128
    int result = -1;
129

130
    if (!pattern || !yuv1 || !yuv2) {
131
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate test surfaces");
132
        goto done;
133
    }
134

135
    mode = GetYUVConversionModeForResolution(pattern->w, pattern->h);
136
    colorspace = GetColorspaceForYUVConversionMode(mode);
137

138
    /* Verify conversion from YUV formats */
139
    for (i = 0; i < SDL_arraysize(formats); ++i) {
140
        if (!ConvertRGBtoYUV(formats[i], pattern->pixels, pattern->pitch, yuv1, pattern->w, pattern->h, mode, 0, 100)) {
141
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ConvertRGBtoYUV() doesn't support converting to %s\n", SDL_GetPixelFormatName(formats[i]));
142
            goto done;
143
        }
144
        yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w);
145
        if (!verify_yuv_data(formats[i], colorspace, yuv1, yuv1_pitch, pattern, tight_tolerance)) {
146
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to RGB\n", SDL_GetPixelFormatName(formats[i]));
147
            goto done;
148
        }
149
    }
150

151
    /* Verify conversion to YUV formats */
152
    for (i = 0; i < SDL_arraysize(formats); ++i) {
153
        yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
154
        if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
155
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
156
            goto done;
157
        }
158
        if (!verify_yuv_data(formats[i], colorspace, yuv1, yuv1_pitch, pattern, tight_tolerance)) {
159
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from RGB to %s\n", SDL_GetPixelFormatName(formats[i]));
160
            goto done;
161
        }
162
    }
163

164
    /* Verify conversion between YUV formats */
165
    for (i = 0; i < SDL_arraysize(formats); ++i) {
166
        for (j = 0; j < SDL_arraysize(formats); ++j) {
167
            yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
168
            yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
169
            if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
170
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
171
                goto done;
172
            }
173
            if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, 0, yuv1, yuv1_pitch, formats[j], colorspace, 0, yuv2, yuv2_pitch) < 0) {
174
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
175
                goto done;
176
            }
177
            if (!verify_yuv_data(formats[j], colorspace, yuv2, yuv2_pitch, pattern, tight_tolerance)) {
178
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
179
                goto done;
180
            }
181
        }
182
    }
183

184
    /* Verify conversion between YUV formats in-place */
185
    for (i = 0; i < SDL_arraysize(formats); ++i) {
186
        for (j = 0; j < SDL_arraysize(formats); ++j) {
187
            if (is_packed_yuv_format(formats[i]) != is_packed_yuv_format(formats[j])) {
188
                /* Can't change plane vs packed pixel layout in-place */
189
                continue;
190
            }
191

192
            yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
193
            yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
194
            if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
195
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
196
                goto done;
197
            }
198
            if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, 0, yuv1, yuv1_pitch, formats[j], colorspace, 0, yuv1, yuv2_pitch) < 0) {
199
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
200
                goto done;
201
            }
202
            if (!verify_yuv_data(formats[j], colorspace, yuv1, yuv2_pitch, pattern, tight_tolerance)) {
203
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
204
                goto done;
205
            }
206
        }
207
    }
208

209
    /* Verify round trip through BT.2020 */
210
    colorspace = SDL_COLORSPACE_BT2020_FULL;
211
    if (!ConvertRGBtoYUV(SDL_PIXELFORMAT_P010, pattern->pixels, pattern->pitch, yuv1, pattern->w, pattern->h, YUV_CONVERSION_BT2020, 0, 100)) {
212
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ConvertRGBtoYUV() doesn't support converting to %s\n", SDL_GetPixelFormatName(SDL_PIXELFORMAT_P010));
213
        goto done;
214
    }
215
    yuv1_pitch = CalculateYUVPitch(SDL_PIXELFORMAT_P010, pattern->w);
216
    if (!verify_yuv_data(SDL_PIXELFORMAT_P010, colorspace, yuv1, yuv1_pitch, pattern, tight_tolerance)) {
217
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to RGB\n", SDL_GetPixelFormatName(SDL_PIXELFORMAT_P010));
218
        goto done;
219
    }
220

221
    /* The pitch needs to be Uint16 aligned for P010 pixels */
222
    yuv1_pitch = CalculateYUVPitch(SDL_PIXELFORMAT_P010, pattern->w) + ((extra_pitch + 1) & ~1);
223
    if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, SDL_PIXELFORMAT_P010, colorspace, 0, yuv1, yuv1_pitch) < 0) {
224
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format), SDL_GetPixelFormatName(SDL_PIXELFORMAT_P010), SDL_GetError());
225
        goto done;
226
    }
227
    /* Going through XRGB2101010 format during P010 conversion is slightly lossy, so use looser tolerance here */
228
    if (!verify_yuv_data(SDL_PIXELFORMAT_P010, colorspace, yuv1, yuv1_pitch, pattern, loose_tolerance)) {
229
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from RGB to %s\n", SDL_GetPixelFormatName(SDL_PIXELFORMAT_P010));
230
        goto done;
231
    }
232

233
    result = 0;
234

235
done:
236
    SDL_free(yuv1);
237
    SDL_free(yuv2);
238
    SDL_DestroySurface(pattern);
239
    return result;
240
}
241

242
int main(int argc, char **argv)
243
{
244
    struct
245
    {
246
        SDL_bool enable_intrinsics;
247
        int pattern_size;
248
        int extra_pitch;
249
    } automated_test_params[] = {
250
        /* Test: single pixel */
251
        { SDL_FALSE, 1, 0 },
252
        /* Test: even width and height */
253
        { SDL_FALSE, 2, 0 },
254
        { SDL_FALSE, 4, 0 },
255
        /* Test: odd width and height */
256
        { SDL_FALSE, 1, 0 },
257
        { SDL_FALSE, 3, 0 },
258
        /* Test: even width and height, extra pitch */
259
        { SDL_FALSE, 2, 3 },
260
        { SDL_FALSE, 4, 3 },
261
        /* Test: odd width and height, extra pitch */
262
        { SDL_FALSE, 1, 3 },
263
        { SDL_FALSE, 3, 3 },
264
        /* Test: even width and height with intrinsics */
265
        { SDL_TRUE, 32, 0 },
266
        /* Test: odd width and height with intrinsics */
267
        { SDL_TRUE, 33, 0 },
268
        { SDL_TRUE, 37, 0 },
269
        /* Test: even width and height with intrinsics, extra pitch */
270
        { SDL_TRUE, 32, 3 },
271
        /* Test: odd width and height with intrinsics, extra pitch */
272
        { SDL_TRUE, 33, 3 },
273
        { SDL_TRUE, 37, 3 },
274
    };
275
    char *filename = NULL;
276
    SDL_Surface *original;
277
    SDL_Surface *converted;
278
    SDL_Surface *bmp;
279
    SDL_Window *window;
280
    SDL_Renderer *renderer;
281
    SDL_Texture *output[3];
282
    const char *titles[3] = { "ORIGINAL", "SOFTWARE", "HARDWARE" };
283
    char title[128];
284
    YUV_CONVERSION_MODE yuv_mode;
285
    const char *yuv_mode_name;
286
    Uint32 yuv_format = SDL_PIXELFORMAT_YV12;
287
    const char *yuv_format_name;
288
    SDL_Colorspace yuv_colorspace;
289
    Uint32 rgb_format = SDL_PIXELFORMAT_RGBX8888;
290
    SDL_Colorspace rgb_colorspace = SDL_COLORSPACE_SRGB;
291
    SDL_PropertiesID props;
292
    SDL_bool monochrome = SDL_FALSE;
293
    int luminance = 100;
294
    int current = 0;
295
    int pitch;
296
    Uint8 *raw_yuv;
297
    Uint64 then, now;
298
    int i, iterations = 100;
299
    SDL_bool should_run_automated_tests = SDL_FALSE;
300
    SDLTest_CommonState *state;
301

302
    /* Initialize test framework */
303
    state = SDLTest_CommonCreateState(argv, 0);
304
    if (!state) {
305
        return 1;
306
    }
307

308
    /* Enable standard application logging */
309
    SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
310

311
    /* Parse commandline */
312
    for (i = 1; i < argc;) {
313
        int consumed;
314

315
        consumed = SDLTest_CommonArg(state, i);
316
        if (!consumed) {
317
            if (SDL_strcmp(argv[i], "--jpeg") == 0) {
318
                SetYUVConversionMode(YUV_CONVERSION_JPEG);
319
                consumed = 1;
320
            } else if (SDL_strcmp(argv[i], "--bt601") == 0) {
321
                SetYUVConversionMode(YUV_CONVERSION_BT601);
322
                consumed = 1;
323
            } else if (SDL_strcmp(argv[i], "--bt709") == 0) {
324
                SetYUVConversionMode(YUV_CONVERSION_BT709);
325
                consumed = 1;
326
            } else if (SDL_strcmp(argv[i], "--bt2020") == 0) {
327
                SetYUVConversionMode(YUV_CONVERSION_BT2020);
328
                consumed = 1;
329
            } else if (SDL_strcmp(argv[i], "--auto") == 0) {
330
                SetYUVConversionMode(YUV_CONVERSION_AUTOMATIC);
331
                consumed = 1;
332
            } else if (SDL_strcmp(argv[i], "--yv12") == 0) {
333
                yuv_format = SDL_PIXELFORMAT_YV12;
334
                consumed = 1;
335
            } else if (SDL_strcmp(argv[i], "--iyuv") == 0) {
336
                yuv_format = SDL_PIXELFORMAT_IYUV;
337
                consumed = 1;
338
            } else if (SDL_strcmp(argv[i], "--yuy2") == 0) {
339
                yuv_format = SDL_PIXELFORMAT_YUY2;
340
                consumed = 1;
341
            } else if (SDL_strcmp(argv[i], "--uyvy") == 0) {
342
                yuv_format = SDL_PIXELFORMAT_UYVY;
343
                consumed = 1;
344
            } else if (SDL_strcmp(argv[i], "--yvyu") == 0) {
345
                yuv_format = SDL_PIXELFORMAT_YVYU;
346
                consumed = 1;
347
            } else if (SDL_strcmp(argv[i], "--nv12") == 0) {
348
                yuv_format = SDL_PIXELFORMAT_NV12;
349
                consumed = 1;
350
            } else if (SDL_strcmp(argv[i], "--nv21") == 0) {
351
                yuv_format = SDL_PIXELFORMAT_NV21;
352
                consumed = 1;
353
            } else if (SDL_strcmp(argv[i], "--rgb555") == 0) {
354
                rgb_format = SDL_PIXELFORMAT_XRGB1555;
355
                consumed = 1;
356
            } else if (SDL_strcmp(argv[i], "--rgb565") == 0) {
357
                rgb_format = SDL_PIXELFORMAT_RGB565;
358
                consumed = 1;
359
            } else if (SDL_strcmp(argv[i], "--rgb24") == 0) {
360
                rgb_format = SDL_PIXELFORMAT_RGB24;
361
                consumed = 1;
362
            } else if (SDL_strcmp(argv[i], "--argb") == 0) {
363
                rgb_format = SDL_PIXELFORMAT_ARGB8888;
364
                consumed = 1;
365
            } else if (SDL_strcmp(argv[i], "--abgr") == 0) {
366
                rgb_format = SDL_PIXELFORMAT_ABGR8888;
367
                consumed = 1;
368
            } else if (SDL_strcmp(argv[i], "--rgba") == 0) {
369
                rgb_format = SDL_PIXELFORMAT_RGBA8888;
370
                consumed = 1;
371
            } else if (SDL_strcmp(argv[i], "--bgra") == 0) {
372
                rgb_format = SDL_PIXELFORMAT_BGRA8888;
373
                consumed = 1;
374
            } else if (SDL_strcmp(argv[i], "--monochrome") == 0) {
375
                monochrome = SDL_TRUE;
376
                consumed = 1;
377
            } else if (SDL_strcmp(argv[i], "--luminance") == 0 && argv[i+1]) {
378
                luminance = SDL_atoi(argv[i+1]);
379
                consumed = 2;
380
            } else if (SDL_strcmp(argv[i], "--automated") == 0) {
381
                should_run_automated_tests = SDL_TRUE;
382
                consumed = 1;
383
            } else if (!filename) {
384
                filename = argv[i];
385
                consumed = 1;
386
            }
387
        }
388
        if (consumed <= 0) {
389
            static const char *options[] = {
390
                "[--jpeg|--bt601|--bt709|--bt2020|--auto]",
391
                "[--yv12|--iyuv|--yuy2|--uyvy|--yvyu|--nv12|--nv21]",
392
                "[--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra]",
393
                "[--monochrome] [--luminance N%]",
394
                "[--automated]",
395
                "[sample.bmp]",
396
                NULL,
397
            };
398
            SDLTest_CommonLogUsage(state, argv[0], options);
399
            SDL_Quit();
400
            SDLTest_CommonDestroyState(state);
401
            return 1;
402
        }
403
        i += consumed;
404
    }
405

406
    /* Run automated tests */
407
    if (should_run_automated_tests) {
408
        for (i = 0; i < (int)SDL_arraysize(automated_test_params); ++i) {
409
            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Running automated test, pattern size %d, extra pitch %d, intrinsics %s\n",
410
                        automated_test_params[i].pattern_size,
411
                        automated_test_params[i].extra_pitch,
412
                        automated_test_params[i].enable_intrinsics ? "enabled" : "disabled");
413
            if (run_automated_tests(automated_test_params[i].pattern_size, automated_test_params[i].extra_pitch) < 0) {
414
                return 2;
415
            }
416
        }
417
        return 0;
418
    }
419

420
    filename = GetResourceFilename(filename, "testyuv.bmp");
421
    bmp = SDL_LoadBMP(filename);
422
    original = SDL_ConvertSurface(bmp, SDL_PIXELFORMAT_RGB24);
423
    SDL_DestroySurface(bmp);
424
    if (!original) {
425
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
426
        return 3;
427
    }
428

429
    yuv_mode = GetYUVConversionModeForResolution(original->w, original->h);
430
    switch (yuv_mode) {
431
    case YUV_CONVERSION_JPEG:
432
        yuv_mode_name = "JPEG";
433
        break;
434
    case YUV_CONVERSION_BT601:
435
        yuv_mode_name = "BT.601";
436
        break;
437
    case YUV_CONVERSION_BT709:
438
        yuv_mode_name = "BT.709";
439
        break;
440
    case YUV_CONVERSION_BT2020:
441
        yuv_mode_name = "BT.2020";
442
        yuv_format = SDL_PIXELFORMAT_P010;
443
        rgb_format = SDL_PIXELFORMAT_XBGR2101010;
444
        rgb_colorspace = SDL_COLORSPACE_HDR10;
445
        break;
446
    default:
447
        yuv_mode_name = "UNKNOWN";
448
        break;
449
    }
450
    yuv_colorspace = GetColorspaceForYUVConversionMode(yuv_mode);
451

452
    raw_yuv = SDL_calloc(1, MAX_YUV_SURFACE_SIZE(original->w, original->h, 0));
453
    ConvertRGBtoYUV(yuv_format, original->pixels, original->pitch, raw_yuv, original->w, original->h, yuv_mode, monochrome, luminance);
454
    pitch = CalculateYUVPitch(yuv_format, original->w);
455

456
    converted = SDL_CreateSurface(original->w, original->h, rgb_format);
457
    if (!converted) {
458
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create converted surface: %s\n", SDL_GetError());
459
        return 3;
460
    }
461

462
    then = SDL_GetTicks();
463
    for (i = 0; i < iterations; ++i) {
464
        SDL_ConvertPixelsAndColorspace(original->w, original->h, yuv_format, yuv_colorspace, 0, raw_yuv, pitch, rgb_format, rgb_colorspace, 0, converted->pixels, converted->pitch);
465
    }
466
    now = SDL_GetTicks();
467
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%d iterations in %" SDL_PRIu64 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations);
468

469
    window = SDL_CreateWindow("YUV test", original->w, original->h, 0);
470
    if (!window) {
471
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
472
        return 4;
473
    }
474

475
    renderer = SDL_CreateRenderer(window, NULL);
476
    if (!renderer) {
477
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
478
        return 4;
479
    }
480

481
    output[0] = SDL_CreateTextureFromSurface(renderer, original);
482
    output[1] = SDL_CreateTextureFromSurface(renderer, converted);
483
    props = SDL_CreateProperties();
484
    SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, yuv_colorspace);
485
    SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, yuv_format);
486
    SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STREAMING);
487
    SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, original->w);
488
    SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, original->h);
489
    output[2] = SDL_CreateTextureWithProperties(renderer, props);
490
    SDL_DestroyProperties(props);
491
    if (!output[0] || !output[1] || !output[2]) {
492
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError());
493
        return 5;
494
    }
495
    SDL_UpdateTexture(output[2], NULL, raw_yuv, pitch);
496

497
    yuv_format_name = SDL_GetPixelFormatName(yuv_format);
498
    if (SDL_strncmp(yuv_format_name, "SDL_PIXELFORMAT_", 16) == 0) {
499
        yuv_format_name += 16;
500
    }
501

502
    {
503
        int done = 0;
504
        while (!done) {
505
            SDL_Event event;
506
            while (SDL_PollEvent(&event) > 0) {
507
                if (event.type == SDL_EVENT_QUIT) {
508
                    done = 1;
509
                }
510
                if (event.type == SDL_EVENT_KEY_DOWN) {
511
                    if (event.key.key == SDLK_ESCAPE) {
512
                        done = 1;
513
                    } else if (event.key.key == SDLK_LEFT) {
514
                        --current;
515
                    } else if (event.key.key == SDLK_RIGHT) {
516
                        ++current;
517
                    }
518
                }
519
                if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
520
                    if (event.button.x < (original->w / 2)) {
521
                        --current;
522
                    } else {
523
                        ++current;
524
                    }
525
                }
526
            }
527

528
            /* Handle wrapping */
529
            if (current < 0) {
530
                current += SDL_arraysize(output);
531
            }
532
            if (current >= SDL_arraysize(output)) {
533
                current -= SDL_arraysize(output);
534
            }
535

536
            SDL_RenderClear(renderer);
537
            SDL_RenderTexture(renderer, output[current], NULL, NULL);
538
            SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
539
            if (current == 0) {
540
                SDLTest_DrawString(renderer, 4, 4, titles[current]);
541
            } else {
542
                (void)SDL_snprintf(title, sizeof(title), "%s %s %s", titles[current], yuv_format_name, yuv_mode_name);
543
                SDLTest_DrawString(renderer, 4, 4, title);
544
            }
545
            SDL_RenderPresent(renderer);
546
            SDL_Delay(10);
547
        }
548
    }
549
    SDL_free(raw_yuv);
550
    SDL_free(filename);
551
    SDL_DestroySurface(original);
552
    SDL_DestroySurface(converted);
553
    SDLTest_CleanupTextDrawing();
554
    SDL_DestroyRenderer(renderer);
555
    SDL_DestroyWindow(window);
556
    SDL_Quit();
557
    SDLTest_CommonDestroyState(state);
558
    return 0;
559
}
560

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.