@@ -23,10 +23,182 @@ final class DefaultCamera: FLTCam, Camera {
23
23
24
24
/// Maximum number of frames pending processing.
25
25
/// 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.
27
27
/// https://github.com/flutter/plugins/pull/4520#discussion_r766335637
28
28
private var maxStreamingPendingFramesCount = 4
29
29
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
+
30
202
func captureOutput(
31
203
_ output: AVCaptureOutput ,
32
204
didOutput sampleBuffer: CMSampleBuffer ,
@@ -240,6 +412,22 @@ final class DefaultCamera: FLTCam, Camera {
240
412
}
241
413
}
242
414
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
+
243
431
func copyPixelBuffer( ) -> Unmanaged < CVPixelBuffer > ? {
244
432
var pixelBuffer : CVPixelBuffer ?
245
433
pixelBufferSynchronizationQueue. sync {
0 commit comments