mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-29 01:08:44 +00:00
Added SDL_PIXELFORMAT_P408 and SDL_PIXELFORMAT_P416
This commit is contained in:
parent
0bb539314d
commit
07ecc125cf
20 changed files with 1091 additions and 226 deletions
|
|
@ -51,7 +51,8 @@ static const SDL_PixelFormat g_AllFormats[] = {
|
|||
SDL_PIXELFORMAT_UYVY,
|
||||
SDL_PIXELFORMAT_YVYU,
|
||||
SDL_PIXELFORMAT_NV12,
|
||||
SDL_PIXELFORMAT_NV21
|
||||
SDL_PIXELFORMAT_NV21,
|
||||
SDL_PIXELFORMAT_P408
|
||||
};
|
||||
static const int g_numAllFormats = SDL_arraysize(g_AllFormats);
|
||||
|
||||
|
|
@ -98,7 +99,8 @@ static const char *g_AllFormatsVerbose[] = {
|
|||
"SDL_PIXELFORMAT_UYVY",
|
||||
"SDL_PIXELFORMAT_YVYU",
|
||||
"SDL_PIXELFORMAT_NV12",
|
||||
"SDL_PIXELFORMAT_NV21"
|
||||
"SDL_PIXELFORMAT_NV21",
|
||||
"SDL_PIXELFORMAT_P408"
|
||||
};
|
||||
|
||||
static const SDL_PixelFormat g_AllLargeFormats[] = {
|
||||
|
|
@ -630,6 +632,22 @@ SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P010_ARRAY, !SDL_ISPIXELFORMAT_ARRAY(SDL
|
|||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P010_10BIT, !SDL_ISPIXELFORMAT_10BIT(SDL_PIXELFORMAT_P010));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P010_FLOAT, !SDL_ISPIXELFORMAT_FLOAT(SDL_PIXELFORMAT_P010));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P010_ALPHA, !SDL_ISPIXELFORMAT_ALPHA(SDL_PIXELFORMAT_P010));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_FORMAT, SDL_PIXELFORMAT_P408 == SDL_DEFINE_PIXELFOURCC('P', '4', '0', '8'));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_FOURCC, SDL_ISPIXELFORMAT_FOURCC(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_INDEXED, !SDL_ISPIXELFORMAT_INDEXED(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_PACKED, !SDL_ISPIXELFORMAT_PACKED(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_ARRAY, !SDL_ISPIXELFORMAT_ARRAY(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_10BIT, !SDL_ISPIXELFORMAT_10BIT(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_FLOAT, !SDL_ISPIXELFORMAT_FLOAT(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P408_ALPHA, !SDL_ISPIXELFORMAT_ALPHA(SDL_PIXELFORMAT_P408));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_FORMAT, SDL_PIXELFORMAT_P416 == SDL_DEFINE_PIXELFOURCC('P', '4', '1', '6'));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_FOURCC, SDL_ISPIXELFORMAT_FOURCC(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_INDEXED, !SDL_ISPIXELFORMAT_INDEXED(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_PACKED, !SDL_ISPIXELFORMAT_PACKED(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_ARRAY, !SDL_ISPIXELFORMAT_ARRAY(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_10BIT, !SDL_ISPIXELFORMAT_10BIT(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_FLOAT, !SDL_ISPIXELFORMAT_FLOAT(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_P416_ALPHA, !SDL_ISPIXELFORMAT_ALPHA(SDL_PIXELFORMAT_P416));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_EXTERNAL_OES_FORMAT, SDL_PIXELFORMAT_EXTERNAL_OES == SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' '));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_EXTERNAL_OES_FOURCC, SDL_ISPIXELFORMAT_FOURCC(SDL_PIXELFORMAT_EXTERNAL_OES));
|
||||
SDL_COMPILE_TIME_ASSERT(SDL_PIXELFORMAT_EXTERNAL_OES_INDEXED, !SDL_ISPIXELFORMAT_INDEXED(SDL_PIXELFORMAT_EXTERNAL_OES));
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
#include "testyuv_cvt.h"
|
||||
#include "testutils.h"
|
||||
|
||||
/* 422 (YUY2, etc) and P010 formats are the largest */
|
||||
#define MAX_YUV_SURFACE_SIZE(W, H, P) ((H + 1) * ((W + 1) + P) * 4)
|
||||
/* 422 (YUY2, etc) and P416 formats are the largest */
|
||||
#define MAX_YUV_SURFACE_SIZE(W, H, P) ((H + 1) * ((W + 1) + P) * 3 * 2)
|
||||
|
||||
/* Return true if the YUV format is packed pixels */
|
||||
static bool is_packed_yuv_format(Uint32 format)
|
||||
|
|
@ -109,6 +109,7 @@ static bool run_automated_tests(int pattern_size, int extra_pitch)
|
|||
const Uint32 formats[] = {
|
||||
SDL_PIXELFORMAT_YV12,
|
||||
SDL_PIXELFORMAT_IYUV,
|
||||
SDL_PIXELFORMAT_P408,
|
||||
SDL_PIXELFORMAT_NV12,
|
||||
SDL_PIXELFORMAT_NV21,
|
||||
SDL_PIXELFORMAT_YUY2,
|
||||
|
|
@ -164,6 +165,11 @@ static bool run_automated_tests(int pattern_size, int extra_pitch)
|
|||
/* Verify conversion between YUV formats */
|
||||
for (i = 0; i < SDL_arraysize(formats); ++i) {
|
||||
for (j = 0; j < SDL_arraysize(formats); ++j) {
|
||||
if (formats[i] != formats[j] && (formats[i] == SDL_PIXELFORMAT_P408 || formats[j] == SDL_PIXELFORMAT_P408)) {
|
||||
// Converting between 444 and 420 formats is lossy and not currently supported
|
||||
continue;
|
||||
}
|
||||
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||
if (!SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch)) {
|
||||
|
|
@ -189,6 +195,11 @@ static bool run_automated_tests(int pattern_size, int extra_pitch)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (formats[i] != formats[j] && (formats[i] == SDL_PIXELFORMAT_P408 || formats[j] == SDL_PIXELFORMAT_P408)) {
|
||||
// Converting between 444 and 420 formats is lossy and not currently supported
|
||||
continue;
|
||||
}
|
||||
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||
if (!SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch)) {
|
||||
|
|
@ -370,16 +381,16 @@ static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_P
|
|||
int pitch;
|
||||
SDL_Surface *converted = NULL;
|
||||
bool result = false;
|
||||
size_t max_size;
|
||||
|
||||
YUV_CONVERSION_MODE yuv_mode = GetYUVConversionModeForResolution(original->w, original->h);
|
||||
if (yuv_mode == YUV_CONVERSION_BT2020) {
|
||||
yuv_format = SDL_PIXELFORMAT_P010;
|
||||
rgb_format = SDL_PIXELFORMAT_XBGR2101010;
|
||||
rgb_colorspace = SDL_COLORSPACE_HDR10;
|
||||
}
|
||||
yuv_colorspace = GetColorspaceForYUVConversionMode(yuv_mode);
|
||||
|
||||
raw_yuv = SDL_calloc(1, MAX_YUV_SURFACE_SIZE(original->w, original->h, 0));
|
||||
max_size = MAX_YUV_SURFACE_SIZE(original->w, original->h, 0);
|
||||
raw_yuv = SDL_calloc(1, max_size);
|
||||
ConvertRGBtoYUV(yuv_format, original->pixels, original->pitch, raw_yuv, original->w, original->h, yuv_mode, monochrome, luminance);
|
||||
pitch = CalculateYUVPitch(yuv_format, original->w);
|
||||
|
||||
|
|
@ -458,6 +469,53 @@ static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_P
|
|||
SDL_free(plane0);
|
||||
SDL_free(plane1);
|
||||
SDL_free(plane2);
|
||||
} else if (planar && (yuv_format == SDL_PIXELFORMAT_P408 || yuv_format == SDL_PIXELFORMAT_P416)) {
|
||||
const int rows = original->h;
|
||||
const Uint8 *src_plane0 = (const Uint8 *)raw_yuv;
|
||||
const Uint8 *src_plane1 = src_plane0 + rows * pitch;
|
||||
const Uint8 *src_plane2 = src_plane1 + rows * pitch;
|
||||
const int Ypitch = pitch + 37;
|
||||
const int UVpitch = Ypitch;
|
||||
Uint8 *plane0 = (Uint8 *)SDL_calloc(1, rows * Ypitch);
|
||||
Uint8 *plane1 = (Uint8 *)SDL_calloc(1, rows * UVpitch);
|
||||
Uint8 *plane2 = (Uint8 *)SDL_calloc(1, rows * UVpitch);
|
||||
int row;
|
||||
const Uint8 *src;
|
||||
Uint8 *dst;
|
||||
|
||||
if (!plane0 || !plane1 || !plane0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create YUV planes: %s", SDL_GetError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
src = src_plane0;
|
||||
dst = plane0;
|
||||
for (row = 0; row < rows; ++row) {
|
||||
SDL_memcpy(dst, src, pitch);
|
||||
src += pitch;
|
||||
dst += Ypitch;
|
||||
}
|
||||
|
||||
src = src_plane1;
|
||||
dst = plane1;
|
||||
for (row = 0; row < rows; ++row) {
|
||||
SDL_memcpy(dst, src, pitch);
|
||||
src += pitch;
|
||||
dst += UVpitch;
|
||||
}
|
||||
|
||||
src = src_plane2;
|
||||
dst = plane2;
|
||||
for (row = 0; row < rows; ++row) {
|
||||
SDL_memcpy(dst, src, pitch);
|
||||
src += pitch;
|
||||
dst += UVpitch;
|
||||
}
|
||||
|
||||
SDL_UpdateYUVTexture(output[2], NULL, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
|
||||
SDL_free(plane0);
|
||||
SDL_free(plane1);
|
||||
SDL_free(plane2);
|
||||
} else if (planar && (yuv_format == SDL_PIXELFORMAT_NV12 || yuv_format == SDL_PIXELFORMAT_NV21 || yuv_format == SDL_PIXELFORMAT_P010)) {
|
||||
const int Yrows = original->h;
|
||||
const int UVrows = ((original->h + 1) / 2);
|
||||
|
|
@ -586,6 +644,7 @@ static bool run_all_format_test(SDL_Window *window, const char *requested_render
|
|||
const SDL_PixelFormat yuv_formats[] = {
|
||||
SDL_PIXELFORMAT_YV12,
|
||||
SDL_PIXELFORMAT_IYUV,
|
||||
SDL_PIXELFORMAT_P408,
|
||||
SDL_PIXELFORMAT_YUY2,
|
||||
SDL_PIXELFORMAT_UYVY,
|
||||
SDL_PIXELFORMAT_YVYU,
|
||||
|
|
@ -676,6 +735,7 @@ static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_S
|
|||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
renderer_name = SDL_GetRendererName(renderer);
|
||||
|
||||
SDL_Texture *output[3];
|
||||
if (!create_textures(renderer, original, yuv_format, rgb_format, planar, monochrome, luminance, output)) {
|
||||
|
|
@ -695,7 +755,6 @@ static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_S
|
|||
break;
|
||||
case YUV_CONVERSION_BT2020:
|
||||
yuv_mode_name = "BT.2020";
|
||||
yuv_format = SDL_PIXELFORMAT_P010;
|
||||
break;
|
||||
default:
|
||||
yuv_mode_name = "UNKNOWN";
|
||||
|
|
@ -745,7 +804,7 @@ static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_S
|
|||
if (current == 0) {
|
||||
SDLTest_DrawString(renderer, 4, 4, titles[current]);
|
||||
} else {
|
||||
if (SDL_snprintf(title, sizeof(title), "%s %s %s", titles[current], yuv_format_name, yuv_mode_name) > 0) {
|
||||
if (SDL_snprintf(title, sizeof(title), "%s %s %s %s", titles[current], yuv_format_name, yuv_mode_name, renderer_name) > 0) {
|
||||
SDLTest_DrawString(renderer, 4, 4, title);
|
||||
}
|
||||
}
|
||||
|
|
@ -838,9 +897,6 @@ int main(int argc, char **argv)
|
|||
} else if (SDL_strcmp(argv[i], "--bt709") == 0) {
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT709);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--bt2020") == 0) {
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT2020);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--auto") == 0) {
|
||||
SetYUVConversionMode(YUV_CONVERSION_AUTOMATIC);
|
||||
consumed = 1;
|
||||
|
|
@ -850,6 +906,9 @@ int main(int argc, char **argv)
|
|||
} else if (SDL_strcmp(argv[i], "--iyuv") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_IYUV;
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--p408") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_P408;
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--yuy2") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_YUY2;
|
||||
consumed = 1;
|
||||
|
|
@ -865,6 +924,16 @@ int main(int argc, char **argv)
|
|||
} else if (SDL_strcmp(argv[i], "--nv21") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_NV21;
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--p010") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_P010;
|
||||
rgb_format = SDL_PIXELFORMAT_XBGR2101010;
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT2020);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--p416") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_P416;
|
||||
rgb_format = SDL_PIXELFORMAT_XBGR2101010;
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT2020);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--rgb555") == 0) {
|
||||
rgb_format = SDL_PIXELFORMAT_XRGB1555;
|
||||
consumed = 1;
|
||||
|
|
@ -911,8 +980,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
if (consumed <= 0) {
|
||||
static const char *options[] = {
|
||||
"[--jpeg|--bt601|--bt709|--bt2020|--auto]",
|
||||
"[--yv12|--iyuv|--yuy2|--uyvy|--yvyu|--nv12|--nv21]",
|
||||
"[--jpeg|--bt601|--bt709|--auto]",
|
||||
"[--yv12|--iyuv|--p408|--yuy2|--uyvy|--yvyu|--nv12|--nv21|--p010|--p416]",
|
||||
"[--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra]",
|
||||
"[--monochrome] [--luminance N%] [--planar]",
|
||||
"[--automated] [--colorspace-test] [--renderer NAME]",
|
||||
|
|
|
|||
|
|
@ -222,6 +222,53 @@ static void RGBtoYUV(const Uint8 *rgb, int rgb_bits, int *yuv, int yuv_bits, YUV
|
|||
}
|
||||
}
|
||||
|
||||
static void ConvertRGBtoPlanar1x1(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
{
|
||||
int x, y;
|
||||
int yuv[3];
|
||||
Uint8 *Y, *U, *V;
|
||||
const Uint8 *rgb;
|
||||
int rgb_row_advance = (pitch - w * 3);
|
||||
int yuv_bits;
|
||||
int yuv_bytes_per_pixel = SDL_BYTESPERPIXEL(format);
|
||||
|
||||
rgb = src;
|
||||
Y = out;
|
||||
U = (Y + h * w * yuv_bytes_per_pixel);
|
||||
V = (U + h * w * yuv_bytes_per_pixel);
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
yuv_bits = 8;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
yuv_bits = 16;
|
||||
break;
|
||||
default:
|
||||
SDL_assert(!"Unsupported planar YUV format");
|
||||
return;
|
||||
}
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
for (x = 0; x < w; ++x) {
|
||||
RGBtoYUV(rgb, 8, yuv, yuv_bits, mode, monochrome, luminance);
|
||||
rgb += 3;
|
||||
if (format == SDL_PIXELFORMAT_P408) {
|
||||
*Y = (Uint8)yuv[0];
|
||||
*U = (Uint8)yuv[1];
|
||||
*V = (Uint8)yuv[2];
|
||||
} else {
|
||||
*(Uint16 *)Y = (Uint16)yuv[0];
|
||||
*(Uint16 *)U = (Uint16)yuv[1];
|
||||
*(Uint16 *)V = (Uint16)yuv[2];
|
||||
}
|
||||
Y += yuv_bytes_per_pixel;
|
||||
U += yuv_bytes_per_pixel;
|
||||
V += yuv_bytes_per_pixel;
|
||||
}
|
||||
rgb += rgb_row_advance;
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertRGBtoPlanar2x2(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
{
|
||||
int x, y;
|
||||
|
|
@ -517,6 +564,10 @@ static void ConvertRGBtoPacked4(Uint32 format, Uint8 *src, int pitch, Uint8 *out
|
|||
bool ConvertRGBtoYUV(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
{
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
ConvertRGBtoPlanar1x1(format, src, pitch, out, w, h, mode, monochrome, luminance);
|
||||
return true;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
ConvertRGBtoPlanar2x2_P010(format, src, pitch, out, w, h, mode, monochrome, luminance);
|
||||
return true;
|
||||
|
|
@ -540,9 +591,11 @@ int CalculateYUVPitch(Uint32 format, int width)
|
|||
{
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
return width * 2;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
return width;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue