Skip to content

Commit 7f4d39c

Browse files
committed
[camera_avfoundation] Adds support for video stabilization
- Implements getSupportedVideoStabilizationModes() and setVideoStabilizationMode() methods in AVFoundationCamera.
1 parent 3caa48b commit 7f4d39c

File tree

24 files changed

+649
-27
lines changed

24 files changed

+649
-27
lines changed

packages/camera/camera_avfoundation/AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,4 @@ Aleksandr Yurkovskiy <sanekyy@gmail.com>
6464
Anton Borries <mail@antonborri.es>
6565
Alex Li <google@alexv525.com>
6666
Rahul Raj <64.rahulraj@gmail.com>
67+
Rui Craveiro <ruicraveiro@squarealfa.com>

packages/camera/camera_avfoundation/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.10.0
2+
3+
* Adds video stabilization.
4+
15
## 0.9.22+4
26

37
* Migrates `FLTCameraDeviceDiscovering` and `FLTDeviceOrientationProviding` classes to Swift.

packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 60;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -340,8 +340,6 @@
340340
03BB766E2665316900CE5A93 /* PBXTargetDependency */,
341341
);
342342
name = RunnerTests;
343-
packageProductDependencies = (
344-
);
345343
productName = camera_exampleTests;
346344
productReference = 03BB76682665316900CE5A93 /* RunnerTests.xctest */;
347345
productType = "com.apple.product-type.bundle.unit-test";
@@ -401,7 +399,7 @@
401399
);
402400
mainGroup = 97C146E51CF9000F007C117D;
403401
packageReferences = (
404-
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
402+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
405403
);
406404
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
407405
projectDirPath = "";
@@ -879,7 +877,7 @@
879877
/* End XCConfigurationList section */
880878

881879
/* Begin XCLocalSwiftPackageReference section */
882-
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
880+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
883881
isa = XCLocalSwiftPackageReference;
884882
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
885883
};

packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
buildConfiguration = "Debug"
4545
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
4646
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
47+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
4748
shouldUseLaunchSchemeArgsEnv = "YES">
4849
<MacroExpansion>
4950
<BuildableReference
@@ -71,6 +72,7 @@
7172
buildConfiguration = "Debug"
7273
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
7374
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
75+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
7476
launchStyle = "0"
7577
useCustomWorkingDirectory = "NO"
7678
ignoresPersistentStateOnLaunch = "NO"

packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCamera.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ final class MockCamera: NSObject, Camera {
4141
var setDescriptionWhileRecordingStub: ((String, ((FlutterError?) -> Void)?) -> Void)?
4242
var startImageStreamStub: ((FlutterBinaryMessenger, (FlutterError?) -> Void) -> Void)?
4343
var stopImageStreamStub: (() -> Void)?
44+
var setVideoStabilizationModeStub:
45+
((FCPPlatformVideoStabilizationMode, (FlutterError?) -> Void) -> Void)?
46+
var getIsVideoStabilizationModeSupportedStub: ((FCPPlatformVideoStabilizationMode) -> Bool)?
4447

4548
var dartAPI: FCPCameraEventApi? {
4649
get {
@@ -185,6 +188,16 @@ final class MockCamera: NSObject, Camera {
185188
resumePreviewStub?()
186189
}
187190

191+
func setVideoStabilizationMode(
192+
_ mode: FCPPlatformVideoStabilizationMode, withCompletion: @escaping (FlutterError?) -> Void
193+
) {
194+
setVideoStabilizationModeStub?(mode, withCompletion)
195+
}
196+
197+
func isVideoStabilizationModeSupported(_ mode: FCPPlatformVideoStabilizationMode) -> Bool {
198+
return getIsVideoStabilizationModeSupportedStub?(mode) ?? false
199+
}
200+
188201
func setDescriptionWhileRecording(
189202
_ cameraName: String,
190203
withCompletion completion: @escaping (FlutterError?) -> Void

packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureConnection.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ final class MockCaptureConnection: NSObject, FLTCaptureConnection {
2626
var inputPorts: [AVCaptureInput.Port] = []
2727
var isVideoMirroringSupported = false
2828
var isVideoOrientationSupported = false
29+
var preferredVideoStabilizationMode = AVCaptureVideoStabilizationMode.off
2930
}

packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureDevice.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ class MockCaptureDevice: NSObject, FLTCaptureDevice {
114114
return 0
115115
}
116116

117+
func isVideoStabilizationModeSupported(_ videoStabilizationMode: AVCaptureVideoStabilizationMode)
118+
-> Bool
119+
{
120+
return false
121+
}
122+
117123
func lockForConfiguration() throws {
118124
try lockForConfigurationStub?()
119125
}

packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/Camera.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ protocol Camera: FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate,
102102

103103
func setZoomLevel(_ zoom: CGFloat, withCompletion: @escaping (_ error: FlutterError?) -> Void)
104104

105+
func setVideoStabilizationMode(
106+
_ mode: FCPPlatformVideoStabilizationMode,
107+
withCompletion: @escaping (_ error: FlutterError?) -> Void)
108+
109+
func isVideoStabilizationModeSupported(_ mode: FCPPlatformVideoStabilizationMode) -> Bool
110+
105111
func setFlashMode(
106112
_ mode: FCPPlatformFlashMode,
107113
withCompletion: @escaping (_ error: FlutterError?) -> Void

packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,28 @@ extension CameraPlugin: FCPCameraApi {
517517
}
518518
}
519519

520+
public func setVideoStabilizationMode(
521+
_ mode: FCPPlatformVideoStabilizationMode, completion: @escaping (FlutterError?) -> Void
522+
) {
523+
captureSessionQueue.async { [weak self] in
524+
self?.camera?.setVideoStabilizationMode(mode, withCompletion: completion)
525+
}
526+
}
527+
528+
public func isVideoStabilizationModeSupported(
529+
_ mode: FCPPlatformVideoStabilizationMode,
530+
completion: @escaping (NSNumber?, FlutterError?) -> Void
531+
) {
532+
captureSessionQueue.async { [weak self] in
533+
534+
if let isSupported = self?.camera?.isVideoStabilizationModeSupported(mode) {
535+
completion(NSNumber(value: isSupported), nil)
536+
} else {
537+
completion(nil, nil)
538+
}
539+
}
540+
}
541+
520542
public func pausePreview(completion: @escaping (FlutterError?) -> Void) {
521543
captureSessionQueue.async { [weak self] in
522544
self?.camera?.pausePreview()

packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/DefaultCamera.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,33 @@ final class DefaultCamera: NSObject, Camera {
950950
completion(nil)
951951
}
952952

953+
func setVideoStabilizationMode(
954+
_ mode: FCPPlatformVideoStabilizationMode,
955+
withCompletion completion: @escaping (FlutterError?) -> Void
956+
) {
957+
let stabilizationMode = getAvCaptureVideoStabilizationMode(mode)
958+
959+
guard captureDevice.isVideoStabilizationModeSupported(stabilizationMode) else {
960+
completion(
961+
FlutterError(
962+
code: "VIDEO_STABILIZATION_ERROR",
963+
message: "Unavailable video stabilization mode.",
964+
details: nil
965+
)
966+
)
967+
return
968+
}
969+
if let connection = captureVideoOutput.connection(with: .video) {
970+
connection.preferredVideoStabilizationMode = stabilizationMode
971+
}
972+
completion(nil)
973+
}
974+
975+
func isVideoStabilizationModeSupported(_ mode: FCPPlatformVideoStabilizationMode) -> Bool {
976+
let stabilizationMode = getAvCaptureVideoStabilizationMode(mode)
977+
return captureDevice.isVideoStabilizationModeSupported(stabilizationMode)
978+
}
979+
953980
func setFlashMode(
954981
_ mode: FCPPlatformFlashMode,
955982
withCompletion completion: @escaping (FlutterError?) -> Void

0 commit comments

Comments
 (0)