test/testyuv.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:47 -0800
changeset 11731 30f337dc8c74
parent 11702 cf166abbde4a
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Added iOS and OSX versions of the Metal shaders
slouken@11702
     1
/*
slouken@11702
     2
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@11702
     3
slouken@11702
     4
  This software is provided 'as-is', without any express or implied
slouken@11702
     5
  warranty.  In no event will the authors be held liable for any damages
slouken@11702
     6
  arising from the use of this software.
slouken@11702
     7
slouken@11702
     8
  Permission is granted to anyone to use this software for any purpose,
slouken@11702
     9
  including commercial applications, and to alter it and redistribute it
slouken@11702
    10
  freely.
slouken@11702
    11
*/
slouken@11702
    12
#include <stdlib.h>
slouken@11702
    13
#include <stdio.h>
slouken@11702
    14
#include <string.h>
slouken@11702
    15
slouken@11702
    16
#include "SDL.h"
slouken@11702
    17
#include "SDL_test_font.h"
slouken@11702
    18
#include "testyuv_cvt.h"
slouken@11702
    19
slouken@11702
    20
slouken@11702
    21
/* 422 (YUY2, etc) formats are the largest */
slouken@11702
    22
#define MAX_YUV_SURFACE_SIZE(W, H, P)  (H*4*(W+P+1)/2)
slouken@11702
    23
slouken@11702
    24
slouken@11702
    25
/* Return true if the YUV format is packed pixels */
slouken@11702
    26
static SDL_bool is_packed_yuv_format(Uint32 format)
slouken@11702
    27
{
slouken@11702
    28
    return (format == SDL_PIXELFORMAT_YUY2 ||
slouken@11702
    29
            format == SDL_PIXELFORMAT_UYVY ||
slouken@11702
    30
            format == SDL_PIXELFORMAT_YVYU);
slouken@11702
    31
}
slouken@11702
    32
slouken@11702
    33
/* Create a surface with a good pattern for verifying YUV conversion */
slouken@11702
    34
static SDL_Surface *generate_test_pattern(int pattern_size)
slouken@11702
    35
{
slouken@11702
    36
    SDL_Surface *pattern = SDL_CreateRGBSurfaceWithFormat(0, pattern_size, pattern_size, 0, SDL_PIXELFORMAT_RGB24);
slouken@11702
    37
slouken@11702
    38
    if (pattern) {
slouken@11702
    39
        int i, x, y;
slouken@11702
    40
        Uint8 *p, c;
slouken@11702
    41
        const int thickness = 2;    /* Important so 2x2 blocks of color are the same, to avoid Cr/Cb interpolation over pixels */
slouken@11702
    42
slouken@11702
    43
        /* R, G, B in alternating horizontal bands */
slouken@11702
    44
        for (y = 0; y < pattern->h; y += thickness) {
slouken@11702
    45
            for (i = 0; i < thickness; ++i) {
slouken@11702
    46
                p = (Uint8 *)pattern->pixels + (y + i) * pattern->pitch + ((y/thickness) % 3);
slouken@11702
    47
                for (x = 0; x < pattern->w; ++x) {
slouken@11702
    48
                    *p = 0xFF;
slouken@11702
    49
                    p += 3;
slouken@11702
    50
                }
slouken@11702
    51
            }
slouken@11702
    52
        }
slouken@11702
    53
slouken@11702
    54
        /* Black and white in alternating vertical bands */
slouken@11702
    55
        c = 0xFF;
slouken@11702
    56
        for (x = 1*thickness; x < pattern->w; x += 2*thickness) {
slouken@11702
    57
            for (i = 0; i < thickness; ++i) {
slouken@11702
    58
                p = (Uint8 *)pattern->pixels + (x + i)*3;
slouken@11702
    59
                for (y = 0; y < pattern->h; ++y) {
slouken@11702
    60
                    SDL_memset(p, c, 3);
slouken@11702
    61
                    p += pattern->pitch;
slouken@11702
    62
                }
slouken@11702
    63
            }
slouken@11702
    64
            if (c) {
slouken@11702
    65
                c = 0x00;
slouken@11702
    66
            } else {
slouken@11702
    67
                c = 0xFF;
slouken@11702
    68
            }
slouken@11702
    69
        }
slouken@11702
    70
    }
slouken@11702
    71
    return pattern;
slouken@11702
    72
}
slouken@11702
    73
slouken@11702
    74
static SDL_bool verify_yuv_data(Uint32 format, const Uint8 *yuv, int yuv_pitch, SDL_Surface *surface)
slouken@11702
    75
{
slouken@11702
    76
    const int tolerance = 20;
slouken@11702
    77
    const int size = (surface->h * surface->pitch);
slouken@11702
    78
    Uint8 *rgb;
slouken@11702
    79
    SDL_bool result = SDL_FALSE;
slouken@11702
    80
slouken@11702
    81
    rgb = (Uint8 *)SDL_malloc(size);
slouken@11702
    82
    if (!rgb) {
slouken@11702
    83
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory");
slouken@11702
    84
        return SDL_FALSE;
slouken@11702
    85
    }
slouken@11702
    86
slouken@11702
    87
    if (SDL_ConvertPixels(surface->w, surface->h, format, yuv, yuv_pitch, surface->format->format, rgb, surface->pitch) == 0) {
slouken@11702
    88
        int x, y;
slouken@11702
    89
        result = SDL_TRUE;
slouken@11702
    90
        for (y = 0; y < surface->h; ++y) {
slouken@11702
    91
            const Uint8 *actual = rgb + y * surface->pitch;
slouken@11702
    92
            const Uint8 *expected = (const Uint8 *)surface->pixels + y * surface->pitch;
slouken@11702
    93
            for (x = 0; x < surface->w; ++x) {
slouken@11702
    94
                int deltaR = (int)actual[0] - expected[0];
slouken@11702
    95
                int deltaG = (int)actual[1] - expected[1];
slouken@11702
    96
                int deltaB = (int)actual[2] - expected[2];
slouken@11702
    97
                int distance = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB);
slouken@11702
    98
                if (distance > tolerance) {
slouken@11702
    99
                    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);
slouken@11702
   100
                    result = SDL_FALSE;
slouken@11702
   101
                }
slouken@11702
   102
                actual += 3;
slouken@11702
   103
                expected += 3;
slouken@11702
   104
            }
slouken@11702
   105
        }
slouken@11702
   106
    } else {
slouken@11702
   107
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(format), SDL_GetPixelFormatName(surface->format->format), SDL_GetError());
slouken@11702
   108
    }
slouken@11702
   109
    SDL_free(rgb);
slouken@11702
   110
slouken@11702
   111
    return result;
slouken@11702
   112
}
slouken@11702
   113
slouken@11702
   114
static int run_automated_tests(int pattern_size, int extra_pitch)
slouken@11702
   115
{
slouken@11702
   116
    const Uint32 formats[] = {
slouken@11702
   117
        SDL_PIXELFORMAT_YV12,
slouken@11702
   118
        SDL_PIXELFORMAT_IYUV,
slouken@11702
   119
        SDL_PIXELFORMAT_NV12,
slouken@11702
   120
        SDL_PIXELFORMAT_NV21,
slouken@11702
   121
        SDL_PIXELFORMAT_YUY2,
slouken@11702
   122
        SDL_PIXELFORMAT_UYVY,
slouken@11702
   123
        SDL_PIXELFORMAT_YVYU
slouken@11702
   124
    };
slouken@11702
   125
    int i, j;
slouken@11702
   126
    SDL_Surface *pattern = generate_test_pattern(pattern_size);
slouken@11702
   127
    const int yuv_len = MAX_YUV_SURFACE_SIZE(pattern->w, pattern->h, extra_pitch);
slouken@11702
   128
    Uint8 *yuv1 = (Uint8 *)SDL_malloc(yuv_len);
slouken@11702
   129
    Uint8 *yuv2 = (Uint8 *)SDL_malloc(yuv_len);
slouken@11702
   130
    int yuv1_pitch, yuv2_pitch;
slouken@11702
   131
    int result = -1;
slouken@11702
   132
    
slouken@11702
   133
    if (!pattern || !yuv1 || !yuv2) {
slouken@11702
   134
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate test surfaces");
slouken@11702
   135
        goto done;
slouken@11702
   136
    }
slouken@11702
   137
slouken@11702
   138
    /* Verify conversion from YUV formats */
slouken@11702
   139
    for (i = 0; i < SDL_arraysize(formats); ++i) {
slouken@11702
   140
        if (!ConvertRGBtoYUV(formats[i], pattern->pixels, pattern->pitch, yuv1, pattern->w, pattern->h, SDL_GetYUVConversionModeForResolution(pattern->w, pattern->h), 0, 100)) {
slouken@11702
   141
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ConvertRGBtoYUV() doesn't support converting to %s\n", SDL_GetPixelFormatName(formats[i]));
slouken@11702
   142
            goto done;
slouken@11702
   143
        }
slouken@11702
   144
        yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w);
slouken@11702
   145
        if (!verify_yuv_data(formats[i], yuv1, yuv1_pitch, pattern)) {
slouken@11702
   146
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to RGB\n", SDL_GetPixelFormatName(formats[i]));
slouken@11702
   147
            goto done;
slouken@11702
   148
        }
slouken@11702
   149
    }
slouken@11702
   150
slouken@11702
   151
    /* Verify conversion to YUV formats */
slouken@11702
   152
    for (i = 0; i < SDL_arraysize(formats); ++i) {
slouken@11702
   153
        yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
slouken@11702
   154
        if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
slouken@11702
   155
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
slouken@11702
   156
            goto done;
slouken@11702
   157
        }
slouken@11702
   158
        if (!verify_yuv_data(formats[i], yuv1, yuv1_pitch, pattern)) {
slouken@11702
   159
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from RGB to %s\n", SDL_GetPixelFormatName(formats[i]));
slouken@11702
   160
            goto done;
slouken@11702
   161
        }
slouken@11702
   162
    }
slouken@11702
   163
slouken@11702
   164
    /* Verify conversion between YUV formats */
slouken@11702
   165
    for (i = 0; i < SDL_arraysize(formats); ++i) {
slouken@11702
   166
        for (j = 0; j < SDL_arraysize(formats); ++j) {
slouken@11702
   167
            yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
slouken@11702
   168
            yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
slouken@11702
   169
            if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
slouken@11702
   170
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
slouken@11702
   171
                goto done;
slouken@11702
   172
            }
slouken@11702
   173
            if (SDL_ConvertPixels(pattern->w, pattern->h, formats[i], yuv1, yuv1_pitch, formats[j], yuv2, yuv2_pitch) < 0) {
slouken@11702
   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());
slouken@11702
   175
                goto done;
slouken@11702
   176
            }
slouken@11702
   177
            if (!verify_yuv_data(formats[j], yuv2, yuv2_pitch, pattern)) {
slouken@11702
   178
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
slouken@11702
   179
                goto done;
slouken@11702
   180
            }
slouken@11702
   181
        }
slouken@11702
   182
    }
slouken@11702
   183
slouken@11702
   184
    /* Verify conversion between YUV formats in-place */
slouken@11702
   185
    for (i = 0; i < SDL_arraysize(formats); ++i) {
slouken@11702
   186
        for (j = 0; j < SDL_arraysize(formats); ++j) {
slouken@11702
   187
            if (is_packed_yuv_format(formats[i]) != is_packed_yuv_format(formats[j])) {
slouken@11702
   188
                /* Can't change plane vs packed pixel layout in-place */
slouken@11702
   189
                continue;
slouken@11702
   190
            }
slouken@11702
   191
slouken@11702
   192
            yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
slouken@11702
   193
            yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
slouken@11702
   194
            if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
slouken@11702
   195
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
slouken@11702
   196
                goto done;
slouken@11702
   197
            }
slouken@11702
   198
            if (SDL_ConvertPixels(pattern->w, pattern->h, formats[i], yuv1, yuv1_pitch, formats[j], yuv1, yuv2_pitch) < 0) {
slouken@11702
   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());
slouken@11702
   200
                goto done;
slouken@11702
   201
            }
slouken@11702
   202
            if (!verify_yuv_data(formats[j], yuv1, yuv2_pitch, pattern)) {
slouken@11702
   203
                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
slouken@11702
   204
                goto done;
slouken@11702
   205
            }
slouken@11702
   206
        }
slouken@11702
   207
    }
slouken@11702
   208
slouken@11702
   209
slouken@11702
   210
    result = 0;
slouken@11702
   211
slouken@11702
   212
done:
slouken@11702
   213
    SDL_free(yuv1);
slouken@11702
   214
    SDL_free(yuv2);
slouken@11702
   215
    SDL_FreeSurface(pattern);
slouken@11702
   216
    return result;
slouken@11702
   217
}
slouken@11702
   218
slouken@11702
   219
int
slouken@11702
   220
main(int argc, char **argv)
slouken@11702
   221
{
slouken@11702
   222
    struct {
slouken@11702
   223
        SDL_bool enable_intrinsics;
slouken@11702
   224
        int pattern_size;
slouken@11702
   225
        int extra_pitch;
slouken@11702
   226
    } automated_test_params[] = {
slouken@11702
   227
        /* Test: even width and height */
slouken@11702
   228
        { SDL_FALSE, 2, 0 },
slouken@11702
   229
        { SDL_FALSE, 4, 0 },
slouken@11702
   230
        /* Test: odd width and height */
slouken@11702
   231
        { SDL_FALSE, 1, 0 },
slouken@11702
   232
        { SDL_FALSE, 3, 0 },
slouken@11702
   233
        /* Test: even width and height, extra pitch */
slouken@11702
   234
        { SDL_FALSE, 2, 3 },
slouken@11702
   235
        { SDL_FALSE, 4, 3 },
slouken@11702
   236
        /* Test: odd width and height, extra pitch */
slouken@11702
   237
        { SDL_FALSE, 1, 3 },
slouken@11702
   238
        { SDL_FALSE, 3, 3 },
slouken@11702
   239
        /* Test: even width and height with intrinsics */
slouken@11702
   240
        { SDL_TRUE, 32, 0 },
slouken@11702
   241
        /* Test: odd width and height with intrinsics */
slouken@11702
   242
        { SDL_TRUE, 33, 0 },
slouken@11702
   243
        { SDL_TRUE, 37, 0 },
slouken@11702
   244
        /* Test: even width and height with intrinsics, extra pitch */
slouken@11702
   245
        { SDL_TRUE, 32, 3 },
slouken@11702
   246
        /* Test: odd width and height with intrinsics, extra pitch */
slouken@11702
   247
        { SDL_TRUE, 33, 3 },
slouken@11702
   248
        { SDL_TRUE, 37, 3 },
slouken@11702
   249
    };
slouken@11702
   250
    int arg = 1;
slouken@11702
   251
    const char *filename;
slouken@11702
   252
    SDL_Surface *original;
slouken@11702
   253
    SDL_Surface *converted;
slouken@11702
   254
    SDL_Window *window;
slouken@11702
   255
    SDL_Renderer *renderer;
slouken@11702
   256
    SDL_Texture *output[3];
slouken@11702
   257
    const char *titles[3] = { "ORIGINAL", "SOFTWARE", "HARDWARE" };
slouken@11702
   258
    char title[128];
slouken@11702
   259
    const char *yuv_name;
slouken@11702
   260
    const char *yuv_mode;
slouken@11702
   261
    Uint32 rgb_format = SDL_PIXELFORMAT_RGBX8888;
slouken@11702
   262
    Uint32 yuv_format = SDL_PIXELFORMAT_YV12;
slouken@11702
   263
    int current = 0;
slouken@11702
   264
    int pitch;
slouken@11702
   265
    Uint8 *raw_yuv;
slouken@11702
   266
    Uint32 then, now, i, iterations = 100;
slouken@11702
   267
    SDL_bool should_run_automated_tests = SDL_FALSE;
slouken@11702
   268
slouken@11702
   269
    while (argv[arg] && *argv[arg] == '-') {
slouken@11702
   270
        if (SDL_strcmp(argv[arg], "--jpeg") == 0) {
slouken@11702
   271
            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_JPEG);
slouken@11702
   272
        } else if (SDL_strcmp(argv[arg], "--bt601") == 0) {
slouken@11702
   273
            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT601);
slouken@11702
   274
        } else if (SDL_strcmp(argv[arg], "--bt709") == 0) {
slouken@11702
   275
            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT709);
slouken@11702
   276
        } else if (SDL_strcmp(argv[arg], "--auto") == 0) {
slouken@11702
   277
            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_AUTOMATIC);
slouken@11702
   278
        } else if (SDL_strcmp(argv[arg], "--yv12") == 0) {
slouken@11702
   279
            yuv_format = SDL_PIXELFORMAT_YV12;
slouken@11702
   280
        } else if (SDL_strcmp(argv[arg], "--iyuv") == 0) {
slouken@11702
   281
            yuv_format = SDL_PIXELFORMAT_IYUV;
slouken@11702
   282
        } else if (SDL_strcmp(argv[arg], "--yuy2") == 0) {
slouken@11702
   283
            yuv_format = SDL_PIXELFORMAT_YUY2;
slouken@11702
   284
        } else if (SDL_strcmp(argv[arg], "--uyvy") == 0) {
slouken@11702
   285
            yuv_format = SDL_PIXELFORMAT_UYVY;
slouken@11702
   286
        } else if (SDL_strcmp(argv[arg], "--yvyu") == 0) {
slouken@11702
   287
            yuv_format = SDL_PIXELFORMAT_YVYU;
slouken@11702
   288
        } else if (SDL_strcmp(argv[arg], "--nv12") == 0) {
slouken@11702
   289
            yuv_format = SDL_PIXELFORMAT_NV12;
slouken@11702
   290
        } else if (SDL_strcmp(argv[arg], "--nv21") == 0) {
slouken@11702
   291
            yuv_format = SDL_PIXELFORMAT_NV21;
slouken@11702
   292
        } else if (SDL_strcmp(argv[arg], "--rgb555") == 0) {
slouken@11702
   293
            rgb_format = SDL_PIXELFORMAT_RGB555;
slouken@11702
   294
        } else if (SDL_strcmp(argv[arg], "--rgb565") == 0) {
slouken@11702
   295
            rgb_format = SDL_PIXELFORMAT_RGB565;
slouken@11702
   296
        } else if (SDL_strcmp(argv[arg], "--rgb24") == 0) {
slouken@11702
   297
            rgb_format = SDL_PIXELFORMAT_RGB24;
slouken@11702
   298
        } else if (SDL_strcmp(argv[arg], "--argb") == 0) {
slouken@11702
   299
            rgb_format = SDL_PIXELFORMAT_ARGB8888;
slouken@11702
   300
        } else if (SDL_strcmp(argv[arg], "--abgr") == 0) {
slouken@11702
   301
            rgb_format = SDL_PIXELFORMAT_ABGR8888;
slouken@11702
   302
        } else if (SDL_strcmp(argv[arg], "--rgba") == 0) {
slouken@11702
   303
            rgb_format = SDL_PIXELFORMAT_RGBA8888;
slouken@11702
   304
        } else if (SDL_strcmp(argv[arg], "--bgra") == 0) {
slouken@11702
   305
            rgb_format = SDL_PIXELFORMAT_BGRA8888;
slouken@11702
   306
        } else if (SDL_strcmp(argv[arg], "--automated") == 0) {
slouken@11702
   307
            should_run_automated_tests = SDL_TRUE;
slouken@11702
   308
        } else {
slouken@11702
   309
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s [--jpeg|--bt601|-bt709|--auto] [--yv12|--iyuv|--yuy2|--uyvy|--yvyu|--nv12|--nv21] [--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra] [image_filename]\n", argv[0]);
slouken@11702
   310
            return 1;
slouken@11702
   311
        }
slouken@11702
   312
        ++arg;
slouken@11702
   313
    }
slouken@11702
   314
slouken@11702
   315
    /* Run automated tests */
slouken@11702
   316
    if (should_run_automated_tests) {
slouken@11702
   317
        for (i = 0; i < SDL_arraysize(automated_test_params); ++i) {
slouken@11702
   318
            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Running automated test, pattern size %d, extra pitch %d, intrinsics %s\n", 
slouken@11702
   319
                automated_test_params[i].pattern_size,
slouken@11702
   320
                automated_test_params[i].extra_pitch,
slouken@11702
   321
                automated_test_params[i].enable_intrinsics ? "enabled" : "disabled");
slouken@11702
   322
            if (run_automated_tests(automated_test_params[i].pattern_size, automated_test_params[i].extra_pitch) < 0) {
slouken@11702
   323
                return 2;
slouken@11702
   324
            }
slouken@11702
   325
        }
slouken@11702
   326
        return 0;
slouken@11702
   327
    }
slouken@11702
   328
slouken@11702
   329
    if (argv[arg]) {
slouken@11702
   330
        filename = argv[arg];
slouken@11702
   331
    } else {
slouken@11702
   332
        filename = "testyuv.bmp";
slouken@11702
   333
    }
slouken@11702
   334
    original = SDL_ConvertSurfaceFormat(SDL_LoadBMP(filename), SDL_PIXELFORMAT_RGB24, 0);
slouken@11702
   335
    if (!original) {
slouken@11702
   336
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
slouken@11702
   337
        return 3;
slouken@11702
   338
    }
slouken@11702
   339
slouken@11702
   340
    raw_yuv = SDL_calloc(1, MAX_YUV_SURFACE_SIZE(original->w, original->h, 0));
slouken@11702
   341
    ConvertRGBtoYUV(yuv_format, original->pixels, original->pitch, raw_yuv, original->w, original->h,
slouken@11702
   342
        SDL_GetYUVConversionModeForResolution(original->w, original->h),
slouken@11702
   343
        0, 100);
slouken@11702
   344
    pitch = CalculateYUVPitch(yuv_format, original->w);
slouken@11702
   345
slouken@11702
   346
    converted = SDL_CreateRGBSurfaceWithFormat(0, original->w, original->h, 0, rgb_format);
slouken@11702
   347
    if (!converted) {
slouken@11702
   348
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create converted surface: %s\n", SDL_GetError());
slouken@11702
   349
        return 3;
slouken@11702
   350
    }
slouken@11702
   351
slouken@11702
   352
    then = SDL_GetTicks();
slouken@11702
   353
    for ( i = 0; i < iterations; ++i ) {
slouken@11702
   354
        SDL_ConvertPixels(original->w, original->h, yuv_format, raw_yuv, pitch, rgb_format, converted->pixels, converted->pitch);
slouken@11702
   355
    }
slouken@11702
   356
    now = SDL_GetTicks();
slouken@11702
   357
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%d iterations in %d ms, %.2fms each\n", iterations, (now - then), (float)(now - then)/iterations);
slouken@11702
   358
slouken@11702
   359
    window = SDL_CreateWindow("YUV test",
slouken@11702
   360
                              SDL_WINDOWPOS_UNDEFINED,
slouken@11702
   361
                              SDL_WINDOWPOS_UNDEFINED,
slouken@11702
   362
                              original->w, original->h,
slouken@11702
   363
                              0);
slouken@11702
   364
    if (!window) {
slouken@11702
   365
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
slouken@11702
   366
        return 4;
slouken@11702
   367
    }
slouken@11702
   368
slouken@11702
   369
    renderer = SDL_CreateRenderer(window, -1, 0);
slouken@11702
   370
    if (!renderer) {
slouken@11702
   371
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
slouken@11702
   372
        return 4;
slouken@11702
   373
    }
slouken@11702
   374
slouken@11702
   375
    output[0] = SDL_CreateTextureFromSurface(renderer, original);
slouken@11702
   376
    output[1] = SDL_CreateTextureFromSurface(renderer, converted);
slouken@11702
   377
    output[2] = SDL_CreateTexture(renderer, yuv_format, SDL_TEXTUREACCESS_STREAMING, original->w, original->h);
slouken@11702
   378
    if (!output[0] || !output[1] || !output[2]) {
slouken@11702
   379
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError());
slouken@11702
   380
        return 5;
slouken@11702
   381
    }
slouken@11702
   382
    SDL_UpdateTexture(output[2], NULL, raw_yuv, pitch);
slouken@11702
   383
    
slouken@11702
   384
    yuv_name = SDL_GetPixelFormatName(yuv_format);
slouken@11702
   385
    if (SDL_strncmp(yuv_name, "SDL_PIXELFORMAT_", 16) == 0) {
slouken@11702
   386
        yuv_name += 16;
slouken@11702
   387
    }
slouken@11702
   388
slouken@11702
   389
    switch (SDL_GetYUVConversionModeForResolution(original->w, original->h)) {
slouken@11702
   390
    case SDL_YUV_CONVERSION_JPEG:
slouken@11702
   391
        yuv_mode = "JPEG";
slouken@11702
   392
        break;
slouken@11702
   393
    case SDL_YUV_CONVERSION_BT601:
slouken@11702
   394
        yuv_mode = "BT.601";
slouken@11702
   395
        break;
slouken@11702
   396
    case SDL_YUV_CONVERSION_BT709:
slouken@11702
   397
        yuv_mode = "BT.709";
slouken@11702
   398
        break;
slouken@11702
   399
    default:
slouken@11702
   400
        yuv_mode = "UNKNOWN";
slouken@11702
   401
        break;
slouken@11702
   402
    }
slouken@11702
   403
slouken@11702
   404
    { int done = 0;
slouken@11702
   405
        while ( !done )
slouken@11702
   406
        {
slouken@11702
   407
            SDL_Event event;
slouken@11702
   408
            while (SDL_PollEvent(&event) > 0) {
slouken@11702
   409
                if (event.type == SDL_QUIT) {
slouken@11702
   410
                    done = 1;
slouken@11702
   411
                }
slouken@11702
   412
                if (event.type == SDL_KEYDOWN) {
slouken@11702
   413
                    if (event.key.keysym.sym == SDLK_ESCAPE) {
slouken@11702
   414
                        done = 1;
slouken@11702
   415
                    } else if (event.key.keysym.sym == SDLK_LEFT) {
slouken@11702
   416
                        --current;
slouken@11702
   417
                    } else if (event.key.keysym.sym == SDLK_RIGHT) {
slouken@11702
   418
                        ++current;
slouken@11702
   419
                    }
slouken@11702
   420
                }
slouken@11702
   421
                if (event.type == SDL_MOUSEBUTTONDOWN) {
slouken@11702
   422
                    if (event.button.x < (original->w/2)) {
slouken@11702
   423
                        --current;
slouken@11702
   424
                    } else {
slouken@11702
   425
                        ++current;
slouken@11702
   426
                    }
slouken@11702
   427
                }
slouken@11702
   428
            }
slouken@11702
   429
slouken@11702
   430
            /* Handle wrapping */
slouken@11702
   431
            if (current < 0) {
slouken@11702
   432
                current += SDL_arraysize(output);
slouken@11702
   433
            }
slouken@11702
   434
            if (current >= SDL_arraysize(output)) {
slouken@11702
   435
                current -= SDL_arraysize(output);
slouken@11702
   436
            }
slouken@11702
   437
slouken@11702
   438
            SDL_RenderClear(renderer);
slouken@11702
   439
            SDL_RenderCopy(renderer, output[current], NULL, NULL);
slouken@11702
   440
            SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
slouken@11702
   441
            if (current == 0) {
slouken@11702
   442
                SDLTest_DrawString(renderer, 4, 4, titles[current]);
slouken@11702
   443
            } else {
slouken@11702
   444
                SDL_snprintf(title, sizeof(title), "%s %s %s", titles[current], yuv_name, yuv_mode);
slouken@11702
   445
                SDLTest_DrawString(renderer, 4, 4, title);
slouken@11702
   446
            }
slouken@11702
   447
            SDL_RenderPresent(renderer);
slouken@11702
   448
            SDL_Delay(10);
slouken@11702
   449
        }
slouken@11702
   450
    }
slouken@11702
   451
    SDL_Quit();
slouken@11702
   452
    return 0;
slouken@11702
   453
}
slouken@11702
   454
slouken@11702
   455
/* vi: set ts=4 sw=4 expandtab: */