feat: Custom Orientation (#715)
* feat: Custom Orientation * Update CameraView.swift * Update CameraView.swift * Try outputRotation approach * whoops * fix: Refactor `VideoCapture` instance * Update orientation in didSetProps * Update Orientation in iOS * expose to objc * Fix Orientation values * format
This commit is contained in:
parent
dbfdf82c67
commit
48da1819fc
@ -41,8 +41,8 @@ fun CameraView.startRecording(options: ReadableMap, onRecordCallback: Callback)
|
|||||||
val file = File.createTempFile("VisionCamera-${id}", ".mp4")
|
val file = File.createTempFile("VisionCamera-${id}", ".mp4")
|
||||||
val fileOptions = FileOutputOptions.Builder(file).build()
|
val fileOptions = FileOutputOptions.Builder(file).build()
|
||||||
|
|
||||||
var recording = videoCapture!!
|
val recorder = videoCapture!!.output
|
||||||
.prepareRecording(context, fileOptions)
|
var recording = recorder.prepareRecording(context, fileOptions)
|
||||||
|
|
||||||
if (audio == true) {
|
if (audio == true) {
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
|
@ -97,6 +97,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
var isActive = false
|
var isActive = false
|
||||||
var torch = "off"
|
var torch = "off"
|
||||||
var zoom: Float = 1f // in "factor"
|
var zoom: Float = 1f // in "factor"
|
||||||
|
var orientation: String? = null
|
||||||
var enableZoomGesture = false
|
var enableZoomGesture = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
@ -124,7 +125,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
|
|
||||||
internal var camera: Camera? = null
|
internal var camera: Camera? = null
|
||||||
internal var imageCapture: ImageCapture? = null
|
internal var imageCapture: ImageCapture? = null
|
||||||
internal var videoCapture: Recorder? = null
|
internal var videoCapture: VideoCapture<Recorder>? = null
|
||||||
private var imageAnalysis: ImageAnalysis? = null
|
private var imageAnalysis: ImageAnalysis? = null
|
||||||
private var preview: Preview? = null
|
private var preview: Preview? = null
|
||||||
|
|
||||||
@ -141,10 +142,26 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
private val lifecycleRegistry: LifecycleRegistry
|
private val lifecycleRegistry: LifecycleRegistry
|
||||||
private var hostLifecycleState: Lifecycle.State
|
private var hostLifecycleState: Lifecycle.State
|
||||||
|
|
||||||
private val rotation: Int
|
private val inputRotation: Int
|
||||||
get() {
|
get() {
|
||||||
return context.displayRotation
|
return context.displayRotation
|
||||||
}
|
}
|
||||||
|
private val outputRotation: Int
|
||||||
|
get() {
|
||||||
|
if (orientation != null) {
|
||||||
|
// user is overriding output orientation
|
||||||
|
return when (orientation!!) {
|
||||||
|
"portrait" -> Surface.ROTATION_0
|
||||||
|
"landscapeRight" -> Surface.ROTATION_90
|
||||||
|
"portraitUpsideDown" -> Surface.ROTATION_180
|
||||||
|
"landscapeLeft" -> Surface.ROTATION_270
|
||||||
|
else -> throw InvalidTypeScriptUnionError("orientation", orientation!!)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// use same as input rotation
|
||||||
|
return inputRotation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var minZoom: Float = 1f
|
private var minZoom: Float = 1f
|
||||||
private var maxZoom: Float = 1f
|
private var maxZoom: Float = 1f
|
||||||
@ -234,16 +251,17 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
|
updateOrientation()
|
||||||
|
}
|
||||||
|
|
||||||
if (preview?.targetRotation != rotation) {
|
@SuppressLint("RestrictedApi")
|
||||||
preview?.targetRotation = rotation
|
private fun updateOrientation() {
|
||||||
imageCapture?.targetRotation = rotation
|
preview?.targetRotation = inputRotation
|
||||||
imageAnalysis?.targetRotation = rotation
|
imageCapture?.targetRotation = outputRotation
|
||||||
// TODO: videoCapture?.setTargetRotation(rotation)
|
videoCapture?.targetRotation = outputRotation
|
||||||
}
|
imageAnalysis?.targetRotation = outputRotation
|
||||||
}
|
}
|
||||||
|
|
||||||
private external fun initHybrid(): HybridData
|
private external fun initHybrid(): HybridData
|
||||||
@ -298,6 +316,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
val shouldReconfigureSession = changedProps.containsAny(propsThatRequireSessionReconfiguration)
|
val shouldReconfigureSession = changedProps.containsAny(propsThatRequireSessionReconfiguration)
|
||||||
val shouldReconfigureZoom = shouldReconfigureSession || changedProps.contains("zoom")
|
val shouldReconfigureZoom = shouldReconfigureSession || changedProps.contains("zoom")
|
||||||
val shouldReconfigureTorch = shouldReconfigureSession || changedProps.contains("torch")
|
val shouldReconfigureTorch = shouldReconfigureSession || changedProps.contains("torch")
|
||||||
|
val shouldUpdateOrientation = shouldReconfigureSession || changedProps.contains("orientation")
|
||||||
|
|
||||||
if (changedProps.contains("isActive")) {
|
if (changedProps.contains("isActive")) {
|
||||||
updateLifecycleState()
|
updateLifecycleState()
|
||||||
@ -312,6 +331,9 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
if (shouldReconfigureTorch) {
|
if (shouldReconfigureTorch) {
|
||||||
camera!!.cameraControl.enableTorch(torch == "on")
|
camera!!.cameraControl.enableTorch(torch == "on")
|
||||||
}
|
}
|
||||||
|
if (shouldUpdateOrientation) {
|
||||||
|
updateOrientation()
|
||||||
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Log.e(TAG, "update() threw: ${e.message}")
|
Log.e(TAG, "update() threw: ${e.message}")
|
||||||
invokeOnError(e)
|
invokeOnError(e)
|
||||||
@ -362,17 +384,17 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
}
|
}
|
||||||
|
|
||||||
val previewBuilder = Preview.Builder()
|
val previewBuilder = Preview.Builder()
|
||||||
.setTargetRotation(rotation)
|
.setTargetRotation(inputRotation)
|
||||||
|
|
||||||
val imageCaptureBuilder = ImageCapture.Builder()
|
val imageCaptureBuilder = ImageCapture.Builder()
|
||||||
.setTargetRotation(rotation)
|
.setTargetRotation(outputRotation)
|
||||||
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
||||||
|
|
||||||
val videoRecorderBuilder = Recorder.Builder()
|
val videoRecorderBuilder = Recorder.Builder()
|
||||||
.setExecutor(cameraExecutor)
|
.setExecutor(cameraExecutor)
|
||||||
|
|
||||||
val imageAnalysisBuilder = ImageAnalysis.Builder()
|
val imageAnalysisBuilder = ImageAnalysis.Builder()
|
||||||
.setTargetRotation(rotation)
|
.setTargetRotation(outputRotation)
|
||||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
.setBackgroundExecutor(frameProcessorThread)
|
.setBackgroundExecutor(frameProcessorThread)
|
||||||
|
|
||||||
@ -422,12 +444,9 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val videoRecorder = videoRecorderBuilder.build()
|
|
||||||
val videoCapture = VideoCapture.withOutput(videoRecorder)
|
|
||||||
videoCapture.targetRotation = rotation
|
|
||||||
|
|
||||||
// Unbind use cases before rebinding
|
// Unbind use cases before rebinding
|
||||||
this.videoCapture = null
|
videoCapture = null
|
||||||
imageCapture = null
|
imageCapture = null
|
||||||
imageAnalysis = null
|
imageAnalysis = null
|
||||||
cameraProvider.unbindAll()
|
cameraProvider.unbindAll()
|
||||||
@ -436,8 +455,11 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
|||||||
val useCases = ArrayList<UseCase>()
|
val useCases = ArrayList<UseCase>()
|
||||||
if (video == true) {
|
if (video == true) {
|
||||||
Log.i(TAG, "Adding VideoCapture use-case...")
|
Log.i(TAG, "Adding VideoCapture use-case...")
|
||||||
this.videoCapture = videoRecorder
|
|
||||||
useCases.add(videoCapture)
|
val videoRecorder = videoRecorderBuilder.build()
|
||||||
|
videoCapture = VideoCapture.withOutput(videoRecorder)
|
||||||
|
videoCapture!!.targetRotation = outputRotation
|
||||||
|
useCases.add(videoCapture!!)
|
||||||
}
|
}
|
||||||
if (photo == true) {
|
if (photo == true) {
|
||||||
if (fallbackToSnapshot) {
|
if (fallbackToSnapshot) {
|
||||||
|
@ -165,6 +165,13 @@ class CameraViewManager(reactContext: ReactApplicationContext) : SimpleViewManag
|
|||||||
view.enableZoomGesture = enableZoomGesture
|
view.enableZoomGesture = enableZoomGesture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "orientation")
|
||||||
|
fun setOrientation(view: CameraView, orientation: String) {
|
||||||
|
if (view.orientation != orientation)
|
||||||
|
addChangedPropToTransaction(view, "orientation")
|
||||||
|
view.orientation = orientation
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "CameraView"
|
const val TAG = "CameraView"
|
||||||
|
|
||||||
|
@ -230,6 +230,7 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
|
|||||||
video={true}
|
video={true}
|
||||||
audio={hasMicrophonePermission}
|
audio={hasMicrophonePermission}
|
||||||
frameProcessor={device.supportsParallelVideoProcessing ? frameProcessor : undefined}
|
frameProcessor={device.supportsParallelVideoProcessing ? frameProcessor : undefined}
|
||||||
|
orientation="portrait"
|
||||||
frameProcessorFps={1}
|
frameProcessorFps={1}
|
||||||
onFrameProcessorPerformanceSuggestionAvailable={onFrameProcessorSuggestionAvailable}
|
onFrameProcessorPerformanceSuggestionAvailable={onFrameProcessorSuggestionAvailable}
|
||||||
/>
|
/>
|
||||||
|
61
ios/CameraView+Orientation.swift
Normal file
61
ios/CameraView+Orientation.swift
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// CameraView+Orientation.swift
|
||||||
|
// VisionCamera
|
||||||
|
//
|
||||||
|
// Created by Marc Rousavy on 04.01.22.
|
||||||
|
// Copyright © 2022 mrousavy. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension CameraView {
|
||||||
|
/// Returns the current _interface_ orientation of the main window
|
||||||
|
private var windowInterfaceOrientation: UIInterfaceOrientation {
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .unknown
|
||||||
|
} else {
|
||||||
|
return UIApplication.shared.statusBarOrientation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Orientation of the input connection (preview)
|
||||||
|
private var inputOrientation: UIInterfaceOrientation {
|
||||||
|
return windowInterfaceOrientation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orientation of the output connections (photo, video, frame processor)
|
||||||
|
private var outputOrientation: UIInterfaceOrientation {
|
||||||
|
if let userOrientation = orientation as String?,
|
||||||
|
let parsedOrientation = try? UIInterfaceOrientation(withString: userOrientation) {
|
||||||
|
// user is overriding output orientation
|
||||||
|
return parsedOrientation
|
||||||
|
} else {
|
||||||
|
// use same as input orientation
|
||||||
|
return inputOrientation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal func updateOrientation() {
|
||||||
|
// Updates the Orientation for all rotable connections (outputs) as well as for the preview layer
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// `windowInterfaceOrientation` and `videoPreviewLayer` should only be accessed from UI thread
|
||||||
|
let isMirrored = self.videoDeviceInput?.device.position == .front
|
||||||
|
|
||||||
|
self.videoPreviewLayer.connection?.setInterfaceOrientation(self.inputOrientation)
|
||||||
|
|
||||||
|
self.cameraQueue.async {
|
||||||
|
// Run those updates on cameraQueue since they can be blocking.
|
||||||
|
self.captureSession.outputs.forEach { output in
|
||||||
|
output.connections.forEach { connection in
|
||||||
|
if connection.isVideoMirroringSupported {
|
||||||
|
connection.automaticallyAdjustsVideoMirroring = false
|
||||||
|
connection.isVideoMirrored = isMirrored
|
||||||
|
}
|
||||||
|
connection.setInterfaceOrientation(self.outputOrientation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -56,6 +56,7 @@ public final class CameraView: UIView {
|
|||||||
@objc var hdr: NSNumber? // nullable bool
|
@objc var hdr: NSNumber? // nullable bool
|
||||||
@objc var lowLightBoost: NSNumber? // nullable bool
|
@objc var lowLightBoost: NSNumber? // nullable bool
|
||||||
@objc var colorSpace: NSString?
|
@objc var colorSpace: NSString?
|
||||||
|
@objc var orientation: NSString?
|
||||||
// other props
|
// other props
|
||||||
@objc var isActive = false
|
@objc var isActive = false
|
||||||
@objc var torch = "off"
|
@objc var torch = "off"
|
||||||
@ -116,15 +117,6 @@ public final class CameraView: UIView {
|
|||||||
return captureSession.isRunning
|
return captureSession.isRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current _interface_ orientation of the main window
|
|
||||||
private var windowInterfaceOrientation: UIInterfaceOrientation {
|
|
||||||
if #available(iOS 13.0, *) {
|
|
||||||
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .unknown
|
|
||||||
} else {
|
|
||||||
return UIApplication.shared.statusBarOrientation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience wrapper to get layer as its statically known type.
|
/// Convenience wrapper to get layer as its statically known type.
|
||||||
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
|
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
|
||||||
// swiftlint:disable force_cast
|
// swiftlint:disable force_cast
|
||||||
@ -205,6 +197,7 @@ public final class CameraView: UIView {
|
|||||||
let shouldUpdateTorch = willReconfigure || changedProps.contains("torch") || shouldCheckActive
|
let shouldUpdateTorch = willReconfigure || changedProps.contains("torch") || shouldCheckActive
|
||||||
let shouldUpdateZoom = willReconfigure || changedProps.contains("zoom") || shouldCheckActive
|
let shouldUpdateZoom = willReconfigure || changedProps.contains("zoom") || shouldCheckActive
|
||||||
let shouldUpdateVideoStabilization = willReconfigure || changedProps.contains("videoStabilizationMode")
|
let shouldUpdateVideoStabilization = willReconfigure || changedProps.contains("videoStabilizationMode")
|
||||||
|
let shouldUpdateOrientation = changedProps.contains("orientation")
|
||||||
|
|
||||||
if shouldReconfigure ||
|
if shouldReconfigure ||
|
||||||
shouldReconfigureAudioSession ||
|
shouldReconfigureAudioSession ||
|
||||||
@ -213,7 +206,8 @@ public final class CameraView: UIView {
|
|||||||
shouldUpdateZoom ||
|
shouldUpdateZoom ||
|
||||||
shouldReconfigureFormat ||
|
shouldReconfigureFormat ||
|
||||||
shouldReconfigureDevice ||
|
shouldReconfigureDevice ||
|
||||||
shouldUpdateVideoStabilization {
|
shouldUpdateVideoStabilization ||
|
||||||
|
shouldUpdateOrientation {
|
||||||
cameraQueue.async {
|
cameraQueue.async {
|
||||||
if shouldReconfigure {
|
if shouldReconfigure {
|
||||||
self.configureCaptureSession()
|
self.configureCaptureSession()
|
||||||
@ -246,6 +240,10 @@ public final class CameraView: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if shouldUpdateOrientation {
|
||||||
|
self.updateOrientation()
|
||||||
|
}
|
||||||
|
|
||||||
// This is a wack workaround, but if I immediately set torch mode after `startRunning()`, the session isn't quite ready yet and will ignore torch.
|
// This is a wack workaround, but if I immediately set torch mode after `startRunning()`, the session isn't quite ready yet and will ignore torch.
|
||||||
if shouldUpdateTorch {
|
if shouldUpdateTorch {
|
||||||
self.cameraQueue.asyncAfter(deadline: .now() + 0.1) {
|
self.cameraQueue.asyncAfter(deadline: .now() + 0.1) {
|
||||||
@ -316,27 +314,7 @@ public final class CameraView: UIView {
|
|||||||
|
|
||||||
@objc
|
@objc
|
||||||
func onOrientationChanged() {
|
func onOrientationChanged() {
|
||||||
// Updates the Orientation for all rotable connections (outputs) as well as for the preview layer
|
updateOrientation()
|
||||||
DispatchQueue.main.async {
|
|
||||||
// `windowInterfaceOrientation` and `videoPreviewLayer` should only be accessed from UI thread
|
|
||||||
let isMirrored = self.videoDeviceInput?.device.position == .front
|
|
||||||
let orientation = self.windowInterfaceOrientation
|
|
||||||
|
|
||||||
self.videoPreviewLayer.connection?.setInterfaceOrientation(orientation)
|
|
||||||
|
|
||||||
self.cameraQueue.async {
|
|
||||||
// Run those updates on cameraQueue since they can be blocking.
|
|
||||||
self.captureSession.outputs.forEach { output in
|
|
||||||
output.connections.forEach { connection in
|
|
||||||
if connection.isVideoMirroringSupported {
|
|
||||||
connection.automaticallyAdjustsVideoMirroring = false
|
|
||||||
connection.isVideoMirrored = isMirrored
|
|
||||||
}
|
|
||||||
connection.setInterfaceOrientation(orientation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pragma MARK: Event Invokers
|
// pragma MARK: Event Invokers
|
||||||
|
@ -45,6 +45,7 @@ RCT_EXPORT_VIEW_PROPERTY(preset, NSString);
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(torch, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(torch, NSString);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(zoom, NSNumber);
|
RCT_EXPORT_VIEW_PROPERTY(zoom, NSNumber);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(enableZoomGesture, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(enableZoomGesture, BOOL);
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(orientation, NSString);
|
||||||
// Camera View Events
|
// Camera View Events
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock);
|
||||||
|
31
ios/Parsers/UIInterfaceOrientation+descriptor.swift
Normal file
31
ios/Parsers/UIInterfaceOrientation+descriptor.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// UIInterfaceOrientation+descriptor.swift
|
||||||
|
// VisionCamera
|
||||||
|
//
|
||||||
|
// Created by Marc Rousavy on 04.01.22.
|
||||||
|
// Copyright © 2022 mrousavy. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIInterfaceOrientation {
|
||||||
|
init(withString string: String) throws {
|
||||||
|
switch string {
|
||||||
|
case "portrait":
|
||||||
|
self = .portrait
|
||||||
|
return
|
||||||
|
case "portraitUpsideDown":
|
||||||
|
self = .portraitUpsideDown
|
||||||
|
return
|
||||||
|
case "landscapeLeft":
|
||||||
|
self = .landscapeLeft
|
||||||
|
return
|
||||||
|
case "landscapeRight":
|
||||||
|
self = .landscapeRight
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
throw EnumParserError.invalidValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,8 @@
|
|||||||
B82FBA962614B69D00909718 /* RCTBridge+runOnJS.mm in Sources */ = {isa = PBXBuildFile; fileRef = B82FBA952614B69D00909718 /* RCTBridge+runOnJS.mm */; };
|
B82FBA962614B69D00909718 /* RCTBridge+runOnJS.mm in Sources */ = {isa = PBXBuildFile; fileRef = B82FBA952614B69D00909718 /* RCTBridge+runOnJS.mm */; };
|
||||||
B84760A62608EE7C004C3180 /* FrameHostObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = B84760A52608EE7C004C3180 /* FrameHostObject.mm */; };
|
B84760A62608EE7C004C3180 /* FrameHostObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = B84760A52608EE7C004C3180 /* FrameHostObject.mm */; };
|
||||||
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84760DE2608F57D004C3180 /* CameraQueues.swift */; };
|
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84760DE2608F57D004C3180 /* CameraQueues.swift */; };
|
||||||
|
B864005027849A2400E9D2CA /* UIInterfaceOrientation+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B864004F27849A2400E9D2CA /* UIInterfaceOrientation+descriptor.swift */; };
|
||||||
|
B86400522784A23400E9D2CA /* CameraView+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86400512784A23400E9D2CA /* CameraView+Orientation.swift */; };
|
||||||
B86DC971260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */; };
|
B86DC971260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */; };
|
||||||
B86DC974260E310600FB17B2 /* CameraView+AVAudioSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */; };
|
B86DC974260E310600FB17B2 /* CameraView+AVAudioSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */; };
|
||||||
B86DC977260E315100FB17B2 /* CameraView+AVCaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */; };
|
B86DC977260E315100FB17B2 /* CameraView+AVCaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */; };
|
||||||
@ -93,6 +95,8 @@
|
|||||||
B84760A52608EE7C004C3180 /* FrameHostObject.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameHostObject.mm; sourceTree = "<group>"; };
|
B84760A52608EE7C004C3180 /* FrameHostObject.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameHostObject.mm; sourceTree = "<group>"; };
|
||||||
B84760DE2608F57D004C3180 /* CameraQueues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraQueues.swift; sourceTree = "<group>"; };
|
B84760DE2608F57D004C3180 /* CameraQueues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraQueues.swift; sourceTree = "<group>"; };
|
||||||
B84C10592694A182006EFA70 /* MakeJSIRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MakeJSIRuntime.h; sourceTree = "<group>"; };
|
B84C10592694A182006EFA70 /* MakeJSIRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MakeJSIRuntime.h; sourceTree = "<group>"; };
|
||||||
|
B864004F27849A2400E9D2CA /* UIInterfaceOrientation+descriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIInterfaceOrientation+descriptor.swift"; sourceTree = "<group>"; };
|
||||||
|
B86400512784A23400E9D2CA /* CameraView+Orientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+Orientation.swift"; sourceTree = "<group>"; };
|
||||||
B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVAudioSession+trySetAllowHaptics.swift"; sourceTree = "<group>"; };
|
B86DC970260E2D5200FB17B2 /* AVAudioSession+trySetAllowHaptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVAudioSession+trySetAllowHaptics.swift"; sourceTree = "<group>"; };
|
||||||
B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVAudioSession.swift"; sourceTree = "<group>"; };
|
B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVAudioSession.swift"; sourceTree = "<group>"; };
|
||||||
B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVCaptureSession.swift"; sourceTree = "<group>"; };
|
B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVCaptureSession.swift"; sourceTree = "<group>"; };
|
||||||
@ -180,6 +184,7 @@
|
|||||||
B887515D25E0102000DB86D6 /* CameraView+RecordVideo.swift */,
|
B887515D25E0102000DB86D6 /* CameraView+RecordVideo.swift */,
|
||||||
B887517125E0102000DB86D6 /* CameraView+TakePhoto.swift */,
|
B887517125E0102000DB86D6 /* CameraView+TakePhoto.swift */,
|
||||||
B887518225E0102000DB86D6 /* CameraView+Zoom.swift */,
|
B887518225E0102000DB86D6 /* CameraView+Zoom.swift */,
|
||||||
|
B86400512784A23400E9D2CA /* CameraView+Orientation.swift */,
|
||||||
B887515F25E0102000DB86D6 /* CameraViewManager.m */,
|
B887515F25E0102000DB86D6 /* CameraViewManager.m */,
|
||||||
B887518125E0102000DB86D6 /* CameraViewManager.swift */,
|
B887518125E0102000DB86D6 /* CameraViewManager.swift */,
|
||||||
B8DB3BC9263DC4D8004C18D7 /* RecordingSession.swift */,
|
B8DB3BC9263DC4D8004C18D7 /* RecordingSession.swift */,
|
||||||
@ -248,6 +253,7 @@
|
|||||||
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */,
|
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */,
|
||||||
B887517F25E0102000DB86D6 /* AVCaptureDevice.Format.AutoFocusSystem+descriptor.swift */,
|
B887517F25E0102000DB86D6 /* AVCaptureDevice.Format.AutoFocusSystem+descriptor.swift */,
|
||||||
B8DB3BCB263DC97E004C18D7 /* AVFileType+descriptor.swift */,
|
B8DB3BCB263DC97E004C18D7 /* AVFileType+descriptor.swift */,
|
||||||
|
B864004F27849A2400E9D2CA /* UIInterfaceOrientation+descriptor.swift */,
|
||||||
);
|
);
|
||||||
path = Parsers;
|
path = Parsers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -391,12 +397,14 @@
|
|||||||
B80E06A0266632F000728644 /* AVAudioSession+updateCategory.swift in Sources */,
|
B80E06A0266632F000728644 /* AVAudioSession+updateCategory.swift in Sources */,
|
||||||
B887519425E0102000DB86D6 /* MakeReactError.swift in Sources */,
|
B887519425E0102000DB86D6 /* MakeReactError.swift in Sources */,
|
||||||
B887519525E0102000DB86D6 /* ReactLogger.swift in Sources */,
|
B887519525E0102000DB86D6 /* ReactLogger.swift in Sources */,
|
||||||
|
B86400522784A23400E9D2CA /* CameraView+Orientation.swift in Sources */,
|
||||||
B887519B25E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift in Sources */,
|
B887519B25E0102000DB86D6 /* AVCaptureSession.Preset+descriptor.swift in Sources */,
|
||||||
B88751A725E0102000DB86D6 /* CameraView+Zoom.swift in Sources */,
|
B88751A725E0102000DB86D6 /* CameraView+Zoom.swift in Sources */,
|
||||||
B887518525E0102000DB86D6 /* PhotoCaptureDelegate.swift in Sources */,
|
B887518525E0102000DB86D6 /* PhotoCaptureDelegate.swift in Sources */,
|
||||||
B887518B25E0102000DB86D6 /* AVCaptureDevice.Format+isBetterThan.swift in Sources */,
|
B887518B25E0102000DB86D6 /* AVCaptureDevice.Format+isBetterThan.swift in Sources */,
|
||||||
B8BD3BA2266E22D2006C80A2 /* Callback.swift in Sources */,
|
B8BD3BA2266E22D2006C80A2 /* Callback.swift in Sources */,
|
||||||
B84760A62608EE7C004C3180 /* FrameHostObject.mm in Sources */,
|
B84760A62608EE7C004C3180 /* FrameHostObject.mm in Sources */,
|
||||||
|
B864005027849A2400E9D2CA /* UIInterfaceOrientation+descriptor.swift in Sources */,
|
||||||
B8103E1C25FF553B007A1684 /* FrameProcessorUtils.mm in Sources */,
|
B8103E1C25FF553B007A1684 /* FrameProcessorUtils.mm in Sources */,
|
||||||
B887518E25E0102000DB86D6 /* AVFrameRateRange+includes.swift in Sources */,
|
B887518E25E0102000DB86D6 /* AVFrameRateRange+includes.swift in Sources */,
|
||||||
B88751A125E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift in Sources */,
|
B88751A125E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift in Sources */,
|
||||||
|
@ -156,6 +156,10 @@ export interface CameraProps extends ViewProps {
|
|||||||
* @default false
|
* @default false
|
||||||
*/
|
*/
|
||||||
enableHighQualityPhotos?: boolean;
|
enableHighQualityPhotos?: boolean;
|
||||||
|
/**
|
||||||
|
* Represents the orientation of the Camera, and all outputs. If this value is not set, VisionCamera will use the device orientation per default.
|
||||||
|
*/
|
||||||
|
orientation?: 'portrait' | 'portraitUpsideDown' | 'landscapeLeft' | 'landscapeRight';
|
||||||
|
|
||||||
//#region Events
|
//#region Events
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user