From 114074bfd8417670acd41a95657051eb62dad670 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 31 Dec 2023 15:15:06 -0600 Subject: [PATCH] Don't set HDR metadata on the DXGI swapchain This is no longer recommended by Microsoft due inconsistencies with display support for HDR metadata. --- .../video/ffmpeg-renderers/d3d11va.cpp | 101 +++++------------- .../video/ffmpeg-renderers/d3d11va.h | 3 +- 2 files changed, 28 insertions(+), 76 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp index 49b4a89c..e9825edf 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp @@ -82,6 +82,7 @@ D3D11VARenderer::D3D11VARenderer(int decoderSelectionPass) m_RenderTargetView(nullptr), m_LastColorSpace(-1), m_LastFullRange(false), + m_LastColorTrc(AVCOL_TRC_UNSPECIFIED), m_AllowTearing(false), m_VideoGenericPixelShader(nullptr), m_VideoBt601LimPixelShader(nullptr), @@ -467,79 +468,6 @@ bool D3D11VARenderer::prepareDecoderContext(AVCodecContext* context, AVDictionar return true; } -void D3D11VARenderer::setHdrMode(bool enabled) -{ - HRESULT hr; - - // According to MSDN, we need to lock the context even if we're just using DXGI functions - // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-render-multi-thread-intro - lockContext(this); - - if (enabled) { - DXGI_HDR_METADATA_HDR10 hdr10Metadata; - SS_HDR_METADATA sunshineHdrMetadata; - - // Sunshine will have HDR metadata but GFE will not - if (!LiGetHdrMetadata(&sunshineHdrMetadata)) { - RtlZeroMemory(&sunshineHdrMetadata, sizeof(sunshineHdrMetadata)); - } - - hdr10Metadata.RedPrimary[0] = sunshineHdrMetadata.displayPrimaries[0].x; - hdr10Metadata.RedPrimary[1] = sunshineHdrMetadata.displayPrimaries[0].y; - hdr10Metadata.GreenPrimary[0] = sunshineHdrMetadata.displayPrimaries[1].x; - hdr10Metadata.GreenPrimary[1] = sunshineHdrMetadata.displayPrimaries[1].y; - hdr10Metadata.BluePrimary[0] = sunshineHdrMetadata.displayPrimaries[2].x; - hdr10Metadata.BluePrimary[1] = sunshineHdrMetadata.displayPrimaries[2].y; - hdr10Metadata.WhitePoint[0] = sunshineHdrMetadata.whitePoint.x; - hdr10Metadata.WhitePoint[1] = sunshineHdrMetadata.whitePoint.y; - hdr10Metadata.MaxMasteringLuminance = sunshineHdrMetadata.maxDisplayLuminance; - hdr10Metadata.MinMasteringLuminance = sunshineHdrMetadata.minDisplayLuminance; - hdr10Metadata.MaxContentLightLevel = sunshineHdrMetadata.maxContentLightLevel; - hdr10Metadata.MaxFrameAverageLightLevel = sunshineHdrMetadata.maxFrameAverageLightLevel; - - hr = m_SwapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(hdr10Metadata), &hdr10Metadata); - if (SUCCEEDED(hr)) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Set display HDR mode: enabled"); - } - else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to enter HDR mode: %x", - hr); - } - - // Switch to Rec 2020 PQ (SMPTE ST 2084) colorspace for HDR10 rendering - hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); - if (FAILED(hr)) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) failed: %x", - hr); - } - } - else { - // Restore default sRGB colorspace - hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709); - if (FAILED(hr)) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) failed: %x", - hr); - } - - hr = m_SwapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_NONE, 0, nullptr); - if (SUCCEEDED(hr)) { - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Set display HDR mode: disabled"); - } - else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to exit HDR mode: %x", - hr); - } - } - - unlockContext(this); -} - void D3D11VARenderer::renderFrame(AVFrame* frame) { // Acquire the context lock for rendering to prevent concurrent @@ -578,8 +506,33 @@ void D3D11VARenderer::renderFrame(AVFrame* frame) flags = 0; } + HRESULT hr; + + if (frame->color_trc != m_LastColorTrc) { + if (frame->color_trc == AVCOL_TRC_SMPTE2084) { + // Switch to Rec 2020 PQ (SMPTE ST 2084) colorspace for HDR10 rendering + hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); + if (FAILED(hr)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) failed: %x", + hr); + } + } + else { + // Restore default sRGB colorspace + hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709); + if (FAILED(hr)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) failed: %x", + hr); + } + } + + m_LastColorTrc = frame->color_trc; + } + // Present according to the decoder parameters - HRESULT hr = m_SwapChain->Present(0, flags); + hr = m_SwapChain->Present(0, flags); // Release the context lock unlockContext(this); diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.h b/app/streaming/video/ffmpeg-renderers/d3d11va.h index 3c05d0d8..8421fdb4 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.h +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.h @@ -1,7 +1,6 @@ #pragma once #include "renderer.h" -#include "pacer/pacer.h" #include #include @@ -19,7 +18,6 @@ public: virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary**) override; virtual void renderFrame(AVFrame* frame) override; virtual void notifyOverlayUpdated(Overlay::OverlayType) override; - virtual void setHdrMode(bool enabled) override; virtual int getRendererAttributes() override; virtual int getDecoderCapabilities() override; virtual bool needsTestFrame() override; @@ -50,6 +48,7 @@ private: int m_DisplayHeight; int m_LastColorSpace; bool m_LastFullRange; + AVColorTransferCharacteristic m_LastColorTrc; bool m_AllowTearing;