Search code examples
macosavfoundation

Unable to mirror AVCaptureVideoPreviewLayer on macOS


I'm using AVCaptureVideoPreviewLayer (macOS, not iOS) to capture video input from an attached camera. I've setup a capture session and created a UIView to display the image:

self.captureLayer = AVCaptureVideoPreviewLayer(session: self.captureSession); self.playerView.layer = self.captureLayer;

Everything is working fine, and I see the image from the camera, but now I want to mirror the image (vertically). I'm using a CATransform3DMakeScale:

self.captureLayer.transform = CATransform3DMakeScale(-1.0, 1.0, 1.0);

Instead of mirroring the image however, the layer just goes blank (background of the parent view).

I've tried other transforms (e.g. resizes) and they work fine. I've also tried mirroring the superlayer:

self.captureLayer.superLayer?.transform = CATransform3DMakeScale(-1.0, 1.0, 1.0);

And this works (although it mirrors the entire window including the title bar!).

Any help appreciated. I believe the transform is correct, but for some reason it's not applying to a AVCaptureVideoPreviewLayer.


Solution

  • You can make use of avcaptureconnection properties to do this.

    self.cameraLayer = AVCaptureVideoPreviewLayer(session: frontVideoSession)
    self.cameraLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
    
        if (self.cameraLayer!.connection.isVideoMirroringSupported)
        {
            self.cameraLayer!.connection.automaticallyAdjustsVideoMirroring = false
            self.cameraLayer!.connection.isVideoMirrored = true
        }
    

    You can read more about this at https://developer.apple.com/reference/avfoundation/avcaptureconnection/1389172-isvideomirrored


    The isVideoMirrored flag allows you to choose whether you want to mirror the video or not. If it is set to true, it will mirror the video, if it set to false, it will not mirror. In order for you to use this flag, you must set automaticallyAdjustsVideoMirroring flag to false.


    Wrote an example code for you https://github.com/manishganvir/mac-camera-mirror-example. Please check the same. Snippet below

    do {
             let input = try AVCaptureDeviceInput(device: camDevice)
    
    
              VideoSession.addInput(input)
    
              self.cameraLayer = AVCaptureVideoPreviewLayer(session: VideoSession)
              print(" connection " , self.cameraLayer!.connection.isVideoMirroringSupported , self.cameraLayer!.connection.automaticallyAdjustsVideoMirroring);
    
              if (self.cameraLayer!.connection.isVideoMirroringSupported)
              {
                     self.cameraLayer!.connection.automaticallyAdjustsVideoMirroring = false
                     self.cameraLayer!.connection.isVideoMirrored = true
              }
              self.cameraLayer!.frame = self.view.bounds
    
              self.view.layer = self.cameraLayer!
              self.view.wantsLayer = true
    
              VideoSession.startRunning()
       }