@@ -23,10 +23,182 @@ final class DefaultCamera: FLTCam, Camera {
2323
2424 /// Maximum number of frames pending processing.
2525 /// To limit memory consumption, limit the number of frames pending processing.
26- /// After some testing, 4 was determined to be the best maximuńm value.
26+ /// After some testing, 4 was determined to be the best maximum value.
2727 /// https://github.com/flutter/plugins/pull/4520#discussion_r766335637
2828 private var maxStreamingPendingFramesCount = 4
2929
30+ private var exposureMode = FCPPlatformExposureMode . auto
31+ private var focusMode = FCPPlatformFocusMode . auto
32+
33+ func reportInitializationState( ) {
34+ // Get all the state on the current thread, not the main thread.
35+ let state = FCPPlatformCameraState . make (
36+ withPreviewSize: FCPPlatformSize . make (
37+ withWidth: Double ( previewSize. width) ,
38+ height: Double ( previewSize. height)
39+ ) ,
40+ exposureMode: exposureMode,
41+ focusMode: focusMode,
42+ exposurePointSupported: captureDevice. isExposurePointOfInterestSupported,
43+ focusPointSupported: captureDevice. isFocusPointOfInterestSupported
44+ )
45+
46+ FLTEnsureToRunOnMainQueue { [ weak self] in
47+ self ? . dartAPI? . initialized ( with: state) { _ in
48+ // Ignore any errors, as this is just an event broadcast.
49+ }
50+ }
51+ }
52+
53+ func receivedImageStreamData( ) {
54+ streamingPendingFramesCount -= 1
55+ }
56+
57+ func start( ) {
58+ videoCaptureSession. startRunning ( )
59+ audioCaptureSession. startRunning ( )
60+ }
61+
62+ func stop( ) {
63+ videoCaptureSession. stopRunning ( )
64+ audioCaptureSession. stopRunning ( )
65+ }
66+
67+ func setExposureMode( _ mode: FCPPlatformExposureMode ) {
68+ exposureMode = mode
69+ applyExposureMode ( )
70+ }
71+
72+ private func applyExposureMode( ) {
73+ try ? captureDevice. lockForConfiguration ( )
74+ switch exposureMode {
75+ case . locked:
76+ // AVCaptureExposureMode.autoExpose automatically adjusts the exposure one time, and then locks exposure for the device
77+ captureDevice. setExposureMode ( . autoExpose)
78+ case . auto:
79+ if captureDevice. isExposureModeSupported ( . continuousAutoExposure) {
80+ captureDevice. setExposureMode ( . continuousAutoExposure)
81+ } else {
82+ captureDevice. setExposureMode ( . autoExpose)
83+ }
84+ @unknown default :
85+ assertionFailure ( " Unknown exposure mode " )
86+ }
87+ captureDevice. unlockForConfiguration ( )
88+ }
89+
90+ func setExposureOffset( _ offset: Double ) {
91+ try ? captureDevice. lockForConfiguration ( )
92+ captureDevice. setExposureTargetBias ( Float ( offset) , completionHandler: nil )
93+ captureDevice. unlockForConfiguration ( )
94+ }
95+
96+ func setExposurePoint(
97+ _ point: FCPPlatformPoint ? , withCompletion completion: @escaping ( FlutterError ? ) -> Void
98+ ) {
99+ guard captureDevice. isExposurePointOfInterestSupported else {
100+ completion (
101+ FlutterError (
102+ code: " setExposurePointFailed " ,
103+ message: " Device does not have exposure point capabilities " ,
104+ details: nil ) )
105+ return
106+ }
107+
108+ let orientation = UIDevice . current. orientation
109+ try ? captureDevice. lockForConfiguration ( )
110+ // A nil point resets to the center.
111+ let exposurePoint = cgPoint (
112+ for: point ?? FCPPlatformPoint . makeWith ( x: 0.5 , y: 0.5 ) , withOrientation: orientation)
113+ captureDevice. setExposurePointOfInterest ( exposurePoint)
114+ captureDevice. unlockForConfiguration ( )
115+ // Retrigger auto exposure
116+ applyExposureMode ( )
117+ completion ( nil )
118+ }
119+
120+ func setFocusMode( _ mode: FCPPlatformFocusMode ) {
121+ focusMode = mode
122+ applyFocusMode ( )
123+ }
124+
125+ func setFocusPoint( _ point: FCPPlatformPoint ? , completion: @escaping ( FlutterError ? ) -> Void ) {
126+ guard captureDevice. isFocusPointOfInterestSupported else {
127+ completion (
128+ FlutterError (
129+ code: " setFocusPointFailed " ,
130+ message: " Device does not have focus point capabilities " ,
131+ details: nil ) )
132+ return
133+ }
134+
135+ let orientation = deviceOrientationProvider. orientation ( )
136+ try ? captureDevice. lockForConfiguration ( )
137+ // A nil point resets to the center.
138+ captureDevice. setFocusPointOfInterest (
139+ cgPoint (
140+ for: point ?? . makeWith( x: 0.5 , y: 0.5 ) ,
141+ withOrientation: orientation)
142+ )
143+ captureDevice. unlockForConfiguration ( )
144+ // Retrigger auto focus
145+ applyFocusMode ( )
146+ completion ( nil )
147+ }
148+
149+ private func applyFocusMode( ) {
150+ applyFocusMode ( focusMode, onDevice: captureDevice)
151+ }
152+
153+ private func applyFocusMode(
154+ _ focusMode: FCPPlatformFocusMode , onDevice captureDevice: FLTCaptureDevice
155+ ) {
156+ try ? captureDevice. lockForConfiguration ( )
157+ switch focusMode {
158+ case . locked:
159+ // AVCaptureFocusMode.autoFocus automatically adjusts the focus one time, and then locks focus
160+ if captureDevice. isFocusModeSupported ( . autoFocus) {
161+ captureDevice. setFocusMode ( . autoFocus)
162+ }
163+ case . auto:
164+ if captureDevice. isFocusModeSupported ( . continuousAutoFocus) {
165+ captureDevice. setFocusMode ( . continuousAutoFocus)
166+ } else if captureDevice. isFocusModeSupported ( . autoFocus) {
167+ captureDevice. setFocusMode ( . autoFocus)
168+ }
169+ @unknown default :
170+ assertionFailure ( " Unknown focus mode " )
171+ }
172+ captureDevice. unlockForConfiguration ( )
173+ }
174+
175+ private func cgPoint(
176+ for point: FCPPlatformPoint , withOrientation orientation: UIDeviceOrientation
177+ )
178+ -> CGPoint
179+ {
180+ var x = point. x
181+ var y = point. y
182+ switch orientation {
183+ case . portrait: // 90 ccw
184+ y = 1 - point. x
185+ x = point. y
186+ case . portraitUpsideDown: // 90 cw
187+ x = 1 - point. y
188+ y = point. x
189+ case . landscapeRight: // 180
190+ x = 1 - point. x
191+ y = 1 - point. y
192+ case . landscapeLeft:
193+ // No rotation required
194+ break
195+ default :
196+ // No rotation required
197+ break
198+ }
199+ return CGPoint ( x: x, y: y)
200+ }
201+
30202 func captureOutput(
31203 _ output: AVCaptureOutput ,
32204 didOutput sampleBuffer: CMSampleBuffer ,
@@ -240,6 +412,22 @@ final class DefaultCamera: FLTCam, Camera {
240412 }
241413 }
242414
415+ func close( ) {
416+ stop ( )
417+ for input in videoCaptureSession. inputs {
418+ videoCaptureSession. removeInput ( FLTDefaultCaptureInput ( input: input) )
419+ }
420+ for output in videoCaptureSession. outputs {
421+ videoCaptureSession. removeOutput ( output)
422+ }
423+ for input in audioCaptureSession. inputs {
424+ audioCaptureSession. removeInput ( FLTDefaultCaptureInput ( input: input) )
425+ }
426+ for output in audioCaptureSession. outputs {
427+ audioCaptureSession. removeOutput ( output)
428+ }
429+ }
430+
243431 func copyPixelBuffer( ) -> Unmanaged < CVPixelBuffer > ? {
244432 var pixelBuffer : CVPixelBuffer ?
245433 pixelBufferSynchronizationQueue. sync {
0 commit comments