Files
ux/macos/Classes/Camera/AVCaptureConnection+macOS.swift
agra 4c10604cb8 camera: pin macOS connections to 0° rotation (sensor-native landscape)
Diagnostic from a fresh build with NSLog confirmed the rotation
behaviour on macOS: with `videoRotationAngle = 90`
(`.portrait`), `AVCapturePhoto.cgImageRepresentation()` returned a
720x1280 CGImage — *physical* portrait pixels, not just an EXIF
tag. So Apple's AVCaptureSession.h docs claiming
"AVCapturePhotoOutput uses EXIF only" don't hold on macOS. The
data-output connection on macOS also honors the same setter, which
is why preview + video flipped to rotated as soon as the photo fix
landed.

Pin macOS to 0° rotation (`.landscapeRight`):
  - Photo: 1280x720 (sensor-native landscape, matches what the user
    sees on screen).
  - Preview: 1280x720 (matches the new desktop 4:3 page aspect).
  - Video: 1280x720 (was already correct before the .portrait
    change; back to that state).

The snapshot orientation argument is still ignored on macOS —
desktop cameras don't rotate. The argument carries through for iOS
where the camera page passes the device orientation.
2026-05-13 21:24:52 +03:00

41 lines
1.8 KiB
Swift

import AVFoundation
/// macOS counterpart of `AVCaptureConnection+iOS.swift`.
///
/// macOS desktop cameras are physically fixed landscape, but
/// `AVCapturePhotoOutput`'s connection defaults to a setting that
/// rotates the captured JPEG 90° CW. We pin the connection to
/// landscape (or 0° rotation, depending on the available API) so
/// the JPEG matches what the preview shows.
///
/// `videoOrientation` was deprecated in macOS 14 / iOS 17 in favour
/// of `videoRotationAngle` (a `CGFloat` in degrees). On macOS 14+
/// `videoOrientation` may be silently ignored that's exactly the
/// symptom we hit ("photo still rotated 90° CW even after setting
/// videoOrientation = .landscapeRight"). Prefer the new API where
/// available, fall back to the deprecated one for older macOS.
extension AVCaptureConnection {
func applyUxCaptureOrientation(_ orientation: DeviceOrientationFlutter) {
// Pin to 0° rotation (`.landscapeRight`) on macOS desktop
// cameras are physically landscape and any non-zero rotation
// physically rotates the buffer. Diagnostic build confirmed
// a 720x1280 CGImage (portrait) when this was set to 90°,
// proving Apple's docs ("AVCapturePhotoOutput uses EXIF only,
// no physical rotation") don't apply on macOS and the data
// output's connection honors the same setter, so preview +
// video also rotate.
//
// The Flutter snapshot is always `portraitUp` on macOS
// (desktops don't rotate); we ignore it and force landscape.
if #available(macOS 14.0, *) {
if isVideoRotationAngleSupported(0) {
videoRotationAngle = 0
return
}
}
if isVideoOrientationSupported {
videoOrientation = .landscapeRight
}
}
}