Properly rotate/mirror video in AVCaptureVideoDataOutput and flipping input devices

Hey all, I have a pretty complicated camera setup so bear with me.

You know how Instagram's Camera supports recording a video and flipping Camera devices while recording?

I built the same thing using AVCaptureVideoDataOutput and it works fine, but it does not support rotation. (neither does Instagram, but I still need it, lol)

So there's two ways to implement rotation (and mirroring) in AVCaptureVideoDataOutput:

1. Set it on the AVCaptureConnection

Rotation and vertical mirror mode can be set directly on the AVCaptureVideoDataOutput's connection to the Camera:

let output = AVCaptureVideoDataOutput(...)
cameraSession.addOutput(output)
for connection in output.connections {
  connection.videoRotation = 90
  connection.isVideoMirrored = true
}

But according to the documentation this is expensive and comes with a performance overhead. I haven't really benchmarked it yet, but I assume rotating and mirroring 4k buffers isn't cheap.

I'm building a camera library that is used by a lot of people, so all performance decisions have a big impact.

2. Set it on AVAssetWriter

Instead of actually physically rotating large pixel buffers, we can also just set the AVAssetWriter's transform property to some affine transformation - which is comparable to how EXIF tags work.

We can set both rotation and mirror modes using CGAffineTransforms.

Obviously this is much more efficient and does not come with a performance overhead on the camera pipeline at all, so I'd prefer to go this route.

Problem

The problem is that when I start recording with the front Camera (AVAssetWriter.transform has a mirror on the CGAffineTransform), and then flip to the back Camera, the back Camera is also mirrored.

Now I thought I could just avoid rotation on my buffers and only use isVideoMirrored on the AVCaptureConnection when we are using the front camera, which is a fair performance compromise - but this won't work because isVideoMirrored applies mirroring alongside the vertical axis - and since the video stream is naturally in landscape orientation, this will flip the image upside down instead of mirroring it alongside the vertical axis... whoops! 😅

This is pretty obvious as the transform applies to the entire video stream, but now I am not sure if the AVAssetWriter approach will work for my use-case.

I think I will need to eagerly physically rotate the pixel buffers by setting the AVCaptureConnection's videoRotation & isVideoMirrored properties, but I wanted to ask here in case someone knows any alternatives to doing that in order to avoid the performance and memory overhead of rotating buffers?

Thanks!

Properly rotate/mirror video in AVCaptureVideoDataOutput and flipping input devices
 
 
Q