Hi AVFoundation team,
I'm seeing a uniform 90° offset in AVCaptureDevice.RotationCoordinator's
reported angles between iPhone 17 Pro and iPhone 14 Pro using the front-facing
.builtInWideAngleCamera (Center Stage on 17 Pro), and I'd like to confirm
whether this is by design and what the recommended consumption pattern is when
the rendering surface is an AVSampleBufferDisplayLayer rather than an
AVCaptureVideoPreviewLayer.
Here is the github repo of sample project.
Setup
- Devices: iPhone 14 Pro (iOS 26.5) and iPhone 17 Pro (iOS 26.4.2)
- Camera: front, AVCaptureDeviceTypeBuiltInWideAngleCamera
- Active format: 1920×1080
- Three RotationCoordinator instances are created on the same AVCaptureDevice,
varying only the previewLayer: argument: - previewLayer: nil - previewLayer: AVSampleBufferDisplayLayer (the surface receiving frames from AVCaptureVideoDataOutput) - previewLayer: AVCaptureVideoPreviewLayer (with .session = captureSession, not displayed)
Each instance is KVO-observed for videoRotationAngleForHorizonLevelPreview and videoRotationAngleForHorizonLevelCapture.
Observed angles
Device / Orientation: 14 Pro · Portrait (interface=1) RC[nil] prev / cap: 0° / 90° RC[AVSampleBufferLayer] prev / cap: 90° / 90° RC[AVCaptureVideoPreviewLayer] prev / cap: 0° / 90° ──────────────────────────────────────── Device / Orientation: 14 Pro · LandscapeRight (interface=3) RC[nil] prev / cap: 0° / 180° RC[AVSampleBufferLayer] prev / cap: 180° / 180° RC[AVCaptureVideoPreviewLayer] prev / cap: 0° / 180° ──────────────────────────────────────── Device / Orientation: 17 Pro · Portrait (interface=1) RC[nil] prev / cap: 0° / 0° RC[AVSampleBufferLayer] prev / cap: 0° / 0° RC[AVCaptureVideoPreviewLayer] prev / cap: 0° / 0° ──────────────────────────────────────── Device / Orientation: 17 Pro · LandscapeRight (interface=3) RC[nil] prev / cap: 0° / 90° RC[AVSampleBufferLayer] prev / cap: 90° / 90° RC[AVCaptureVideoPreviewLayer] prev / cap: 0° / 90°
The −90° offset on 17 Pro is uniform: it appears in every RC variant, in both the preview-angle and the capture-angle properties, at every orientation tested. It is not specific to the previewLayer: argument.
Hi, thank you for mentioning this.
Yes, the Center Stage front camera on iPhone 17 and iPhone 17 Pro is mounted differently compared to front cameras on previous iPhone generations.
However, to maintain backwards compatibility, AVCaptureVideoDataOutput continues to output buffers in the same orientation/rotation as previous generations by default. This means that the AVCaptureVideoDataOutput's connection's videoRotationAngle is non-0 by default for the Center Stage front camera.
To compensate for this difference, you can do something like the following:
let videoRotationAngleForHorizonLevelPreview = rotationCoordinator.videoRotationAngleForHorizonLevelPreview
let videoConnectionVideoRotationAngle = videoOutputConnection.videoRotationAngle
// Subtract how much we should apply (videoRotationAngleForHorizonLevelPreview) by how much is already applied (videoConnectionVideoRotationAngle)
let rotationAngleToApply = videoRotationAngleForHorizonLevelPreview - videoConnectionVideoRotationAngle
// Use rotationAngleToApply for your AVSampleBufferDisplayLayer or AVAssetWriter video input's transform
Alternatively, you could set the videoRotationAngle on your AVCaptureVideoDataOutput to 0 and solely rely on the rotation coordinator's videoRotationAngleForHorizonLevelPreview. This will yield better performance for AVFoundation as it will no longer output "physically rotated" buffers.