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;