Plumb HDR metadata from Sunshine

This commit is contained in:
Cameron Gutman
2023-02-02 23:11:27 -06:00
parent cf665ec774
commit eefe8522c4
4 changed files with 69 additions and 2 deletions

View File

@@ -309,6 +309,7 @@ void ClConnectionStatusUpdate(int status)
void ClSetHdrMode(bool enabled)
{
[renderer setHdrMode:enabled];
[_callbacks setHdrMode:enabled];
}

View File

@@ -17,6 +17,7 @@
- (void)setupWithVideoFormat:(int)videoFormat frameRate:(int)frameRate;
- (void)start;
- (void)stop;
- (void)setHdrMode:(BOOL)enabled;
- (int)submitDecodeBuffer:(unsigned char *)data length:(int)length bufferType:(int)bufferType frameType:(int)frameType pts:(unsigned int)pts;

View File

@@ -22,6 +22,8 @@
int frameRate;
NSData *spsData, *ppsData, *vpsData;
NSData *masteringDisplayColorVolume;
NSData *contentLightLevelInfo;
CMVideoFormatDescriptionRef formatDesc;
CADisplayLink* _displayLink;
@@ -242,6 +244,16 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
const size_t parameterSetSizes[] = { [vpsData length], [spsData length], [ppsData length] };
Log(LOG_I, @"Constructing new HEVC format description");
NSMutableDictionary* videoFormatParams = [[NSMutableDictionary alloc] init];
if (contentLightLevelInfo) {
[videoFormatParams setObject:contentLightLevelInfo forKey:(__bridge NSString*)kCMFormatDescriptionExtension_ContentLightLevelInfo];
}
if (masteringDisplayColorVolume) {
[videoFormatParams setObject:masteringDisplayColorVolume forKey:(__bridge NSString*)kCMFormatDescriptionExtension_MasteringDisplayColorVolume];
}
if (@available(iOS 11.0, *)) {
status = CMVideoFormatDescriptionCreateFromHEVCParameterSets(kCFAllocatorDefault,
@@ -249,7 +261,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
parameterSetPointers,
parameterSetSizes,
NAL_LENGTH_PREFIX_SIZE,
nil,
(__bridge CFDictionaryRef)videoFormatParams,
&formatDesc);
} else {
// This means Moonlight-common-c decided to give us an HEVC stream
@@ -363,4 +375,57 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
return DR_OK;
}
- (void)setHdrMode:(BOOL)enabled {
// Free old metadata
masteringDisplayColorVolume = nil;
contentLightLevelInfo = nil;
// Update metadata from host if provided
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);
masteringDisplayColorVolume = [NSData dataWithBytes:&mdcv length: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);
contentLightLevelInfo = [NSData dataWithBytes:&cll length:sizeof(cll)];
}
}
// Request an IDR frame to trigger us to re-create the format with the adjusted metadata
LiRequestIdrFrame();
}
@end