refactor: enable EDR metadata for Metal and add more error handling
This commit is contained in:
@@ -104,7 +104,7 @@ static const NSUInteger MaxFramesInFlight = 3;
|
|||||||
|
|
||||||
// EDR tone-mapping is possible but it's unclear how
|
// EDR tone-mapping is possible but it's unclear how
|
||||||
// best to tone-map Windows content
|
// best to tone-map Windows content
|
||||||
static BOOL useEDR = NO;
|
static BOOL useEDR = YES;
|
||||||
|
|
||||||
CFStringRef __currentColorSpace;
|
CFStringRef __currentColorSpace;
|
||||||
|
|
||||||
@@ -223,14 +223,20 @@ CFStringRef __currentColorSpace;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyEDRFromFrame:(Frame *)frame withColorspace:(int)colorspace toLayer:(CAMetalLayer *)layer {
|
- (void)applyEDRFromFrame:(Frame *)frame withColorspace:(int)colorspace toLayer:(CAMetalLayer *)layer {
|
||||||
|
// Validate input parameters
|
||||||
|
if (!frame || !layer) {
|
||||||
|
Log(LOG_E, @"applyEDRFromFrame called with nil frame or layer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[self reportMaxEDRHeadroom];
|
[self reportMaxEDRHeadroom];
|
||||||
[self setInitialEDRMetadata];
|
[self setInitialEDRMetadata];
|
||||||
|
|
||||||
CFDictionaryRef ext = [frame getFormatDescExtensions];
|
CFDictionaryRef ext = [frame getFormatDescExtensions];
|
||||||
CFStringRef frame_trc = CFDictionaryGetValue(ext, kCVImageBufferTransferFunctionKey);
|
CFStringRef frame_trc = ext ? CFDictionaryGetValue(ext, kCVImageBufferTransferFunctionKey) : nil;
|
||||||
|
|
||||||
// These can only be changed on the main thread
|
// These can only be changed on the main thread
|
||||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
void (^updateLayerBlock)(void) = ^{
|
||||||
if (@available(iOS 16.0, *)) {
|
if (@available(iOS 16.0, *)) {
|
||||||
layer.wantsExtendedDynamicRangeContent = YES;
|
layer.wantsExtendedDynamicRangeContent = YES;
|
||||||
}
|
}
|
||||||
@@ -260,24 +266,49 @@ CFStringRef __currentColorSpace;
|
|||||||
|
|
||||||
// CAEDRMetadata is only available on iOS 16.0+
|
// CAEDRMetadata is only available on iOS 16.0+
|
||||||
if (@available(iOS 16.0, tvOS 16.0, *)) {
|
if (@available(iOS 16.0, tvOS 16.0, *)) {
|
||||||
CFDataRef masteringDisplayColorVolume = CVBufferCopyAttachment(frame.pixelBuffer, kCVImageBufferMasteringDisplayColorVolumeKey, nil);
|
if (frame.pixelBuffer) {
|
||||||
CFDataRef contentLightLevel = CVBufferCopyAttachment(frame.pixelBuffer, kCVImageBufferContentLightLevelInfoKey, nil);
|
CFDataRef masteringDisplayColorVolume = CVBufferCopyAttachment(frame.pixelBuffer, kCVImageBufferMasteringDisplayColorVolumeKey, nil);
|
||||||
if (masteringDisplayColorVolume) {
|
CFDataRef contentLightLevel = CVBufferCopyAttachment(frame.pixelBuffer, kCVImageBufferContentLightLevelInfoKey, nil);
|
||||||
// This tone-mapper does receive the host's max nits in MDCV when connecting to Windows,
|
|
||||||
// but I think using this for tone-mapping would break apps not using system calibration (most apps).
|
// Configure optical output scale (100.0f is standard for HDR10)
|
||||||
layer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithDisplayInfo:(__bridge NSData *)masteringDisplayColorVolume
|
const float opticalOutputScale = 100.0f;
|
||||||
contentInfo:contentLightLevel ? (__bridge NSData *)contentLightLevel : nil
|
|
||||||
opticalOutputScale:100.0f];
|
if (masteringDisplayColorVolume) {
|
||||||
} else {
|
// This tone-mapper does receive the host's max nits in MDCV when connecting to Windows,
|
||||||
layer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithMinLuminance:0.005f
|
// but I think using this for tone-mapping would break apps not using system calibration (most apps).
|
||||||
maxLuminance:1000.0f
|
layer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithDisplayInfo:(__bridge NSData *)masteringDisplayColorVolume
|
||||||
opticalOutputScale:100.0f];
|
contentInfo:contentLightLevel ? (__bridge NSData *)contentLightLevel : nil
|
||||||
|
opticalOutputScale:opticalOutputScale];
|
||||||
|
CFRelease(masteringDisplayColorVolume);
|
||||||
|
} else {
|
||||||
|
layer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithMinLuminance:0.005f
|
||||||
|
maxLuminance:1000.0f
|
||||||
|
opticalOutputScale:opticalOutputScale];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up contentLightLevel if it was created
|
||||||
|
if (contentLightLevel) {
|
||||||
|
CFRelease(contentLightLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOnce(LOG_I, @"EDRMetadata set to colorspace %@, transfer function %@, %@",
|
||||||
|
layer.colorspace,
|
||||||
|
frame_trc ? (__bridge NSString *)frame_trc : @"<none>",
|
||||||
|
layer.EDRMetadata);
|
||||||
}
|
}
|
||||||
LogOnce(LOG_I, @"EDRMetadata set to colorspace %@, transfer function %@, %@", layer.colorspace, frame_trc, layer.EDRMetadata);
|
|
||||||
} else {
|
} else {
|
||||||
LogOnce(LOG_I, @"EDRMetadata not available on iOS < 16.0, colorspace %@, transfer function %@", layer.colorspace, frame_trc);
|
LogOnce(LOG_I, @"EDRMetadata not available on iOS < 16.0, colorspace %@, transfer function %@",
|
||||||
|
layer.colorspace,
|
||||||
|
frame_trc ? (__bridge NSString *)frame_trc : @"<none>");
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Check if we're already on the main thread
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
updateLayerBlock();
|
||||||
|
} else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), updateLayerBlock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user