Skip to content

Commit

Permalink
fix: Properly set maxPhotoDimensions on PhotoOutput (#2659)
Browse files Browse the repository at this point in the history
* fix: Properly set `maxPhotoDimensions` on PhotoOutput

* fix: Remove `maxPhotoDimensions` since it is the highest value by default anyways I think

* fix: Remove `enableHighQualityPhotos` entirely

* fix: Update RN Worklets

* Revert "fix: Remove `enableHighQualityPhotos` entirely"

This reverts commit 7110b76.

* fix: Use high res capture / maxPhotoDimensions always.

* Update CameraSession+Configuration.swift
  • Loading branch information
mrousavy authored Mar 19, 2024
1 parent ca6518f commit 7f14f25
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 62 deletions.
8 changes: 4 additions & 4 deletions package/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ PODS:
- react-native-video/Video (= 5.2.1)
- react-native-video/Video (5.2.1):
- React-Core
- react-native-worklets-core (0.3.0):
- react-native-worklets-core (0.4.0):
- React
- React-callinvoker
- React-Core
Expand Down Expand Up @@ -484,7 +484,7 @@ PODS:
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.10)
- SocketRocket (0.6.1)
- VisionCamera (4.0.0-beta.6):
- VisionCamera (4.0.0-beta.7):
- React
- React-callinvoker
- React-Core
Expand Down Expand Up @@ -697,7 +697,7 @@ SPEC CHECKSUMS:
react-native-mmkv: e97c0c79403fb94577e5d902ab1ebd42b0715b43
react-native-safe-area-context: 0ee144a6170530ccc37a0fd9388e28d06f516a89
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
react-native-worklets-core: a894d572639fcf37c6d284cc799882d25d00c93d
react-native-worklets-core: 2efe80a3ee87fe5e6fefa814e0e20c2708d3ad25
React-NativeModulesApple: b6868ee904013a7923128892ee4a032498a1024a
React-perflogger: 31ea61077185eb1428baf60c0db6e2886f141a5a
React-RCTActionSheet: 392090a3abc8992eb269ef0eaa561750588fc39d
Expand All @@ -724,7 +724,7 @@ SPEC CHECKSUMS:
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
VisionCamera: 7a9e59cc5e65d458d9809a9ac23700265df0f14e
VisionCamera: e0f80a131dbfa1361fdfc0231cb02e3312903acf
Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5

PODFILE CHECKSUM: 27f53791141a3303d814e09b55770336416ff4eb
Expand Down
2 changes: 1 addition & 1 deletion package/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"react-native-static-safe-area-insets": "^2.2.0",
"react-native-vector-icons": "^10.0.0",
"react-native-video": "^5.2.1",
"react-native-worklets-core": "0.3.0"
"react-native-worklets-core": "0.4.0"
},
"devDependencies": {
"@babel/core": "^7.22.10",
Expand Down
8 changes: 4 additions & 4 deletions package/example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5178,10 +5178,10 @@ react-native-video@^5.2.1:
prop-types "^15.7.2"
shaka-player "^2.5.9"

react-native-worklets-core@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/react-native-worklets-core/-/react-native-worklets-core-0.3.0.tgz#4d6c4c4999d3bf2f8c67fa46fdd70d8b5bc7ba0e"
integrity sha512-bOoo6xbl+f+mz0Q65bLkUP3FxgYt7f/Bzi0c5Yj8Ix4vQCKMtgHwafrqCNRhW32N7TpTv3+zOoyQMJwQVr/frQ==
react-native-worklets-core@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/react-native-worklets-core/-/react-native-worklets-core-0.4.0.tgz#708f204d89327d88e155cccb5fc23421ca764b6f"
integrity sha512-0rYCwxnG6L85mih+3xe1r2RhhwKqjgVN9jikVh0iMPKDf9L4OZMJnl6Kh4zjXiW9rkyI5lBghfM4XIcLMfeU6w==
dependencies:
string-hash-64 "^1.0.3"

Expand Down
6 changes: 2 additions & 4 deletions package/ios/CameraView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public final class CameraView: UIView, CameraSessionDelegate {
// props that require reconfiguring
@objc var cameraId: NSString?
@objc var enableDepthData = false
@objc var enableHighQualityPhotos = false
@objc var enablePortraitEffectsMatteDelivery = false
@objc var enableBufferCompression = false
// use cases
Expand Down Expand Up @@ -179,10 +178,9 @@ public final class CameraView: UIView, CameraSessionDelegate {

// Photo
if photo {
config.photo = .enabled(config: CameraConfiguration.Photo(enableHighQualityPhotos: enableHighQualityPhotos,
config.photo = .enabled(config: CameraConfiguration.Photo(qualityBalance: getPhotoQualityBalance(),
enableDepthData: enableDepthData,
enablePortraitEffectsMatte: enablePortraitEffectsMatteDelivery,
qualityBalance: getPhotoQualityBalance()))
enablePortraitEffectsMatte: enablePortraitEffectsMatteDelivery))
} else {
config.photo = .disabled
}
Expand Down
1 change: 0 additions & 1 deletion package/ios/CameraViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ @interface RCT_EXTERN_REMAP_MODULE (CameraView, CameraViewManager, RCTViewManage
RCT_EXPORT_VIEW_PROPERTY(isActive, BOOL);
RCT_EXPORT_VIEW_PROPERTY(cameraId, NSString);
RCT_EXPORT_VIEW_PROPERTY(enableDepthData, BOOL);
RCT_EXPORT_VIEW_PROPERTY(enableHighQualityPhotos, BOOL);
RCT_EXPORT_VIEW_PROPERTY(enablePortraitEffectsMatteDelivery, BOOL);
RCT_EXPORT_VIEW_PROPERTY(enableBufferCompression, BOOL);
// use cases
Expand Down
3 changes: 1 addition & 2 deletions package/ios/Core/CameraConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,9 @@ class CameraConfiguration {
A Photo Output configuration
*/
struct Photo: Equatable {
var enableHighQualityPhotos = false
var qualityBalance = QualityBalance.balanced
var enableDepthData = false
var enablePortraitEffectsMatte = false
var qualityBalance = QualityBalance.balanced
}

/**
Expand Down
35 changes: 17 additions & 18 deletions package/ios/Core/CameraSession+Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,6 @@ extension CameraSession {
let qualityPrioritization = AVCapturePhotoOutput.QualityPrioritization(fromQualityBalance: photo.qualityBalance)
photoOutput.maxPhotoQualityPrioritization = qualityPrioritization
}
if photo.enableHighQualityPhotos {
// TODO: Refactor this into an extension method. Same for AVCapturePhotoOutput.
if #available(iOS 16.0, *) {
if let device = videoDeviceInput?.device,
let targetFormat = configuration.format {
guard let format = device.formats.first(where: { f in targetFormat.isEqualTo(format: f) }) else {
throw CameraError.parameter(.invalid(unionName: "format", receivedValue: targetFormat.toJSValue().description))
}
guard let maxSupportedDimension = format.supportedMaxPhotoDimensions.max(by: { ($0.width * $0.height) < ($1.width * $1.height) }) else {
throw CameraError.unknown(message: "supportedMaxPhotoDimensions was empty!", cause: nil)
}
photoOutput.maxPhotoDimensions = maxSupportedDimension
}
} else {
photoOutput.isHighResolutionCaptureEnabled = true
}
}
// TODO: Enable isResponsiveCaptureEnabled? (iOS 17+)
// TODO: Enable isFastCapturePrioritizationEnabled? (iOS 17+)
if photo.enableDepthData {
Expand Down Expand Up @@ -215,7 +198,7 @@ extension CameraSession {
ReactLogger.log(level: .info, message: "Successfully configured Format!")
}

func configurePixelFormat(configuration: CameraConfiguration) throws {
func configureVideoOutputFormat(configuration: CameraConfiguration) throws {
guard case let .enabled(video) = configuration.video,
let videoOutput else {
// Video is not enabled
Expand All @@ -230,6 +213,22 @@ extension CameraSession {
]
}

func configurePhotoOutputFormat(configuration _: CameraConfiguration) throws {
guard let videoDeviceInput, let photoOutput else {
// Photo is not enabled
return
}

// Configure the PhotoOutput Settings to use the given max-resolution.
// We need to run this after device.activeFormat has been set, otherwise the resolution is different.
let format = videoDeviceInput.device.activeFormat
if #available(iOS 16.0, *) {
photoOutput.maxPhotoDimensions = format.photoDimensions
} else {
photoOutput.isHighResolutionCaptureEnabled = true
}
}

// pragma MARK: Side-Props

/**
Expand Down
13 changes: 5 additions & 8 deletions package/ios/Core/CameraSession+Photo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,11 @@ extension CameraSession {
// Create photo settings
let photoSettings = AVCapturePhotoSettings()

// high resolution capture
if photo.enableHighQualityPhotos {
// TODO: On iOS 16+ this will be removed in favor of maxPhotoDimensions.
if #available(iOS 16.0, *) {
photoSettings.maxPhotoDimensions = photoOutput.maxPhotoDimensions
} else {
photoSettings.isHighResolutionPhotoEnabled = true
}
// set photo resolution
if #available(iOS 16.0, *) {
photoSettings.maxPhotoDimensions = photoOutput.maxPhotoDimensions
} else {
photoSettings.isHighResolutionPhotoEnabled = photoOutput.isHighResolutionCaptureEnabled
}

// depth data
Expand Down
7 changes: 4 additions & 3 deletions package/ios/Core/CameraSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,11 @@ class CameraSession: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, AVC
if difference.formatChanged {
try self.configureFormat(configuration: config, device: device)
}
// 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.
// 5. After step 2. and 4., we also need to configure some output properties that depend on format.
// This needs to be done AFTER we updated the `format`, as this controls the supported properties.
if difference.outputsChanged || difference.formatChanged {
try self.configurePixelFormat(configuration: config)
try self.configureVideoOutputFormat(configuration: config)
try self.configurePhotoOutputFormat(configuration: config)
}
// 6. Configure side-props (fps, lowLightBoost)
if difference.sidePropsChanged {
Expand Down
2 changes: 1 addition & 1 deletion package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"react": "^18.2.0",
"react-native": "^0.72.3",
"react-native-builder-bob": "^0.21.3",
"react-native-worklets-core": "^0.3.0",
"react-native-worklets-core": "^0.4.0",
"release-it": "^16.1.3",
"typescript": "^5.1.6"
},
Expand Down
12 changes: 0 additions & 12 deletions package/src/CameraProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,18 +265,6 @@ export interface CameraProps extends ViewProps {
* @default false
*/
enablePortraitEffectsMatteDelivery?: boolean
/**
* Indicates whether the Camera should prepare the photo pipeline to provide maximum quality photos.
*
* This enables:
* * High Resolution Capture ([`isHighResolutionCaptureEnabled`](https://developer.apple.com/documentation/avfoundation/avcapturephotooutput/1648721-ishighresolutioncaptureenabled))
* * Virtual Device fusion for greater detail ([`isVirtualDeviceConstituentPhotoDeliveryEnabled`](https://developer.apple.com/documentation/avfoundation/avcapturephotooutput/3192189-isvirtualdeviceconstituentphotod))
* * Dual Device fusion for greater detail ([`isDualCameraDualPhotoDeliveryEnabled`](https://developer.apple.com/documentation/avfoundation/avcapturephotosettings/2873917-isdualcameradualphotodeliveryena))
*
* @platform iOS
* @default false
*/
enableHighQualityPhotos?: boolean
/**
* If `true`, show a debug view to display the FPS of the Video Pipeline (Frame Processor).
* This is useful for debugging your Frame Processor's speed.
Expand Down
8 changes: 4 additions & 4 deletions package/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6599,10 +6599,10 @@ react-native-builder-bob@^0.21.3:
optionalDependencies:
jetifier "^2.0.0"

react-native-worklets-core@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/react-native-worklets-core/-/react-native-worklets-core-0.3.0.tgz#4d6c4c4999d3bf2f8c67fa46fdd70d8b5bc7ba0e"
integrity sha512-bOoo6xbl+f+mz0Q65bLkUP3FxgYt7f/Bzi0c5Yj8Ix4vQCKMtgHwafrqCNRhW32N7TpTv3+zOoyQMJwQVr/frQ==
react-native-worklets-core@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/react-native-worklets-core/-/react-native-worklets-core-0.4.0.tgz#708f204d89327d88e155cccb5fc23421ca764b6f"
integrity sha512-0rYCwxnG6L85mih+3xe1r2RhhwKqjgVN9jikVh0iMPKDf9L4OZMJnl6Kh4zjXiW9rkyI5lBghfM4XIcLMfeU6w==
dependencies:
string-hash-64 "^1.0.3"

Expand Down

0 comments on commit 7f14f25

Please sign in to comment.