feat: Split videoHdr and photoHdr into two settings (#2161)

* feat: Split `videoHdr` and `photoHdr` into two settings

* fix: Rename all `hdr`

* fix: Fix HDR on Android

* Update CameraDeviceDetails.kt

* Update CameraDeviceDetails.kt

* fix: Correctly configure `pixelFormat` AFTER `format`

* Update CameraSession+Configuration.swift

* fix: Also after format changed
This commit is contained in:
Marc Rousavy
2023-11-15 18:33:12 +01:00
committed by GitHub
parent 75fd924899
commit c5dfb6c247
26 changed files with 129 additions and 88 deletions

View File

@@ -38,7 +38,8 @@ public final class CameraView: UIView, CameraSessionDelegate {
// props that require format reconfiguring
@objc var format: NSDictionary?
@objc var fps: NSNumber?
@objc var hdr = false
@objc var videoHdr = false
@objc var photoHdr = false
@objc var lowLightBoost = false
@objc var orientation: NSString?
// other props
@@ -164,7 +165,7 @@ public final class CameraView: UIView, CameraSessionDelegate {
if video || enableFrameProcessor {
config.video = .enabled(config: CameraConfiguration.Video(pixelFormat: getPixelFormat(),
enableBufferCompression: enableBufferCompression,
enableHdr: hdr,
enableHdr: videoHdr,
enableFrameProcessor: enableFrameProcessor))
} else {
config.video = .disabled

View File

@@ -36,7 +36,8 @@ RCT_EXPORT_VIEW_PROPERTY(enableFrameProcessor, BOOL);
// device format
RCT_EXPORT_VIEW_PROPERTY(format, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(fps, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(hdr, BOOL);
RCT_EXPORT_VIEW_PROPERTY(videoHdr, BOOL);
RCT_EXPORT_VIEW_PROPERTY(photoHdr, BOOL);
RCT_EXPORT_VIEW_PROPERTY(lowLightBoost, BOOL);
RCT_EXPORT_VIEW_PROPERTY(videoStabilizationMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(pixelFormat, NSString);

View File

@@ -207,7 +207,7 @@ extension CameraConfiguration.Video {
// Find the best matching format
guard let format = videoOutput.findPixelFormat(firstOf: targetFormats) else {
throw CameraError.format(.invalidHdr)
throw CameraError.format(.invalidVideoHdr)
}
// YUV 4:2:0 10-bit (compressed/uncompressed)
return format

View File

@@ -108,7 +108,7 @@ enum DeviceError: String {
enum FormatError {
case invalidFps(fps: Int)
case invalidHdr
case invalidVideoHdr
case invalidFormat
case incompatiblePixelFormatWithHDR
@@ -118,8 +118,8 @@ enum FormatError {
return "invalid-format"
case .invalidFps:
return "invalid-fps"
case .invalidHdr:
return "invalid-hdr"
case .invalidVideoHdr:
return "invalid-video-hdr"
case .incompatiblePixelFormatWithHDR:
return "incompatible-pixel-format-with-hdr-setting"
}
@@ -131,8 +131,8 @@ enum FormatError {
return "The given format was invalid. Did you check if the current device supports the given format in `device.formats`?"
case let .invalidFps(fps):
return "The given format cannot run at \(fps) FPS! Make sure your FPS is lower than `format.maxFps` but higher than `format.minFps`."
case .invalidHdr:
return "The currently selected format does not support HDR capture! Make sure you select a format which includes `supportsPhotoHDR`/`supportsVideoHDR`!"
case .invalidVideoHdr:
return "The currently selected format does not support 10-bit Video HDR streaming! Make sure you select a format which includes `supportsVideoHdr`!"
case .incompatiblePixelFormatWithHDR:
return "The currently selected pixelFormat is not compatible with HDR! HDR only works with the `yuv` pixelFormat."
}

View File

@@ -100,7 +100,7 @@ extension CameraSession {
}
// Video Output + Frame Processor
if case let .enabled(video) = configuration.video {
if case .enabled = configuration.video {
ReactLogger.log(level: .info, message: "Adding Video Data output...")
// 1. Add
@@ -113,11 +113,6 @@ extension CameraSession {
// 2. Configure
videoOutput.setSampleBufferDelegate(self, queue: CameraQueues.videoQueue)
videoOutput.alwaysDiscardsLateVideoFrames = true
let pixelFormatType = try video.getPixelFormat(for: videoOutput)
videoOutput.videoSettings = [
String(kCVPixelBufferPixelFormatTypeKey): pixelFormatType,
]
self.videoOutput = videoOutput
}
@@ -210,6 +205,21 @@ extension CameraSession {
ReactLogger.log(level: .info, message: "Successfully configured Format!")
}
func configurePixelFormat(configuration: CameraConfiguration) throws {
guard case let .enabled(video) = configuration.video,
let videoOutput else {
// Video is not enabled
return
}
// Configure the VideoOutput Settings to use the given Pixel Format.
// We need to run this after device.activeFormat has been set, otherwise the VideoOutput can't stream the given Pixel Format.
let pixelFormatType = try video.getPixelFormat(for: videoOutput)
videoOutput.videoSettings = [
String(kCVPixelBufferPixelFormatTypeKey): pixelFormatType,
]
}
// pragma MARK: Side-Props
/**

View File

@@ -141,21 +141,26 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
if difference.formatChanged {
try self.configureFormat(configuration: config, device: device)
}
// 5. Configure side-props (fps, lowLightBoost)
// 5. After step 2. and 4., we also need to configure the PixelFormat.
// This needs to be done AFTER we updated the `format`, as this controls the supported PixelFormats.
if difference.outputsChanged || difference.formatChanged {
try self.configurePixelFormat(configuration: config)
}
// 6. Configure side-props (fps, lowLightBoost)
if difference.sidePropsChanged {
try self.configureSideProps(configuration: config, device: device)
}
// 6. Configure zoom
// 7. Configure zoom
if difference.zoomChanged {
self.configureZoom(configuration: config, device: device)
}
}
}
// 7. Start or stop the session if needed
// 8. Start or stop the session if needed
self.checkIsActive(configuration: config)
// 8. Enable or disable the Torch if needed (requires session to be running)
// 9. Enable or disable the Torch if needed (requires session to be running)
if difference.torchChanged {
try self.withDeviceLock { device in
try self.configureTorch(configuration: config, device: device)

View File

@@ -28,7 +28,7 @@ extension AVCaptureDevice.Format {
return maxRange?.maxFrameRate ?? 0
}
var supportsVideoHDR: Bool {
var supportsVideoHdr: Bool {
let pixelFormat = CMFormatDescriptionGetMediaSubType(formatDescription)
let hdrFormats = [
kCVPixelFormatType_420YpCbCr10BiPlanarFullRange,
@@ -38,7 +38,7 @@ extension AVCaptureDevice.Format {
return hdrFormats.contains(pixelFormat)
}
var supportsPhotoHDR: Bool {
var supportsPhotoHdr: Bool {
// TODO: Supports Photo HDR on iOS?
return false
}

View File

@@ -31,8 +31,8 @@ struct CameraDeviceFormat: Equatable, CustomStringConvertible {
let videoStabilizationModes: [VideoStabilizationMode]
let autoFocusSystem: AutoFocusSystem
let supportsVideoHDR: Bool
let supportsPhotoHDR: Bool
let supportsVideoHdr: Bool
let supportsPhotoHdr: Bool
let pixelFormats: [PixelFormat]
@@ -51,8 +51,8 @@ struct CameraDeviceFormat: Equatable, CustomStringConvertible {
maxZoom = format.videoMaxZoomFactor
videoStabilizationModes = format.videoStabilizationModes.map { VideoStabilizationMode(from: $0) }
autoFocusSystem = AutoFocusSystem(fromFocusSystem: format.autoFocusSystem)
supportsVideoHDR = format.supportsVideoHDR
supportsPhotoHDR = format.supportsPhotoHDR
supportsVideoHdr = format.supportsVideoHdr
supportsPhotoHdr = format.supportsPhotoHdr
pixelFormats = CameraDeviceFormat.getAllPixelFormats()
supportsDepthCapture = format.supportsDepthCapture
}
@@ -73,8 +73,8 @@ struct CameraDeviceFormat: Equatable, CustomStringConvertible {
videoStabilizationModes = try jsVideoStabilizationModes.map { try VideoStabilizationMode(jsValue: $0) }
let jsAutoFocusSystem = jsValue["autoFocusSystem"] as! String
autoFocusSystem = try AutoFocusSystem(jsValue: jsAutoFocusSystem)
supportsVideoHDR = jsValue["supportsVideoHDR"] as! Bool
supportsPhotoHDR = jsValue["supportsPhotoHDR"] as! Bool
supportsVideoHdr = jsValue["supportsVideoHdr"] as! Bool
supportsPhotoHdr = jsValue["supportsPhotoHdr"] as! Bool
let jsPixelFormats = jsValue["pixelFormats"] as! [String]
pixelFormats = try jsPixelFormats.map { try PixelFormat(jsValue: $0) }
supportsDepthCapture = jsValue["supportsDepthCapture"] as! Bool
@@ -98,8 +98,8 @@ struct CameraDeviceFormat: Equatable, CustomStringConvertible {
"minISO": minISO,
"fieldOfView": fieldOfView,
"maxZoom": maxZoom,
"supportsVideoHDR": supportsVideoHDR,
"supportsPhotoHDR": supportsPhotoHDR,
"supportsVideoHdr": supportsVideoHdr,
"supportsPhotoHdr": supportsPhotoHdr,
"minFps": minFps,
"maxFps": maxFps,
"pixelFormats": pixelFormats.map(\.jsValue),