From 202886f87392fc3e964aae5a3ec99eed1d99acf7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 16 Feb 2024 20:05:11 -0800 Subject: [PATCH] Make use of the HDR light range when playing HDR video --- test/testffmpeg.c | 69 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/test/testffmpeg.c b/test/testffmpeg.c index d1b8e0901a..b5babd5386 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -99,28 +99,51 @@ static int done; /* This function isn't platform specific, but we haven't hooked up HDR video support on other platforms yet */ #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_APPLE) -static void GetDisplayHDRProperties(SDL_bool *HDR_display, float *SDR_white_level) +static void GetDisplayHDRProperties(SDL_bool *HDR_display, float *SDR_white_level, float *HDR_white_level) { SDL_PropertiesID props; + *HDR_display = SDL_FALSE; + *SDR_white_level = SDR_DISPLAY_WHITE_LEVEL; + *HDR_white_level = SDR_DISPLAY_WHITE_LEVEL; + props = SDL_GetRendererProperties(renderer); if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SCRGB) { /* We're not displaying in HDR, use the SDR white level */ - *HDR_display = SDL_FALSE; - *SDR_white_level = SDR_DISPLAY_WHITE_LEVEL; return; } props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window)); if (!SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE)) { /* HDR is not enabled on the display */ - *HDR_display = SDL_FALSE; - *SDR_white_level = SDR_DISPLAY_WHITE_LEVEL; return; } *HDR_display = SDL_TRUE; *SDR_white_level = SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT, DEFAULT_SDR_WHITE_LEVEL); + *HDR_white_level = SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT, DEFAULT_HDR_WHITE_LEVEL); +} + +static void UpdateVideoColorScale(SDL_bool HDR_video) +{ + SDL_bool HDR_display = SDL_FALSE; + float SDR_white_level, HDR_white_level, video_white_level; + + GetDisplayHDRProperties(&HDR_display, &SDR_white_level, &HDR_white_level); + + if (HDR_video) { + video_white_level = DEFAULT_HDR_WHITE_LEVEL; + } else { + video_white_level = SDR_DISPLAY_WHITE_LEVEL; + } + + if (HDR_display && HDR_video) { + /* Scale the HDR range of the video to the HDR range of the display */ + SDL_SetRenderColorScale(renderer, HDR_white_level / video_white_level); + } else { + /* Scale the range of the video to the SDR range of the display */ + SDL_SetRenderColorScale(renderer, SDR_white_level / video_white_level); + } } #endif /* SDL_PLATFORM_WIN32 || SDL_PLATFORM_APPLE */ @@ -675,10 +698,8 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) SDL_QueryTexture(*texture, NULL, NULL, &texture_width, &texture_height); } if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) { - float SDR_white_level, video_white_level; - SDL_bool HDR_display = SDL_FALSE; - SDL_bool HDR_video = SDL_FALSE; Uint32 format; + SDL_bool HDR_video = SDL_FALSE; switch (desc.Format) { case DXGI_FORMAT_NV12: @@ -701,8 +722,6 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) SDL_DestroyTexture(*texture); } - GetDisplayHDRProperties(&HDR_display, &SDR_white_level); - 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, format); @@ -715,16 +734,7 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) return SDL_FALSE; } - if (HDR_video != HDR_display) { - if (HDR_display) { - video_white_level = SDR_DISPLAY_WHITE_LEVEL; - } else { - video_white_level = DEFAULT_HDR_WHITE_LEVEL; - } - SDL_SetRenderColorScale(renderer, SDR_white_level / video_white_level); - } else { - SDL_SetRenderColorScale(renderer, 1.0f); - } + UpdateVideoColorScale(HDR_video); } ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, NULL); @@ -749,8 +759,6 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex size_t nPixelBufferHeight = CVPixelBufferGetHeightOfPlane(pPixelBuffer, 0); SDL_PropertiesID props; Uint32 format; - float SDR_white_level, video_white_level; - SDL_bool HDR_display = SDL_FALSE; SDL_bool HDR_video = SDL_FALSE; switch (nPixelBufferType) { @@ -778,8 +786,6 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex SDL_DestroyTexture(*texture); } - GetDisplayHDRProperties(&HDR_display, &SDR_white_level); - props = SDL_CreateProperties(); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); @@ -793,19 +799,8 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex return SDL_FALSE; } - if (HDR_video != HDR_display) { - if (HDR_display) { - video_white_level = SDR_DISPLAY_WHITE_LEVEL; - } else { - video_white_level = DEFAULT_HDR_WHITE_LEVEL; - } - SDL_SetRenderColorScale(renderer, SDR_white_level / video_white_level); - } else if (HDR_display) { - /* Apple platforms already scale up the brightness of content so we need to scale it down by the same amount for HDR video */ - SDL_SetRenderColorScale(renderer, SDR_white_level / DEFAULT_SDR_WHITE_LEVEL); - } else { - SDL_SetRenderColorScale(renderer, 1.0f); - } + UpdateVideoColorScale(HDR_video); + return SDL_TRUE; #else return SDL_FALSE;