From 8180d058c603e1fd419af8d8b7e3aa934d49229f Mon Sep 17 00:00:00 2001
From: thexai <58434170+thexai@users.noreply.github.com>
Date: Mon, 4 Jan 2021 00:51:57 +0100
Subject: [PATCH] [Windows] Add video, HDR metadata, shader and swapchain infos
to debug info OSD
---
system/keymaps/keyboard.xml | 1 +
.../DVDCodecs/Video/DVDVideoCodec.h | 2 +
.../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 2 +
xbmc/cores/VideoPlayer/VideoPlayer.cpp | 3 +
.../VideoPlayer/VideoRenderers/BaseRenderer.h | 4 +
.../VideoPlayer/VideoRenderers/CMakeLists.txt | 1 +
.../VideoPlayer/VideoRenderers/DebugInfo.h | 33 +++++++
.../VideoRenderers/DebugRenderer.cpp | 88 +++++++++++++++----
.../VideoRenderers/DebugRenderer.h | 10 ++-
.../VideoRenderers/RenderManager.cpp | 43 ++++++---
.../VideoRenderers/RenderManager.h | 2 +
.../VideoShaders/WinVideoFilter.cpp | 45 +++++++++-
.../VideoShaders/WinVideoFilter.h | 2 +
.../VideoRenderers/WinRenderer.cpp | 8 ++
.../VideoPlayer/VideoRenderers/WinRenderer.h | 3 +
.../VideoRenderers/windows/RendererBase.cpp | 80 +++++++++++++++++
.../VideoRenderers/windows/RendererBase.h | 6 +-
xbmc/input/actions/ActionIDs.h | 3 +
xbmc/input/actions/ActionTranslator.cpp | 1 +
xbmc/rendering/dx/DeviceResources.cpp | 38 ++++++++
xbmc/rendering/dx/DeviceResources.h | 4 +
xbmc/windowing/WinSystem.h | 4 +
xbmc/windowing/win10/WinSystemWin10DX.cpp | 5 ++
xbmc/windowing/win10/WinSystemWin10DX.h | 3 +
xbmc/windowing/windows/WinSystemWin32DX.cpp | 5 ++
xbmc/windowing/windows/WinSystemWin32DX.h | 3 +
26 files changed, 365 insertions(+), 34 deletions(-)
create mode 100644 xbmc/cores/VideoPlayer/VideoRenderers/DebugInfo.h
diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml
index 32d97bb2ae128..1c64413d7c16b 100644
--- a/system/keymaps/keyboard.xml
+++ b/system/keymaps/keyboard.xml
@@ -365,6 +365,7 @@
Info
PlayerProcessInfo
PlayerDebug
+ PlayerDebugVideo
AspectRatio
AspectRatio
ShowSubtitles
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
index a9c0e149f0423..708678cb59dca 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
@@ -68,6 +68,8 @@ struct VideoPicture
bool hasLightMetadata = false;
AVContentLightMetadata lightMetadata;
+ AVPixelFormat pixelFormat; //< source pixel format
+
unsigned int iWidth;
unsigned int iHeight;
unsigned int iDisplayWidth; //< width of the picture without black bars
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index ad6bbe118c3c4..1a98610eaa67d 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -969,6 +969,8 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(VideoPicture* pVideoPicture)
pVideoPicture->iFlags |= DVP_FLAG_DROPPED;
}
+ pVideoPicture->pixelFormat = m_pCodecContext->sw_pix_fmt;
+
pVideoPicture->chroma_position = m_pCodecContext->chroma_sample_location;
pVideoPicture->color_primaries = m_pCodecContext->color_primaries == AVCOL_PRI_UNSPECIFIED ? m_hints.colorPrimaries : m_pCodecContext->color_primaries;
pVideoPicture->color_transfer = m_pCodecContext->color_trc == AVCOL_TRC_UNSPECIFIED ? m_hints.colorTransferCharacteristic : m_pCodecContext->color_trc;
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 7b095623427a5..0823b1b41fadf 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -4340,6 +4340,9 @@ bool CVideoPlayer::OnAction(const CAction &action)
case ACTION_PLAYER_DEBUG:
m_renderManager.ToggleDebug();
break;
+ case ACTION_PLAYER_DEBUG_VIDEO:
+ m_renderManager.ToggleDebugVideo();
+ break;
case ACTION_PLAYER_PROCESS_INFO:
if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() != WINDOW_DIALOG_PLAYER_PROCESS_INFO)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
index 7f9864d26847c..6f3c60502835f 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
@@ -8,6 +8,7 @@
#pragma once
+#include "DebugInfo.h"
#include "RenderInfo.h"
#include "VideoShaders/ShaderFormats.h"
#include "cores/IPlayer.h"
@@ -92,6 +93,9 @@ class CBaseRenderer
void SetVideoSettings(const CVideoSettings &settings);
+ // Gets debug info from render buffer
+ virtual DEBUG_INFO_VIDEO GetDebugInfo(int idx) { return {}; };
+
protected:
void CalcNormalRenderRect(float offsetX, float offsetY, float width, float height,
float inputFrameRatio, float zoomAmount, float verticalShift);
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
index 3bc0cc7f65664..40aa37a9f6074 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
@@ -11,6 +11,7 @@ set(SOURCES BaseRenderer.cpp
set(HEADERS BaseRenderer.h
ColorManager.h
+ DebugInfo.h
OverlayRenderer.h
OverlayRendererGUI.h
OverlayRendererUtil.h
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/DebugInfo.h b/xbmc/cores/VideoPlayer/VideoRenderers/DebugInfo.h
new file mode 100644
index 0000000000000..d800c1a837a06
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/DebugInfo.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005-2021 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include
+
+struct DEBUG_INFO_PLAYER
+{
+ std::string audio;
+ std::string video;
+ std::string player;
+ std::string vsync;
+};
+
+struct DEBUG_INFO_VIDEO
+{
+ std::string videoSource;
+ std::string metaPrim;
+ std::string metaLight;
+ std::string shader;
+};
+
+struct DEBUG_INFO_RENDER
+{
+ std::string renderFlags;
+ std::string videoOutput;
+};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.cpp
index 86dc6e1453818..f04dfaf4031eb 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.cpp
@@ -17,7 +17,7 @@ using namespace OVERLAY;
CDebugRenderer::CDebugRenderer()
{
- for (int i=0; i<4; i++)
+ for (int i = 0; i < 6; i++)
{
m_overlay[i] = nullptr;
m_strDebug[i] = " ";
@@ -33,50 +33,105 @@ CDebugRenderer::~CDebugRenderer()
}
}
-void CDebugRenderer::SetInfo(std::string &info1, std::string &info2, std::string &info3, std::string &info4)
+void CDebugRenderer::SetInfo(DEBUG_INFO_PLAYER& info)
{
m_overlayRenderer.Release(0);
- if (info1 != m_strDebug[0])
+ if (info.audio != m_strDebug[0])
{
- m_strDebug[0] = info1;
+ m_strDebug[0] = info.audio;
if (m_overlay[0])
m_overlay[0]->Release();
m_overlay[0] = new CDVDOverlayText();
m_overlay[0]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[0]));
}
- if (info2 != m_strDebug[1])
+ if (info.video != m_strDebug[1])
{
- m_strDebug[1] = info2;
+ m_strDebug[1] = info.video;
if (m_overlay[1])
m_overlay[1]->Release();
m_overlay[1] = new CDVDOverlayText();
m_overlay[1]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[1]));
}
- if (info3 != m_strDebug[2])
+ if (info.player != m_strDebug[2])
{
- m_strDebug[2] = info3;
+ m_strDebug[2] = info.player;
if (m_overlay[2])
m_overlay[2]->Release();
m_overlay[2] = new CDVDOverlayText();
m_overlay[2]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[2]));
}
- if (info4 != m_strDebug[3])
+ if (info.vsync != m_strDebug[3])
{
- m_strDebug[3] = info4;
+ m_strDebug[3] = info.vsync;
if (m_overlay[3])
m_overlay[3]->Release();
m_overlay[3] = new CDVDOverlayText();
m_overlay[3]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[3]));
}
- m_overlayRenderer.AddOverlay(m_overlay[0], 0, 0);
- m_overlayRenderer.AddOverlay(m_overlay[1], 0, 0);
- m_overlayRenderer.AddOverlay(m_overlay[2], 0, 0);
- m_overlayRenderer.AddOverlay(m_overlay[3], 0, 0);
+ for (int i = 0; i < 4; i++)
+ m_overlayRenderer.AddOverlay(m_overlay[i], 0, 0);
}
-void CDebugRenderer::Render(CRect &src, CRect &dst, CRect &view)
+void CDebugRenderer::SetInfo(DEBUG_INFO_VIDEO& video, DEBUG_INFO_RENDER& render)
+{
+ m_overlayRenderer.Release(0);
+
+ if (video.videoSource != m_strDebug[0])
+ {
+ m_strDebug[0] = video.videoSource;
+ if (m_overlay[0])
+ m_overlay[0]->Release();
+ m_overlay[0] = new CDVDOverlayText();
+ m_overlay[0]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[0]));
+ }
+ if (video.metaPrim != m_strDebug[1])
+ {
+ m_strDebug[1] = video.metaPrim;
+ if (m_overlay[1])
+ m_overlay[1]->Release();
+ m_overlay[1] = new CDVDOverlayText();
+ m_overlay[1]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[1]));
+ }
+ if (video.metaLight != m_strDebug[2])
+ {
+ m_strDebug[2] = video.metaLight;
+ if (m_overlay[2])
+ m_overlay[2]->Release();
+ m_overlay[2] = new CDVDOverlayText();
+ m_overlay[2]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[2]));
+ }
+ if (video.shader != m_strDebug[3])
+ {
+ m_strDebug[3] = video.shader;
+ if (m_overlay[3])
+ m_overlay[3]->Release();
+ m_overlay[3] = new CDVDOverlayText();
+ m_overlay[3]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[3]));
+ }
+ if (render.renderFlags != m_strDebug[4])
+ {
+ m_strDebug[4] = render.renderFlags;
+ if (m_overlay[4])
+ m_overlay[4]->Release();
+ m_overlay[4] = new CDVDOverlayText();
+ m_overlay[4]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[4]));
+ }
+ if (render.videoOutput != m_strDebug[5])
+ {
+ m_strDebug[5] = render.videoOutput;
+ if (m_overlay[5])
+ m_overlay[5]->Release();
+ m_overlay[5] = new CDVDOverlayText();
+ m_overlay[5]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[5]));
+ }
+
+ for (int i = 0; i < 6; i++)
+ m_overlayRenderer.AddOverlay(m_overlay[i], 0, 0);
+}
+
+void CDebugRenderer::Render(CRect& src, CRect& dst, CRect& view)
{
m_overlayRenderer.SetVideoRect(src, dst, view);
m_overlayRenderer.Render(0);
@@ -110,7 +165,8 @@ void CDebugRenderer::CRenderer::Render(int idx)
COverlayText *text = dynamic_cast(o);
if (text)
- text->PrepareRender("arial.ttf", 1, 100, 16, 0, m_font, m_fontBorder, UTILS::COLOR::NONE, m_rv);
+ text->PrepareRender("arial.ttf", 1, 100, 15, 0, m_font, m_fontBorder, UTILS::COLOR::NONE,
+ m_rv);
RESOLUTION_INFO res = CServiceBroker::GetWinSystem()->GetGfxContext().GetResInfo(CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution());
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.h
index 4b32e1e5bfbda..cd87ae2a45404 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.h
@@ -8,6 +8,7 @@
#pragma once
+#include "DebugInfo.h"
#include "OverlayRenderer.h"
#include
@@ -19,8 +20,9 @@ class CDebugRenderer
public:
CDebugRenderer();
virtual ~CDebugRenderer();
- void SetInfo(std::string &info1, std::string &info2, std::string &info3, std::string &info4);
- void Render(CRect &src, CRect &dst, CRect &view);
+ void SetInfo(DEBUG_INFO_PLAYER& info);
+ void SetInfo(DEBUG_INFO_VIDEO& video, DEBUG_INFO_RENDER& render);
+ void Render(CRect& src, CRect& dst, CRect& view);
void Flush();
protected:
@@ -32,7 +34,7 @@ class CDebugRenderer
void Render(int idx) override;
};
- std::string m_strDebug[4];
- CDVDOverlayText *m_overlay[4];
+ std::string m_strDebug[6];
+ CDVDOverlayText* m_overlay[6];
CRenderer m_overlayRenderer;
};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
index 7cbaf7d0f154d..ee3963ddb3335 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
@@ -720,22 +720,33 @@ void CRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui)
if (m_renderDebug)
{
- std::string audio, video, player, vsync;
-
- m_playerPort->GetDebugInfo(audio, video, player);
+ if (m_renderDebugVideo)
+ {
+ DEBUG_INFO_VIDEO video = m_pRenderer->GetDebugInfo(m_presentsource);
+ DEBUG_INFO_RENDER render = CServiceBroker::GetWinSystem()->GetDebugInfo();
- double refreshrate, clockspeed;
- int missedvblanks;
- vsync = StringUtils::Format("VSyncOff: %.1f latency: %.3f ", m_clockSync.m_syncOffset / 1000, DVD_TIME_TO_MSEC(m_displayLatency) / 1000.0f);
- if (m_dvdClock.GetClockInfo(missedvblanks, clockspeed, refreshrate))
+ m_debugRenderer.SetInfo(video, render);
+ }
+ else
{
- vsync += StringUtils::Format("VSync: refresh:%.3f missed:%i speed:%.3f%%",
- refreshrate,
- missedvblanks,
- clockspeed * 100);
+ DEBUG_INFO_PLAYER info;
+
+ m_playerPort->GetDebugInfo(info.audio, info.video, info.player);
+
+ double refreshrate, clockspeed;
+ int missedvblanks;
+ info.vsync =
+ StringUtils::Format("VSyncOff: %.1f latency: %.3f ", m_clockSync.m_syncOffset / 1000,
+ DVD_TIME_TO_MSEC(m_displayLatency) / 1000.0f);
+ if (m_dvdClock.GetClockInfo(missedvblanks, clockspeed, refreshrate))
+ {
+ info.vsync += StringUtils::Format("VSync: refresh:%.3f missed:%i speed:%.3f%%",
+ refreshrate, missedvblanks, clockspeed * 100);
+ }
+
+ m_debugRenderer.SetInfo(info);
}
- m_debugRenderer.SetInfo(audio, video, player, vsync);
m_debugRenderer.Render(src, dst, view);
m_debugTimer.Set(1000);
@@ -894,6 +905,14 @@ void CRenderManager::ToggleDebug()
{
m_renderDebug = !m_renderDebug;
m_debugTimer.SetExpired();
+ m_renderDebugVideo = false;
+}
+
+void CRenderManager::ToggleDebugVideo()
+{
+ m_renderDebug = !m_renderDebug;
+ m_debugTimer.SetExpired();
+ m_renderDebugVideo = true;
}
bool CRenderManager::AddVideoPicture(const VideoPicture& picture, volatile std::atomic_bool& bStop, EINTERLACEMETHOD deintMethod, bool wait)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
index ba5b21c112b25..eb165794a3ec7 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
@@ -72,6 +72,7 @@ class CRenderManager
bool Flush(bool wait, bool saveBuffers);
bool IsConfigured() const;
void ToggleDebug();
+ void ToggleDebugVideo();
unsigned int AllocRenderCapture();
void ReleaseRenderCapture(unsigned int captureId);
@@ -141,6 +142,7 @@ class CRenderManager
bool m_bRenderGUI = true;
bool m_renderedOverlay = false;
bool m_renderDebug = false;
+ bool m_renderDebugVideo = false;
XbmcThreads::EndTime m_debugTimer;
std::atomic_bool m_showVideo = {false};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
index a7f526c06980e..f442893c3d3cf 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
@@ -207,11 +207,14 @@ void COutputShader::ApplyEffectParameters(CD3DEffect &effect, unsigned sourceWid
effect.SetScalar("g_toneP1", param);
effect.SetFloatArray("g_coefsDst", coefs, 3);
+ m_toneMappingDebug = param;
}
else if (m_toneMapping && m_toneMappingMethod == VS_TONEMAPMETHOD_ACES)
{
- effect.SetScalar("g_luminance", GetLuminanceValue());
+ float lumin = GetLuminanceValue();
+ effect.SetScalar("g_luminance", lumin);
effect.SetScalar("g_toneP1", m_toneMappingParam);
+ m_toneMappingDebug = lumin;
}
else if (m_toneMapping && m_toneMappingMethod == VS_TONEMAPMETHOD_HABLE)
{
@@ -220,6 +223,7 @@ void COutputShader::ApplyEffectParameters(CD3DEffect &effect, unsigned sourceWid
float lumin_div100 = lumin / (100.0f * m_toneMappingParam);
effect.SetScalar("g_toneP1", lumin_factor);
effect.SetScalar("g_toneP2", lumin_div100);
+ m_toneMappingDebug = lumin;
}
}
@@ -509,6 +513,45 @@ void COutputShader::CreateDitherView()
m_useDithering = true;
}
+std::string COutputShader::GetDebugInfo()
+{
+ std::string tone = "OFF";
+ std::string hlg = "OFF";
+ std::string lut = "OFF";
+ std::string dither = "OFF";
+
+ if (m_toneMapping)
+ {
+ std::string method;
+ switch (m_toneMappingMethod)
+ {
+ case VS_TONEMAPMETHOD_REINHARD:
+ method = "Reinhard";
+ break;
+ case VS_TONEMAPMETHOD_ACES:
+ method = "ACES";
+ break;
+ case VS_TONEMAPMETHOD_HABLE:
+ method = "Hable";
+ break;
+ }
+ tone = StringUtils::Format("ON ({}, {:.2f}, {:.2f}{})", method, m_toneMappingParam,
+ m_toneMappingDebug, (m_toneMappingMethod == 1) ? "" : " nits");
+ }
+
+ if (m_useHLGtoPQ)
+ hlg = "ON (peak 1000 nits)";
+
+ if (m_useLut)
+ lut = StringUtils::Format("ON (size {})", m_lutSize);
+
+ if (m_useDithering)
+ dither = StringUtils::Format("ON (depth {})", m_ditherDepth);
+
+ return StringUtils::Format("Tone mapping: {} | HLG to PQ: {} | 3D LUT: {} | Dithering: {}", tone,
+ hlg, lut, dither);
+}
+
//==================================================================================
bool CYUV2RGBShader::Create(AVPixelFormat fmt, AVColorPrimaries dstPrimaries,
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
index 647f5ffbe6e57..3516905c5b0c3 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
@@ -69,6 +69,7 @@ class COutputShader : public CWinShader
void SetDisplayMetadata(bool hasDisplayMetadata, AVMasteringDisplayMetadata displayMetadata,
bool hasLightMetadata, AVContentLightMetadata lightMetadata);
void SetToneMapParam(int method, float param);
+ std::string GetDebugInfo();
static bool CreateLUTView(int lutSize, uint16_t* lutData, bool isRGB, ID3D11ShaderResourceView** ppLUTView);
@@ -98,6 +99,7 @@ class COutputShader : public CWinShader
int m_ditherDepth = 0;
int m_toneMappingMethod = 0;
float m_toneMappingParam = 1.0f;
+ float m_toneMappingDebug = .0f;
CRect m_sourceRect = {};
CPoint m_destPoints[4] = {};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
index 4e52d1cede32c..07b0f72d5ef4e 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
@@ -333,3 +333,11 @@ bool CWinRenderer::NeedBuffer(int idx)
return m_renderer->NeedBuffer(idx);
}
+
+DEBUG_INFO_VIDEO CWinRenderer::GetDebugInfo(int idx)
+{
+ if (!m_bConfigured)
+ return {};
+
+ return m_renderer->GetDebugInfo(idx);
+}
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
index ad625ecaf9399..79bac51f49bd3 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
@@ -46,6 +46,9 @@ class CWinRenderer : public CBaseRenderer
bool WantsDoublePass() override;
bool ConfigChanged(const VideoPicture& picture) override;
+ // Debug info video
+ DEBUG_INFO_VIDEO GetDebugInfo(int idx) override;
+
protected:
void PreInit();
int NextBuffer() const;
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.cpp
index 311c891326a21..c593fde708411 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.cpp
@@ -35,6 +35,7 @@ void CRenderBuffer::AppendPicture(const VideoPicture& picture)
full_range = picture.color_range == 1;
bits = picture.colorBits;
stereoMode = picture.stereoMode;
+ pixelFormat = picture.pixelFormat;
hasDisplayMetadata = picture.hasDisplayMetadata;
displayMetadata = picture.displayMetadata;
@@ -637,3 +638,82 @@ void CRendererBase::ProcessHDR(CRenderBuffer* rb)
}
}
}
+
+DEBUG_INFO_VIDEO CRendererBase::GetDebugInfo(int idx)
+{
+ CRenderBuffer* rb = m_renderBuffers[idx];
+
+ const char* px = av_get_pix_fmt_name(rb->pixelFormat);
+ const char* pr = av_color_primaries_name(rb->primaries);
+ const char* tr = av_color_transfer_name(rb->color_transfer);
+
+ const std::string pixel = px ? px : "unknown";
+ const std::string prim = pr ? pr : "unknown";
+ const std::string trans = tr ? tr : "unknown";
+
+ const int max = static_cast(std::exp2(rb->bits));
+ const int range_min = rb->full_range ? 0 : (max * 16) / 256;
+ const int range_max = rb->full_range ? max - 1 : (max * 235) / 256;
+
+ DEBUG_INFO_VIDEO info;
+
+ info.videoSource = StringUtils::Format(
+ "Source: {}x{}{}, fr: {:.3f}, pixel: {} {}-bit, range: {}-{}, matx: {}, trc: {}",
+ m_sourceWidth, m_sourceHeight, (rb->pictureFlags & DVP_FLAG_INTERLACED) ? "i" : "p", m_fps,
+ pixel, rb->bits, range_min, range_max, prim, trans);
+
+ info.metaPrim = "Primaries (meta): ";
+ info.metaLight = "HDR light (meta): ";
+
+ if (rb->hasDisplayMetadata && rb->displayMetadata.has_primaries &&
+ rb->displayMetadata.display_primaries[0][0].num)
+ {
+ double prim[3][2];
+ double wp[2];
+
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 2; j++)
+ prim[i][j] = static_cast(rb->displayMetadata.display_primaries[i][j].num) /
+ static_cast(rb->displayMetadata.display_primaries[i][j].den);
+ }
+
+ for (int j = 0; j < 2; j++)
+ wp[j] = static_cast(rb->displayMetadata.white_point[j].num) /
+ static_cast(rb->displayMetadata.white_point[j].den);
+
+ info.metaPrim += StringUtils::Format(
+ "R({:.3f} {:.3f}), G({:.3f} {:.3f}), B({:.3f} {:.3f}), WP({:.3f} {:.3f})", prim[0][0],
+ prim[0][1], prim[1][0], prim[1][1], prim[2][0], prim[2][1], wp[0], wp[1]);
+ }
+ else
+ {
+ info.metaPrim += "none";
+ }
+
+ if (rb->hasDisplayMetadata && rb->displayMetadata.has_luminance &&
+ rb->displayMetadata.max_luminance.num)
+ {
+ double maxML = static_cast(rb->displayMetadata.max_luminance.num) /
+ static_cast(rb->displayMetadata.max_luminance.den);
+ double minML = static_cast(rb->displayMetadata.min_luminance.num) /
+ static_cast(rb->displayMetadata.min_luminance.den);
+
+ info.metaLight += StringUtils::Format("max ML: {:.0f}, min ML: {:.4f}", maxML, minML);
+
+ if (rb->hasLightMetadata && rb->lightMetadata.MaxCLL)
+ {
+ info.metaLight += StringUtils::Format(", max CLL: {}, max FALL: {}", rb->lightMetadata.MaxCLL,
+ rb->lightMetadata.MaxFALL);
+ }
+ }
+ else
+ {
+ info.metaLight += "none";
+ }
+
+ if (m_outputShader)
+ info.shader = m_outputShader->GetDebugInfo();
+
+ return info;
+}
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.h b/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.h
index 7720e190f8113..5df7dcd020c33 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.h
@@ -8,6 +8,7 @@
#pragma once
#include "VideoRenderers/ColorManager.h"
+#include "VideoRenderers/DebugInfo.h"
#include "VideoRenderers/RenderInfo.h"
#include "VideoRenderers/VideoShaders/WinVideoFilter.h"
#include "cores/VideoSettings.h"
@@ -19,6 +20,7 @@
#include
extern "C" {
#include
+#include
}
struct VideoPicture;
@@ -79,7 +81,7 @@ class CRenderBuffer
bool full_range = false;
int bits = 8;
uint8_t texBits = 8;
-
+ AVPixelFormat pixelFormat = AV_PIX_FMT_NONE; // source pixel format
bool hasDisplayMetadata = false;
bool hasLightMetadata = false;
AVMasteringDisplayMetadata displayMetadata = {};
@@ -127,6 +129,8 @@ class CRendererBase
bool Flush(bool saveBuffers);
void SetBufferSize(int numBuffers) { m_iBuffersRequired = numBuffers; }
+ DEBUG_INFO_VIDEO GetDebugInfo(int idx);
+
static DXGI_FORMAT GetDXGIFormat(const VideoPicture &picture);
static DXGI_FORMAT GetDXGIFormat(CVideoBuffer* videoBuffer);
static AVPixelFormat GetAVFormat(DXGI_FORMAT dxgi_format);
diff --git a/xbmc/input/actions/ActionIDs.h b/xbmc/input/actions/ActionIDs.h
index 01233668f9386..8b47683edc39f 100644
--- a/xbmc/input/actions/ActionIDs.h
+++ b/xbmc/input/actions/ActionIDs.h
@@ -432,6 +432,9 @@
#define ACTION_CYCLE_TONEMAP_METHOD 261 //!< Switch to next tonemap method
+//! Show debug info for video (source format, metadata, shaders, render flags and output format)
+#define ACTION_PLAYER_DEBUG_VIDEO 262
+
// Voice actions
#define ACTION_VOICE_RECOGNIZE 300
diff --git a/xbmc/input/actions/ActionTranslator.cpp b/xbmc/input/actions/ActionTranslator.cpp
index 774d225d6e470..3a73dcd8fa617 100644
--- a/xbmc/input/actions/ActionTranslator.cpp
+++ b/xbmc/input/actions/ActionTranslator.cpp
@@ -53,6 +53,7 @@ static const std::map ActionMappings = {
{"browsesubtitle", ACTION_BROWSE_SUBTITLE},
{"cyclesubtitle", ACTION_CYCLE_SUBTITLE},
{"playerdebug", ACTION_PLAYER_DEBUG},
+ {"playerdebugvideo", ACTION_PLAYER_DEBUG_VIDEO},
{"codecinfo", ACTION_PLAYER_PROCESS_INFO},
{"playerprocessinfo", ACTION_PLAYER_PROCESS_INFO},
{"playerprogramselect", ACTION_PLAYER_PROGRAM_SELECT},
diff --git a/xbmc/rendering/dx/DeviceResources.cpp b/xbmc/rendering/dx/DeviceResources.cpp
index 8322bf15d1501..ea206b2086fab 100644
--- a/xbmc/rendering/dx/DeviceResources.cpp
+++ b/xbmc/rendering/dx/DeviceResources.cpp
@@ -1225,3 +1225,41 @@ HDR_STATUS DX::DeviceResources::ToggleHDR()
return hdrStatus;
}
+
+DEBUG_INFO_RENDER DX::DeviceResources::GetDebugInfo() const
+{
+ if (m_swapChain == nullptr)
+ return {};
+
+ DXGI_SWAP_CHAIN_DESC1 desc = {};
+ m_swapChain->GetDesc1(&desc);
+
+ DXGI_MODE_DESC md = {};
+ GetDisplayMode(&md);
+
+ const int bits = (desc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) ? 10 : 8;
+ const int max = (desc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) ? 1024 : 256;
+ const int range_min = DX::Windowing()->UseLimitedColor() ? (max * 16) / 256 : 0;
+ const int range_max = DX::Windowing()->UseLimitedColor() ? (max * 235) / 256 : max - 1;
+
+ DEBUG_INFO_RENDER info;
+
+ info.renderFlags = StringUtils::Format(
+ "Swapchain: {} buffers, flip {}, {}, EOTF: {} (Windows HDR {})", desc.BufferCount,
+ (desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD) ? "discard" : "sequential",
+ Windowing()->IsFullScreen()
+ ? ((desc.Flags == DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) ? "fullscreen exclusive"
+ : "fullscreen windowed")
+ : "windowed screen",
+ m_IsTransferPQ ? "PQ" : "SDR", m_IsHDROutput ? "on" : "off");
+
+ info.videoOutput = StringUtils::Format(
+ "Output: {}x{}{} @ {:.2f} Hz, pixel: {} {}-bit, range: {} ({}-{})", desc.Width, desc.Height,
+ (md.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE) ? "p" : "i",
+ static_cast(md.RefreshRate.Numerator) /
+ static_cast(md.RefreshRate.Denominator),
+ (desc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) ? "R10G10B10A2" : "B8G8R8A8", bits,
+ DX::Windowing()->UseLimitedColor() ? "limited" : "full", range_min, range_max);
+
+ return info;
+}
diff --git a/xbmc/rendering/dx/DeviceResources.h b/xbmc/rendering/dx/DeviceResources.h
index f972719f526f7..7a9b46277c8ff 100644
--- a/xbmc/rendering/dx/DeviceResources.h
+++ b/xbmc/rendering/dx/DeviceResources.h
@@ -21,6 +21,7 @@
#include
struct RESOLUTION_INFO;
+struct DEBUG_INFO_RENDER;
namespace DX
{
@@ -109,6 +110,9 @@ namespace DX
#endif // TARGET_WINDOWS_STORE
bool IsNV12SharedTexturesSupported() const { return m_NV12SharedTexturesSupport; }
+ // Gets debug info from swapchain
+ DEBUG_INFO_RENDER GetDebugInfo() const;
+
private:
class CBackBuffer : public CD3DTexture
{
diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h
index 5e7c2c595d335..819d8245827eb 100644
--- a/xbmc/windowing/WinSystem.h
+++ b/xbmc/windowing/WinSystem.h
@@ -13,6 +13,7 @@
#include "Resolution.h"
#include "VideoSync.h"
#include "WinEvents.h"
+#include "cores/VideoPlayer/VideoRenderers/DebugInfo.h"
#include "guilib/DispResource.h"
#include
@@ -167,6 +168,9 @@ class CWinSystemBase
static const char* SETTING_WINSYSTEM_IS_HDR_DISPLAY;
+ // Gets debug info from video renderer
+ virtual DEBUG_INFO_RENDER GetDebugInfo() { return {}; };
+
protected:
void UpdateDesktopResolution(RESOLUTION_INFO& newRes, const std::string &output, int width, int height, float refreshRate, uint32_t dwFlags);
virtual std::unique_ptr GetOSScreenSaverImpl() { return nullptr; }
diff --git a/xbmc/windowing/win10/WinSystemWin10DX.cpp b/xbmc/windowing/win10/WinSystemWin10DX.cpp
index e7dee222f4747..20b5216f2efcd 100644
--- a/xbmc/windowing/win10/WinSystemWin10DX.cpp
+++ b/xbmc/windowing/win10/WinSystemWin10DX.cpp
@@ -196,3 +196,8 @@ void CWinSystemWin10DX::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace)
{
m_deviceResources->SetHdrColorSpace(colorSpace);
}
+
+DEBUG_INFO_RENDER CWinSystemWin10DX::GetDebugInfo()
+{
+ return m_deviceResources->GetDebugInfo();
+}
diff --git a/xbmc/windowing/win10/WinSystemWin10DX.h b/xbmc/windowing/win10/WinSystemWin10DX.h
index 0701cc0638d4e..a09e1d3999978 100644
--- a/xbmc/windowing/win10/WinSystemWin10DX.h
+++ b/xbmc/windowing/win10/WinSystemWin10DX.h
@@ -77,6 +77,9 @@ class CWinSystemWin10DX : public CWinSystemWin10, public CRenderSystemDX
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const;
+ // Get debug info from swapchain
+ DEBUG_INFO_RENDER GetDebugInfo() override;
+
protected:
void SetDeviceFullScreen(bool fullScreen, RESOLUTION_INFO& res) override;
void ReleaseBackBuffer() override;
diff --git a/xbmc/windowing/windows/WinSystemWin32DX.cpp b/xbmc/windowing/windows/WinSystemWin32DX.cpp
index 0732b474c4f9b..99b551a00f55d 100644
--- a/xbmc/windowing/windows/WinSystemWin32DX.cpp
+++ b/xbmc/windowing/windows/WinSystemWin32DX.cpp
@@ -421,3 +421,8 @@ void CWinSystemWin32DX::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace)
{
m_deviceResources->SetHdrColorSpace(colorSpace);
}
+
+DEBUG_INFO_RENDER CWinSystemWin32DX::GetDebugInfo()
+{
+ return m_deviceResources->GetDebugInfo();
+}
diff --git a/xbmc/windowing/windows/WinSystemWin32DX.h b/xbmc/windowing/windows/WinSystemWin32DX.h
index ff05cb30ddc53..ba159283f6ff8 100644
--- a/xbmc/windowing/windows/WinSystemWin32DX.h
+++ b/xbmc/windowing/windows/WinSystemWin32DX.h
@@ -79,6 +79,9 @@ class CWinSystemWin32DX : public CWinSystemWin32, public CRenderSystemDX
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const;
+ // Get debug info from swapchain
+ DEBUG_INFO_RENDER GetDebugInfo() override;
+
protected:
void SetDeviceFullScreen(bool fullScreen, RESOLUTION_INFO& res) override;
void ReleaseBackBuffer() override;