mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-17 14:43:09 +00:00
Plumb HDR metadata for VideoToolbox
This commit is contained in:
parent
c65cea0f66
commit
5de29928cd
1 changed files with 77 additions and 0 deletions
|
@ -38,6 +38,8 @@ public:
|
||||||
: m_HwContext(nullptr),
|
: m_HwContext(nullptr),
|
||||||
m_DisplayLayer(nullptr),
|
m_DisplayLayer(nullptr),
|
||||||
m_FormatDesc(nullptr),
|
m_FormatDesc(nullptr),
|
||||||
|
m_ContentLightLevelInfo(nullptr),
|
||||||
|
m_MasteringDisplayColorVolume(nullptr),
|
||||||
m_StreamView(nullptr),
|
m_StreamView(nullptr),
|
||||||
m_DisplayLink(nullptr),
|
m_DisplayLink(nullptr),
|
||||||
m_LastColorSpace(-1),
|
m_LastColorSpace(-1),
|
||||||
|
@ -87,6 +89,14 @@ public:
|
||||||
CGColorSpaceRelease(m_ColorSpace);
|
CGColorSpaceRelease(m_ColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_MasteringDisplayColorVolume != nullptr) {
|
||||||
|
CFRelease(m_MasteringDisplayColorVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ContentLightLevelInfo != nullptr) {
|
||||||
|
CFRelease(m_ContentLightLevelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Overlay::OverlayMax; i++) {
|
for (int i = 0; i < Overlay::OverlayMax; i++) {
|
||||||
if (m_OverlayTextFields[i] != nullptr) {
|
if (m_OverlayTextFields[i] != nullptr) {
|
||||||
[m_OverlayTextFields[i] removeFromSuperview];
|
[m_OverlayTextFields[i] removeFromSuperview];
|
||||||
|
@ -183,6 +193,63 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void setHdrMode(bool enabled) override
|
||||||
|
{
|
||||||
|
// Free existing HDR metadata
|
||||||
|
if (m_MasteringDisplayColorVolume != nullptr) {
|
||||||
|
CFRelease(m_MasteringDisplayColorVolume);
|
||||||
|
m_MasteringDisplayColorVolume = nullptr;
|
||||||
|
}
|
||||||
|
if (m_ContentLightLevelInfo != nullptr) {
|
||||||
|
CFRelease(m_ContentLightLevelInfo);
|
||||||
|
m_ContentLightLevelInfo = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store new HDR metadata if available
|
||||||
|
SS_HDR_METADATA hdrMetadata;
|
||||||
|
if (enabled && LiGetHdrMetadata(&hdrMetadata)) {
|
||||||
|
if (hdrMetadata.displayPrimaries[0].x != 0 && hdrMetadata.maxDisplayLuminance != 0) {
|
||||||
|
// This data is all in big-endian
|
||||||
|
struct {
|
||||||
|
vector_ushort2 primaries[3];
|
||||||
|
vector_ushort2 white_point;
|
||||||
|
uint32_t luminance_max;
|
||||||
|
uint32_t luminance_min;
|
||||||
|
} __attribute__((packed, aligned(4))) mdcv;
|
||||||
|
|
||||||
|
// mdcv is in GBR order while SS_HDR_METADATA is in RGB order
|
||||||
|
mdcv.primaries[0].x = __builtin_bswap16(hdrMetadata.displayPrimaries[1].x);
|
||||||
|
mdcv.primaries[0].y = __builtin_bswap16(hdrMetadata.displayPrimaries[1].y);
|
||||||
|
mdcv.primaries[1].x = __builtin_bswap16(hdrMetadata.displayPrimaries[2].x);
|
||||||
|
mdcv.primaries[1].y = __builtin_bswap16(hdrMetadata.displayPrimaries[2].y);
|
||||||
|
mdcv.primaries[2].x = __builtin_bswap16(hdrMetadata.displayPrimaries[0].x);
|
||||||
|
mdcv.primaries[2].y = __builtin_bswap16(hdrMetadata.displayPrimaries[0].y);
|
||||||
|
|
||||||
|
mdcv.white_point.x = __builtin_bswap16(hdrMetadata.whitePoint.x);
|
||||||
|
mdcv.white_point.y = __builtin_bswap16(hdrMetadata.whitePoint.y);
|
||||||
|
|
||||||
|
// These luminance values are in 10000ths of a nit
|
||||||
|
mdcv.luminance_max = __builtin_bswap32((uint32_t)hdrMetadata.maxDisplayLuminance * 10000);
|
||||||
|
mdcv.luminance_min = __builtin_bswap32(hdrMetadata.minDisplayLuminance);
|
||||||
|
|
||||||
|
m_MasteringDisplayColorVolume = CFDataCreate(nullptr, (const UInt8*)&mdcv, sizeof(mdcv));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdrMetadata.maxContentLightLevel != 0 && hdrMetadata.maxFrameAverageLightLevel != 0) {
|
||||||
|
// This data is all in big-endian
|
||||||
|
struct {
|
||||||
|
uint16_t max_content_light_level;
|
||||||
|
uint16_t max_frame_average_light_level;
|
||||||
|
} __attribute__((packed, aligned(2))) cll;
|
||||||
|
|
||||||
|
cll.max_content_light_level = __builtin_bswap16(hdrMetadata.maxContentLightLevel);
|
||||||
|
cll.max_frame_average_light_level = __builtin_bswap16(hdrMetadata.maxFrameAverageLightLevel);
|
||||||
|
|
||||||
|
m_ContentLightLevelInfo = CFDataCreate(nullptr, (const UInt8*)&cll, sizeof(cll));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Caller frees frame after we return
|
// Caller frees frame after we return
|
||||||
virtual void renderFrame(AVFrame* frame) override
|
virtual void renderFrame(AVFrame* frame) override
|
||||||
{
|
{
|
||||||
|
@ -238,6 +305,14 @@ public:
|
||||||
CVBufferSetAttachment(pixBuf, kCVImageBufferCGColorSpaceKey, m_ColorSpace, kCVAttachmentMode_ShouldPropagate);
|
CVBufferSetAttachment(pixBuf, kCVImageBufferCGColorSpaceKey, m_ColorSpace, kCVAttachmentMode_ShouldPropagate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attach HDR metadata if it has been provided by the host
|
||||||
|
if (m_MasteringDisplayColorVolume != nullptr) {
|
||||||
|
CVBufferSetAttachment(pixBuf, kCVImageBufferMasteringDisplayColorVolumeKey, m_MasteringDisplayColorVolume, kCVAttachmentMode_ShouldPropagate);
|
||||||
|
}
|
||||||
|
if (m_ContentLightLevelInfo != nullptr) {
|
||||||
|
CVBufferSetAttachment(pixBuf, kCVImageBufferContentLightLevelInfoKey, m_ContentLightLevelInfo, kCVAttachmentMode_ShouldPropagate);
|
||||||
|
}
|
||||||
|
|
||||||
// If the format has changed or doesn't exist yet, construct it with the
|
// If the format has changed or doesn't exist yet, construct it with the
|
||||||
// pixel buffer data
|
// pixel buffer data
|
||||||
if (!m_FormatDesc || !CMVideoFormatDescriptionMatchesImageBuffer(m_FormatDesc, pixBuf)) {
|
if (!m_FormatDesc || !CMVideoFormatDescriptionMatchesImageBuffer(m_FormatDesc, pixBuf)) {
|
||||||
|
@ -512,6 +587,8 @@ private:
|
||||||
AVBufferRef* m_HwContext;
|
AVBufferRef* m_HwContext;
|
||||||
AVSampleBufferDisplayLayer* m_DisplayLayer;
|
AVSampleBufferDisplayLayer* m_DisplayLayer;
|
||||||
CMVideoFormatDescriptionRef m_FormatDesc;
|
CMVideoFormatDescriptionRef m_FormatDesc;
|
||||||
|
CFDataRef m_ContentLightLevelInfo;
|
||||||
|
CFDataRef m_MasteringDisplayColorVolume;
|
||||||
NSView* m_StreamView;
|
NSView* m_StreamView;
|
||||||
dispatch_block_t m_OverlayUpdateBlocks[Overlay::OverlayMax];
|
dispatch_block_t m_OverlayUpdateBlocks[Overlay::OverlayMax];
|
||||||
NSTextField* m_OverlayTextFields[Overlay::OverlayMax];
|
NSTextField* m_OverlayTextFields[Overlay::OverlayMax];
|
||||||
|
|
Loading…
Reference in a new issue