Skip to content

[camera_avfoundation] Adds support for video stabilization#10367

Merged
auto-submit[bot] merged 1 commit intoflutter:mainfrom
ruicraveiro:main
Feb 12, 2026
Merged

[camera_avfoundation] Adds support for video stabilization#10367
auto-submit[bot] merged 1 commit intoflutter:mainfrom
ruicraveiro:main

Conversation

@ruicraveiro
Copy link
Contributor

Implements getSupportedVideoStabilizationModes() and setVideoStabilizationMode() methods in AVFoundationCamera.

Address issue flutter/flutter#89525.
It is the camera_avfoundation sub-PR for #7108.

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for video stabilization, which is a great new feature. The implementation looks solid across Dart, Swift, and Objective-C. I've found a minor issue in the Dart implementation related to a copy-paste error in a comment and a suggestion for a safer fallback value for forward compatibility. The rest of the changes, including the native implementation and tests, are well done.

Comment on lines +543 to +564
/// Returns a [ResolutionPreset]'s Pigeon representation.
PlatformVideoStabilizationMode? _pigeonVideoStabilizationMode(
VideoStabilizationMode videoStabilizationMode,
) {
switch (videoStabilizationMode) {
case VideoStabilizationMode.off:
return PlatformVideoStabilizationMode.off;
case VideoStabilizationMode.level1:
return PlatformVideoStabilizationMode.standard;
case VideoStabilizationMode.level2:
return PlatformVideoStabilizationMode.cinematic;
case VideoStabilizationMode.level3:
return PlatformVideoStabilizationMode.cinematicExtended;
}
// The enum comes from a different package, which could get a new value at
// any time, so provide a fallback that ensures this won't break when used
// with a version that contains new values. This is deliberately outside
// the switch rather than a `default` so that the linter will flag the
// switch as needing an update.
// ignore: dead_code
return PlatformVideoStabilizationMode.cinematic;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are a couple of improvements that can be made in this method:

  1. The documentation comment appears to be a copy-paste error and refers to ResolutionPreset instead of VideoStabilizationMode.
  2. The fallback return value for unknown VideoStabilizationMode values is PlatformVideoStabilizationMode.cinematic. It would be safer to return null here. The function has a nullable return type, and the calling method _getSupportedVideoStabilizationModeMap already handles null by correctly treating the mode as unsupported. This would prevent new enum values from being incorrectly mapped to cinematic mode.
  /// Returns a [VideoStabilizationMode]'s Pigeon representation.
  PlatformVideoStabilizationMode? _pigeonVideoStabilizationMode(
    VideoStabilizationMode videoStabilizationMode,
  ) {
    switch (videoStabilizationMode) {
      case VideoStabilizationMode.off:
        return PlatformVideoStabilizationMode.off;
      case VideoStabilizationMode.level1:
        return PlatformVideoStabilizationMode.standard;
      case VideoStabilizationMode.level2:
        return PlatformVideoStabilizationMode.cinematic;
      case VideoStabilizationMode.level3:
        return PlatformVideoStabilizationMode.cinematicExtended;
    }
    // The enum comes from a different package, which could get a new value at
    // any time, so provide a fallback that ensures this won't break when used
    // with a version that contains new values. This is deliberately outside
    // the switch rather than a `default` so that the linter will flag the
    // switch as needing an update.
    // ignore: dead_code
    return null;
  }

@ruicraveiro ruicraveiro force-pushed the main branch 5 times, most recently from 6b092c1 to 187b287 Compare November 10, 2025 23:51
@stuartmorgan-g stuartmorgan-g added federated: partial_changes PR that contains changes for only a single package of a federated plugin change triage-ios Should be looked at in iOS triage labels Nov 11, 2025
@ruicraveiro ruicraveiro force-pushed the main branch 7 times, most recently from 797cbeb to 881874f Compare November 17, 2025 13:34
@LongCatIsLooong
Copy link
Contributor

cc @hellohuanlin from ios triage

@ruicraveiro
Copy link
Contributor Author

ruicraveiro commented Nov 21, 2025

Hi, I have been updating this PR so that it is based on the latest commit in main, but I wonder if there is any point in doing so if the PR takes much longer to be reviewed. Please advise me when you're close to start the review and I'll be happy to rebase once again.

@okorohelijah
Copy link
Contributor

@hellohuanlin review- from triage meeting

@hellohuanlin
Copy link
Contributor

Triage meeting: @hellohuanlin

@ruicraveiro ruicraveiro force-pushed the main branch 2 times, most recently from 68b305f to fbe0583 Compare December 19, 2025 20:26
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you know why this change is needed?

Copy link
Contributor Author

@ruicraveiro ruicraveiro Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leftover after running the example project. I included this by mistake, so I will be removing it.

completion(
FlutterError(
code: "VIDEO_STABILIZATION_ERROR",
message: "Unavailable video stabilization mode.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick - maybe something like

FlutterError(
        code: "VIDEO_STABILIZATION_ERROR",
        message: "The requested stabilization mode is not supported.",
        details: [
            "requested_mode": stabilizationMode.rawValue,
        ]
)

/// Sets the video stabilization mode.
- (void)setVideoStabilizationMode:(FCPPlatformVideoStabilizationMode)mode
completion:(void (^)(FlutterError *_Nullable))completion;
/// Sets the video stabilization mode.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be like /// Gets if the video stabilization mode is supported.

@ObjCSelector('setVideoStabilizationMode:')
void setVideoStabilizationMode(PlatformVideoStabilizationMode mode);

/// Sets the video stabilization mode.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment should be updated too :)

@@ -1,3 +1,7 @@
## 0.10.0

* Adds video stabilization.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a bit more detail? Maybe make a reference to the AVCaptureVideoStabilizationMode api you added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how much more detail it makes sense to add to the CHANGELOG, so I just added a mention to the 2 methods added to the Dart classes. Let me know if you need even more details.

@LouiseHsu
Copy link
Contributor

From triage: Are you planning to address the feedback? :)

@ruicraveiro
Copy link
Contributor Author

From triage: Are you planning to address the feedback? :)

Hi, yes, but I still haven't found the time. Maybe next week.

@ruicraveiro
Copy link
Contributor Author

Hi @LouiseHsu, I just force-pushed an updated commit. It contains changes to address all your feedback. It also contains the changes needed after rebasing from the current main branch (the biggest of which was the migration of CameraProperties to swift). So, this commit also has getAvCaptureVideoStabilizationMode ported from ObjectiveC to Swift.

@ruicraveiro ruicraveiro force-pushed the main branch 2 times, most recently from 635aaab to 4d9a89a Compare January 30, 2026 13:36
Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pigeon part may conflict with #10939
CC @RobertOdrowaz

) {
captureSessionQueue.async { [weak self] in

if let isSupported = self?.camera?.isVideoStabilizationModeSupported(mode) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a bit confusing to do if let isSupported, since it's a boolean type. Can you do if let camera = ... and get isSupported from inside the if statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, improved.

switch videoStabilizationMode {
case .off:
return .off

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove these blank lines

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks!

Copy link
Contributor

@LouiseHsu LouiseHsu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once @hellohuanlin comments have been addressed + merge conflicts.

@ruicraveiro ruicraveiro force-pushed the main branch 5 times, most recently from f249f53 to c01d1d7 Compare February 10, 2026 21:01
@ruicraveiro
Copy link
Contributor Author

Hi, just in case it went unnoticed, I made all the requested adjustments a few days ago.

- Implements getSupportedVideoStabilizationModes() and
  setVideoStabilizationMode() methods in AVFoundationCamera.
@vashworth vashworth added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 12, 2026
@auto-submit auto-submit bot merged commit 09104b0 into flutter:main Feb 12, 2026
81 checks passed
github-merge-queue bot pushed a commit to flutter/flutter that referenced this pull request Feb 13, 2026
flutter/packages@af1d610...09104b0

2026-02-12 8490712+ruicraveiro@users.noreply.github.com
[camera_avfoundation] Adds support for video stabilization
(flutter/packages#10367)
2026-02-12 stuartmorgan@google.com [google_maps_flutter] Add README
section about SDK versions (flutter/packages#11005)
2026-02-12 stuartmorgan@google.com [url_launcher] Modernize
`url_launcher_ios` example (flutter/packages#11002)
2026-02-12 107683152+OlehSv@users.noreply.github.com
[google_maps_flutter] Improved perfomance of clusterization
(flutter/packages#10562)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
rickhohler pushed a commit to rickhohler/flutter that referenced this pull request Feb 19, 2026
…r#182383)

flutter/packages@af1d610...09104b0

2026-02-12 8490712+ruicraveiro@users.noreply.github.com
[camera_avfoundation] Adds support for video stabilization
(flutter/packages#10367)
2026-02-12 stuartmorgan@google.com [google_maps_flutter] Add README
section about SDK versions (flutter/packages#11005)
2026-02-12 stuartmorgan@google.com [url_launcher] Modernize
`url_launcher_ios` example (flutter/packages#11002)
2026-02-12 107683152+OlehSv@users.noreply.github.com
[google_maps_flutter] Improved perfomance of clusterization
(flutter/packages#10562)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App federated: partial_changes PR that contains changes for only a single package of a federated plugin change p: camera platform-ios platform-macos triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants