CameraView fix for iOS: orientation and video recording#3167
CameraView fix for iOS: orientation and video recording#3167zhitaop wants to merge 6 commits intoCommunityToolkit:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves iOS CameraView behavior by centralizing orientation configuration for photo/video capture and refining video recording resource management to prevent post-recording crashes.
Changes:
- Centralizes photo/video orientation configuration via a new
ConfigureAVCaptureConnection()helper (iOS 17+ rotation coordinator; iOS ≤16 accelerometer fallback). - Simplifies iOS video recording by reusing the existing camera input and only adding/removing recording-specific resources (
audioInput,videoOutput). - Adds lifecycle cleanup for rotation coordinator and motion manager resources in
Dispose().
| captureInput = new AVCaptureDeviceInput(captureDevice, out NSError? error); | ||
| if (error is not null) | ||
| { | ||
| throw new CameraException($"Error creating capture device input: {error.LocalizedDescription}"); | ||
| } | ||
| captureSession.AddInput(captureInput); |
There was a problem hiding this comment.
captureSession.BeginConfiguration() is called before creating AVCaptureDeviceInput, but when error is non-null this method throws without calling captureSession.CommitConfiguration(). This can leave the session in a configuration state and break subsequent preview/recording setup. Consider wrapping the configuration block in a try/finally (always commit), and also validate captureSession.CanAddInput(captureInput) before calling AddInput, disposing captureInput and committing before throwing if it cannot be added.
| if (!UIDevice.CurrentDevice.CheckSystemVersion(17, 0)) | ||
| { | ||
| motionManager ??= new(); | ||
| motionManager.StartAccelerometerUpdates(); | ||
| } | ||
| orientationDidChangeObserver = UIDevice.Notifications.ObserveOrientationDidChange((_, _) => UpdateVideoOrientation()); |
There was a problem hiding this comment.
CMMotionManager.StartAccelerometerUpdates() is started in CreatePlatformView() (iOS 16 and below) but is only stopped in Dispose(). If the camera preview is stopped while the view stays alive, accelerometer updates will continue indefinitely, impacting battery/perf. Consider stopping updates in PlatformStopCameraPreview() (and restarting when starting preview), or tying it to connect/disconnect lifecycle instead of view creation.
| { | ||
| captureConnection.AutomaticallyAdjustsVideoMirroring = false; | ||
| captureConnection.VideoMirrored = true; | ||
| } |
There was a problem hiding this comment.
ConfigureAVCaptureConnection only forces mirroring when the selected camera is front-facing, but it never resets mirroring when switching back to a rear camera. Because photoOutput is reused across camera switches, this can leave AutomaticallyAdjustsVideoMirroring disabled and VideoMirrored still true for subsequent rear-camera captures/recordings. Consider adding an else branch to re-enable automatic mirroring (or explicitly set VideoMirrored = false) when the camera is not front-facing.
| } | |
| } | |
| else if (captureConnection.SupportsVideoMirroring) | |
| { | |
| captureConnection.AutomaticallyAdjustsVideoMirroring = true; | |
| captureConnection.VideoMirrored = false; | |
| } |
…os' into fix/camera-update-ios
| if (cameraView.SelectedCamera?.Position is CameraPosition.Front && captureConnection.SupportsVideoMirroring) | ||
| { | ||
| captureConnection.AutomaticallyAdjustsVideoMirroring = false; | ||
| captureConnection.VideoMirrored = true; |
There was a problem hiding this comment.
ConfigureAVCaptureConnection only enables mirroring for the front camera, but never explicitly disables it for non-front cameras. Since outputs/connections can be reused across camera switches, this can leave the back camera unexpectedly mirrored. Set mirroring explicitly for both cases (and restore AutomaticallyAdjustsVideoMirroring as appropriate) based on the selected camera position.
| if (cameraView.SelectedCamera?.Position is CameraPosition.Front && captureConnection.SupportsVideoMirroring) | |
| { | |
| captureConnection.AutomaticallyAdjustsVideoMirroring = false; | |
| captureConnection.VideoMirrored = true; | |
| if (captureConnection.SupportsVideoMirroring) | |
| { | |
| if (cameraView.SelectedCamera?.Position is CameraPosition.Front) | |
| { | |
| captureConnection.AutomaticallyAdjustsVideoMirroring = false; | |
| captureConnection.VideoMirrored = true; | |
| } | |
| else | |
| { | |
| captureConnection.AutomaticallyAdjustsVideoMirroring = true; | |
| captureConnection.VideoMirrored = false; | |
| } |
Description of Change
This PR fixes a bug on iOS where camera preview is stopped after video recording, and attempting to capture an image would crash the app. This is done by fixing video recording clean up logic so only recording-specific resources (
audioInput,videoOutput) are added and removed.Simplifies video recording session management by removing the separate video input and reusing the existing capture input
Improves iOS camera orientation handling for both photo capture and video recording. Centralized orientation handling logic in
ConfigureAVCaptureConnection():AVCaptureDeviceRotationCoordinatoron iOS 17+CMMotionManageron iOS 16 and belowLinked Issues
PR Checklist
approved(bug) orChampioned(feature/proposal)mainat time of PRAdditional information