Use YUV colorspaces instead of a global YUV conversion mode
Fixes https://github.com/libsdl-org/SDL/issues/8669main
parent
9e76f23561
commit
50a805cdd1
|
@ -1382,6 +1382,9 @@ The following functions have been renamed:
|
|||
* SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled()
|
||||
|
||||
The following functions have been removed:
|
||||
* SDL_GetYUVConversionMode()
|
||||
* SDL_GetYUVConversionModeForResolution()
|
||||
* SDL_SetYUVConversionMode() - use SDL_SetSurfaceColorspace() to set the surface colorspace and SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER with SDL_CreateTextureWithProperties() to set the texture colorspace. The default colorspace for YUV pixel formats is SDL_COLORSPACE_BT601_LIMITED.
|
||||
* SDL_SoftStretchLinear() - use SDL_SoftStretch() with SDL_SCALEMODE_LINEAR
|
||||
|
||||
## SDL_system.h
|
||||
|
|
|
@ -555,6 +555,11 @@ typedef enum
|
|||
#define SDL_COLORSPACETRANSFER(X) (SDL_TransferCharacteristics)(((X) >> 5) & 0x1F)
|
||||
#define SDL_COLORSPACEMATRIX(X) (SDL_MatrixCoefficients)((X) & 0x1F)
|
||||
|
||||
#define SDL_ISCOLORSPACE_YUV_BT601(X) (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT601 || SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT470BG)
|
||||
#define SDL_ISCOLORSPACE_YUV_BT709(X) (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT709)
|
||||
#define SDL_ISCOLORSPACE_LIMITED_RANGE(X) (SDL_COLORSPACERANGE(X) == SDL_COLOR_RANGE_LIMITED)
|
||||
#define SDL_ISCOLORSPACE_FULL_RANGE(X) (SDL_COLORSPACERANGE(X) == SDL_COLOR_RANGE_LIMITED)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_COLORSPACE_UNKNOWN,
|
||||
|
@ -620,6 +625,10 @@ typedef enum
|
|||
|
||||
/* The default colorspace for RGB surfaces if no colorspace is specified */
|
||||
SDL_COLORSPACE_RGB_DEFAULT = SDL_COLORSPACE_SRGB,
|
||||
|
||||
/* The default colorspace for YUV surfaces if no colorspace is specified */
|
||||
SDL_COLORSPACE_YUV_DEFAULT = SDL_COLORSPACE_BT601_LIMITED,
|
||||
|
||||
} SDL_Colorspace;
|
||||
|
||||
/**
|
||||
|
|
|
@ -458,7 +458,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
|
|||
* - `SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER`: an SDL_ColorSpace value
|
||||
* describing the texture colorspace, defaults to SDL_COLORSPACE_SCRGB for
|
||||
* floating point textures, SDL_COLORSPACE_HDR10 for 10-bit textures,
|
||||
* SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_BT709_FULL
|
||||
* SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_BT601_LIMITED
|
||||
* for YUV textures.
|
||||
* - `SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER`: one of the enumerated values in
|
||||
* SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer
|
||||
|
|
|
@ -138,17 +138,6 @@ typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrec
|
|||
struct SDL_Surface *dst, const SDL_Rect *dstrect);
|
||||
|
||||
|
||||
/**
|
||||
* The formula used for converting between YUV and RGB
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_YUV_CONVERSION_JPEG, /**< Full range JPEG */
|
||||
SDL_YUV_CONVERSION_BT601, /**< BT.601 (the default) */
|
||||
SDL_YUV_CONVERSION_BT709, /**< BT.709 */
|
||||
SDL_YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */
|
||||
} SDL_YUV_CONVERSION_MODE;
|
||||
|
||||
/**
|
||||
* Allocate a new RGB surface with a specific pixel format.
|
||||
*
|
||||
|
@ -1031,36 +1020,6 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, con
|
|||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
|
||||
|
||||
/**
|
||||
* Set the YUV conversion mode
|
||||
*
|
||||
* \param mode YUV conversion mode
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode);
|
||||
|
||||
/**
|
||||
* Get the YUV conversion mode
|
||||
*
|
||||
* \returns YUV conversion mode
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionMode(void);
|
||||
|
||||
/**
|
||||
* Get the YUV conversion mode, returning the correct mode for the resolution
|
||||
* when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC
|
||||
*
|
||||
* \param width width
|
||||
* \param height height
|
||||
* \returns YUV conversion mode
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*/
|
||||
extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionModeForResolution(int width, int height);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -347,8 +347,6 @@ SDL3_0.0.0 {
|
|||
SDL_GetWindowSizeInPixels;
|
||||
SDL_GetWindowSurface;
|
||||
SDL_GetWindowTitle;
|
||||
SDL_GetYUVConversionMode;
|
||||
SDL_GetYUVConversionModeForResolution;
|
||||
SDL_CloseHaptic;
|
||||
SDL_DestroyHapticEffect;
|
||||
SDL_HapticEffectSupported;
|
||||
|
@ -594,7 +592,6 @@ SDL3_0.0.0 {
|
|||
SDL_SetWindowSize;
|
||||
SDL_SetWindowTitle;
|
||||
SDL_SetWindowsMessageHook;
|
||||
SDL_SetYUVConversionMode;
|
||||
SDL_ShowCursor;
|
||||
SDL_ShowMessageBox;
|
||||
SDL_ShowSimpleMessageBox;
|
||||
|
|
|
@ -371,8 +371,6 @@
|
|||
#define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL
|
||||
#define SDL_GetWindowSurface SDL_GetWindowSurface_REAL
|
||||
#define SDL_GetWindowTitle SDL_GetWindowTitle_REAL
|
||||
#define SDL_GetYUVConversionMode SDL_GetYUVConversionMode_REAL
|
||||
#define SDL_GetYUVConversionModeForResolution SDL_GetYUVConversionModeForResolution_REAL
|
||||
#define SDL_CloseHaptic SDL_CloseHaptic_REAL
|
||||
#define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL
|
||||
#define SDL_HapticEffectSupported SDL_HapticEffectSupported_REAL
|
||||
|
@ -617,7 +615,6 @@
|
|||
#define SDL_SetWindowSize SDL_SetWindowSize_REAL
|
||||
#define SDL_SetWindowTitle SDL_SetWindowTitle_REAL
|
||||
#define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL
|
||||
#define SDL_SetYUVConversionMode SDL_SetYUVConversionMode_REAL
|
||||
#define SDL_ShowCursor SDL_ShowCursor_REAL
|
||||
#define SDL_ShowMessageBox SDL_ShowMessageBox_REAL
|
||||
#define SDL_ShowSimpleMessageBox SDL_ShowSimpleMessageBox_REAL
|
||||
|
|
|
@ -430,8 +430,6 @@ SDL_DYNAPI_PROC(int,SDL_GetWindowSize,(SDL_Window *a, int *b, int *c),(a,b,c),re
|
|||
SDL_DYNAPI_PROC(int,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetWindowTitle,(SDL_Window *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionMode,(void),(),return)
|
||||
SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionModeForResolution,(int a, int b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_CloseHaptic,(SDL_Haptic *a),(a),)
|
||||
SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_HapticEffectSupported,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return)
|
||||
|
@ -659,7 +657,6 @@ SDL_DYNAPI_PROC(int,SDL_SetWindowPosition,(SDL_Window *a, int b, int c),(a,b,c),
|
|||
SDL_DYNAPI_PROC(int,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowSize,(SDL_Window *a, int b, int c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowTitle,(SDL_Window *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_SetYUVConversionMode,(SDL_YUV_CONVERSION_MODE a),(a),)
|
||||
SDL_DYNAPI_PROC(int,SDL_ShowCursor,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ShowMessageBox,(const SDL_MessageBoxData *a, int *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ShowSimpleMessageBox,(Uint32 a, const char *b, const char *c, SDL_Window *d),(a,b,c,d),return)
|
||||
|
|
|
@ -944,17 +944,19 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, LPDIREC
|
|||
}
|
||||
#if SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
*shader = data->shaders[SHADER_YUV_JPEG];
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
*shader = data->shaders[SHADER_YUV_BT601];
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
*shader = data->shaders[SHADER_YUV_BT709];
|
||||
break;
|
||||
default:
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
*shader = data->shaders[SHADER_YUV_BT601];
|
||||
} else {
|
||||
*shader = data->shaders[SHADER_YUV_JPEG];
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
*shader = data->shaders[SHADER_YUV_BT709];
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
|
||||
|
|
|
@ -2151,17 +2151,19 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
};
|
||||
D3D11_Shader shader;
|
||||
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
shader = SHADER_YUV_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
shader = SHADER_YUV_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
shader = SHADER_YUV_BT709;
|
||||
break;
|
||||
default:
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = SHADER_YUV_BT601;
|
||||
} else {
|
||||
shader = SHADER_YUV_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = SHADER_YUV_BT709;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
|
||||
|
@ -2175,17 +2177,19 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
};
|
||||
D3D11_Shader shader;
|
||||
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
|
||||
break;
|
||||
default:
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
|
||||
} else {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
|
||||
|
|
|
@ -2589,17 +2589,19 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
};
|
||||
D3D12_Shader shader;
|
||||
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
shader = SHADER_YUV_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
shader = SHADER_YUV_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
shader = SHADER_YUV_BT709;
|
||||
break;
|
||||
default:
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = SHADER_YUV_BT601;
|
||||
} else {
|
||||
shader = SHADER_YUV_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = SHADER_YUV_BT709;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
|
||||
|
@ -2620,17 +2622,19 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
};
|
||||
D3D12_Shader shader;
|
||||
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
|
||||
break;
|
||||
default:
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601;
|
||||
} else {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
|
||||
|
|
|
@ -638,20 +638,20 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
#if SDL_HAVE_YUV
|
||||
if (yuv || nv12) {
|
||||
size_t offset = 0;
|
||||
SDL_YUV_CONVERSION_MODE mode = SDL_GetYUVConversionModeForResolution(texture->w, texture->h);
|
||||
switch (mode) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
offset = CONSTANTS_OFFSET_DECODE_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
offset = CONSTANTS_OFFSET_DECODE_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
offset = CONSTANTS_OFFSET_DECODE_BT709;
|
||||
break;
|
||||
default:
|
||||
offset = 0;
|
||||
break;
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
offset = CONSTANTS_OFFSET_DECODE_BT601;
|
||||
} else {
|
||||
offset = CONSTANTS_OFFSET_DECODE_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
offset = CONSTANTS_OFFSET_DECODE_BT709;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
texturedata.conversionBufferOffset = offset;
|
||||
}
|
||||
|
@ -1723,10 +1723,10 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
|||
};
|
||||
|
||||
float decodetransformBT709[4 * 4] = {
|
||||
0.0, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.0000, 0.0000, 1.4020, 0.0, /* Rcoeff */
|
||||
1.0000, -0.3441, -0.7141, 0.0, /* Gcoeff */
|
||||
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
|
||||
-0.0627451017, -0.501960814, -0.501960814, 0.0, /* offset */
|
||||
1.1644, 0.0000, 1.7927, 0.0, /* Rcoeff */
|
||||
1.1644, -0.2132, -0.5329, 0.0, /* Gcoeff */
|
||||
1.1644, 2.1124, 0.0000, 0.0, /* Bcoeff */
|
||||
};
|
||||
|
||||
if (!IsMetalAvailable()) {
|
||||
|
|
|
@ -662,45 +662,46 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
|
|||
|
||||
#if SDL_HAVE_YUV
|
||||
if (data->yuv || data->nv12) {
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_JPEG;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
data->shader = SHADER_NV12_JPEG;
|
||||
} else {
|
||||
data->shader = SHADER_NV21_JPEG;
|
||||
}
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_BT601;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
data->shader = SHADER_NV12_RG_BT601;
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_BT601;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
data->shader = SHADER_NV12_RG_BT601;
|
||||
} else {
|
||||
data->shader = SHADER_NV12_RA_BT601;
|
||||
}
|
||||
} else {
|
||||
data->shader = SHADER_NV12_RA_BT601;
|
||||
data->shader = SHADER_NV21_BT601;
|
||||
}
|
||||
} else {
|
||||
data->shader = SHADER_NV21_BT601;
|
||||
}
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_BT709;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
data->shader = SHADER_NV12_RG_BT709;
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_JPEG;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
data->shader = SHADER_NV12_JPEG;
|
||||
} else {
|
||||
data->shader = SHADER_NV12_RA_BT709;
|
||||
data->shader = SHADER_NV21_JPEG;
|
||||
}
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
if (data->yuv) {
|
||||
data->shader = SHADER_YUV_BT709;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
data->shader = SHADER_NV12_RG_BT709;
|
||||
} else {
|
||||
data->shader = SHADER_NV12_RA_BT709;
|
||||
}
|
||||
} else {
|
||||
data->shader = SHADER_NV21_BT709;
|
||||
}
|
||||
} else {
|
||||
data->shader = SHADER_NV21_BT709;
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SDL_assert(!"unsupported YUV conversion mode");
|
||||
break;
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV conversion mode");
|
||||
}
|
||||
}
|
||||
#endif /* SDL_HAVE_YUV */
|
||||
|
|
|
@ -588,7 +588,7 @@ static int GLES2_CacheShaders(GLES2_RenderData *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h)
|
||||
static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, SDL_Colorspace colorspace)
|
||||
{
|
||||
GLuint vertex;
|
||||
GLuint fragment;
|
||||
|
@ -615,58 +615,67 @@ static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source,
|
|||
break;
|
||||
#if SDL_HAVE_YUV
|
||||
case GLES2_IMAGESOURCE_TEXTURE_YUV:
|
||||
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601;
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709;
|
||||
} else {
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
break;
|
||||
case GLES2_IMAGESOURCE_TEXTURE_NV12:
|
||||
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601;
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601;
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601;
|
||||
}
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601;
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG;
|
||||
}
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709;
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709;
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709;
|
||||
}
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709;
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
|
||||
} else {
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
break;
|
||||
case GLES2_IMAGESOURCE_TEXTURE_NV21:
|
||||
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601;
|
||||
} else {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709;
|
||||
} else {
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Unsupported YUV conversion mode");
|
||||
goto fault;
|
||||
}
|
||||
break;
|
||||
|
@ -961,7 +970,7 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co
|
|||
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
|
||||
}
|
||||
|
||||
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
|
||||
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->colorspace : SDL_COLORSPACE_SRGB) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -341,17 +341,20 @@ static void VITA_GXM_SetYUVProfile(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
{
|
||||
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata;
|
||||
int ret = 0;
|
||||
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD);
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD);
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
default:
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV profile: %d\n", SDL_GetYUVConversionModeForResolution(texture->w, texture->h));
|
||||
break;
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD);
|
||||
} else {
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_FULL_RANGE);
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD);
|
||||
} else {
|
||||
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_FULL_RANGE);
|
||||
}
|
||||
} else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV conversion mode\n");
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -695,7 +695,7 @@ void SDL_DestroyPixelFormat(SDL_PixelFormat *format)
|
|||
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 format)
|
||||
{
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||
return SDL_COLORSPACE_BT709_FULL;
|
||||
return SDL_COLORSPACE_YUV_DEFAULT;
|
||||
} else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||
return SDL_COLORSPACE_SCRGB;
|
||||
} else if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
||||
|
|
|
@ -1567,13 +1567,20 @@ int SDL_ConvertPixelsAndColorspace(int width, int height,
|
|||
return SDL_InvalidParamError("dst_pitch");
|
||||
}
|
||||
|
||||
if (src_colorspace == SDL_COLORSPACE_UNKNOWN) {
|
||||
src_colorspace = SDL_GetDefaultColorspaceForFormat(src_format);
|
||||
}
|
||||
if (dst_colorspace == SDL_COLORSPACE_UNKNOWN) {
|
||||
dst_colorspace = SDL_GetDefaultColorspaceForFormat(dst_format);
|
||||
}
|
||||
|
||||
#if SDL_HAVE_YUV
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
|
||||
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
||||
} else if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
||||
return SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
|
||||
return SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
||||
} else if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
|
||||
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
||||
}
|
||||
#else
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||
|
@ -1599,17 +1606,13 @@ int SDL_ConvertPixelsAndColorspace(int width, int height,
|
|||
&src_surface, &src_fmt, &src_blitmap)) {
|
||||
return -1;
|
||||
}
|
||||
if (src_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&src_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, src_colorspace);
|
||||
}
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&src_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, src_colorspace);
|
||||
|
||||
if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst, dst_pitch,
|
||||
&dst_surface, &dst_fmt, &dst_blitmap)) {
|
||||
return -1;
|
||||
}
|
||||
if (dst_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&dst_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, dst_colorspace);
|
||||
}
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&dst_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, dst_colorspace);
|
||||
|
||||
/* Set up the rect and go! */
|
||||
rect.x = 0;
|
||||
|
|
|
@ -25,37 +25,11 @@
|
|||
|
||||
#include "yuv2rgb/yuv_rgb.h"
|
||||
|
||||
#define SDL_YUV_SD_THRESHOLD 576
|
||||
|
||||
static SDL_YUV_CONVERSION_MODE SDL_YUV_ConversionMode = SDL_YUV_CONVERSION_BT601;
|
||||
|
||||
#if SDL_HAVE_YUV
|
||||
static SDL_bool IsPlanar2x2Format(Uint32 format);
|
||||
#endif
|
||||
|
||||
void SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode)
|
||||
{
|
||||
SDL_YUV_ConversionMode = mode;
|
||||
}
|
||||
|
||||
SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionMode(void)
|
||||
{
|
||||
return SDL_YUV_ConversionMode;
|
||||
}
|
||||
|
||||
SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionModeForResolution(int width, int height)
|
||||
{
|
||||
SDL_YUV_CONVERSION_MODE mode = SDL_GetYUVConversionMode();
|
||||
if (mode == SDL_YUV_CONVERSION_AUTOMATIC) {
|
||||
if (height <= SDL_YUV_SD_THRESHOLD) {
|
||||
mode = SDL_YUV_CONVERSION_BT601;
|
||||
} else {
|
||||
mode = SDL_YUV_CONVERSION_BT709;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate YUV size and pitch. Check for overflow.
|
||||
* Output 'pitch' that can be used with SDL_ConvertPixels()
|
||||
|
@ -185,20 +159,23 @@ int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitc
|
|||
|
||||
#if SDL_HAVE_YUV
|
||||
|
||||
static int GetYUVConversionType(int width, int height, YCbCrType *yuv_type)
|
||||
static int GetYUVConversionType(SDL_Colorspace colorspace, YCbCrType *yuv_type)
|
||||
{
|
||||
switch (SDL_GetYUVConversionModeForResolution(width, height)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
*yuv_type = YCBCR_JPEG;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
*yuv_type = YCBCR_601;
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
*yuv_type = YCBCR_709;
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unexpected YUV conversion mode");
|
||||
if (SDL_ISCOLORSPACE_YUV_BT601(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
*yuv_type = YCBCR_601;
|
||||
} else {
|
||||
*yuv_type = YCBCR_JPEG;
|
||||
}
|
||||
} else if (SDL_ISCOLORSPACE_YUV_BT709(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
*yuv_type = YCBCR_709;
|
||||
} else {
|
||||
/* BT709 full range isn't supported yet */
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
} else {
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -578,8 +555,8 @@ static SDL_bool yuv_rgb_std(
|
|||
}
|
||||
|
||||
int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
||||
Uint32 src_format, const void *src, int src_pitch,
|
||||
Uint32 dst_format, void *dst, int dst_pitch)
|
||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
||||
{
|
||||
const Uint8 *y = NULL;
|
||||
const Uint8 *u = NULL;
|
||||
|
@ -592,7 +569,7 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (GetYUVConversionType(width, height, &yuv_type) < 0) {
|
||||
if (GetYUVConversionType(src_colorspace, &yuv_type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -620,14 +597,14 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
|||
}
|
||||
|
||||
/* convert src/src_format to tmp/ARGB8888 */
|
||||
ret = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, tmp, tmp_pitch);
|
||||
ret = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, tmp, tmp_pitch);
|
||||
if (ret < 0) {
|
||||
SDL_free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* convert tmp/ARGB8888 to dst/RGB */
|
||||
ret = SDL_ConvertPixels(width, height, SDL_PIXELFORMAT_ARGB8888, tmp, tmp_pitch, dst_format, dst, dst_pitch);
|
||||
ret = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, tmp, tmp_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
||||
SDL_free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -643,7 +620,7 @@ struct RGB2YUVFactors
|
|||
float v[3]; /* Rfactor, Gfactor, Bfactor */
|
||||
};
|
||||
|
||||
static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch)
|
||||
static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *src, int src_pitch, Uint32 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;
|
||||
|
@ -652,7 +629,7 @@ static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *
|
|||
const int width_remainder = (width & 0x1);
|
||||
int i, j;
|
||||
|
||||
static struct RGB2YUVFactors RGB2YUVFactorTables[SDL_YUV_CONVERSION_BT709 + 1] = {
|
||||
static struct RGB2YUVFactors RGB2YUVFactorTables[] = {
|
||||
/* ITU-T T.871 (JPEG) */
|
||||
{
|
||||
0,
|
||||
|
@ -675,7 +652,7 @@ static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *
|
|||
{ 0.4392f, -0.3989f, -0.0403f },
|
||||
},
|
||||
};
|
||||
const struct RGB2YUVFactors *cvt = &RGB2YUVFactorTables[SDL_GetYUVConversionModeForResolution(width, height)];
|
||||
const struct RGB2YUVFactors *cvt = &RGB2YUVFactorTables[yuv_type];
|
||||
|
||||
#define MAKE_Y(r, g, b) (Uint8)((int)(cvt->y[0] * (r) + cvt->y[1] * (g) + cvt->y[2] * (b) + 0.5f) + cvt->y_offset)
|
||||
#define MAKE_U(r, g, b) (Uint8)((int)(cvt->u[0] * (r) + cvt->u[1] * (g) + cvt->u[2] * (b) + 0.5f) + 128)
|
||||
|
@ -958,9 +935,15 @@ static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *
|
|||
}
|
||||
|
||||
int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
||||
Uint32 src_format, const void *src, int src_pitch,
|
||||
Uint32 dst_format, void *dst, int dst_pitch)
|
||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
||||
{
|
||||
YCbCrType yuv_type = YCBCR_601;
|
||||
|
||||
if (GetYUVConversionType(dst_colorspace, &yuv_type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0 /* Doesn't handle odd widths */
|
||||
/* RGB24 to FOURCC */
|
||||
if (src_format == SDL_PIXELFORMAT_RGB24) {
|
||||
|
@ -969,16 +952,11 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
|||
Uint8 *v;
|
||||
Uint32 y_stride;
|
||||
Uint32 uv_stride;
|
||||
YCbCrType yuv_type;
|
||||
|
||||
if (GetYUVPlanes(width, height, dst_format, dst, dst_pitch, (const Uint8 **)&y, (const Uint8 **)&u, (const Uint8 **)&v, &y_stride, &uv_stride) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (GetYUVConversionType(width, height, &yuv_type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rgb24_yuv420_std(width, height, src, src_pitch, y, u, v, y_stride, uv_stride, yuv_type);
|
||||
return 0;
|
||||
}
|
||||
|
@ -986,7 +964,7 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
|||
|
||||
/* ARGB8888 to FOURCC */
|
||||
if (src_format == SDL_PIXELFORMAT_ARGB8888) {
|
||||
return SDL_ConvertPixels_ARGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst, dst_pitch);
|
||||
return SDL_ConvertPixels_ARGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
}
|
||||
|
||||
/* not ARGB8888 to FOURCC : need an intermediate conversion */
|
||||
|
@ -1008,7 +986,7 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
|||
}
|
||||
|
||||
/* convert tmp/ARGB8888 to dst/FOURCC */
|
||||
ret = SDL_ConvertPixels_ARGB8888_to_YUV(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch);
|
||||
ret = SDL_ConvertPixels_ARGB8888_to_YUV(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
SDL_free(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2345,10 +2323,14 @@ static int SDL_ConvertPixels_Packed4_to_Planar2x2(int width, int height,
|
|||
#endif /* SDL_HAVE_YUV */
|
||||
|
||||
int SDL_ConvertPixels_YUV_to_YUV(int width, int height,
|
||||
Uint32 src_format, const void *src, int src_pitch,
|
||||
Uint32 dst_format, void *dst, int dst_pitch)
|
||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
||||
{
|
||||
#if 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 */
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
|
||||
/* YUV conversion functions */
|
||||
|
||||
extern int SDL_ConvertPixels_YUV_to_RGB(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_YUV_to_RGB(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
||||
|
||||
|
||||
extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch);
|
||||
|
|
|
@ -397,18 +397,19 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV
|
|||
return context;
|
||||
}
|
||||
|
||||
static void SetYUVConversionMode(AVFrame *frame)
|
||||
static SDL_Colorspace GetFrameColorspace(AVFrame *frame)
|
||||
{
|
||||
SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC;
|
||||
SDL_Colorspace colorspace = SDL_COLORSPACE_SRGB;
|
||||
|
||||
if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) {
|
||||
if (frame->color_range == AVCOL_RANGE_JPEG)
|
||||
mode = SDL_YUV_CONVERSION_JPEG;
|
||||
else if (frame->colorspace == AVCOL_SPC_BT709)
|
||||
mode = SDL_YUV_CONVERSION_BT709;
|
||||
else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M)
|
||||
mode = SDL_YUV_CONVERSION_BT601;
|
||||
colorspace = SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR,
|
||||
frame->color_range,
|
||||
frame->color_primaries,
|
||||
frame->color_trc,
|
||||
frame->colorspace,
|
||||
frame->chroma_location);
|
||||
}
|
||||
SDL_SetYUVConversionMode(mode); /* FIXME: no support for linear transfer */
|
||||
return colorspace;
|
||||
}
|
||||
|
||||
static void SDLCALL FreeSwsContextContainer(void *userdata, void *value)
|
||||
|
@ -436,11 +437,18 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
SDL_DestroyTexture(*texture);
|
||||
}
|
||||
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame));
|
||||
if (frame_format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
*texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_ARGB8888);
|
||||
} else {
|
||||
*texture = SDL_CreateTexture(renderer, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, frame_format);
|
||||
}
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STREAMING);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, frame->width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, frame->height);
|
||||
*texture = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!*texture) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
@ -489,7 +497,6 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
|
||||
frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
|
||||
}
|
||||
SetYUVConversionMode(frame);
|
||||
break;
|
||||
default:
|
||||
if (frame->linesize[0] < 0) {
|
||||
|
@ -527,11 +534,16 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
} else {
|
||||
/* First time set up for NV12 textures */
|
||||
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
|
||||
|
||||
SetYUVConversionMode(frame);
|
||||
}
|
||||
|
||||
*texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, frame->width, frame->height);
|
||||
props = SDL_CreateProperties();
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame));
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_NV12);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, frame->width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, frame->height);
|
||||
*texture = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!*texture) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
@ -617,12 +629,16 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
|||
if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) {
|
||||
if (*texture) {
|
||||
SDL_DestroyTexture(*texture);
|
||||
} else {
|
||||
/* First time set up for NV12 textures */
|
||||
SetYUVConversionMode(frame);
|
||||
}
|
||||
|
||||
*texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, desc.Width, desc.Height);
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame));
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_NV12);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, desc.Width);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, desc.Height);
|
||||
*texture = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!*texture) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ static SDL_Surface *generate_test_pattern(int pattern_size)
|
|||
return pattern;
|
||||
}
|
||||
|
||||
static SDL_bool verify_yuv_data(Uint32 format, const Uint8 *yuv, int yuv_pitch, SDL_Surface *surface)
|
||||
static SDL_bool verify_yuv_data(Uint32 format, SDL_Colorspace colorspace, const Uint8 *yuv, int yuv_pitch, SDL_Surface *surface)
|
||||
{
|
||||
const int tolerance = 20;
|
||||
const int size = (surface->h * surface->pitch);
|
||||
|
@ -78,7 +78,7 @@ static SDL_bool verify_yuv_data(Uint32 format, const Uint8 *yuv, int yuv_pitch,
|
|||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (SDL_ConvertPixels(surface->w, surface->h, format, yuv, yuv_pitch, surface->format->format, rgb, surface->pitch) == 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, format, colorspace, yuv, yuv_pitch, surface->format->format, SDL_COLORSPACE_SRGB, rgb, surface->pitch) == 0) {
|
||||
int x, y;
|
||||
result = SDL_TRUE;
|
||||
for (y = 0; y < surface->h; ++y) {
|
||||
|
@ -116,12 +116,19 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
|||
SDL_PIXELFORMAT_UYVY,
|
||||
SDL_PIXELFORMAT_YVYU
|
||||
};
|
||||
const SDL_Colorspace colorspaces[] = {
|
||||
SDL_COLORSPACE_BT601_FULL,
|
||||
SDL_COLORSPACE_BT601_LIMITED,
|
||||
SDL_COLORSPACE_BT709_LIMITED
|
||||
};
|
||||
int i, j;
|
||||
SDL_Surface *pattern = generate_test_pattern(pattern_size);
|
||||
const int yuv_len = MAX_YUV_SURFACE_SIZE(pattern->w, pattern->h, extra_pitch);
|
||||
Uint8 *yuv1 = (Uint8 *)SDL_malloc(yuv_len);
|
||||
Uint8 *yuv2 = (Uint8 *)SDL_malloc(yuv_len);
|
||||
int yuv1_pitch, yuv2_pitch;
|
||||
YUV_CONVERSION_MODE mode;
|
||||
SDL_Colorspace colorspace;
|
||||
int result = -1;
|
||||
|
||||
if (!pattern || !yuv1 || !yuv2) {
|
||||
|
@ -129,14 +136,18 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
|||
goto done;
|
||||
}
|
||||
|
||||
mode = GetYUVConversionModeForResolution(pattern->w, pattern->h);
|
||||
SDL_assert(mode < SDL_arraysize(colorspaces));
|
||||
colorspace = colorspaces[mode];
|
||||
|
||||
/* Verify conversion from YUV formats */
|
||||
for (i = 0; i < SDL_arraysize(formats); ++i) {
|
||||
if (!ConvertRGBtoYUV(formats[i], pattern->pixels, pattern->pitch, yuv1, pattern->w, pattern->h, SDL_GetYUVConversionModeForResolution(pattern->w, pattern->h), 0, 100)) {
|
||||
if (!ConvertRGBtoYUV(formats[i], pattern->pixels, pattern->pitch, yuv1, pattern->w, pattern->h, mode, 0, 100)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ConvertRGBtoYUV() doesn't support converting to %s\n", SDL_GetPixelFormatName(formats[i]));
|
||||
goto done;
|
||||
}
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w);
|
||||
if (!verify_yuv_data(formats[i], yuv1, yuv1_pitch, pattern)) {
|
||||
if (!verify_yuv_data(formats[i], colorspace, yuv1, yuv1_pitch, pattern)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to RGB\n", SDL_GetPixelFormatName(formats[i]));
|
||||
goto done;
|
||||
}
|
||||
|
@ -145,11 +156,11 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
|||
/* Verify conversion to YUV formats */
|
||||
for (i = 0; i < SDL_arraysize(formats); ++i) {
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||
if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
||||
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());
|
||||
goto done;
|
||||
}
|
||||
if (!verify_yuv_data(formats[i], yuv1, yuv1_pitch, pattern)) {
|
||||
if (!verify_yuv_data(formats[i], colorspace, yuv1, yuv1_pitch, pattern)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from RGB to %s\n", SDL_GetPixelFormatName(formats[i]));
|
||||
goto done;
|
||||
}
|
||||
|
@ -160,15 +171,15 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
|||
for (j = 0; j < SDL_arraysize(formats); ++j) {
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||
if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
||||
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());
|
||||
goto done;
|
||||
}
|
||||
if (SDL_ConvertPixels(pattern->w, pattern->h, formats[i], yuv1, yuv1_pitch, formats[j], yuv2, yuv2_pitch) < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, yuv1, yuv1_pitch, formats[j], colorspace, yuv2, yuv2_pitch) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
||||
goto done;
|
||||
}
|
||||
if (!verify_yuv_data(formats[j], yuv2, yuv2_pitch, pattern)) {
|
||||
if (!verify_yuv_data(formats[j], colorspace, yuv2, yuv2_pitch, pattern)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
|
||||
goto done;
|
||||
}
|
||||
|
@ -185,15 +196,15 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
|||
|
||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||
if (SDL_ConvertPixels(pattern->w, pattern->h, pattern->format->format, pattern->pixels, pattern->pitch, formats[i], yuv1, yuv1_pitch) < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
||||
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());
|
||||
goto done;
|
||||
}
|
||||
if (SDL_ConvertPixels(pattern->w, pattern->h, formats[i], yuv1, yuv1_pitch, formats[j], yuv1, yuv2_pitch) < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, yuv1, yuv1_pitch, formats[j], colorspace, yuv1, yuv2_pitch) < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
||||
goto done;
|
||||
}
|
||||
if (!verify_yuv_data(formats[j], yuv1, yuv2_pitch, pattern)) {
|
||||
if (!verify_yuv_data(formats[j], colorspace, yuv1, yuv2_pitch, pattern)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed conversion from %s to %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]));
|
||||
goto done;
|
||||
}
|
||||
|
@ -277,16 +288,16 @@ int main(int argc, char **argv)
|
|||
consumed = SDLTest_CommonArg(state, i);
|
||||
if (!consumed) {
|
||||
if (SDL_strcmp(argv[i], "--jpeg") == 0) {
|
||||
SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_JPEG);
|
||||
SetYUVConversionMode(YUV_CONVERSION_JPEG);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--bt601") == 0) {
|
||||
SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT601);
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT601);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--bt709") == 0) {
|
||||
SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT709);
|
||||
SetYUVConversionMode(YUV_CONVERSION_BT709);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--auto") == 0) {
|
||||
SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_AUTOMATIC);
|
||||
SetYUVConversionMode(YUV_CONVERSION_AUTOMATIC);
|
||||
consumed = 1;
|
||||
} else if (SDL_strcmp(argv[i], "--yv12") == 0) {
|
||||
yuv_format = SDL_PIXELFORMAT_YV12;
|
||||
|
@ -379,7 +390,7 @@ int main(int argc, char **argv)
|
|||
|
||||
raw_yuv = SDL_calloc(1, MAX_YUV_SURFACE_SIZE(original->w, original->h, 0));
|
||||
ConvertRGBtoYUV(yuv_format, original->pixels, original->pitch, raw_yuv, original->w, original->h,
|
||||
SDL_GetYUVConversionModeForResolution(original->w, original->h),
|
||||
GetYUVConversionModeForResolution(original->w, original->h),
|
||||
0, 100);
|
||||
pitch = CalculateYUVPitch(yuv_format, original->w);
|
||||
|
||||
|
@ -422,14 +433,14 @@ int main(int argc, char **argv)
|
|||
yuv_name += 16;
|
||||
}
|
||||
|
||||
switch (SDL_GetYUVConversionModeForResolution(original->w, original->h)) {
|
||||
case SDL_YUV_CONVERSION_JPEG:
|
||||
switch (GetYUVConversionModeForResolution(original->w, original->h)) {
|
||||
case YUV_CONVERSION_JPEG:
|
||||
yuv_mode = "JPEG";
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT601:
|
||||
case YUV_CONVERSION_BT601:
|
||||
yuv_mode = "BT.601";
|
||||
break;
|
||||
case SDL_YUV_CONVERSION_BT709:
|
||||
case YUV_CONVERSION_BT709:
|
||||
yuv_mode = "BT.709";
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -14,14 +14,41 @@
|
|||
|
||||
#include "testyuv_cvt.h"
|
||||
|
||||
#define YUV_SD_THRESHOLD 576
|
||||
|
||||
static YUV_CONVERSION_MODE YUV_ConversionMode = YUV_CONVERSION_BT601;
|
||||
|
||||
void SetYUVConversionMode(YUV_CONVERSION_MODE mode)
|
||||
{
|
||||
YUV_ConversionMode = mode;
|
||||
}
|
||||
|
||||
YUV_CONVERSION_MODE GetYUVConversionMode(void)
|
||||
{
|
||||
return YUV_ConversionMode;
|
||||
}
|
||||
|
||||
YUV_CONVERSION_MODE GetYUVConversionModeForResolution(int width, int height)
|
||||
{
|
||||
YUV_CONVERSION_MODE mode = GetYUVConversionMode();
|
||||
if (mode == YUV_CONVERSION_AUTOMATIC) {
|
||||
if (height <= YUV_SD_THRESHOLD) {
|
||||
mode = YUV_CONVERSION_BT601;
|
||||
} else {
|
||||
mode = YUV_CONVERSION_BT709;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
static float clip3(float x, float y, float z)
|
||||
{
|
||||
return (z < x) ? x : ((z > y) ? y : z);
|
||||
}
|
||||
|
||||
static void RGBtoYUV(const Uint8 *rgb, int *yuv, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
static void RGBtoYUV(const Uint8 *rgb, int *yuv, YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
{
|
||||
if (mode == SDL_YUV_CONVERSION_JPEG) {
|
||||
if (mode == YUV_CONVERSION_JPEG) {
|
||||
/* Full range YUV */
|
||||
yuv[0] = (int)(0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]);
|
||||
yuv[1] = (int)((rgb[2] - yuv[0]) * 0.565 + 128);
|
||||
|
@ -37,7 +64,7 @@ static void RGBtoYUV(const Uint8 *rgb, int *yuv, SDL_YUV_CONVERSION_MODE mode, i
|
|||
*/
|
||||
float S, Z, R, G, B, L, Kr, Kb, Y, U, V;
|
||||
|
||||
if (mode == SDL_YUV_CONVERSION_BT709) {
|
||||
if (mode == YUV_CONVERSION_BT709) {
|
||||
/* BT.709 */
|
||||
Kr = 0.2126f;
|
||||
Kb = 0.0722f;
|
||||
|
@ -75,7 +102,7 @@ static void RGBtoYUV(const Uint8 *rgb, int *yuv, SDL_YUV_CONVERSION_MODE mode, i
|
|||
}
|
||||
}
|
||||
|
||||
static void ConvertRGBtoPlanar2x2(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
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;
|
||||
int yuv[4][3];
|
||||
|
@ -191,7 +218,7 @@ static void ConvertRGBtoPlanar2x2(Uint32 format, Uint8 *src, int pitch, Uint8 *o
|
|||
}
|
||||
}
|
||||
|
||||
static void ConvertRGBtoPacked4(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
static void ConvertRGBtoPacked4(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[2][3];
|
||||
|
@ -261,7 +288,7 @@ static void ConvertRGBtoPacked4(Uint32 format, Uint8 *src, int pitch, Uint8 *out
|
|||
}
|
||||
}
|
||||
|
||||
SDL_bool ConvertRGBtoYUV(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance)
|
||||
SDL_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_YV12:
|
||||
|
|
|
@ -12,5 +12,15 @@
|
|||
|
||||
/* These functions are designed for testing correctness, not for speed */
|
||||
|
||||
extern SDL_bool ConvertRGBtoYUV(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, SDL_YUV_CONVERSION_MODE mode, int monochrome, int luminance);
|
||||
typedef enum
|
||||
{
|
||||
YUV_CONVERSION_JPEG, /**< Full range JPEG */
|
||||
YUV_CONVERSION_BT601, /**< BT.601 (the default) */
|
||||
YUV_CONVERSION_BT709, /**< BT.709 */
|
||||
YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */
|
||||
} YUV_CONVERSION_MODE;
|
||||
|
||||
extern void SetYUVConversionMode(YUV_CONVERSION_MODE mode);
|
||||
extern YUV_CONVERSION_MODE GetYUVConversionModeForResolution(int width, int height);
|
||||
extern SDL_bool ConvertRGBtoYUV(Uint32 format, Uint8 *src, int pitch, Uint8 *out, int w, int h, YUV_CONVERSION_MODE mode, int monochrome, int luminance);
|
||||
extern int CalculateYUVPitch(Uint32 format, int width);
|
||||
|
|
Loading…
Reference in New Issue