38 changes: 26 additions & 12 deletions mythtv/libs/libmythui/mythdisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ QStringList MythDisplay::GetDescription()
}
}

if (m_edid.Valid())
if (m_hdrState.get())
{
auto [types, dummy] = m_edid.GetHDRSupport();
auto hdr = MythEDID::EOTFToStrings(types);
if (hdr.empty())
hdr.append(tr("None"));
auto types = m_hdrState->m_supportedTypes;
auto hdr = m_hdrState->TypesToString();
result.append(tr("Supported HDR formats\t: %1").arg(hdr.join(",")));
if (types && !m_hdrState->m_controllable)
result.append(tr("HDR mode switching is not available"));
}
return result;
}
Expand Down Expand Up @@ -528,13 +528,7 @@ void MythDisplay::Initialise()
else
LOG(VB_GENERAL, LOG_NOTICE, LOC + "Display has custom colourspace");

auto [types, metadata] = m_edid.GetHDRSupport();
auto hdr = MythEDID::EOTFToStrings(types);
if (hdr.empty())
hdr.append("None");
else if ((metadata & MythEDID::Static1) != MythEDID::Static1)
LOG(VB_GENERAL, LOG_WARNING, LOC + "Display does not report support for Static Metadata Type 1");
LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Supported HDR formats: %1").arg(hdr.join(",")));
InitHDR();
}
}

Expand Down Expand Up @@ -883,6 +877,26 @@ MythEDID& MythDisplay::GetEDID()
return m_edid;
}

MythHDRPtr MythDisplay::GetHDRState()
{
return m_hdrState;
}

void MythDisplay::InitHDR()
{
if (m_edid.Valid())
{
m_hdrState = m_edid.GetHDRSupport();
auto hdr = m_hdrState->TypesToString();
if (m_hdrState->m_metadataType != MythHDR::StaticType1 &&
m_hdrState->m_supportedTypes > MythHDR::SDR)
{
LOG(VB_GENERAL, LOG_WARNING, LOC + "Display does not report support for Static Metadata Type 1");
}
LOG(VB_GENERAL, LOG_NOTICE, LOC + QString("Supported HDR formats: %1").arg(hdr.join(",")));
}
}

/*! \brief Estimate the overall display aspect ratio for multi screen setups.
*
* \note This will only work where screens are configured either as a grid (e.g. 2x2)
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythui/mythdisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "mythuiexp.h"
#include "mythdisplaymode.h"
#include "mythedid.h"
#include "mythhdr.h"
#include "mythcommandlineparser.h"

// Std
Expand Down Expand Up @@ -50,6 +51,7 @@ class MUI_PUBLIC MythDisplay : public QObject
double EstimateVirtualAspectRatio();
MythEDID& GetEDID ();
MythDisplayRates GetRefreshRates (QSize Size);
MythHDRPtr GetHDRState ();

public slots:
virtual void ScreenChanged (QScreen *qScreen);
Expand All @@ -71,6 +73,7 @@ class MUI_PUBLIC MythDisplay : public QObject

virtual void UpdateCurrentMode ();
virtual bool SwitchToVideoMode (QSize Size, double Framerate);
virtual void InitHDR ();

void DebugModes () const;
void SetWidget (QWidget *MainWindow);
Expand All @@ -92,6 +95,7 @@ class MUI_PUBLIC MythDisplay : public QObject
QWindow* m_window { nullptr };
QScreen* m_screen { nullptr };
MythDisplayModes m_videoModes { };
MythHDRPtr m_hdrState { nullptr };

private:
Q_DISABLE_COPY(MythDisplay)
Expand Down
37 changes: 14 additions & 23 deletions mythtv/libs/libmythui/mythedid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,15 @@ int MythEDID::VideoLatency(bool Interlaced) const
return m_videoLatency[Interlaced ? 1 : 0];
}

std::pair<int,int> MythEDID::GetHDRSupport() const
MythHDRPtr MythEDID::GetHDRSupport() const
{
return { m_hdrSupport, m_hdrMetaTypes };
}

QString MythEDID::EOTFToString(int EOTF)
{
if (EOTF & SDR) return QObject::tr("SDR");
if (EOTF & HDRTrad) return QObject::tr("HDR(Trad)");
if (EOTF & HDR10) return QObject::tr("HDR10 (SMPTE ST2084)");
if (EOTF & HLG) return QObject::tr("Hybrid Log-Gamma");
return QObject::tr("Unknown");
}

QStringList MythEDID::EOTFToStrings(int EOTF)
{
QStringList res;
if (EOTF & SDR) res << EOTFToString(SDR);
if (EOTF & HDRTrad) res << EOTFToString(HDRTrad);
if (EOTF & HDR10) res << EOTFToString(HDR10);
if (EOTF & HLG) res << EOTFToString(HLG);
return res;
auto result = MythHDR::Create();
result->m_supportedTypes = m_hdrSupport;
result->m_minLuminance = m_minLuminance;
result->m_maxAvgLuminance = m_maxAvgLuminance;
result->m_maxLuminance = m_maxLuminance;
result->m_metadataType = static_cast<MythHDR::HDRMeta>(m_hdrMetaTypes);
return result;
}

// from QEdidParser
Expand Down Expand Up @@ -463,7 +450,11 @@ bool MythEDID::ParseExtended(const quint8* Data, uint Offset, uint Length)
{
if (Length >= 3 && (Offset + 3 < m_size))
{
m_hdrSupport = Data[Offset + 1] & 0x3f;
int hdrsupport = Data[Offset + 1] & 0x3f;
if (hdrsupport & HDR10)
m_hdrSupport |= MythHDR::HDR10;
if (hdrsupport & HLG)
m_hdrSupport |= MythHDR::HLG;
m_hdrMetaTypes = Data[Offset + 2] & 0xff;
}

Expand Down Expand Up @@ -546,7 +537,7 @@ void MythEDID::Debug() const
if (m_vrrMin || m_vrrMax)
LOG(VB_GENERAL, LOG_INFO, LOC + QString("VRR: %1<->%2").arg(m_vrrMin).arg(m_vrrMax));
if (m_hdrSupport)
LOG(VB_GENERAL, LOG_INFO, LOC + QString("HDR types: %1").arg(EOTFToStrings(m_hdrSupport).join(",")));
LOG(VB_GENERAL, LOG_INFO, LOC + QString("HDR types: %1").arg(MythHDR::TypesToString(m_hdrSupport).join(",")));
if (m_maxLuminance > 0.0 || m_maxAvgLuminance > 0.0)
{
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Desired luminance: Min: %1 Max: %2 Avg: %3")
Expand Down
34 changes: 17 additions & 17 deletions mythtv/libs/libmythui/mythedid.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

// MythTV
#include "mythuiexp.h"
#include "mythhdr.h"
#include "mythcolourspace.h"

// Std
Expand All @@ -16,19 +17,6 @@
class MUI_PUBLIC MythEDID
{
public:
enum HDREOTF
{
SDR = 1 << 0,
HDRTrad = 1 << 1,
HDR10 = 1 << 2,
HLG = 1 << 3
};

enum HDRMetadaType
{
Static1 = 1 << 0
};

MythEDID() = default;
explicit MythEDID(QByteArray Data);
MythEDID(const char* Data, int Length);
Expand All @@ -46,11 +34,23 @@ class MUI_PUBLIC MythEDID
int AudioLatency (bool Interlaced) const;
int VideoLatency (bool Interlaced) const;
void Debug () const;
std::pair<int,int> GetHDRSupport() const;
static QString EOTFToString (int EOTF);
static QStringList EOTFToStrings(int EOTF);
MythHDRPtr GetHDRSupport () const;

private:
enum HDREOTF
{
SDR = 1 << 0,
HDRTrad = 1 << 1,
HDR10 = 1 << 2,
HLG = 1 << 3
};

enum HDRMetadaType
{
Unknown = 0,
Static1 = 1 << 0
};

void Parse ();
bool ParseBaseBlock (const quint8* Data);
void ParseDisplayDescriptor(const quint8* Data, uint Offset);
Expand Down Expand Up @@ -84,7 +84,7 @@ class MUI_PUBLIC MythEDID
uint8_t m_deepYUV { 0 };
int m_vrrMin { 0 };
int m_vrrMax { 0 };
int m_hdrSupport { 0 };
MythHDR::HDRTypes m_hdrSupport { MythHDR::SDR };
int m_hdrMetaTypes { 0 };
double m_maxLuminance { 0.0 };
double m_maxAvgLuminance { 0.0 };
Expand Down
58 changes: 58 additions & 0 deletions mythtv/libs/libmythui/mythhdr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// MythTV
#include "mythhdr.h"

/*! \class MythHDRMetadata
* \brief Encapsulates HDR metadata conformant with Static Metadata Type 1 per CTA-861-G Final.
*/
MythHDRMetadata::MythHDRMetadata(const MythHDRMetadata &Other)
: m_displayPrimaries(std::move(Other.m_displayPrimaries)),
m_whitePoint(std::move(Other.m_whitePoint)),
m_maxMasteringLuminance(Other.m_maxMasteringLuminance),
m_minMasteringLuminance(Other.m_minMasteringLuminance),
m_maxContentLightLevel(Other.m_maxContentLightLevel),
m_maxFrameAverageLightLevel(Other.m_maxFrameAverageLightLevel)
{
}

bool MythHDRMetadata::Equals(MythHDRMetadata* Other)
{
return Other &&
m_maxMasteringLuminance == Other->m_maxMasteringLuminance &&
m_minMasteringLuminance == Other->m_minMasteringLuminance &&
m_maxContentLightLevel == Other->m_maxContentLightLevel &&
m_maxFrameAverageLightLevel == Other->m_maxFrameAverageLightLevel &&
m_whitePoint[0] == Other->m_whitePoint[0] &&
m_whitePoint[1] == Other->m_whitePoint[1] &&
m_displayPrimaries[0][0] == Other->m_displayPrimaries[0][0] &&
m_displayPrimaries[0][1] == Other->m_displayPrimaries[0][1] &&
m_displayPrimaries[1][0] == Other->m_displayPrimaries[1][0] &&
m_displayPrimaries[1][1] == Other->m_displayPrimaries[1][1] &&
m_displayPrimaries[2][0] == Other->m_displayPrimaries[2][0] &&
m_displayPrimaries[2][1] == Other->m_displayPrimaries[2][1];
}

MythHDRPtr MythHDR::Create()
{
return std::shared_ptr<MythHDR>(new MythHDR());
}

QString MythHDR::TypeToString(HDRType Type)
{
if (Type & HDR10) return QObject::tr("HDR10");
if (Type & HLG) return QObject::tr("Hybrid Log-Gamma");
return QObject::tr("Unknown");
}

QStringList MythHDR::TypesToString(HDRTypes Types)
{
QStringList res;
if (Types & HDR10) res << TypeToString(HDR10);
if (Types & HLG) res << TypeToString(HLG);
if (res.empty()) res << QObject::tr("None");
return res;
}

QStringList MythHDR::TypesToString()
{
return MythHDR::TypesToString(m_supportedTypes);
}
73 changes: 73 additions & 0 deletions mythtv/libs/libmythui/mythhdr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef MYTHHDR_H
#define MYTHHDR_H

// Qt
#include <QObject>

// Std
#include <memory>

// MythTV
#include "mythuiexp.h"
#include "mythcolourspace.h"

using MythHDRMetaPtr = std::shared_ptr<class MythHDRMetadata>;
class MUI_PUBLIC MythHDRMetadata
{
public:
MythHDRMetadata() = default;
explicit MythHDRMetadata(const MythHDRMetadata& Other);
bool Equals(MythHDRMetadata* Other);

MythPrimariesUInt16 m_displayPrimaries {{{ 0 }}};
MythPrimaryUInt16 m_whitePoint {{ 0 }};
uint16_t m_maxMasteringLuminance { 0 };
uint16_t m_minMasteringLuminance { 0 };
uint16_t m_maxContentLightLevel { 0 };
uint16_t m_maxFrameAverageLightLevel { 0 };
};

using MythHDRPtr = std::shared_ptr<class MythHDR>;
class MUI_PUBLIC MythHDR
{
Q_GADGET

public:
enum HDRType
{
SDR = 0x00,
HDR10 = 0x01,
HLG = 0x02
};
Q_DECLARE_FLAGS(HDRTypes, HDRType)
Q_FLAG(HDRTypes)

enum HDRMeta
{
Unknown = 0,
StaticType1 = 1
};

static MythHDRPtr Create();

static QString TypeToString (HDRType Type);
static QStringList TypesToString(HDRTypes Types);
QStringList TypesToString();

bool m_controllable { false };
HDRType m_currentType { SDR };
HDRTypes m_supportedTypes { SDR };
double m_maxLuminance { 0.0 };
double m_maxAvgLuminance { 0.0 };
double m_minLuminance { 0.0 };
HDRMeta m_metadataType { Unknown };
MythHDRMetaPtr m_metadata { nullptr };

protected:
MythHDR() = default;

private:
Q_DISABLE_COPY(MythHDR)
};

#endif
7 changes: 7 additions & 0 deletions mythtv/libs/libmythui/platforms/mythdisplaydrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ bool MythDisplayDRM::IsPlanar()
#endif
}

void MythDisplayDRM::InitHDR()
{
MythDisplay::InitHDR();
if (m_hdrState.get() && m_device.get() && m_device->Atomic() && m_device->Authenticated())
m_hdrState->m_controllable = true;
}

bool MythDisplayDRM::UsingVideoModes()
{
if (gCoreContext && m_device.get() && m_device->CanSwitchModes())
Expand Down
2 changes: 2 additions & 0 deletions mythtv/libs/libmythui/platforms/mythdisplaydrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ class MUI_PUBLIC MythDisplayDRM : public MythDisplay
void MainWindowReady();
static bool DirectRenderingAvailable();

public:
bool IsPlanar() override;
void InitHDR() override;
bool VideoModesAvailable() override;
bool UsingVideoModes() override;
void UpdateCurrentMode() override;
Expand Down