diff options
author | CrystalP <crystalp@kodi.tv> | 2023-10-17 13:05:12 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-17 13:05:12 -0400 |
commit | 90b8fcf797e578f1d0cbbbfd7898e7ba1839c16b (patch) | |
tree | a1e827fbf08342760257890a65433b53cece1091 | |
parent | 259a6ee947b862a6f167881fb6595b0cc199d0cb (diff) | |
parent | c28972ed9114c60cc33df399d71fc33132e1d97a (diff) | |
download | xbmc-90b8fcf797e578f1d0cbbbfd7898e7ba1839c16b.tar.xz |
Merge pull request #23078 from CrystalP/fix-tonemapping
[rendering] use default luminance for tone mapping of streams with bad metadata, share with all platforms
9 files changed, 104 insertions, 110 deletions
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt index 76f18f0f20..5bb02199e7 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt @@ -6,15 +6,19 @@ set(HEADERS ConvolutionKernels.h if(CORE_SYSTEM_NAME STREQUAL windows OR CORE_SYSTEM_NAME STREQUAL windowsstore) list(APPEND SOURCES ConversionMatrix.cpp + ToneMappers.cpp WinVideoFilter.cpp) list(APPEND HEADERS ConversionMatrix.h + ToneMappers.h WinVideoFilter.h) endif() if(TARGET OpenGL::GL OR TARGET OpenGL::GLES) - list(APPEND SOURCES ConversionMatrix.cpp) - list(APPEND HEADERS ConversionMatrix.h) + list(APPEND SOURCES ConversionMatrix.cpp + ToneMappers.cpp) + list(APPEND HEADERS ConversionMatrix.h + ToneMappers.h) endif() if(TARGET OpenGL::GL) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.cpp new file mode 100644 index 0000000000..f98cd71c01 --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * See LICENSES/README.md for more information. + */ + +#include "ToneMappers.h" + +float CToneMappers::GetLuminanceValue(bool hasDisplayMetadata, + const AVMasteringDisplayMetadata& displayMetadata, + bool hasLightMetadata, + const AVContentLightMetadata& lightMetadata) +{ + // default for bad quality HDR-PQ sources (missing or invalid metadata) + const float defaultLuminance = 400.0f; + float lum1 = defaultLuminance; + + unsigned int maxLuminance = static_cast<unsigned int>(defaultLuminance); + + if (hasDisplayMetadata && displayMetadata.has_luminance && displayMetadata.max_luminance.den) + { + const uint16_t lum = displayMetadata.max_luminance.num / displayMetadata.max_luminance.den; + + if (lum > 0) + maxLuminance = lum; + } + + if (hasLightMetadata) + { + float lum2; + + if (lightMetadata.MaxCLL >= maxLuminance) + { + lum1 = static_cast<float>(maxLuminance); + lum2 = static_cast<float>(lightMetadata.MaxCLL); + } + else + { + lum1 = static_cast<float>(lightMetadata.MaxCLL); + lum2 = static_cast<float>(maxLuminance); + } + const float lum3 = static_cast<float>(lightMetadata.MaxFALL); + + lum1 = (lum1 * 0.5f) + (lum2 * 0.2f) + (lum3 * 0.3f); + } + else if (hasDisplayMetadata && displayMetadata.has_luminance) + { + lum1 = static_cast<float>(maxLuminance); + } + + return lum1; +} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.h new file mode 100644 index 0000000000..0d668838cb --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/ToneMappers.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +extern "C" +{ +#include <libavutil/mastering_display_metadata.h> +} + +class CToneMappers +{ +public: + static float GetLuminanceValue(bool hasDisplayMetadata, + const AVMasteringDisplayMetadata& displayMetadata, + bool hasLightMetadata, + const AVContentLightMetadata& lightMetadata); +}; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp index 83f146b248..e68976ca9c 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp @@ -9,6 +9,7 @@ #include "WinVideoFilter.h" #include "ConvolutionKernels.h" +#include "ToneMappers.h" #include "Util.h" #include "VideoRenderers/windows/RendererBase.h" #include "cores/VideoPlayer/VideoRenderers/VideoShaders/dither.h" @@ -206,53 +207,24 @@ void COutputShader::ApplyEffectParameters(CD3DEffect &effect, unsigned sourceWid } else if (m_toneMapping && m_toneMappingMethod == VS_TONEMAPMETHOD_ACES) { - float lumin = GetLuminanceValue(); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); effect.SetScalar("g_luminance", lumin); effect.SetScalar("g_toneP1", m_toneMappingParam); m_toneMappingDebug = lumin; } else if (m_toneMapping && m_toneMappingMethod == VS_TONEMAPMETHOD_HABLE) { - float lumin = GetLuminanceValue(); - float lumin_factor = (10000.0f / lumin) * (2.0f / m_toneMappingParam); - float lumin_div100 = lumin / (100.0f * m_toneMappingParam); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); + const float lumin_factor = (10000.0f / lumin) * (2.0f / m_toneMappingParam); + const float lumin_div100 = lumin / (100.0f * m_toneMappingParam); effect.SetScalar("g_toneP1", lumin_factor); effect.SetScalar("g_toneP2", lumin_div100); m_toneMappingDebug = lumin; } } -float COutputShader::GetLuminanceValue() const -{ - float lum1 = 400.0f; // default for bad quality HDR-PQ sources (with no metadata) - float lum2 = lum1; - float lum3 = lum1; - - if (m_hasLightMetadata) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - if (m_lightMetadata.MaxCLL >= lum) - { - lum1 = static_cast<float>(lum); - lum2 = static_cast<float>(m_lightMetadata.MaxCLL); - } - else - { - lum1 = static_cast<float>(m_lightMetadata.MaxCLL); - lum2 = static_cast<float>(lum); - } - lum3 = static_cast<float>(m_lightMetadata.MaxFALL); - lum1 = (lum1 * 0.5f) + (lum2 * 0.2f) + (lum3 * 0.3f); - } - else if (m_hasDisplayMetadata && m_displayMetadata.has_luminance) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - lum1 = static_cast<float>(lum); - } - - return lum1; -} - void COutputShader::GetDefines(DefinesMap& map) const { if (m_useLut) diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h index de901afcc1..d559dda519 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h @@ -91,7 +91,6 @@ private: void PrepareParameters(unsigned sourceWidth, unsigned sourceHeight, CRect sourceRect, const CPoint points[4]); void SetShaderParameters(CD3DTexture &sourceTexture, unsigned range, float contrast, float brightness); void CreateDitherView(); - float GetLuminanceValue() const; bool m_useLut = false; bool m_useDithering = false; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp index 4491ad2464..e9ff471f3d 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp @@ -12,6 +12,7 @@ #include "../RenderFlags.h" #include "ConvolutionKernels.h" #include "ServiceBroker.h" +#include "ToneMappers.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include "utils/GLUtils.h" @@ -192,13 +193,16 @@ bool BaseYUV2RGBGLSLShader::OnEnabled() } else if (m_toneMappingMethod == VS_TONEMAPMETHOD_ACES) { - glUniform1f(m_hLuminance, GetLuminanceValue()); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); + glUniform1f(m_hLuminance, lumin); glUniform1f(m_hToneP1, m_toneMappingParam); } else if (m_toneMappingMethod == VS_TONEMAPMETHOD_HABLE) { - float lumin = GetLuminanceValue(); - float param = (10000.0f / lumin) * (2.0f / m_toneMappingParam); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); + const float param = (10000.0f / lumin) * (2.0f / m_toneMappingParam); glUniform1f(m_hLuminance, lumin); glUniform1f(m_hToneP1, param); } @@ -256,38 +260,6 @@ void BaseYUV2RGBGLSLShader::SetToneMapParam(ETONEMAPMETHOD method, float param) m_toneMappingParam = param; } -float BaseYUV2RGBGLSLShader::GetLuminanceValue() const //Maybe move this to linuxrenderer?! same as in baserenderer -{ - float lum1 = 400.0f; // default for bad quality HDR-PQ sources (with no metadata) - float lum2 = lum1; - float lum3 = lum1; - - if (m_hasLightMetadata) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - if (m_lightMetadata.MaxCLL >= lum) - { - lum1 = static_cast<float>(lum); - lum2 = static_cast<float>(m_lightMetadata.MaxCLL); - } - else - { - lum1 = static_cast<float>(m_lightMetadata.MaxCLL); - lum2 = static_cast<float>(lum); - } - lum3 = static_cast<float>(m_lightMetadata.MaxFALL); - lum1 = (lum1 * 0.5f) + (lum2 * 0.2f) + (lum3 * 0.3f); - } - else if (m_hasDisplayMetadata && m_displayMetadata.has_luminance && - m_displayMetadata.max_luminance.num) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - lum1 = static_cast<float>(lum); - } - - return lum1; -} - ////////////////////////////////////////////////////////////////////// // YUV2RGBProgressiveShader - YUV2RGB with no deinterlacing // Use for weave deinterlacing / progressive diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h index 18e10faf91..6604291049 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h @@ -54,7 +54,6 @@ public: bool hasLightMetadata, AVContentLightMetadata lightMetadata); void SetToneMapParam(ETONEMAPMETHOD method, float param); - float GetLuminanceValue() const; void SetConvertFullColorRange(bool convertFullRange) { m_convertFullRange = convertFullRange; } diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.cpp index 4682a3db1a..63e4d304a4 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.cpp @@ -10,6 +10,7 @@ #include "YUV2RGBShaderGLES.h" #include "../RenderFlags.h" +#include "ToneMappers.h" #include "settings/AdvancedSettings.h" #include "utils/GLUtils.h" #include "utils/log.h" @@ -158,13 +159,16 @@ bool BaseYUV2RGBGLSLShader::OnEnabled() } else if (m_toneMappingMethod == VS_TONEMAPMETHOD_ACES) { - glUniform1f(m_hLuminance, GetLuminanceValue()); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); + glUniform1f(m_hLuminance, lumin); glUniform1f(m_hToneP1, m_toneMappingParam); } else if (m_toneMappingMethod == VS_TONEMAPMETHOD_HABLE) { - float lumin = GetLuminanceValue(); - float param = (10000.0f / lumin) * (2.0f / m_toneMappingParam); + const float lumin = CToneMappers::GetLuminanceValue(m_hasDisplayMetadata, m_displayMetadata, + m_hasLightMetadata, m_lightMetadata); + const float param = (10000.0f / lumin) * (2.0f / m_toneMappingParam); glUniform1f(m_hLuminance, lumin); glUniform1f(m_hToneP1, param); } @@ -211,38 +215,6 @@ void BaseYUV2RGBGLSLShader::SetDisplayMetadata(bool hasDisplayMetadata, m_lightMetadata = lightMetadata; } -float BaseYUV2RGBGLSLShader::GetLuminanceValue() const -{ - float lum1 = 400.0f; // default for bad quality HDR-PQ sources (with no metadata) - float lum2 = lum1; - float lum3 = lum1; - - if (m_hasLightMetadata) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - if (m_lightMetadata.MaxCLL >= lum) - { - lum1 = static_cast<float>(lum); - lum2 = static_cast<float>(m_lightMetadata.MaxCLL); - } - else - { - lum1 = static_cast<float>(m_lightMetadata.MaxCLL); - lum2 = static_cast<float>(lum); - } - lum3 = static_cast<float>(m_lightMetadata.MaxFALL); - lum1 = (lum1 * 0.5f) + (lum2 * 0.2f) + (lum3 * 0.3f); - } - else if (m_hasDisplayMetadata && m_displayMetadata.has_luminance && - m_displayMetadata.max_luminance.num > 0) - { - uint16_t lum = m_displayMetadata.max_luminance.num / m_displayMetadata.max_luminance.den; - lum1 = static_cast<float>(lum); - } - - return lum1; -} - ////////////////////////////////////////////////////////////////////// // YUV2RGBProgressiveShader - YUV2RGB with no deinterlacing // Use for weave deinterlacing / progressive diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h index df369f518f..44b1a8221a 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h @@ -45,7 +45,6 @@ class BaseYUV2RGBGLSLShader : public CGLSLShaderProgram bool hasLightMetadata, AVContentLightMetadata lightMetadata); void SetToneMapParam(float param) { m_toneMappingParam = param; } - float GetLuminanceValue() const; GLint GetVertexLoc() { return m_hVertex; } GLint GetYcoordLoc() { return m_hYcoord; } |