Skip to content

Commit

Permalink
[Windows] Add video, HDR metadata, shader and swapchain infos to debu…
Browse files Browse the repository at this point in the history
…g info OSD
  • Loading branch information
thexai committed Feb 19, 2021
1 parent bdf369a commit d4ee93e
Show file tree
Hide file tree
Showing 17 changed files with 236 additions and 51 deletions.
7 changes: 7 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ class CBaseRenderer

void SetVideoSettings(const CVideoSettings &settings);

// Get debug info from render buffer
virtual void GetDebugInfo(int idx,
std::string& format,
std::string& meta_prim,
std::string& meta_light,
std::string& shader){};

protected:
void CalcNormalRenderRect(float offsetX, float offsetY, float width, float height,
float inputFrameRatio, float zoomAmount, float verticalShift);
Expand Down
54 changes: 16 additions & 38 deletions xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ using namespace OVERLAY;

CDebugRenderer::CDebugRenderer()
{
for (int i=0; i<4; i++)
for (int i = 0; i < m_strDebug.size(); i++)
{
m_overlay[i] = nullptr;
m_strDebug[i] = " ";
Expand All @@ -33,50 +33,27 @@ CDebugRenderer::~CDebugRenderer()
}
}

void CDebugRenderer::SetInfo(std::string &info1, std::string &info2, std::string &info3, std::string &info4)
void CDebugRenderer::SetInfo(std::array<std::string, 10>& info)
{
m_overlayRenderer.Release(0);

if (info1 != m_strDebug[0])
for (int i = 0; i < info.size(); i++)
{
m_strDebug[0] = info1;
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])
{
m_strDebug[1] = info2;
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])
{
m_strDebug[2] = info3;
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])
{
m_strDebug[3] = info4;
if (m_overlay[3])
m_overlay[3]->Release();
m_overlay[3] = new CDVDOverlayText();
m_overlay[3]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[3]));
if (info[i] != m_strDebug[i])
{
m_strDebug[i] = info[i];
if (m_overlay[i])
m_overlay[i]->Release();
m_overlay[i] = new CDVDOverlayText();
m_overlay[i]->AddElement(new CDVDOverlayText::CElementText(m_strDebug[i]));
}
}

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 < info.size(); i++)
m_overlayRenderer.AddOverlay(m_overlay[i], 0, 0);
}

void CDebugRenderer::Render(CRect &src, CRect &dst, CRect &view)
void CDebugRenderer::Render(CRect& src, CRect& dst, CRect& view)
{
m_overlayRenderer.SetVideoRect(src, dst, view);
m_overlayRenderer.Render(0);
Expand Down Expand Up @@ -110,7 +87,8 @@ void CDebugRenderer::CRenderer::Render(int idx)

COverlayText *text = dynamic_cast<COverlayText*>(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());

Expand Down
9 changes: 5 additions & 4 deletions xbmc/cores/VideoPlayer/VideoRenderers/DebugRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "OverlayRenderer.h"

#include <array>
#include <string>

class CDVDOverlayText;
Expand All @@ -19,8 +20,8 @@ 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(std::array<std::string, 10>& info);
void Render(CRect& src, CRect& dst, CRect& view);
void Flush();

protected:
Expand All @@ -32,7 +33,7 @@ class CDebugRenderer
void Render(int idx) override;
};

std::string m_strDebug[4];
CDVDOverlayText *m_overlay[4];
std::array<std::string, 10> m_strDebug = {};
CDVDOverlayText* m_overlay[10] = {};
CRenderer m_overlayRenderer;
};
19 changes: 11 additions & 8 deletions xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,22 +720,25 @@ void CRenderManager::Render(bool clear, DWORD flags, DWORD alpha, bool gui)

if (m_renderDebug)
{
std::string audio, video, player, vsync;
std::array<std::string, 10> info = {};

m_playerPort->GetDebugInfo(audio, video, player);
m_playerPort->GetDebugInfo(info[0], info[1], info[2]);

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);
info[3] =
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))
{
vsync += StringUtils::Format("VSync: refresh:%.3f missed:%i speed:%.3f%%",
refreshrate,
missedvblanks,
clockspeed * 100);
info[3] += StringUtils::Format("VSync: refresh:%.3f missed:%i speed:%.3f%%", refreshrate,
missedvblanks, clockspeed * 100);
}

m_debugRenderer.SetInfo(audio, video, player, vsync);
m_pRenderer->GetDebugInfo(m_presentsource, info[4], info[5], info[6], info[7]);
CServiceBroker::GetWinSystem()->GetDebugInfo(info[8], info[9]);

m_debugRenderer.SetInfo(info);
m_debugRenderer.Render(src, dst, view);

m_debugTimer.Set(1000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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] = {};
Expand Down
12 changes: 12 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,15 @@ bool CWinRenderer::NeedBuffer(int idx)

return m_renderer->NeedBuffer(idx);
}

void CWinRenderer::GetDebugInfo(int idx,
std::string& format,
std::string& meta_prim,
std::string& meta_light,
std::string& shader)
{
if (!m_bConfigured)
return;

return m_renderer->GetDebugInfo(idx, format, meta_prim, meta_light, shader);
}
7 changes: 7 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class CWinRenderer : public CBaseRenderer
bool WantsDoublePass() override;
bool ConfigChanged(const VideoPicture& picture) override;

// Get debug info from render buffer
void GetDebugInfo(int idx,
std::string& format,
std::string& meta_prim,
std::string& meta_light,
std::string& shader) override;

protected:
void PreInit();
int NextBuffer() const;
Expand Down
68 changes: 68 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,71 @@ void CRendererBase::ProcessHDR(CRenderBuffer* rb)
}
}
}

void CRendererBase::GetDebugInfo(int idx,
std::string& format,
std::string& meta_prim,
std::string& meta_light,
std::string& shader)
{
CRenderBuffer* rb = m_renderBuffers[idx];

const char* px = av_get_pix_fmt_name(rb->av_format);
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<int>(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;

format = StringUtils::Format(
"Source: pixel: {} {}-bit, range: {} ({}-{}), matrix: {}, transfer: {}, {}", pixel, rb->bits,
rb->full_range ? "full" : "limited", range_min, range_max, prim, trans,
(rb->pictureFlags & DVP_FLAG_INTERLACED) ? "interlaced" : "progressive");

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<double>(rb->displayMetadata.display_primaries[i][j].num) /
static_cast<double>(rb->displayMetadata.display_primaries[i][j].den);
}

for (int j = 0; j < 2; j++)
wp[j] = static_cast<double>(rb->displayMetadata.white_point[j].num) /
static_cast<double>(rb->displayMetadata.white_point[j].den);

meta_prim = StringUtils::Format("Primaries (meta): 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]);
}

if (rb->hasDisplayMetadata && rb->displayMetadata.has_luminance &&
rb->displayMetadata.max_luminance.num)
{
double maxML = static_cast<double>(rb->displayMetadata.max_luminance.num) /
static_cast<double>(rb->displayMetadata.max_luminance.den);
double minML = static_cast<double>(rb->displayMetadata.min_luminance.num) /
static_cast<double>(rb->displayMetadata.min_luminance.den);

meta_light =
StringUtils::Format("HDR light (meta): max ML: {:.0f}, min ML: {:.4f}", maxML, minML);

if (rb->hasLightMetadata && rb->lightMetadata.MaxCLL)
meta_light.append(StringUtils::Format(", max CLL: {}, max FALL: {}", rb->lightMetadata.MaxCLL,
rb->lightMetadata.MaxFALL));
}

if (m_outputShader)
shader = m_outputShader->GetDebugInfo();
}
7 changes: 7 additions & 0 deletions xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <dxgi1_5.h>
extern "C" {
#include <libavutil/mastering_display_metadata.h>
#include <libavutil/pixdesc.h>
}

struct VideoPicture;
Expand Down Expand Up @@ -127,6 +128,12 @@ class CRendererBase
bool Flush(bool saveBuffers);
void SetBufferSize(int numBuffers) { m_iBuffersRequired = numBuffers; }

void GetDebugInfo(int idx,
std::string& format,
std::string& meta_prim,
std::string& meta_light,
std::string& shader);

static DXGI_FORMAT GetDXGIFormat(const VideoPicture &picture);
static DXGI_FORMAT GetDXGIFormat(CVideoBuffer* videoBuffer);
static AVPixelFormat GetAVFormat(DXGI_FORMAT dxgi_format);
Expand Down
Loading

0 comments on commit d4ee93e

Please sign in to comment.