-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[camera] add video stabilization #7108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9bdf58e
39e2adf
edf33b0
741e032
738ba2d
b404388
c900fa4
e1f7cb8
d220078
887c565
8d986ed
8040dc6
dba6738
f027dfc
b85a0be
291a740
1d06d3d
680097f
a8e6544
754c577
55a4da8
06719a5
15d918c
69eb909
672d834
1cef9b3
e6b483f
45fa745
ddc370c
1e4885c
183088d
c333768
94651bc
1ec3f54
a9366c2
81afd32
99e604f
a816c5b
94fd363
76db0eb
3c4252b
c99c727
a77bea1
5bb8379
4f8b587
4fe99bb
bf6c7d9
39bf897
539c65e
f60a5ff
6689162
068141d
75382f6
0317cce
d71672f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,3 +64,4 @@ Aleksandr Yurkovskiy <[email protected]> | |
Anton Borries <[email protected]> | ||
Alex Li <[email protected]> | ||
Rahul Raj <[email protected]> | ||
Rui Craveiro <[email protected]> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 0.12.0 | ||
|
||
* Adds support for video stabilization. | ||
|
||
## 0.11.1 | ||
|
||
* Adds API support query for image streaming. | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -54,6 +54,7 @@ class CameraValue { | |||||||||||||||||||||||||||||||
this.recordingOrientation, | ||||||||||||||||||||||||||||||||
this.isPreviewPaused = false, | ||||||||||||||||||||||||||||||||
this.previewPauseOrientation, | ||||||||||||||||||||||||||||||||
this.videoStabilizationMode = VideoStabilizationMode.off, | ||||||||||||||||||||||||||||||||
}) : _isRecordingPaused = isRecordingPaused; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// Creates a new camera controller state for an uninitialized controller. | ||||||||||||||||||||||||||||||||
|
@@ -72,6 +73,7 @@ class CameraValue { | |||||||||||||||||||||||||||||||
deviceOrientation: DeviceOrientation.portraitUp, | ||||||||||||||||||||||||||||||||
isPreviewPaused: false, | ||||||||||||||||||||||||||||||||
description: description, | ||||||||||||||||||||||||||||||||
videoStabilizationMode: VideoStabilizationMode.off, | ||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// True after [CameraController.initialize] has completed successfully. | ||||||||||||||||||||||||||||||||
|
@@ -148,6 +150,9 @@ class CameraValue { | |||||||||||||||||||||||||||||||
/// The properties of the camera device controlled by this controller. | ||||||||||||||||||||||||||||||||
final CameraDescription description; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// The video stabilization mode in | ||||||||||||||||||||||||||||||||
final VideoStabilizationMode videoStabilizationMode; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// Creates a modified copy of the object. | ||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||
/// Explicitly specified fields get the specified value, all other fields get | ||||||||||||||||||||||||||||||||
|
@@ -171,6 +176,7 @@ class CameraValue { | |||||||||||||||||||||||||||||||
bool? isPreviewPaused, | ||||||||||||||||||||||||||||||||
CameraDescription? description, | ||||||||||||||||||||||||||||||||
Optional<DeviceOrientation>? previewPauseOrientation, | ||||||||||||||||||||||||||||||||
VideoStabilizationMode? videoStabilizationMode, | ||||||||||||||||||||||||||||||||
}) { | ||||||||||||||||||||||||||||||||
return CameraValue( | ||||||||||||||||||||||||||||||||
isInitialized: isInitialized ?? this.isInitialized, | ||||||||||||||||||||||||||||||||
|
@@ -198,6 +204,8 @@ class CameraValue { | |||||||||||||||||||||||||||||||
previewPauseOrientation: previewPauseOrientation == null | ||||||||||||||||||||||||||||||||
? this.previewPauseOrientation | ||||||||||||||||||||||||||||||||
: previewPauseOrientation.orNull, | ||||||||||||||||||||||||||||||||
videoStabilizationMode: | ||||||||||||||||||||||||||||||||
videoStabilizationMode ?? this.videoStabilizationMode, | ||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
@@ -219,6 +227,7 @@ class CameraValue { | |||||||||||||||||||||||||||||||
'recordingOrientation: $recordingOrientation, ' | ||||||||||||||||||||||||||||||||
'isPreviewPaused: $isPreviewPaused, ' | ||||||||||||||||||||||||||||||||
'previewPausedOrientation: $previewPauseOrientation, ' | ||||||||||||||||||||||||||||||||
'videoStabilizationMode: $videoStabilizationMode, ' | ||||||||||||||||||||||||||||||||
'description: $description)'; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
@@ -687,6 +696,80 @@ class CameraController extends ValueNotifier<CameraValue> { | |||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// Set the video stabilization mode for the selected camera. | ||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||
/// On Android (when using camera_android_camerax) and on iOS | ||||||||||||||||||||||||||||||||
/// the supplied [mode] value should be a mode in the list returned | ||||||||||||||||||||||||||||||||
/// by [getSupportedVideoStabilizationModes]. | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only true for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will also remove it, especially since after that comment, I document both allowFallback cases. |
||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||
/// When [allowFallback] is true (default) and when | ||||||||||||||||||||||||||||||||
/// the camera supports any video stabilization other than | ||||||||||||||||||||||||||||||||
/// [VideoStabilizationMode.off], then the camera will | ||||||||||||||||||||||||||||||||
/// be set to the best video stabilization mode up to, and including, [mode]. | ||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||
/// When either [allowFallback] is false or the only | ||||||||||||||||||||||||||||||||
/// supported video stabilization mode is [VideoStabilizationMode.off], | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes it sound like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Three separate cases:
Here's the table again:
Let me know if you still have a different understanding. For me it is very clear that if level1, 2 or 3 are available, there is no reason to exclude off. It is also very clear, and I agreed with you, that we shouldn't introduce off artificially if the device doesn't return any available mode. What is really hard to define is the behaviour of when off is the only mode, even more so because I think that this is a theoretical discussion as I don't expect the case of where the platform returns only off to ever happen. None of the devices I tested showed that behaviour, as they would either report no supported stabilization mode or at least 2 supported modes, one of them always being off. So, maybe, because it isn't really something expected to happen, I can simplify the comment and ignore that case. Let me know what you think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not following. How are these separate cases? What is the conceptual difference here? |
||||||||||||||||||||||||||||||||
/// and if [mode] is not one of the supported modes, | ||||||||||||||||||||||||||||||||
/// then it throws an [ArgumentError]. | ||||||||||||||||||||||||||||||||
Future<void> setVideoStabilizationMode( | ||||||||||||||||||||||||||||||||
VideoStabilizationMode mode, { | ||||||||||||||||||||||||||||||||
bool allowFallback = true, | ||||||||||||||||||||||||||||||||
}) async { | ||||||||||||||||||||||||||||||||
_throwIfNotInitialized('setVideoStabilizationMode'); | ||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||
final VideoStabilizationMode requestMode = | ||||||||||||||||||||||||||||||||
allowFallback ? await _getVideoStabilizationFallbackMode(mode) : mode; | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
await CameraPlatform.instance | ||||||||||||||||||||||||||||||||
.setVideoStabilizationMode(_cameraId, requestMode); | ||||||||||||||||||||||||||||||||
value = value.copyWith(videoStabilizationMode: mode); | ||||||||||||||||||||||||||||||||
} on PlatformException catch (e) { | ||||||||||||||||||||||||||||||||
throw CameraException(e.code, e.message); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
Future<VideoStabilizationMode> _getVideoStabilizationFallbackMode( | ||||||||||||||||||||||||||||||||
VideoStabilizationMode mode) async { | ||||||||||||||||||||||||||||||||
final Iterable<VideoStabilizationMode> supportedModes = await CameraPlatform | ||||||||||||||||||||||||||||||||
.instance | ||||||||||||||||||||||||||||||||
.getSupportedVideoStabilizationModes(_cameraId); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// if there are no supported modes or if the only supported mode is Off | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: capitalize as a sentence. |
||||||||||||||||||||||||||||||||
// and something else is requested, then we throw an ArgumentError. | ||||||||||||||||||||||||||||||||
if (supportedModes.isEmpty || | ||||||||||||||||||||||||||||||||
(mode != VideoStabilizationMode.off && | ||||||||||||||||||||||||||||||||
supportedModes.every((VideoStabilizationMode sm) => | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are you referring to? The comment ... and something else ... (where it would be some other mode)? Is it the 'sm' variable, which stands for 'supportedMode'? Or something else? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, the variable |
||||||||||||||||||||||||||||||||
sm == VideoStabilizationMode.off))) { | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be impossible? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This goes back to my previous comment. As I understand it, no it shouldn't be impossible, but I never expect it to actually happen. |
||||||||||||||||||||||||||||||||
throw ArgumentError('Unavailable video stabilization mode.', 'mode'); | ||||||||||||||||||||||||||||||||
stuartmorgan-g marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
VideoStabilizationMode requestMode = VideoStabilizationMode.off; | ||||||||||||||||||||||||||||||||
for (final VideoStabilizationMode supportedMode in supportedModes) { | ||||||||||||||||||||||||||||||||
if (supportedMode.index <= mode.index && | ||||||||||||||||||||||||||||||||
supportedMode.index >= requestMode.index) { | ||||||||||||||||||||||||||||||||
requestMode = supportedMode; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
return requestMode; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// Gets a list of video stabilization modes that are supported for the selected camera. | ||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||
/// Will return the list of supported video stabilization modes | ||||||||||||||||||||||||||||||||
/// on Android (when using camera_android_camerax package) and | ||||||||||||||||||||||||||||||||
/// on iOS. Throws an [UnimplementedError] on all other platforms. | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should not throw on other platforms, it should return an empty list. See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#api-support-queries There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I'll make that change. |
||||||||||||||||||||||||||||||||
Future<Iterable<VideoStabilizationMode>> | ||||||||||||||||||||||||||||||||
getSupportedVideoStabilizationModes() { | ||||||||||||||||||||||||||||||||
_throwIfNotInitialized('isVideoStabilizationModeSupported'); | ||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||
return CameraPlatform.instance | ||||||||||||||||||||||||||||||||
.getSupportedVideoStabilizationModes(_cameraId); | ||||||||||||||||||||||||||||||||
} on PlatformException catch (e) { | ||||||||||||||||||||||||||||||||
throw CameraException(e.code, e.message); | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
/// Sets the flash mode for taking pictures. | ||||||||||||||||||||||||||||||||
Future<void> setFlashMode(FlashMode mode) async { | ||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment should not be calling out specific platforms; the restriction should have the same behavior on all platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right and the comment is only creating confusion. Will remove it.