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 counterpart of `AVCaptureConnection+iOS.swift`.
|
||||||
///
|
///
|
||||||
/// macOS desktop cameras are physically fixed landscape — applying any
|
/// macOS desktop cameras are physically fixed landscape. AVFoundation
|
||||||
/// `AVCaptureVideoOrientation` would skew the captured photo (and on
|
/// initialises `connection.videoOrientation` to `.portrait` by
|
||||||
/// some macOS versions the preview's data-output buffers) by 90°.
|
/// default though — same as iOS — which on macOS *also* rotates the
|
||||||
/// The orientation snapshot from Flutter (always `portraitUp` on
|
/// sensor frame 90° CW (manifested as a 90° CW selfie photo + a
|
||||||
/// macOS — desktops don't rotate) is therefore ignored at the
|
/// rotated preview). So we *do* set the orientation on macOS, but
|
||||||
/// connection layer; the recorded video's track transform is still
|
/// pin it to `.landscapeRight` regardless of the snapshot Flutter
|
||||||
/// `.identity` from VideoRecorder's existing mapping, so video stays
|
/// passes (which is always `portraitUp` on macOS — desktops don't
|
||||||
/// landscape too.
|
/// 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 {
|
extension AVCaptureConnection {
|
||||||
func applyUxCaptureOrientation(_ orientation: DeviceOrientationFlutter) {
|
func applyUxCaptureOrientation(_ orientation: DeviceOrientationFlutter) {
|
||||||
// Intentionally empty.
|
if isVideoOrientationSupported {
|
||||||
|
videoOrientation = .landscapeRight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user