Camera Video Orientation

I noticed that on the iOS devices, by default the

videoOrientation
property of the video device's
AVCaptureConnection
is
landscapeLeft
for the front camera and
landscapeRight
for the rear. Meanwhile the actual pixel data in both cases is oriented as
landscapeLeft
. As far as I can tell it's not a bug of any kind because I found the following code in thissample.


extension PreviewMetalView.Rotation {
  init?(with interfaceOrientation: UIInterfaceOrientation, videoOrientation: AVCaptureVideoOrientation, cameraPosition: AVCaptureDevice.Position) {
       /*
       Calculate the rotation between the videoOrientation and the interfaceOrientation.
       The direction of the rotation depends upon the camera position.
       */
       switch videoOrientation {
            case .portrait:
                 switch interfaceOrientation {
                      case .landscapeRight:
                           if cameraPosition == .front {
                                self = .rotate90Degrees
                           } else {
                                self = .rotate270Degrees
                           }

                      case .landscapeLeft:
                           if cameraPosition == .front {
                                self = .rotate270Degrees
                           } else {
                                self = .rotate90Degrees
                           }

                      case .portrait:
                           self = .rotate0Degrees

                      case .portraitUpsideDown:
                           self = .rotate180Degrees

                      default: return nil
                 }
            case .portraitUpsideDown:
                 switch interfaceOrientation {
                      case .landscapeRight:
                           if cameraPosition == .front {
                                self = .rotate270Degrees
                           } else {
                                self = .rotate90Degrees
                           }

                      case .landscapeLeft:
                           if cameraPosition == .front {
                                self = .rotate90Degrees
                           } else {
                                self = .rotate270Degrees
                           }

                      case .portrait:
                           self = .rotate180Degrees

                      case .portraitUpsideDown:
                           self = .rotate0Degrees

                      default: return nil
                 }

            case .landscapeRight:
                 switch interfaceOrientation {
                      case .landscapeRight:
                           self = .rotate0Degrees

                      case .landscapeLeft:
                           self = .rotate180Degrees

                      case .portrait:
                           if cameraPosition == .front {
                                self = .rotate270Degrees
                           } else {
                                self = .rotate90Degrees
                           }

                      case .portraitUpsideDown:
                           if cameraPosition == .front {
                                self = .rotate90Degrees
                           } else {
                                self = .rotate270Degrees
                           }

                      default: return nil
                 }

            case .landscapeLeft:
                 switch interfaceOrientation {
                      case .landscapeLeft:
                           self = .rotate0Degrees

                      case .landscapeRight:
                           self = .rotate180Degrees

                      case .portrait:
                           if cameraPosition == .front {
                                self = .rotate90Degrees
                           } else {
                                self = .rotate270Degrees
                           }

                      case .portraitUpsideDown:
                           if cameraPosition == .front {
                                self = .rotate270Degrees
                           } else {
                                self = .rotate90Degrees
                           }

                      default: return nil
                 }
            }
       }
}


It seems that

videoOrientation
works differently for the front and rear cameras and I couldn't find anything about that in the documentation or on the web. Does anyone know the reason of such a strange behaviour of the property?

Replies

Could this be the explanation ? I tried to find the logic there.


- It is landscape, because that's the most usual way of handing the camera when shooting


Now, imagine yourself in the camera eye.

- for the back camera, the button is on the right: hence landscapeRight

Now, if you are in the front camera (really imagine yoursef in the camera)

- for the front camera, the button is on the left, hence landscapeLeft


Hope that helps.

It could be the right answer, but a) if I'm the camera then it should be left for the rear and right for the front; b) the property is on the

AVCaptureConnection
so it must not be device-dependent in any way, it's the orientation of the buffers provided by the connection from theoretically any sources, not only 2 built-in cameras.

Left or right is just a convention: when in landscape, do you put the button on the right or on the left ?

In fact, the explanation is probably better if we look from the perspective of the CMOS image sensor (CIS). Depending which camera is used:

- for the back camera, the button is on the right: hence landscapeRight

Now, if you are in the front camera (really imagine yoursef in the camera)

- for the front camera, the button is on the left, hence landscapeLeft


This being said, I'm not in the designer's head, so that was just the best explanation I could find, for what it's worth.