Skip to content

Commit

Permalink
libmythtv: Add some HDR tracking classess
Browse files Browse the repository at this point in the history
- these are a work in progress and are likely to change significantly
  • Loading branch information
mark-kendall committed Jan 24, 2021
1 parent 9b91d60 commit b5465c0
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 0 deletions.
115 changes: 115 additions & 0 deletions mythtv/libs/libmythtv/drm/mythhdrtrackerdrm.cpp
@@ -0,0 +1,115 @@
// MythTV
#include "mythlogging.h"
#include "mythframe.h"
#include "drm/mythhdrtrackerdrm.h"
#include "platforms/mythdisplaydrm.h"

#define LOC QString("HDRDrm: ")

HDRTracker MythHDRTrackerDRM::Create(MythDisplay* _Display, int HDRSupport)
{
auto * display = dynamic_cast<MythDisplayDRM*>(_Display);
if (!display)
return nullptr;

// Display support for HDR formats has already been checked. We need to check
// here that we have a valid, authenticated DRM device and that the connector
// supports the HDR_OUTPUT_METADATA property
auto device = display->GetDevice();
if (!(device && device->Authenticated() && device->Atomic()))
return nullptr;

if (auto connector = device->GetConnector(); connector.get())
if (auto hdrprop = MythDRMProperty::GetProperty("HDR_OUTPUT_METADATA", connector->m_properties); hdrprop.get())
return std::shared_ptr<MythHDRTracker>(new MythHDRTrackerDRM(device, connector, hdrprop, HDRSupport));

return nullptr;
}

MythHDRTrackerDRM::MythHDRTrackerDRM(MythDRMPtr Device, DRMConn Connector, DRMProp HDRProp, int HDRSupport)
: MythHDRTracker(HDRSupport),
m_device(Device),
m_connector(Connector),
m_hdrProp(HDRProp)
{
m_connector = m_device->GetConnector();
m_hdrProp = MythDRMProperty::GetProperty("HDR_OUTPUT_METADATA", m_connector->m_properties);
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Tracking HDR signalling for: %1")
.arg(MythEDID::EOTFToStrings(m_hdrSupport).join(",")));
}

MythHDRTrackerDRM::~MythHDRTrackerDRM()
{
MythHDRTrackerDRM::Reset();
}

void MythHDRTrackerDRM::Reset()
{
if (m_hdrBlob)
{
m_device->QueueAtomics({{ m_connector->m_id, m_hdrProp->m_id, 0 }});
drmModeDestroyPropertyBlob(m_device->GetFD(), m_hdrBlob);
m_hdrBlob = 0;
}
}

void MythHDRTrackerDRM::Update(MythVideoFrame* Frame)
{
if (!Frame)
return;

// Do we have an HDR EOTF that is supported by the display and HDR Metadata blob support
if (auto eotf = MythVideoDRMUtils::FFmpegTransferToEOTF(Frame->m_colortransfer, m_hdrSupport);
eotf >= HDMI_EOTF_SMPTE_ST2084)
{
bool needhdrblob = false;
// HLG has no static metadata
if (HDMI_EOTF_BT_2100_HLG == eotf)
{
if (!(m_hdrBlob && m_drmMetadata.hdmi_metadata_type1.eotf == HDMI_EOTF_BT_2100_HLG))
{
needhdrblob = true;
m_ffmpegMetadata = nullptr;
m_drmMetadata = MythVideoDRMUtils::s_defaultMetadata;
m_drmMetadata.hdmi_metadata_type1.eotf = eotf;
}
}
// We need static metadata for HDR10
else if (Frame->m_hdrMetadata.get())
{
if (!m_ffmpegMetadata.get() || !m_ffmpegMetadata.get()->Equals(Frame->m_hdrMetadata.get()) ||
m_drmMetadata.hdmi_metadata_type1.eotf != HDMI_EOTF_SMPTE_ST2084)
{
needhdrblob = true;
m_ffmpegMetadata = Frame->m_hdrMetadata;
m_drmMetadata = MythVideoDRMUtils::s_defaultMetadata;
m_drmMetadata.hdmi_metadata_type1.eotf = eotf;
m_drmMetadata.hdmi_metadata_type1.max_display_mastering_luminance = m_ffmpegMetadata->m_maxMasteringLuminance;
m_drmMetadata.hdmi_metadata_type1.min_display_mastering_luminance = m_ffmpegMetadata->m_minMasteringLuminance;
m_drmMetadata.hdmi_metadata_type1.max_cll = m_ffmpegMetadata->m_maxContentLightLevel;
m_drmMetadata.hdmi_metadata_type1.max_fall = m_ffmpegMetadata->m_maxFrameAverageLightLevel;
m_drmMetadata.hdmi_metadata_type1.white_point.x = m_ffmpegMetadata->m_whitePoint[0];
m_drmMetadata.hdmi_metadata_type1.white_point.y = m_ffmpegMetadata->m_whitePoint[1];
for (size_t i = 0; i < 3; ++i)
{
m_drmMetadata.hdmi_metadata_type1.display_primaries[i].x = m_ffmpegMetadata->m_displayPrimaries[i][0];
m_drmMetadata.hdmi_metadata_type1.display_primaries[i].y = m_ffmpegMetadata->m_displayPrimaries[i][1];
}
}
}

if (needhdrblob)
{
if (m_hdrBlob)
drmModeDestroyPropertyBlob(m_device->GetFD(), m_hdrBlob);
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Creating HDR info frame for %1")
.arg(eotf == HDMI_EOTF_BT_2100_HLG ? "HLG" : "HDR10"));
drmModeCreatePropertyBlob(m_device->GetFD(), &m_drmMetadata, sizeof(m_drmMetadata), &m_hdrBlob);
m_device->QueueAtomics({{ m_connector->m_id, m_hdrProp->m_id, m_hdrBlob }});
}
}
else
{
Reset();
}
}
30 changes: 30 additions & 0 deletions mythtv/libs/libmythtv/drm/mythhdrtrackerdrm.h
@@ -0,0 +1,30 @@
#ifndef MYTHHDRTRACKERDRM_H
#define MYTHHDRTRACKERDRM_H

// MythTV
#include "mythhdrtracker.h"
#include "drm/mythvideodrmutils.h"
#include "platforms/mythdrmdevice.h"
#include "platforms/drm/mythdrmproperty.h"

using DRMMeta = hdr_output_metadata;

class MythHDRTrackerDRM : public MythHDRTracker
{
public:
static HDRTracker Create(MythDisplay* _Display, int HDRSupport);
~MythHDRTrackerDRM() override;
void Update(MythVideoFrame* Frame) override;
void Reset() override;

protected:
MythHDRTrackerDRM(MythDRMPtr Device, DRMConn Connector, DRMProp HDRProp, int HDRSupport);

MythDRMPtr m_device { nullptr };
DRMConn m_connector { nullptr };
DRMProp m_hdrProp { nullptr };
DRMMeta m_drmMetadata;
uint32_t m_hdrBlob { 0 };
};

#endif
4 changes: 4 additions & 0 deletions mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -159,6 +159,7 @@ HEADERS += mythavutil.h
HEADERS += recordingfile.h
HEADERS += driveroption.h
HEADERS += mythhdrmetadata.h
HEADERS += mythhdrtracker.h

SOURCES += recordinginfo.cpp
SOURCES += dbcheck.cpp
Expand Down Expand Up @@ -196,6 +197,7 @@ SOURCES += mythframe.cpp
SOURCES += mythavutil.cpp
SOURCES += recordingfile.cpp
SOURCES += mythhdrmetadata.cpp
SOURCES += mythhdrtracker.cpp

# DiSEqC
HEADERS += diseqc.h diseqcsettings.h
Expand Down Expand Up @@ -533,9 +535,11 @@ using_frontend {
HEADERS += drm/mythvideodrm.h
HEADERS += drm/mythvideodrmbuffer.h
HEADERS += drm/mythvideodrmutils.h
HEADERS += drm/mythhdrtrackerdrm.h
SOURCES += drm/mythvideodrm.cpp
SOURCES += drm/mythvideodrmbuffer.cpp
SOURCES += drm/mythvideodrmutils.cpp
SOURCES += drm/mythhdrtrackerdrm.cpp
}

using_vaapi {
Expand Down
44 changes: 44 additions & 0 deletions mythtv/libs/libmythtv/mythhdrtracker.cpp
@@ -0,0 +1,44 @@
// MythTV
#ifdef USING_DRM_VIDEO
#include "drm/mythhdrtrackerdrm.h"
#endif
#include "mythhdrtracker.h"

HDRTracker MythHDRTracker::Create(MythDisplay* _Display)
{
if (!_Display)
return nullptr;

// Check the EDID for HDR support first
const auto & edid = _Display->GetEDID();
if (!edid.Valid())
return nullptr;

auto [types, metadata] = edid.GetHDRSupport();

// We only support HDR10 and HLG
if (types < MythEDID::HDR10)
{
LOG(VB_PLAYBACK, LOG_INFO, "No HDR support detected for this display");
return nullptr;
}

// We only know how to deal with HDR Static Metablock Type 1 (which is the only type)
if ((metadata & MythEDID::Static1) != MythEDID::Static1)
return nullptr;

HDRTracker result = nullptr;
#ifdef USING_DRM_VIDEO
result = MythHDRTrackerDRM::Create(_Display, types);
#endif

if (!result.get())
LOG(VB_PLAYBACK, LOG_INFO, "HDR signalling support not available");
return result;
}

MythHDRTracker::MythHDRTracker(int HDRSupport)
: m_hdrSupport(HDRSupport)
{
}

27 changes: 27 additions & 0 deletions mythtv/libs/libmythtv/mythhdrtracker.h
@@ -0,0 +1,27 @@
#ifndef MYTHHDRTRACKER_H
#define MYTHHDRTRACKER_H

// MythTV
#include "mythhdrmetadata.h"

// Std
#include <memory>

using HDRTracker = std::shared_ptr<class MythHDRTracker>;

class MythHDRTracker
{
public:
static HDRTracker Create(class MythDisplay* _Display);
virtual void Update(class MythVideoFrame* Frame) = 0;
virtual void Reset() = 0;

protected:
explicit MythHDRTracker(int HDRSupport);
virtual ~MythHDRTracker() = default;

MythHDRPtr m_ffmpegMetadata { nullptr };
int m_hdrSupport { 0 };
};

#endif

1 comment on commit b5465c0

@kmdewaal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my system compilation of mythhdrtracker.cpp fails:

mythhdrtracker.cpp: In static member function ‘static HDRTracker MythHDRTracker::Create(MythDisplay*)’:
mythhdrtracker.cpp:13:33: error: invalid use of incomplete type ‘class MythDisplay’
13 | const auto & edid = _Display->GetEDID();

Adding #include "mythdisplay.h" to get MythDisplay (and a lot more) defined fixes it for me.

Please sign in to comment.