camera: pin macOS photo connection to .landscapeRight
`AVCaptureVideoDataOutput`'s connection on macOS doesn't honor `videoOrientation` (or its `isVideoOrientationSupported` is false) — which is why the preview + recorded video were landscape and looked fine even with our previously-no-op extension. `AVCapturePhotoOutput`'s connection on macOS *does* honor it, and its default is `.portrait` — same as iOS — so leaving it untouched rotated the captured JPEG 90° CW relative to the landscape sensor. The extension now sets `.landscapeRight` unconditionally (guarded by `isVideoOrientationSupported`, so on the data output it's a no-op): photo connection pins to landscape, JPEG EXIF orientation = 1 (no rotation), captured image matches the preview. Video + preview already correct → unaffected.
This commit is contained in:
@@ -2,16 +2,21 @@ import AVFoundation
|
||||
|
||||
/// macOS counterpart of `AVCaptureConnection+iOS.swift`.
|
||||
///
|
||||
/// macOS desktop cameras are physically fixed landscape — applying any
|
||||
/// `AVCaptureVideoOrientation` would skew the captured photo (and on
|
||||
/// some macOS versions the preview's data-output buffers) by 90°.
|
||||
/// The orientation snapshot from Flutter (always `portraitUp` on
|
||||
/// macOS — desktops don't rotate) is therefore ignored at the
|
||||
/// connection layer; the recorded video's track transform is still
|
||||
/// `.identity` from VideoRecorder's existing mapping, so video stays
|
||||
/// landscape too.
|
||||
/// macOS desktop cameras are physically fixed landscape. AVFoundation
|
||||
/// initialises `connection.videoOrientation` to `.portrait` by
|
||||
/// default though — same as iOS — which on macOS *also* rotates the
|
||||
/// sensor frame 90° CW (manifested as a 90° CW selfie photo + a
|
||||
/// rotated preview). So we *do* set the orientation on macOS, but
|
||||
/// pin it to `.landscapeRight` regardless of the snapshot Flutter
|
||||
/// passes (which is always `portraitUp` on macOS — desktops don't
|
||||
/// rotate). That tells AVFoundation "leave the sensor frame alone";
|
||||
/// captured JPEG ends up landscape with EXIF orientation = 1 (no
|
||||
/// rotation), and preview data-output buffers flow at the sensor's
|
||||
/// native aspect.
|
||||
extension AVCaptureConnection {
|
||||
func applyUxCaptureOrientation(_ orientation: DeviceOrientationFlutter) {
|
||||
// Intentionally empty.
|
||||
if isVideoOrientationSupported {
|
||||
videoOrientation = .landscapeRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user