From 30f41c02aec763d32e62351452da9ef582bc3472 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 6 Mar 2026 13:30:59 -0800 Subject: Move contrib libraries to contrib repo --- contrib/SDL-3.2.8/src/video/SDL_yuv.c | 2592 --------------------------------- 1 file changed, 2592 deletions(-) delete mode 100644 contrib/SDL-3.2.8/src/video/SDL_yuv.c (limited to 'contrib/SDL-3.2.8/src/video/SDL_yuv.c') diff --git a/contrib/SDL-3.2.8/src/video/SDL_yuv.c b/contrib/SDL-3.2.8/src/video/SDL_yuv.c deleted file mode 100644 index ccacfcf..0000000 --- a/contrib/SDL-3.2.8/src/video/SDL_yuv.c +++ /dev/null @@ -1,2592 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#include "SDL_pixels_c.h" -#include "SDL_yuv_c.h" - -#include "yuv2rgb/yuv_rgb.h" - - -#ifdef SDL_HAVE_YUV -static bool IsPlanar2x2Format(SDL_PixelFormat format); -#endif - -/* - * Calculate YUV size and pitch. Check for overflow. - * Output 'pitch' that can be used with SDL_ConvertPixels() - */ -bool SDL_CalculateYUVSize(SDL_PixelFormat format, int w, int h, size_t *size, size_t *pitch) -{ -#ifdef SDL_HAVE_YUV - int sz_plane = 0, sz_plane_chroma = 0, sz_plane_packed = 0; - - if (IsPlanar2x2Format(format) == true) { - { - /* sz_plane == w * h; */ - size_t s1; - if (!SDL_size_mul_check_overflow(w, h, &s1)) { - return SDL_SetError("width * height would overflow"); - } - sz_plane = (int) s1; - } - - { - /* sz_plane_chroma == ((w + 1) / 2) * ((h + 1) / 2); */ - size_t s1, s2, s3; - if (!SDL_size_add_check_overflow(w, 1, &s1)) { - return SDL_SetError("width + 1 would overflow"); - } - s1 = s1 / 2; - if (!SDL_size_add_check_overflow(h, 1, &s2)) { - return SDL_SetError("height + 1 would overflow"); - } - s2 = s2 / 2; - if (!SDL_size_mul_check_overflow(s1, s2, &s3)) { - return SDL_SetError("width * height would overflow"); - } - sz_plane_chroma = (int) s3; - } - } else { - /* sz_plane_packed == ((w + 1) / 2) * h; */ - size_t s1, s2; - if (!SDL_size_add_check_overflow(w, 1, &s1)) { - return SDL_SetError("width + 1 would overflow"); - } - s1 = s1 / 2; - if (!SDL_size_mul_check_overflow(s1, h, &s2)) { - return SDL_SetError("width * height would overflow"); - } - sz_plane_packed = (int) s2; - } - - switch (format) { - case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */ - case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */ - - if (pitch) { - *pitch = w; - } - - if (size) { - // dst_size == sz_plane + sz_plane_chroma + sz_plane_chroma; - size_t s1, s2; - if (!SDL_size_add_check_overflow(sz_plane, sz_plane_chroma, &s1)) { - return SDL_SetError("Y + U would overflow"); - } - if (!SDL_size_add_check_overflow(s1, sz_plane_chroma, &s2)) { - return SDL_SetError("Y + U + V would overflow"); - } - *size = (int)s2; - } - break; - - case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ - case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ - case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ - - if (pitch) { - /* pitch == ((w + 1) / 2) * 4; */ - size_t p1, p2; - if (!SDL_size_add_check_overflow(w, 1, &p1)) { - return SDL_SetError("width + 1 would overflow"); - } - p1 = p1 / 2; - if (!SDL_size_mul_check_overflow(p1, 4, &p2)) { - return SDL_SetError("width * 4 would overflow"); - } - *pitch = p2; - } - - if (size) { - /* dst_size == 4 * sz_plane_packed; */ - size_t s1; - if (!SDL_size_mul_check_overflow(sz_plane_packed, 4, &s1)) { - return SDL_SetError("plane * 4 would overflow"); - } - *size = (int) s1; - } - break; - - case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */ - case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */ - if (pitch) { - *pitch = w; - } - - if (size) { - // dst_size == sz_plane + sz_plane_chroma + sz_plane_chroma; - size_t s1, s2; - if (!SDL_size_add_check_overflow(sz_plane, sz_plane_chroma, &s1)) { - return SDL_SetError("Y + U would overflow"); - } - if (!SDL_size_add_check_overflow(s1, sz_plane_chroma, &s2)) { - return SDL_SetError("Y + U + V would overflow"); - } - *size = (int) s2; - } - break; - - default: - return SDL_Unsupported(); - } - - return true; -#else - return SDL_Unsupported(); -#endif -} - -#ifdef SDL_HAVE_YUV - -static bool GetYUVConversionType(SDL_Colorspace colorspace, YCbCrType *yuv_type) -{ - if (SDL_ISCOLORSPACE_MATRIX_BT601(colorspace)) { - if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) { - *yuv_type = YCBCR_601_LIMITED; - } else { - *yuv_type = YCBCR_601_FULL; - } - return true; - } - - if (SDL_ISCOLORSPACE_MATRIX_BT709(colorspace)) { - if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) { - *yuv_type = YCBCR_709_LIMITED; - } else { - *yuv_type = YCBCR_709_FULL; - } - return true; - } - - if (SDL_ISCOLORSPACE_MATRIX_BT2020_NCL(colorspace)) { - if (SDL_ISCOLORSPACE_FULL_RANGE(colorspace)) { - *yuv_type = YCBCR_2020_NCL_FULL; - return true; - } - } - - return SDL_SetError("Unsupported YUV colorspace"); -} - -static bool IsPlanar2x2Format(SDL_PixelFormat format) -{ - return format == SDL_PIXELFORMAT_YV12 || format == SDL_PIXELFORMAT_IYUV || format == SDL_PIXELFORMAT_NV12 || format == SDL_PIXELFORMAT_NV21 || format == SDL_PIXELFORMAT_P010; -} - -static bool IsPacked4Format(Uint32 format) -{ - return format == SDL_PIXELFORMAT_YUY2 || format == SDL_PIXELFORMAT_UYVY || format == SDL_PIXELFORMAT_YVYU; -} - -static bool GetYUVPlanes(int width, int height, SDL_PixelFormat format, const void *yuv, int yuv_pitch, - const Uint8 **y, const Uint8 **u, const Uint8 **v, Uint32 *y_stride, Uint32 *uv_stride) -{ - const Uint8 *planes[3] = { NULL, NULL, NULL }; - int pitches[3] = { 0, 0, 0 }; - int uv_width; - - switch (format) { - case SDL_PIXELFORMAT_YV12: - case SDL_PIXELFORMAT_IYUV: - pitches[0] = yuv_pitch; - pitches[1] = (pitches[0] + 1) / 2; - pitches[2] = (pitches[0] + 1) / 2; - planes[0] = (const Uint8 *)yuv; - planes[1] = planes[0] + pitches[0] * height; - planes[2] = planes[1] + pitches[1] * ((height + 1) / 2); - break; - case SDL_PIXELFORMAT_YUY2: - case SDL_PIXELFORMAT_UYVY: - case SDL_PIXELFORMAT_YVYU: - pitches[0] = yuv_pitch; - planes[0] = (const Uint8 *)yuv; - break; - case SDL_PIXELFORMAT_NV12: - case SDL_PIXELFORMAT_NV21: - pitches[0] = yuv_pitch; - pitches[1] = 2 * ((pitches[0] + 1) / 2); - planes[0] = (const Uint8 *)yuv; - planes[1] = planes[0] + pitches[0] * height; - break; - case SDL_PIXELFORMAT_P010: - pitches[0] = yuv_pitch; - uv_width = ((width + 1) / 2) * 2; - pitches[1] = SDL_max(pitches[0], (int)(uv_width * sizeof(Uint16))); - planes[0] = (const Uint8 *)yuv; - planes[1] = planes[0] + pitches[0] * height; - break; - default: - return SDL_SetError("GetYUVPlanes(): Unsupported YUV format: %s", SDL_GetPixelFormatName(format)); - } - - switch (format) { - case SDL_PIXELFORMAT_YV12: - *y = planes[0]; - *y_stride = pitches[0]; - *v = planes[1]; - *u = planes[2]; - *uv_stride = pitches[1]; - break; - case SDL_PIXELFORMAT_IYUV: - *y = planes[0]; - *y_stride = pitches[0]; - *v = planes[2]; - *u = planes[1]; - *uv_stride = pitches[1]; - break; - case SDL_PIXELFORMAT_YUY2: - *y = planes[0]; - *y_stride = pitches[0]; - *v = *y + 3; - *u = *y + 1; - *uv_stride = pitches[0]; - break; - case SDL_PIXELFORMAT_UYVY: - *y = planes[0] + 1; - *y_stride = pitches[0]; - *v = *y + 1; - *u = *y - 1; - *uv_stride = pitches[0]; - break; - case SDL_PIXELFORMAT_YVYU: - *y = planes[0]; - *y_stride = pitches[0]; - *v = *y + 1; - *u = *y + 3; - *uv_stride = pitches[0]; - break; - case SDL_PIXELFORMAT_NV12: - *y = planes[0]; - *y_stride = pitches[0]; - *u = planes[1]; - *v = *u + 1; - *uv_stride = pitches[1]; - break; - case SDL_PIXELFORMAT_NV21: - *y = planes[0]; - *y_stride = pitches[0]; - *v = planes[1]; - *u = *v + 1; - *uv_stride = pitches[1]; - break; - case SDL_PIXELFORMAT_P010: - *y = planes[0]; - *y_stride = pitches[0]; - *u = planes[1]; - *v = *u + sizeof(Uint16); - *uv_stride = pitches[1]; - break; - default: - // Should have caught this above - return SDL_SetError("GetYUVPlanes[2]: Unsupported YUV format: %s", SDL_GetPixelFormatName(format)); - } - return true; -} - -#ifdef SDL_SSE2_INTRINSICS -static bool SDL_TARGETING("sse2") yuv_rgb_sse( - SDL_PixelFormat src_format, SDL_PixelFormat dst_format, - Uint32 width, Uint32 height, - const Uint8 *y, const Uint8 *u, const Uint8 *v, Uint32 y_stride, Uint32 uv_stride, - Uint8 *rgb, Uint32 rgb_stride, - YCbCrType yuv_type) -{ - if (!SDL_HasSSE2()) { - return false; - } - - if (src_format == SDL_PIXELFORMAT_YV12 || - src_format == SDL_PIXELFORMAT_IYUV) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuv420_rgb565_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuv420_rgb24_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuv420_rgba_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuv420_bgra_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuv420_argb_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuv420_abgr_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - - if (src_format == SDL_PIXELFORMAT_YUY2 || - src_format == SDL_PIXELFORMAT_UYVY || - src_format == SDL_PIXELFORMAT_YVYU) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuv422_rgb565_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuv422_rgb24_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuv422_rgba_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuv422_bgra_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuv422_argb_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuv422_abgr_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - - if (src_format == SDL_PIXELFORMAT_NV12 || - src_format == SDL_PIXELFORMAT_NV21) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuvnv12_rgb565_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuvnv12_rgb24_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuvnv12_rgba_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuvnv12_bgra_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuvnv12_argb_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuvnv12_abgr_sseu(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - return false; -} -#else -static bool yuv_rgb_sse( - SDL_PixelFormat src_format, SDL_PixelFormat dst_format, - Uint32 width, Uint32 height, - const Uint8 *y, const Uint8 *u, const Uint8 *v, Uint32 y_stride, Uint32 uv_stride, - Uint8 *rgb, Uint32 rgb_stride, - YCbCrType yuv_type) -{ - return false; -} -#endif - -#ifdef SDL_LSX_INTRINSICS -static bool yuv_rgb_lsx( - SDL_PixelFormat src_format, SDL_PixelFormat dst_format, - Uint32 width, Uint32 height, - const Uint8 *y, const Uint8 *u, const Uint8 *v, Uint32 y_stride, Uint32 uv_stride, - Uint8 *rgb, Uint32 rgb_stride, - YCbCrType yuv_type) -{ - if (!SDL_HasLSX()) { - return false; - } - if (src_format == SDL_PIXELFORMAT_YV12 || - src_format == SDL_PIXELFORMAT_IYUV) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB24: - yuv420_rgb24_lsx(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuv420_rgba_lsx(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuv420_bgra_lsx(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuv420_argb_lsx(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuv420_abgr_lsx(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - return false; -} -#else -static bool yuv_rgb_lsx( - SDL_PixelFormat src_format, SDL_PixelFormat dst_format, - Uint32 width, Uint32 height, - const Uint8 *y, const Uint8 *u, const Uint8 *v, Uint32 y_stride, Uint32 uv_stride, - Uint8 *rgb, Uint32 rgb_stride, - YCbCrType yuv_type) -{ - return false; -} -#endif - -static bool yuv_rgb_std( - SDL_PixelFormat src_format, SDL_PixelFormat dst_format, - Uint32 width, Uint32 height, - const Uint8 *y, const Uint8 *u, const Uint8 *v, Uint32 y_stride, Uint32 uv_stride, - Uint8 *rgb, Uint32 rgb_stride, - YCbCrType yuv_type) -{ - if (src_format == SDL_PIXELFORMAT_YV12 || - src_format == SDL_PIXELFORMAT_IYUV) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuv420_rgb565_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuv420_rgb24_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuv420_rgba_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuv420_bgra_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuv420_argb_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuv420_abgr_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - - if (src_format == SDL_PIXELFORMAT_YUY2 || - src_format == SDL_PIXELFORMAT_UYVY || - src_format == SDL_PIXELFORMAT_YVYU) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuv422_rgb565_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuv422_rgb24_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuv422_rgba_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuv422_bgra_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuv422_argb_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuv422_abgr_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - - if (src_format == SDL_PIXELFORMAT_NV12 || - src_format == SDL_PIXELFORMAT_NV21) { - - switch (dst_format) { - case SDL_PIXELFORMAT_RGB565: - yuvnv12_rgb565_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGB24: - yuvnv12_rgb24_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_RGBA8888: - yuvnv12_rgba_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_BGRX8888: - case SDL_PIXELFORMAT_BGRA8888: - yuvnv12_bgra_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_ARGB8888: - yuvnv12_argb_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - case SDL_PIXELFORMAT_XBGR8888: - case SDL_PIXELFORMAT_ABGR8888: - yuvnv12_abgr_std(width, height, y, u, v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - - if (src_format == SDL_PIXELFORMAT_P010) { - switch (dst_format) { - case SDL_PIXELFORMAT_XBGR2101010: - yuvp010_xbgr2101010_std(width, height, (const uint16_t *)y, (const uint16_t *)u, (const uint16_t *)v, y_stride, uv_stride, rgb, rgb_stride, yuv_type); - return true; - default: - break; - } - } - return false; -} - -bool SDL_ConvertPixels_YUV_to_RGB(int width, int height, - SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, - SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch) -{ - const Uint8 *y = NULL; - const Uint8 *u = NULL; - const Uint8 *v = NULL; - Uint32 y_stride = 0; - Uint32 uv_stride = 0; - - if (!GetYUVPlanes(width, height, src_format, src, src_pitch, &y, &u, &v, &y_stride, &uv_stride)) { - return false; - } - - if (SDL_COLORSPACEPRIMARIES(src_colorspace) == SDL_COLORSPACEPRIMARIES(dst_colorspace)) { - YCbCrType yuv_type = YCBCR_601_LIMITED; - - if (!GetYUVConversionType(src_colorspace, &yuv_type)) { - return false; - } - - if (yuv_rgb_sse(src_format, dst_format, width, height, y, u, v, y_stride, uv_stride, (Uint8 *)dst, dst_pitch, yuv_type)) { - return true; - } - - if (yuv_rgb_lsx(src_format, dst_format, width, height, y, u, v, y_stride, uv_stride, (Uint8 *)dst, dst_pitch, yuv_type)) { - return true; - } - - if (yuv_rgb_std(src_format, dst_format, width, height, y, u, v, y_stride, uv_stride, (Uint8 *)dst, dst_pitch, yuv_type)) { - return true; - } - } - - // No fast path for the RGB format, instead convert using an intermediate buffer - if (src_format == SDL_PIXELFORMAT_P010 && dst_format != SDL_PIXELFORMAT_XBGR2101010) { - bool result; - void *tmp; - int tmp_pitch = (width * sizeof(Uint32)); - - tmp = SDL_malloc((size_t)tmp_pitch * height); - if (!tmp) { - return false; - } - - // convert src/src_format to tmp/XBGR2101010 - result = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_XBGR2101010, src_colorspace, src_properties, tmp, tmp_pitch); - if (!result) { - SDL_free(tmp); - return false; - } - - // convert tmp/XBGR2101010 to dst/RGB - result = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_XBGR2101010, src_colorspace, src_properties, tmp, tmp_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch); - SDL_free(tmp); - return result; - } - - if (dst_format != SDL_PIXELFORMAT_ARGB8888) { - bool result; - void *tmp; - int tmp_pitch = (width * sizeof(Uint32)); - - tmp = SDL_malloc((size_t)tmp_pitch * height); - if (!tmp) { - return false; - } - - // convert src/src_format to tmp/ARGB8888 - result = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch); - if (!result) { - SDL_free(tmp); - return false; - } - - // convert tmp/ARGB8888 to dst/RGB - result = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch); - SDL_free(tmp); - return result; - } - - return SDL_SetError("Unsupported YUV conversion"); -} - -struct RGB2YUVFactors -{ - int y_offset; - float y[3]; // Rfactor, Gfactor, Bfactor - float u[3]; // Rfactor, Gfactor, Bfactor - float v[3]; // Rfactor, Gfactor, Bfactor -}; - -static struct RGB2YUVFactors RGB2YUVFactorTables[] = { - // ITU-T T.871 (JPEG) - { - 0, - { 0.2990f, 0.5870f, 0.1140f }, - { -0.1687f, -0.3313f, 0.5000f }, - { 0.5000f, -0.4187f, -0.0813f }, - }, - // ITU-R BT.601-7 - { - 16, - { 0.2568f, 0.5041f, 0.0979f }, - { -0.1482f, -0.2910f, 0.4392f }, - { 0.4392f, -0.3678f, -0.0714f }, - }, - // ITU-R BT.709-6 full range - { - 0, - { 0.2126f, 0.7152f, 0.0722f }, - { -0.1141f, -0.3839f, 0.498f }, - { 0.498f, -0.4524f, -0.0457f }, - }, - // ITU-R BT.709-6 - { - 16, - { 0.1826f, 0.6142f, 0.0620f }, - { -0.1006f, -0.3386f, 0.4392f }, - { 0.4392f, -0.3989f, -0.0403f }, - }, - // ITU-R BT.2020 10-bit full range - { - 0, - { 0.2627f, 0.6780f, 0.0593f }, - { -0.1395f, -0.3600f, 0.4995f }, - { 0.4995f, -0.4593f, -0.0402f }, - }, -}; - -static bool SDL_ConvertPixels_XRGB8888_to_YUV(int width, int height, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, YCbCrType yuv_type) -{ - const int src_pitch_x_2 = src_pitch * 2; - const int height_half = height / 2; - const int height_remainder = (height & 0x1); - const int width_half = width / 2; - const int width_remainder = (width & 0x1); - int i, j; - - const struct RGB2YUVFactors *cvt = &RGB2YUVFactorTables[yuv_type]; - -#define MAKE_Y(r, g, b) (Uint8)SDL_clamp(((int)(cvt->y[0] * (r) + cvt->y[1] * (g) + cvt->y[2] * (b) + 0.5f) + cvt->y_offset), 0, 255) -#define MAKE_U(r, g, b) (Uint8)SDL_clamp(((int)(cvt->u[0] * (r) + cvt->u[1] * (g) + cvt->u[2] * (b) + 0.5f) + 128), 0, 255) -#define MAKE_V(r, g, b) (Uint8)SDL_clamp(((int)(cvt->v[0] * (r) + cvt->v[1] * (g) + cvt->v[2] * (b) + 0.5f) + 128), 0, 255) - -#define READ_2x2_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)curr_row)[2 * i + 1]; \ - const Uint32 p3 = ((const Uint32 *)next_row)[2 * i]; \ - const Uint32 p4 = ((const Uint32 *)next_row)[2 * i + 1]; \ - const Uint32 r = ((p1 & 0x00ff0000) + (p2 & 0x00ff0000) + (p3 & 0x00ff0000) + (p4 & 0x00ff0000)) >> 18; \ - const Uint32 g = ((p1 & 0x0000ff00) + (p2 & 0x0000ff00) + (p3 & 0x0000ff00) + (p4 & 0x0000ff00)) >> 10; \ - const Uint32 b = ((p1 & 0x000000ff) + (p2 & 0x000000ff) + (p3 & 0x000000ff) + (p4 & 0x000000ff)) >> 2; - -#define READ_2x1_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)next_row)[2 * i]; \ - const Uint32 r = ((p1 & 0x00ff0000) + (p2 & 0x00ff0000)) >> 17; \ - const Uint32 g = ((p1 & 0x0000ff00) + (p2 & 0x0000ff00)) >> 9; \ - const Uint32 b = ((p1 & 0x000000ff) + (p2 & 0x000000ff)) >> 1; - -#define READ_1x2_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)curr_row)[2 * i + 1]; \ - const Uint32 r = ((p1 & 0x00ff0000) + (p2 & 0x00ff0000)) >> 17; \ - const Uint32 g = ((p1 & 0x0000ff00) + (p2 & 0x0000ff00)) >> 9; \ - const Uint32 b = ((p1 & 0x000000ff) + (p2 & 0x000000ff)) >> 1; - -#define READ_1x1_PIXEL \ - const Uint32 p = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 r = (p & 0x00ff0000) >> 16; \ - const Uint32 g = (p & 0x0000ff00) >> 8; \ - const Uint32 b = (p & 0x000000ff); - -#define READ_TWO_RGB_PIXELS \ - const Uint32 p = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 r = (p & 0x00ff0000) >> 16; \ - const Uint32 g = (p & 0x0000ff00) >> 8; \ - const Uint32 b = (p & 0x000000ff); \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i + 1]; \ - const Uint32 r1 = (p1 & 0x00ff0000) >> 16; \ - const Uint32 g1 = (p1 & 0x0000ff00) >> 8; \ - const Uint32 b1 = (p1 & 0x000000ff); \ - const Uint32 R = (r + r1) / 2; \ - const Uint32 G = (g + g1) / 2; \ - const Uint32 B = (b + b1) / 2; - -#define READ_ONE_RGB_PIXEL READ_1x1_PIXEL - - switch (dst_format) { - case SDL_PIXELFORMAT_YV12: - case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: - case SDL_PIXELFORMAT_NV21: - { - const Uint8 *curr_row, *next_row; - - Uint8 *plane_y; - Uint8 *plane_u; - Uint8 *plane_v; - Uint8 *plane_interleaved_uv; - Uint32 y_stride, uv_stride, y_skip, uv_skip; - - if (!GetYUVPlanes(width, height, dst_format, dst, dst_pitch, - (const Uint8 **)&plane_y, (const Uint8 **)&plane_u, (const Uint8 **)&plane_v, - &y_stride, &uv_stride)) { - return false; - } - - plane_interleaved_uv = (plane_y + height * y_stride); - y_skip = (y_stride - width); - - curr_row = (const Uint8 *)src; - - // Write Y plane - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - const Uint32 p1 = ((const Uint32 *)curr_row)[i]; - const Uint32 r = (p1 & 0x00ff0000) >> 16; - const Uint32 g = (p1 & 0x0000ff00) >> 8; - const Uint32 b = (p1 & 0x000000ff); - *plane_y++ = MAKE_Y(r, g, b); - } - plane_y += y_skip; - curr_row += src_pitch; - } - - curr_row = (const Uint8 *)src; - next_row = (const Uint8 *)src; - next_row += src_pitch; - - if (dst_format == SDL_PIXELFORMAT_YV12 || dst_format == SDL_PIXELFORMAT_IYUV) { - // Write UV planes, not interleaved - uv_skip = (uv_stride - (width + 1) / 2); - for (j = 0; j < height_half; j++) { - for (i = 0; i < width_half; i++) { - READ_2x2_PIXELS; - *plane_u++ = MAKE_U(r, g, b); - *plane_v++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_2x1_PIXELS; - *plane_u++ = MAKE_U(r, g, b); - *plane_v++ = MAKE_V(r, g, b); - } - plane_u += uv_skip; - plane_v += uv_skip; - curr_row += src_pitch_x_2; - next_row += src_pitch_x_2; - } - if (height_remainder) { - for (i = 0; i < width_half; i++) { - READ_1x2_PIXELS; - *plane_u++ = MAKE_U(r, g, b); - *plane_v++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_1x1_PIXEL; - *plane_u++ = MAKE_U(r, g, b); - *plane_v++ = MAKE_V(r, g, b); - } - plane_u += uv_skip; - plane_v += uv_skip; - } - } else if (dst_format == SDL_PIXELFORMAT_NV12) { - uv_skip = (uv_stride - ((width + 1) / 2) * 2); - for (j = 0; j < height_half; j++) { - for (i = 0; i < width_half; i++) { - READ_2x2_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_2x1_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - plane_interleaved_uv += uv_skip; - curr_row += src_pitch_x_2; - next_row += src_pitch_x_2; - } - if (height_remainder) { - for (i = 0; i < width_half; i++) { - READ_1x2_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_1x1_PIXEL; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - } - } else /* dst_format == SDL_PIXELFORMAT_NV21 */ { - uv_skip = (uv_stride - ((width + 1) / 2) * 2); - for (j = 0; j < height_half; j++) { - for (i = 0; i < width_half; i++) { - READ_2x2_PIXELS; - *plane_interleaved_uv++ = MAKE_V(r, g, b); - *plane_interleaved_uv++ = MAKE_U(r, g, b); - } - if (width_remainder) { - READ_2x1_PIXELS; - *plane_interleaved_uv++ = MAKE_V(r, g, b); - *plane_interleaved_uv++ = MAKE_U(r, g, b); - } - plane_interleaved_uv += uv_skip; - curr_row += src_pitch_x_2; - next_row += src_pitch_x_2; - } - if (height_remainder) { - for (i = 0; i < width_half; i++) { - READ_1x2_PIXELS; - *plane_interleaved_uv++ = MAKE_V(r, g, b); - *plane_interleaved_uv++ = MAKE_U(r, g, b); - } - if (width_remainder) { - READ_1x1_PIXEL; - *plane_interleaved_uv++ = MAKE_V(r, g, b); - *plane_interleaved_uv++ = MAKE_U(r, g, b); - } - } - } - } break; - - case SDL_PIXELFORMAT_YUY2: - case SDL_PIXELFORMAT_UYVY: - case SDL_PIXELFORMAT_YVYU: - { - const Uint8 *curr_row = (const Uint8 *)src; - Uint8 *plane = (Uint8 *)dst; - const int row_size = (4 * ((width + 1) / 2)); - int plane_skip; - - if (dst_pitch < row_size) { - return SDL_SetError("Destination pitch is too small, expected at least %d", row_size); - } - plane_skip = (dst_pitch - row_size); - - // Write YUV plane, packed - if (dst_format == SDL_PIXELFORMAT_YUY2) { - for (j = 0; j < height; j++) { - for (i = 0; i < width_half; i++) { - READ_TWO_RGB_PIXELS; - // Y U Y1 V - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_U(R, G, B); - *plane++ = MAKE_Y(r1, g1, b1); - *plane++ = MAKE_V(R, G, B); - } - if (width_remainder) { - READ_ONE_RGB_PIXEL; - // Y U Y V - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_U(r, g, b); - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_V(r, g, b); - } - plane += plane_skip; - curr_row += src_pitch; - } - } else if (dst_format == SDL_PIXELFORMAT_UYVY) { - for (j = 0; j < height; j++) { - for (i = 0; i < width_half; i++) { - READ_TWO_RGB_PIXELS; - // U Y V Y1 - *plane++ = MAKE_U(R, G, B); - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_V(R, G, B); - *plane++ = MAKE_Y(r1, g1, b1); - } - if (width_remainder) { - READ_ONE_RGB_PIXEL; - // U Y V Y - *plane++ = MAKE_U(r, g, b); - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_V(r, g, b); - *plane++ = MAKE_Y(r, g, b); - } - plane += plane_skip; - curr_row += src_pitch; - } - } else if (dst_format == SDL_PIXELFORMAT_YVYU) { - for (j = 0; j < height; j++) { - for (i = 0; i < width_half; i++) { - READ_TWO_RGB_PIXELS; - // Y V Y1 U - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_V(R, G, B); - *plane++ = MAKE_Y(r1, g1, b1); - *plane++ = MAKE_U(R, G, B); - } - if (width_remainder) { - READ_ONE_RGB_PIXEL; - // Y V Y U - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_V(r, g, b); - *plane++ = MAKE_Y(r, g, b); - *plane++ = MAKE_U(r, g, b); - } - plane += plane_skip; - curr_row += src_pitch; - } - } - } break; - - default: - return SDL_SetError("Unsupported YUV destination format: %s", SDL_GetPixelFormatName(dst_format)); - } -#undef MAKE_Y -#undef MAKE_U -#undef MAKE_V -#undef READ_2x2_PIXELS -#undef READ_2x1_PIXELS -#undef READ_1x2_PIXELS -#undef READ_1x1_PIXEL -#undef READ_TWO_RGB_PIXELS -#undef READ_ONE_RGB_PIXEL - return true; -} - -static bool SDL_ConvertPixels_XBGR2101010_to_P010(int width, int height, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, YCbCrType yuv_type) -{ - const int src_pitch_x_2 = src_pitch * 2; - const int height_half = height / 2; - const int height_remainder = (height & 0x1); - const int width_half = width / 2; - const int width_remainder = (width & 0x1); - int i, j; - - const struct RGB2YUVFactors *cvt = &RGB2YUVFactorTables[yuv_type]; - -#define MAKE_Y(r, g, b) (Uint16)(((int)(cvt->y[0] * (r) + cvt->y[1] * (g) + cvt->y[2] * (b) + 0.5f) + cvt->y_offset) << 6) -#define MAKE_U(r, g, b) (Uint16)(((int)(cvt->u[0] * (r) + cvt->u[1] * (g) + cvt->u[2] * (b) + 0.5f) + 512) << 6) -#define MAKE_V(r, g, b) (Uint16)(((int)(cvt->v[0] * (r) + cvt->v[1] * (g) + cvt->v[2] * (b) + 0.5f) + 512) << 6) - -#define READ_2x2_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)curr_row)[2 * i + 1]; \ - const Uint32 p3 = ((const Uint32 *)next_row)[2 * i]; \ - const Uint32 p4 = ((const Uint32 *)next_row)[2 * i + 1]; \ - const Uint32 r = ((p1 & 0x000003ff) + (p2 & 0x000003ff) + (p3 & 0x000003ff) + (p4 & 0x000003ff)) >> 2; \ - const Uint32 g = ((p1 & 0x000ffc00) + (p2 & 0x000ffc00) + (p3 & 0x000ffc00) + (p4 & 0x000ffc00)) >> 12; \ - const Uint32 b = ((p1 & 0x3ff00000) + (p2 & 0x3ff00000) + (p3 & 0x3ff00000) + (p4 & 0x3ff00000)) >> 22; - -#define READ_2x1_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)next_row)[2 * i]; \ - const Uint32 r = ((p1 & 0x000003ff) + (p2 & 0x000003ff)) >> 1; \ - const Uint32 g = ((p1 & 0x000ffc00) + (p2 & 0x000ffc00)) >> 11; \ - const Uint32 b = ((p1 & 0x3ff00000) + (p2 & 0x3ff00000)) >> 21; - -#define READ_1x2_PIXELS \ - const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 p2 = ((const Uint32 *)curr_row)[2 * i + 1]; \ - const Uint32 r = ((p1 & 0x000003ff) + (p2 & 0x000003ff)) >> 1; \ - const Uint32 g = ((p1 & 0x000ffc00) + (p2 & 0x000ffc00)) >> 11; \ - const Uint32 b = ((p1 & 0x3ff00000) + (p2 & 0x3ff00000)) >> 21; - -#define READ_1x1_PIXEL \ - const Uint32 p = ((const Uint32 *)curr_row)[2 * i]; \ - const Uint32 r = (p & 0x000003ff); \ - const Uint32 g = (p & 0x000ffc00) >> 10; \ - const Uint32 b = (p & 0x3ff00000) >> 20; - - const Uint8 *curr_row, *next_row; - - Uint16 *plane_y; - Uint16 *plane_u; - Uint16 *plane_v; - Uint16 *plane_interleaved_uv; - Uint32 y_stride, uv_stride, y_skip, uv_skip; - - if (!GetYUVPlanes(width, height, dst_format, dst, dst_pitch, - (const Uint8 **)&plane_y, (const Uint8 **)&plane_u, (const Uint8 **)&plane_v, - &y_stride, &uv_stride)) { - return false; - } - - y_stride /= sizeof(Uint16); - uv_stride /= sizeof(Uint16); - - plane_interleaved_uv = (plane_y + height * y_stride); - y_skip = (y_stride - width); - - curr_row = (const Uint8 *)src; - - // Write Y plane - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - const Uint32 p1 = ((const Uint32 *)curr_row)[i]; - const Uint32 r = (p1 >> 0) & 0x03ff; - const Uint32 g = (p1 >> 10) & 0x03ff; - const Uint32 b = (p1 >> 20) & 0x03ff; - *plane_y++ = MAKE_Y(r, g, b); - } - plane_y += y_skip; - curr_row += src_pitch; - } - - curr_row = (const Uint8 *)src; - next_row = (const Uint8 *)src; - next_row += src_pitch; - - uv_skip = (uv_stride - ((width + 1) / 2) * 2); - for (j = 0; j < height_half; j++) { - for (i = 0; i < width_half; i++) { - READ_2x2_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_2x1_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - plane_interleaved_uv += uv_skip; - curr_row += src_pitch_x_2; - next_row += src_pitch_x_2; - } - if (height_remainder) { - for (i = 0; i < width_half; i++) { - READ_1x2_PIXELS; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - if (width_remainder) { - READ_1x1_PIXEL; - *plane_interleaved_uv++ = MAKE_U(r, g, b); - *plane_interleaved_uv++ = MAKE_V(r, g, b); - } - } - -#undef MAKE_Y -#undef MAKE_U -#undef MAKE_V -#undef READ_2x2_PIXELS -#undef READ_2x1_PIXELS -#undef READ_1x2_PIXELS -#undef READ_1x1_PIXEL - return true; -} - -bool SDL_ConvertPixels_RGB_to_YUV(int width, int height, - SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, - SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch) -{ - YCbCrType yuv_type = YCBCR_601_LIMITED; - - if (!GetYUVConversionType(dst_colorspace, &yuv_type)) { - return false; - } - -#if 0 // Doesn't handle odd widths - // RGB24 to FOURCC - if (src_format == SDL_PIXELFORMAT_RGB24) { - Uint8 *y; - Uint8 *u; - Uint8 *v; - Uint32 y_stride; - Uint32 uv_stride; - - if (GetYUVPlanes(width, height, dst_format, dst, dst_pitch, (const Uint8 **)&y, (const Uint8 **)&u, (const Uint8 **)&v, &y_stride, &uv_stride) < 0) { - return false; - } - - rgb24_yuv420_std(width, height, src, src_pitch, y, u, v, y_stride, uv_stride, yuv_type); - return true; - } -#endif - - // ARGB8888 to FOURCC - if ((src_format == SDL_PIXELFORMAT_ARGB8888 || src_format == SDL_PIXELFORMAT_XRGB8888) && - SDL_COLORSPACEPRIMARIES(src_colorspace) == SDL_COLORSPACEPRIMARIES(dst_colorspace)) { - return SDL_ConvertPixels_XRGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst, dst_pitch, yuv_type); - } - - if (dst_format == SDL_PIXELFORMAT_P010) { - if (src_format == SDL_PIXELFORMAT_XBGR2101010 && - SDL_COLORSPACEPRIMARIES(src_colorspace) == SDL_COLORSPACEPRIMARIES(dst_colorspace)) { - return SDL_ConvertPixels_XBGR2101010_to_P010(width, height, src, src_pitch, dst_format, dst, dst_pitch, yuv_type); - } - - // We currently only support converting from XBGR2101010 to P010 - bool result; - void *tmp; - int tmp_pitch = (width * sizeof(Uint32)); - - tmp = SDL_malloc((size_t)tmp_pitch * height); - if (!tmp) { - return false; - } - - // convert src/src_format to tmp/XBGR2101010 - result = SDL_ConvertPixelsAndColorspace(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_XBGR2101010, dst_colorspace, dst_properties, tmp, tmp_pitch); - if (!result) { - SDL_free(tmp); - return false; - } - - // convert tmp/XBGR2101010 to dst/P010 - result = SDL_ConvertPixels_XBGR2101010_to_P010(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch, yuv_type); - SDL_free(tmp); - return result; - } - - // not ARGB8888 to FOURCC : need an intermediate conversion - { - bool result; - void *tmp; - int tmp_pitch = (width * sizeof(Uint32)); - - tmp = SDL_malloc((size_t)tmp_pitch * height); - if (!tmp) { - return false; - } - - // convert src/src_format to tmp/XRGB8888 - result = SDL_ConvertPixelsAndColorspace(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_XRGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch); - if (!result) { - SDL_free(tmp); - return false; - } - - // convert tmp/XRGB8888 to dst/FOURCC - result = SDL_ConvertPixels_XRGB8888_to_YUV(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch, yuv_type); - SDL_free(tmp); - return result; - } -} - -static bool SDL_ConvertPixels_YUV_to_YUV_Copy(int width, int height, SDL_PixelFormat format, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int i; - - if (IsPlanar2x2Format(format)) { - // Y plane - for (i = height; i--;) { - SDL_memcpy(dst, src, width); - src = (const Uint8 *)src + src_pitch; - dst = (Uint8 *)dst + dst_pitch; - } - - if (format == SDL_PIXELFORMAT_YV12 || format == SDL_PIXELFORMAT_IYUV) { - // U and V planes are a quarter the size of the Y plane, rounded up - width = (width + 1) / 2; - height = (height + 1) / 2; - src_pitch = (src_pitch + 1) / 2; - dst_pitch = (dst_pitch + 1) / 2; - for (i = height * 2; i--;) { - SDL_memcpy(dst, src, width); - src = (const Uint8 *)src + src_pitch; - dst = (Uint8 *)dst + dst_pitch; - } - } else if (format == SDL_PIXELFORMAT_NV12 || format == SDL_PIXELFORMAT_NV21) { - // U/V plane is half the height of the Y plane, rounded up - height = (height + 1) / 2; - width = ((width + 1) / 2) * 2; - src_pitch = ((src_pitch + 1) / 2) * 2; - dst_pitch = ((dst_pitch + 1) / 2) * 2; - for (i = height; i--;) { - SDL_memcpy(dst, src, width); - src = (const Uint8 *)src + src_pitch; - dst = (Uint8 *)dst + dst_pitch; - } - } else if (format == SDL_PIXELFORMAT_P010) { - // U/V plane is half the height of the Y plane, rounded up - height = (height + 1) / 2; - width = ((width + 1) / 2) * 2; - src_pitch = ((src_pitch + 1) / 2) * 2; - dst_pitch = ((dst_pitch + 1) / 2) * 2; - for (i = height; i--;) { - SDL_memcpy(dst, src, width * sizeof(Uint16)); - src = (const Uint8 *)src + src_pitch; - dst = (Uint8 *)dst + dst_pitch; - } - } - return true; - } - - if (IsPacked4Format(format)) { - // Packed planes - width = 4 * ((width + 1) / 2); - for (i = height; i--;) { - SDL_memcpy(dst, src, width); - src = (const Uint8 *)src + src_pitch; - dst = (Uint8 *)dst + dst_pitch; - } - return true; - } - - return SDL_SetError("SDL_ConvertPixels_YUV_to_YUV_Copy: Unsupported YUV format: %s", SDL_GetPixelFormatName(format)); -} - -static bool SDL_ConvertPixels_SwapUVPlanes(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - if (src == dst) { - int UVpitch = (dst_pitch + 1) / 2; - Uint8 *tmp; - Uint8 *row1 = (Uint8 *)dst; - Uint8 *row2 = row1 + UVheight * UVpitch; - - // Allocate a temporary row for the swap - tmp = (Uint8 *)SDL_malloc(UVwidth); - if (!tmp) { - return false; - } - for (y = 0; y < UVheight; ++y) { - SDL_memcpy(tmp, row1, UVwidth); - SDL_memcpy(row1, row2, UVwidth); - SDL_memcpy(row2, tmp, UVwidth); - row1 += UVpitch; - row2 += UVpitch; - } - SDL_free(tmp); - } else { - const Uint8 *srcUV; - Uint8 *dstUV; - int srcUVPitch = ((src_pitch + 1) / 2); - int dstUVPitch = ((dst_pitch + 1) / 2); - - // Copy the first plane - srcUV = (const Uint8 *)src; - dstUV = (Uint8 *)dst + UVheight * dstUVPitch; - for (y = 0; y < UVheight; ++y) { - SDL_memcpy(dstUV, srcUV, UVwidth); - srcUV += srcUVPitch; - dstUV += dstUVPitch; - } - - // Copy the second plane - dstUV = (Uint8 *)dst; - for (y = 0; y < UVheight; ++y) { - SDL_memcpy(dstUV, srcUV, UVwidth); - srcUV += srcUVPitch; - dstUV += dstUVPitch; - } - } - return true; -} - -#ifdef SDL_SSE2_INTRINSICS -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_PackUVPlanes_to_NV_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2); - const int srcUVPitchLeft = srcUVPitch - UVwidth; - const int dstUVPitch = ((dst_pitch + 1) / 2) * 2; - const int dstUVPitchLeft = dstUVPitch - UVwidth * 2; - const Uint8 *src1, *src2; - Uint8 *dstUV; - Uint8 *tmp = NULL; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - if (src == dst) { - // Need to make a copy of the buffer so we don't clobber it while converting - tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch); - if (tmp == NULL) { - return false; - } - SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch); - src = tmp; - } - - if (reverseUV) { - src2 = (const Uint8 *)src; - src1 = src2 + UVheight * srcUVPitch; - } else { - src1 = (const Uint8 *)src; - src2 = src1 + UVheight * srcUVPitch; - } - dstUV = (Uint8 *)dst; - - y = UVheight; - while (y--) { - x = UVwidth; - while (x >= 16) { - __m128i u = _mm_loadu_si128((__m128i *)src1); - __m128i v = _mm_loadu_si128((__m128i *)src2); - __m128i uv1 = _mm_unpacklo_epi8(u, v); - __m128i uv2 = _mm_unpackhi_epi8(u, v); - _mm_storeu_si128((__m128i *)dstUV, uv1); - _mm_storeu_si128((__m128i *)(dstUV + 16), uv2); - src1 += 16; - src2 += 16; - dstUV += 32; - x -= 16; - } - while (x--) { - *dstUV++ = *src1++; - *dstUV++ = *src2++; - } - src1 += srcUVPitchLeft; - src2 += srcUVPitchLeft; - dstUV += dstUVPitchLeft; - } - - if (tmp) { - SDL_free(tmp); - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_SplitNV_to_UVPlanes_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2) * 2; - const int srcUVPitchLeft = srcUVPitch - UVwidth * 2; - const int dstUVPitch = ((dst_pitch + 1) / 2); - const int dstUVPitchLeft = dstUVPitch - UVwidth; - const Uint8 *srcUV; - Uint8 *dst1, *dst2; - Uint8 *tmp = NULL; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - if (src == dst) { - // Need to make a copy of the buffer so we don't clobber it while converting - tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch); - if (tmp == NULL) { - return false; - } - SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch); - src = tmp; - } - - if (reverseUV) { - dst2 = (Uint8 *)dst; - dst1 = dst2 + UVheight * dstUVPitch; - } else { - dst1 = (Uint8 *)dst; - dst2 = dst1 + UVheight * dstUVPitch; - } - srcUV = (const Uint8 *)src; - - y = UVheight; - while (y--) { - __m128i mask = _mm_set1_epi16(0x00FF); - x = UVwidth; - while (x >= 16) { - __m128i uv1 = _mm_loadu_si128((__m128i *)srcUV); - __m128i uv2 = _mm_loadu_si128((__m128i *)(srcUV + 16)); - __m128i u1 = _mm_and_si128(uv1, mask); - __m128i u2 = _mm_and_si128(uv2, mask); - __m128i u = _mm_packus_epi16(u1, u2); - __m128i v1 = _mm_srli_epi16(uv1, 8); - __m128i v2 = _mm_srli_epi16(uv2, 8); - __m128i v = _mm_packus_epi16(v1, v2); - _mm_storeu_si128((__m128i *)dst1, u); - _mm_storeu_si128((__m128i *)dst2, v); - srcUV += 32; - dst1 += 16; - dst2 += 16; - x -= 16; - } - while (x--) { - *dst1++ = *srcUV++; - *dst2++ = *srcUV++; - } - srcUV += srcUVPitchLeft; - dst1 += dstUVPitchLeft; - dst2 += dstUVPitchLeft; - } - - if (tmp) { - SDL_free(tmp); - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_SwapNV_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2) * 2; - const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16); - const int dstUVPitch = ((dst_pitch + 1) / 2) * 2; - const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16); - const Uint16 *srcUV; - Uint16 *dstUV; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - srcUV = (const Uint16 *)src; - dstUV = (Uint16 *)dst; - y = UVheight; - while (y--) { - x = UVwidth; - while (x >= 8) { - __m128i uv = _mm_loadu_si128((__m128i *)srcUV); - __m128i v = _mm_slli_epi16(uv, 8); - __m128i u = _mm_srli_epi16(uv, 8); - __m128i vu = _mm_or_si128(v, u); - _mm_storeu_si128((__m128i *)dstUV, vu); - srcUV += 8; - dstUV += 8; - x -= 8; - } - while (x--) { - *dstUV++ = SDL_Swap16(*srcUV++); - } - srcUV += srcUVPitchLeft; - dstUV += dstUVPitchLeft; - } - return true; -} -#endif - -static bool SDL_ConvertPixels_PackUVPlanes_to_NV_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2); - const int srcUVPitchLeft = srcUVPitch - UVwidth; - const int dstUVPitch = ((dst_pitch + 1) / 2) * 2; - const int dstUVPitchLeft = dstUVPitch - UVwidth * 2; - const Uint8 *src1, *src2; - Uint8 *dstUV; - Uint8 *tmp = NULL; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - if (src == dst) { - // Need to make a copy of the buffer so we don't clobber it while converting - tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch); - if (!tmp) { - return false; - } - SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch); - src = tmp; - } - - if (reverseUV) { - src2 = (const Uint8 *)src; - src1 = src2 + UVheight * srcUVPitch; - } else { - src1 = (const Uint8 *)src; - src2 = src1 + UVheight * srcUVPitch; - } - dstUV = (Uint8 *)dst; - - y = UVheight; - while (y--) { - x = UVwidth; - while (x--) { - *dstUV++ = *src1++; - *dstUV++ = *src2++; - } - src1 += srcUVPitchLeft; - src2 += srcUVPitchLeft; - dstUV += dstUVPitchLeft; - } - - if (tmp) { - SDL_free(tmp); - } - return true; -} - -static bool SDL_ConvertPixels_SplitNV_to_UVPlanes_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2) * 2; - const int srcUVPitchLeft = srcUVPitch - UVwidth * 2; - const int dstUVPitch = ((dst_pitch + 1) / 2); - const int dstUVPitchLeft = dstUVPitch - UVwidth; - const Uint8 *srcUV; - Uint8 *dst1, *dst2; - Uint8 *tmp = NULL; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - if (src == dst) { - // Need to make a copy of the buffer so we don't clobber it while converting - tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch); - if (!tmp) { - return false; - } - SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch); - src = tmp; - } - - if (reverseUV) { - dst2 = (Uint8 *)dst; - dst1 = dst2 + UVheight * dstUVPitch; - } else { - dst1 = (Uint8 *)dst; - dst2 = dst1 + UVheight * dstUVPitch; - } - srcUV = (const Uint8 *)src; - - y = UVheight; - while (y--) { - x = UVwidth; - while (x--) { - *dst1++ = *srcUV++; - *dst2++ = *srcUV++; - } - srcUV += srcUVPitchLeft; - dst1 += dstUVPitchLeft; - dst2 += dstUVPitchLeft; - } - - if (tmp) { - SDL_free(tmp); - } - return true; -} - -static bool SDL_ConvertPixels_SwapNV_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int UVwidth = (width + 1) / 2; - const int UVheight = (height + 1) / 2; - const int srcUVPitch = ((src_pitch + 1) / 2) * 2; - const int srcUVPitchLeft = (srcUVPitch - UVwidth * 2) / sizeof(Uint16); - const int dstUVPitch = ((dst_pitch + 1) / 2) * 2; - const int dstUVPitchLeft = (dstUVPitch - UVwidth * 2) / sizeof(Uint16); - const Uint16 *srcUV; - Uint16 *dstUV; - - // Skip the Y plane - src = (const Uint8 *)src + height * src_pitch; - dst = (Uint8 *)dst + height * dst_pitch; - - srcUV = (const Uint16 *)src; - dstUV = (Uint16 *)dst; - y = UVheight; - while (y--) { - x = UVwidth; - while (x--) { - *dstUV++ = SDL_Swap16(*srcUV++); - } - srcUV += srcUVPitchLeft; - dstUV += dstUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_PackUVPlanes_to_NV(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_PackUVPlanes_to_NV_SSE2(width, height, src, src_pitch, dst, dst_pitch, reverseUV); - } -#endif - return SDL_ConvertPixels_PackUVPlanes_to_NV_std(width, height, src, src_pitch, dst, dst_pitch, reverseUV); -} - -static bool SDL_ConvertPixels_SplitNV_to_UVPlanes(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch, bool reverseUV) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_SplitNV_to_UVPlanes_SSE2(width, height, src, src_pitch, dst, dst_pitch, reverseUV); - } -#endif - return SDL_ConvertPixels_SplitNV_to_UVPlanes_std(width, height, src, src_pitch, dst, dst_pitch, reverseUV); -} - -static bool SDL_ConvertPixels_SwapNV(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_SwapNV_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_SwapNV_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_Planar2x2_to_Planar2x2(int width, int height, - SDL_PixelFormat src_format, const void *src, int src_pitch, - SDL_PixelFormat dst_format, void *dst, int dst_pitch) -{ - if (src != dst) { - // Copy Y plane - int i; - const Uint8 *srcY = (const Uint8 *)src; - Uint8 *dstY = (Uint8 *)dst; - for (i = height; i--;) { - SDL_memcpy(dstY, srcY, width); - srcY += src_pitch; - dstY += dst_pitch; - } - } - - switch (src_format) { - case SDL_PIXELFORMAT_YV12: - switch (dst_format) { - case SDL_PIXELFORMAT_IYUV: - return SDL_ConvertPixels_SwapUVPlanes(width, height, src, src_pitch, dst, dst_pitch); - case SDL_PIXELFORMAT_NV12: - return SDL_ConvertPixels_PackUVPlanes_to_NV(width, height, src, src_pitch, dst, dst_pitch, true); - case SDL_PIXELFORMAT_NV21: - return SDL_ConvertPixels_PackUVPlanes_to_NV(width, height, src, src_pitch, dst, dst_pitch, false); - default: - break; - } - break; - case SDL_PIXELFORMAT_IYUV: - switch (dst_format) { - case SDL_PIXELFORMAT_YV12: - return SDL_ConvertPixels_SwapUVPlanes(width, height, src, src_pitch, dst, dst_pitch); - case SDL_PIXELFORMAT_NV12: - return SDL_ConvertPixels_PackUVPlanes_to_NV(width, height, src, src_pitch, dst, dst_pitch, false); - case SDL_PIXELFORMAT_NV21: - return SDL_ConvertPixels_PackUVPlanes_to_NV(width, height, src, src_pitch, dst, dst_pitch, true); - default: - break; - } - break; - case SDL_PIXELFORMAT_NV12: - switch (dst_format) { - case SDL_PIXELFORMAT_YV12: - return SDL_ConvertPixels_SplitNV_to_UVPlanes(width, height, src, src_pitch, dst, dst_pitch, true); - case SDL_PIXELFORMAT_IYUV: - return SDL_ConvertPixels_SplitNV_to_UVPlanes(width, height, src, src_pitch, dst, dst_pitch, false); - case SDL_PIXELFORMAT_NV21: - return SDL_ConvertPixels_SwapNV(width, height, src, src_pitch, dst, dst_pitch); - default: - break; - } - break; - case SDL_PIXELFORMAT_NV21: - switch (dst_format) { - case SDL_PIXELFORMAT_YV12: - return SDL_ConvertPixels_SplitNV_to_UVPlanes(width, height, src, src_pitch, dst, dst_pitch, false); - case SDL_PIXELFORMAT_IYUV: - return SDL_ConvertPixels_SplitNV_to_UVPlanes(width, height, src, src_pitch, dst, dst_pitch, true); - case SDL_PIXELFORMAT_NV12: - return SDL_ConvertPixels_SwapNV(width, height, src, src_pitch, dst, dst_pitch); - default: - break; - } - break; - default: - break; - } - return SDL_SetError("SDL_ConvertPixels_Planar2x2_to_Planar2x2: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), - SDL_GetPixelFormatName(dst_format)); -} - -#ifdef SDL_SSE2_INTRINSICS -#define PACKED4_TO_PACKED4_ROW_SSE2(shuffle) \ - while (x >= 4) { \ - __m128i yuv = _mm_loadu_si128((__m128i *)srcYUV); \ - __m128i lo = _mm_unpacklo_epi8(yuv, _mm_setzero_si128()); \ - __m128i hi = _mm_unpackhi_epi8(yuv, _mm_setzero_si128()); \ - lo = _mm_shufflelo_epi16(lo, shuffle); \ - lo = _mm_shufflehi_epi16(lo, shuffle); \ - hi = _mm_shufflelo_epi16(hi, shuffle); \ - hi = _mm_shufflehi_epi16(hi, shuffle); \ - yuv = _mm_packus_epi16(lo, hi); \ - _mm_storeu_si128((__m128i *)dstYUV, yuv); \ - srcYUV += 16; \ - dstYUV += 16; \ - x -= 4; \ - } - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_YUY2_to_UYVY_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(2, 3, 0, 1)); - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - U = srcYUV[1]; - Y2 = srcYUV[2]; - V = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = U; - dstYUV[1] = Y1; - dstYUV[2] = V; - dstYUV[3] = Y2; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_YUY2_to_YVYU_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(1, 2, 3, 0)); - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - U = srcYUV[1]; - Y2 = srcYUV[2]; - V = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = V; - dstYUV[2] = Y2; - dstYUV[3] = U; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_UYVY_to_YUY2_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(2, 3, 0, 1)); - while (x--) { - Uint8 Y1, U, Y2, V; - - U = srcYUV[0]; - Y1 = srcYUV[1]; - V = srcYUV[2]; - Y2 = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = U; - dstYUV[2] = Y2; - dstYUV[3] = V; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_UYVY_to_YVYU_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(0, 3, 2, 1)); - while (x--) { - Uint8 Y1, U, Y2, V; - - U = srcYUV[0]; - Y1 = srcYUV[1]; - V = srcYUV[2]; - Y2 = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = V; - dstYUV[2] = Y2; - dstYUV[3] = U; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_YVYU_to_YUY2_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(1, 2, 3, 0)); - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - V = srcYUV[1]; - Y2 = srcYUV[2]; - U = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = U; - dstYUV[2] = Y2; - dstYUV[3] = V; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} - -static bool SDL_TARGETING("sse2") SDL_ConvertPixels_YVYU_to_UYVY_SSE2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - x = YUVwidth; - while (y--) { - PACKED4_TO_PACKED4_ROW_SSE2(_MM_SHUFFLE(2, 1, 0, 3)); - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - V = srcYUV[1]; - Y2 = srcYUV[2]; - U = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = U; - dstYUV[1] = Y1; - dstYUV[2] = V; - dstYUV[3] = Y2; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - x = YUVwidth; - } - return true; -} -#endif - -static bool SDL_ConvertPixels_YUY2_to_UYVY_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - U = srcYUV[1]; - Y2 = srcYUV[2]; - V = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = U; - dstYUV[1] = Y1; - dstYUV[2] = V; - dstYUV[3] = Y2; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_YUY2_to_YVYU_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - U = srcYUV[1]; - Y2 = srcYUV[2]; - V = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = V; - dstYUV[2] = Y2; - dstYUV[3] = U; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_UYVY_to_YUY2_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - U = srcYUV[0]; - Y1 = srcYUV[1]; - V = srcYUV[2]; - Y2 = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = U; - dstYUV[2] = Y2; - dstYUV[3] = V; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_UYVY_to_YVYU_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - U = srcYUV[0]; - Y1 = srcYUV[1]; - V = srcYUV[2]; - Y2 = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = V; - dstYUV[2] = Y2; - dstYUV[3] = U; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_YVYU_to_YUY2_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - V = srcYUV[1]; - Y2 = srcYUV[2]; - U = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = Y1; - dstYUV[1] = U; - dstYUV[2] = Y2; - dstYUV[3] = V; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_YVYU_to_UYVY_std(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ - int x, y; - const int YUVwidth = (width + 1) / 2; - const int srcYUVPitchLeft = (src_pitch - YUVwidth * 4); - const int dstYUVPitchLeft = (dst_pitch - YUVwidth * 4); - const Uint8 *srcYUV = (const Uint8 *)src; - Uint8 *dstYUV = (Uint8 *)dst; - - y = height; - while (y--) { - x = YUVwidth; - while (x--) { - Uint8 Y1, U, Y2, V; - - Y1 = srcYUV[0]; - V = srcYUV[1]; - Y2 = srcYUV[2]; - U = srcYUV[3]; - srcYUV += 4; - - dstYUV[0] = U; - dstYUV[1] = Y1; - dstYUV[2] = V; - dstYUV[3] = Y2; - dstYUV += 4; - } - srcYUV += srcYUVPitchLeft; - dstYUV += dstYUVPitchLeft; - } - return true; -} - -static bool SDL_ConvertPixels_YUY2_to_UYVY(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_YUY2_to_UYVY_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_YUY2_to_UYVY_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_YUY2_to_YVYU(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_YUY2_to_YVYU_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_YUY2_to_YVYU_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_UYVY_to_YUY2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_UYVY_to_YUY2_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_UYVY_to_YUY2_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_UYVY_to_YVYU(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_UYVY_to_YVYU_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_UYVY_to_YVYU_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_YVYU_to_YUY2(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_YVYU_to_YUY2_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_YVYU_to_YUY2_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_YVYU_to_UYVY(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch) -{ -#ifdef SDL_SSE2_INTRINSICS - if (SDL_HasSSE2()) { - return SDL_ConvertPixels_YVYU_to_UYVY_SSE2(width, height, src, src_pitch, dst, dst_pitch); - } -#endif - return SDL_ConvertPixels_YVYU_to_UYVY_std(width, height, src, src_pitch, dst, dst_pitch); -} - -static bool SDL_ConvertPixels_Packed4_to_Packed4(int width, int height, - SDL_PixelFormat src_format, const void *src, int src_pitch, - SDL_PixelFormat dst_format, void *dst, int dst_pitch) -{ - switch (src_format) { - case SDL_PIXELFORMAT_YUY2: - switch (dst_format) { - case SDL_PIXELFORMAT_UYVY: - return SDL_ConvertPixels_YUY2_to_UYVY(width, height, src, src_pitch, dst, dst_pitch); - case SDL_PIXELFORMAT_YVYU: - return SDL_ConvertPixels_YUY2_to_YVYU(width, height, src, src_pitch, dst, dst_pitch); - default: - break; - } - break; - case SDL_PIXELFORMAT_UYVY: - switch (dst_format) { - case SDL_PIXELFORMAT_YUY2: - return SDL_ConvertPixels_UYVY_to_YUY2(width, height, src, src_pitch, dst, dst_pitch); - case SDL_PIXELFORMAT_YVYU: - return SDL_ConvertPixels_UYVY_to_YVYU(width, height, src, src_pitch, dst, dst_pitch); - default: - break; - } - break; - case SDL_PIXELFORMAT_YVYU: - switch (dst_format) { - case SDL_PIXELFORMAT_YUY2: - return SDL_ConvertPixels_YVYU_to_YUY2(width, height, src, src_pitch, dst, dst_pitch); - case SDL_PIXELFORMAT_UYVY: - return SDL_ConvertPixels_YVYU_to_UYVY(width, height, src, src_pitch, dst, dst_pitch); - default: - break; - } - break; - default: - break; - } - return SDL_SetError("SDL_ConvertPixels_Packed4_to_Packed4: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), - SDL_GetPixelFormatName(dst_format)); -} - -static bool SDL_ConvertPixels_Planar2x2_to_Packed4(int width, int height, - SDL_PixelFormat src_format, const void *src, int src_pitch, - SDL_PixelFormat dst_format, void *dst, int dst_pitch) -{ - int x, y; - const Uint8 *srcY1, *srcY2, *srcU, *srcV; - Uint32 srcY_pitch, srcUV_pitch; - Uint32 srcY_pitch_left, srcUV_pitch_left, srcUV_pixel_stride; - Uint8 *dstY1, *dstY2, *dstU1, *dstU2, *dstV1, *dstV2; - Uint32 dstY_pitch, dstUV_pitch; - Uint32 dst_pitch_left; - - if (src == dst) { - return SDL_SetError("Can't change YUV plane types in-place"); - } - - if (!GetYUVPlanes(width, height, src_format, src, src_pitch, - &srcY1, &srcU, &srcV, &srcY_pitch, &srcUV_pitch)) { - return false; - } - srcY2 = srcY1 + srcY_pitch; - srcY_pitch_left = (srcY_pitch - width); - - if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) { - srcUV_pixel_stride = 2; - srcUV_pitch_left = (srcUV_pitch - 2 * ((width + 1) / 2)); - } else { - srcUV_pixel_stride = 1; - srcUV_pitch_left = (srcUV_pitch - ((width + 1) / 2)); - } - - if (!GetYUVPlanes(width, height, dst_format, dst, dst_pitch, - (const Uint8 **)&dstY1, (const Uint8 **)&dstU1, (const Uint8 **)&dstV1, - &dstY_pitch, &dstUV_pitch)) { - return false; - } - dstY2 = dstY1 + dstY_pitch; - dstU2 = dstU1 + dstUV_pitch; - dstV2 = dstV1 + dstUV_pitch; - dst_pitch_left = (dstY_pitch - 4 * ((width + 1) / 2)); - - // Copy 2x2 blocks of pixels at a time - for (y = 0; y < (height - 1); y += 2) { - for (x = 0; x < (width - 1); x += 2) { - // Row 1 - *dstY1 = *srcY1++; - dstY1 += 2; - *dstY1 = *srcY1++; - dstY1 += 2; - *dstU1 = *srcU; - *dstV1 = *srcV; - - // Row 2 - *dstY2 = *srcY2++; - dstY2 += 2; - *dstY2 = *srcY2++; - dstY2 += 2; - *dstU2 = *srcU; - *dstV2 = *srcV; - - srcU += srcUV_pixel_stride; - srcV += srcUV_pixel_stride; - dstU1 += 4; - dstU2 += 4; - dstV1 += 4; - dstV2 += 4; - } - - // Last column - if (x == (width - 1)) { - // Row 1 - *dstY1 = *srcY1; - dstY1 += 2; - *dstY1 = *srcY1++; - dstY1 += 2; - *dstU1 = *srcU; - *dstV1 = *srcV; - - // Row 2 - *dstY2 = *srcY2; - dstY2 += 2; - *dstY2 = *srcY2++; - dstY2 += 2; - *dstU2 = *srcU; - *dstV2 = *srcV; - - srcU += srcUV_pixel_stride; - srcV += srcUV_pixel_stride; - dstU1 += 4; - dstU2 += 4; - dstV1 += 4; - dstV2 += 4; - } - - srcY1 += srcY_pitch_left + srcY_pitch; - srcY2 += srcY_pitch_left + srcY_pitch; - srcU += srcUV_pitch_left; - srcV += srcUV_pitch_left; - dstY1 += dst_pitch_left + dstY_pitch; - dstY2 += dst_pitch_left + dstY_pitch; - dstU1 += dst_pitch_left + dstUV_pitch; - dstU2 += dst_pitch_left + dstUV_pitch; - dstV1 += dst_pitch_left + dstUV_pitch; - dstV2 += dst_pitch_left + dstUV_pitch; - } - - // Last row - if (y == (height - 1)) { - for (x = 0; x < (width - 1); x += 2) { - // Row 1 - *dstY1 = *srcY1++; - dstY1 += 2; - *dstY1 = *srcY1++; - dstY1 += 2; - *dstU1 = *srcU; - *dstV1 = *srcV; - - srcU += srcUV_pixel_stride; - srcV += srcUV_pixel_stride; - dstU1 += 4; - dstV1 += 4; - } - - // Last column - if (x == (width - 1)) { - // Row 1 - *dstY1 = *srcY1; - dstY1 += 2; - *dstY1 = *srcY1++; - dstY1 += 2; - *dstU1 = *srcU; - *dstV1 = *srcV; - - srcU += srcUV_pixel_stride; - srcV += srcUV_pixel_stride; - dstU1 += 4; - dstV1 += 4; - } - } - return true; -} - -static bool SDL_ConvertPixels_Packed4_to_Planar2x2(int width, int height, - SDL_PixelFormat src_format, const void *src, int src_pitch, - SDL_PixelFormat dst_format, void *dst, int dst_pitch) -{ - int x, y; - const Uint8 *srcY1, *srcY2, *srcU1, *srcU2, *srcV1, *srcV2; - Uint32 srcY_pitch, srcUV_pitch; - Uint32 src_pitch_left; - Uint8 *dstY1, *dstY2, *dstU, *dstV; - Uint32 dstY_pitch, dstUV_pitch; - Uint32 dstY_pitch_left, dstUV_pitch_left, dstUV_pixel_stride; - - if (src == dst) { - return SDL_SetError("Can't change YUV plane types in-place"); - } - - if (!GetYUVPlanes(width, height, src_format, src, src_pitch, - &srcY1, &srcU1, &srcV1, &srcY_pitch, &srcUV_pitch)) { - return false; - } - srcY2 = srcY1 + srcY_pitch; - srcU2 = srcU1 + srcUV_pitch; - srcV2 = srcV1 + srcUV_pitch; - src_pitch_left = (srcY_pitch - 4 * ((width + 1) / 2)); - - if (!GetYUVPlanes(width, height, dst_format, dst, dst_pitch, - (const Uint8 **)&dstY1, (const Uint8 **)&dstU, (const Uint8 **)&dstV, - &dstY_pitch, &dstUV_pitch)) { - return false; - } - dstY2 = dstY1 + dstY_pitch; - dstY_pitch_left = (dstY_pitch - width); - - if (dst_format == SDL_PIXELFORMAT_NV12 || dst_format == SDL_PIXELFORMAT_NV21) { - dstUV_pixel_stride = 2; - dstUV_pitch_left = (dstUV_pitch - 2 * ((width + 1) / 2)); - } else { - dstUV_pixel_stride = 1; - dstUV_pitch_left = (dstUV_pitch - ((width + 1) / 2)); - } - - // Copy 2x2 blocks of pixels at a time - for (y = 0; y < (height - 1); y += 2) { - for (x = 0; x < (width - 1); x += 2) { - // Row 1 - *dstY1++ = *srcY1; - srcY1 += 2; - *dstY1++ = *srcY1; - srcY1 += 2; - - // Row 2 - *dstY2++ = *srcY2; - srcY2 += 2; - *dstY2++ = *srcY2; - srcY2 += 2; - - *dstU = (Uint8)(((Uint32)*srcU1 + *srcU2) / 2); - *dstV = (Uint8)(((Uint32)*srcV1 + *srcV2) / 2); - - srcU1 += 4; - srcU2 += 4; - srcV1 += 4; - srcV2 += 4; - dstU += dstUV_pixel_stride; - dstV += dstUV_pixel_stride; - } - - // Last column - if (x == (width - 1)) { - // Row 1 - *dstY1 = *srcY1; - srcY1 += 2; - *dstY1++ = *srcY1; - srcY1 += 2; - - // Row 2 - *dstY2 = *srcY2; - srcY2 += 2; - *dstY2++ = *srcY2; - srcY2 += 2; - - *dstU = (Uint8)(((Uint32)*srcU1 + *srcU2) / 2); - *dstV = (Uint8)(((Uint32)*srcV1 + *srcV2) / 2); - - srcU1 += 4; - srcU2 += 4; - srcV1 += 4; - srcV2 += 4; - dstU += dstUV_pixel_stride; - dstV += dstUV_pixel_stride; - } - - srcY1 += src_pitch_left + srcY_pitch; - srcY2 += src_pitch_left + srcY_pitch; - srcU1 += src_pitch_left + srcUV_pitch; - srcU2 += src_pitch_left + srcUV_pitch; - srcV1 += src_pitch_left + srcUV_pitch; - srcV2 += src_pitch_left + srcUV_pitch; - dstY1 += dstY_pitch_left + dstY_pitch; - dstY2 += dstY_pitch_left + dstY_pitch; - dstU += dstUV_pitch_left; - dstV += dstUV_pitch_left; - } - - // Last row - if (y == (height - 1)) { - for (x = 0; x < (width - 1); x += 2) { - *dstY1++ = *srcY1; - srcY1 += 2; - *dstY1++ = *srcY1; - srcY1 += 2; - - *dstU = *srcU1; - *dstV = *srcV1; - - srcU1 += 4; - srcV1 += 4; - dstU += dstUV_pixel_stride; - dstV += dstUV_pixel_stride; - } - - // Last column - if (x == (width - 1)) { - *dstY1 = *srcY1; - *dstU = *srcU1; - *dstV = *srcV1; - } - } - return true; -} - -#endif // SDL_HAVE_YUV - -bool SDL_ConvertPixels_YUV_to_YUV(int width, int height, - SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, - SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch) -{ -#ifdef SDL_HAVE_YUV - if (src_colorspace != dst_colorspace) { - return SDL_SetError("SDL_ConvertPixels_YUV_to_YUV: colorspace conversion not supported"); - } - - if (src_format == dst_format) { - if (src == dst) { - // Nothing to do - return true; - } - return SDL_ConvertPixels_YUV_to_YUV_Copy(width, height, src_format, src, src_pitch, dst, dst_pitch); - } - - if (IsPlanar2x2Format(src_format) && IsPlanar2x2Format(dst_format)) { - return SDL_ConvertPixels_Planar2x2_to_Planar2x2(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch); - } else if (IsPacked4Format(src_format) && IsPacked4Format(dst_format)) { - return SDL_ConvertPixels_Packed4_to_Packed4(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch); - } else if (IsPlanar2x2Format(src_format) && IsPacked4Format(dst_format)) { - return SDL_ConvertPixels_Planar2x2_to_Packed4(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch); - } else if (IsPacked4Format(src_format) && IsPlanar2x2Format(dst_format)) { - return SDL_ConvertPixels_Packed4_to_Planar2x2(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch); - } else { - return SDL_SetError("SDL_ConvertPixels_YUV_to_YUV: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), - SDL_GetPixelFormatName(dst_format)); - } -#else - return SDL_SetError("SDL not built with YUV support"); -#endif -} -- cgit v1.2.3