web-dev-qa-db-fra.com

AVCaptureVideoPreviewLayer orientation - besoin de paysage

Mon application est uniquement en mode paysage. Je présente le AVCaptureVideoPreviewLayer comme ceci:

self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[self.previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];                    
NSLog(@"previewView: %@", self.previewView);
CALayer *rootLayer = [self.previewView layer];
[rootLayer setMasksToBounds:YES];
[self.previewLayer setFrame:[rootLayer bounds]];
    NSLog(@"previewlayer: %f, %f, %f, %f", self.previewLayer.frame.Origin.x, self.previewLayer.frame.Origin.y, self.previewLayer.frame.size.width, self.previewLayer.frame.size.height);
[rootLayer addSublayer:self.previewLayer];
[session startRunning];

self.previewView a un cadre de (0,0,568,320), ce qui est correct. self.previewLayer enregistre une image de (0,0,568,320), ce qui est théoriquement correct. Cependant, l'affichage de la caméra apparaît sous la forme d'un rectangle de portrait au milieu de l'écran Paysage et l'orientation de l'image d'aperçu de la caméra est incorrecte de 90 degrés. Qu'est-ce que je fais mal? La couche d'aperçu de la caméra doit apparaître en plein écran, en mode paysage, et l'image doit être correctement orientée.

53
soleil

L'orientation par défaut de l'appareil photo est Paysage gauche (bouton d'accueil à gauche). Vous devez faire deux choses ici:

1- Modifiez le cadre previewLayer en:

self.previewLayer.frame=self.view.bounds;

Vous devez définir le cadre du calque d'aperçu sur les limites de l'écran afin que ce dernier change lorsque l'écran pivote (vous ne pouvez pas utiliser le cadre de la vue racine car il ne change pas avec la rotation, mais les limites de la vue racine faire). Dans votre exemple, vous définissez le cadre previewlayer sur une propriété previewView que je ne vois pas.

2- Vous devez faire pivoter la connexion de la couche d'aperçu avec la rotation de l'appareil. Ajoutez ce code dans viewDidAppear:

-(void) viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:YES];

  //Get Preview Layer connection
  AVCaptureConnection *previewLayerConnection=self.previewLayer.connection;

  if ([previewLayerConnection isVideoOrientationSupported])
    [previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; 
}

J'espère que cela résout le problème.

Divulgation complète: Ceci est une version simplifiée puisque vous ne vous souciez pas de Paysage à droite ou de Paysage à gauche.

63
Khaled Barazi

MEILLEURE RÉPONSE POUR Swift 3.0 ET XCODE 8.0

private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {

    layer.videoOrientation = orientation

    previewLayer.frame = self.view.bounds

}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let connection =  self.previewLayer?.connection  {

        let currentDevice: UIDevice = UIDevice.current

        let orientation: UIDeviceOrientation = currentDevice.orientation

        let previewLayerConnection : AVCaptureConnection = connection

        if previewLayerConnection.isVideoOrientationSupported {

            switch (orientation) {
            case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)

                break

            case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)

                break

            case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)

                break

            case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)

                break

            default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)

                break
            }
        }
    }
}

MEILLEURE RÉPONSE POUR Swift 2.2 ET XCODE 7.3

private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {

    layer.videoOrientation = orientation

    previewLayer.frame = self.view.bounds

}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let connection =  self.previewLayer?.connection  {

        let currentDevice: UIDevice = UIDevice.currentDevice()

        let orientation: UIDeviceOrientation = currentDevice.orientation

        let previewLayerConnection : AVCaptureConnection = connection

        if (previewLayerConnection.supportsVideoOrientation) {

            switch (orientation) {
            case .Portrait: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)

                break

            case .LandscapeRight: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeLeft)

                break

            case .LandscapeLeft: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeRight)

                break

            case .PortraitUpsideDown: updatePreviewLayer(previewLayerConnection, orientation: .PortraitUpsideDown)

                break

            default: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)

                break
            }
        }
    }
}
63
Maselko
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    if let connection =  self.previewLayer?.connection  {
        var currentDevice: UIDevice = UIDevice.currentDevice()
        var orientation: UIDeviceOrientation = currentDevice.orientation
        var previewLayerConnection : AVCaptureConnection = connection

        if (previewLayerConnection.supportsVideoOrientation) {
            switch (orientation) {
            case .portrait:
                previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
                break
            case .landscapeRight:
                previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeRight
                break
            case .landscapeLeft:
                previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
                break
            case .portraitUpsideDown:
                previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
                break

            default:
                previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
                break
            }
        }
    }
}
27
Janusz Chudzynski

Nous ne pouvons pas utiliser 

[previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; 

parce que UIInterfaceOrientation != AVCaptureVideoOrientation

Mais nous pouvons simplement tester des valeurs ... et ce travail, avec le code suivant.

-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
            break;
        case UIInterfaceOrientationLandscapeLeft:
            [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
            break;
        case UIInterfaceOrientationLandscapeRight:
            [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
            break;
    }
}
14
Emmanuel Crombez

L'API semble avoir quelque peu changé. videoOrientation est maintenant une propriété de la propriété connection de la couche d'aperçu. En outre, pas besoin d'utiliser un commutateur. Réponse pour Swift 3.0:

override func viewDidLayoutSubviews() {
    self.configureVideoOrientation()
}

private func configureVideoOrientation() {
    if let previewLayer = self.previewLayer,
        let connection = previewLayer.connection {
        let orientation = UIDevice.current.orientation

        if connection.isVideoOrientationSupported,
            let videoOrientation = AVCaptureVideoOrientation(rawValue: orientation.rawValue) {
            previewLayer.frame = self.view.bounds
            previewLayer.connection?.videoOrientation = videoOrientation
        }
    }
}
10
John Rogers

Pour tous ceux qui ont du mal à obtenir un aperçu complet de la caméra. Voici le code de production. Bien entendu, l’inconvénient est un décalage lorsque l’orientation change. Si quelqu'un a une meilleure solution pour surmonter cela, veuillez partager

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self initCamera];
}

- (void)initCamera
{
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
    if (captureInput) {
        mSession = [[AVCaptureSession alloc] init];
        [mSession addInput:captureInput];
    }
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    if ([mSession isRunning]) {
        [mSession stopRunning];
        [mCameraLayer removeFromSuperlayer];

        [self initCamera];

        [self startCamera];
    }
}

- (void)startCamera
{
    [mSession startRunning];
    Settings::getInstance()->setClearColor(Color(0, 0, 0, 0));
    mCameraLayer = [AVCaptureVideoPreviewLayer layerWithSession: mSession];
    [self updateCameraLayer];
    [mCameraView.layer addSublayer:mCameraLayer];
}

- (void)stopCamera
{
    [mSession stopRunning];
    [mCameraLayer removeFromSuperlayer];
    Settings::getInstance()->setDefClearColor();
}

- (void)toggleCamera
{
    mSession.isRunning ? [self stopCamera] : [self startCamera];
    [mGLKView setNeedsDisplay];
}

- (void)updateCameraLayer
{
    mCameraLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    mCameraLayer.frame = mCameraView.bounds;
    float x = mCameraView.frame.Origin.x;
    float y = mCameraView.frame.Origin.y;
    float w = mCameraView.frame.size.width;
    float h = mCameraView.frame.size.height;
    CATransform3D transform = CATransform3DIdentity;
    if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
        mCameraLayer.frame = CGRectMake(x, y, h, w);
        transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
        transform = CATransform3DRotate(transform, -M_PI/2, 0, 0, 1);
    } else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation]) {
        mCameraLayer.frame = CGRectMake(x, y, h, w);
        transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
        transform = CATransform3DRotate(transform, M_PI/2, 0, 0, 1);
    } else if (UIDeviceOrientationPortraitUpsideDown == [[UIDevice currentDevice] orientation]) {
        mCameraLayer.frame = mCameraView.bounds;
        transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
    } else {
        mCameraLayer.frame = mCameraView.bounds;
    }
    mCameraLayer.transform  = transform;
}

    enter code here
7
Lance Mao

Comme il existe un avertissement de dépréciation et de conversion à l'aide de la solution ci-dessus et que la configuration de videoOrientation ne semble pas fonctionner dans iOS7, j'ai placé des vérifications d'orientation dans mon getter pour AVCaptureVideoPreviewLayer, comme suit:

- (AVCaptureVideoPreviewLayer *) previewLayer
{
    if(!_previewLayer)
    {
        _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession: self.captureSession];

    [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    _previewLayer.frame = self.view.bounds; // Assume you want the preview layer to fill the view.

    [_previewLayer setPosition:CGPointMake(0,0)];

    if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
        _previewLayer.transform = CATransform3DMakeRotation(-M_PI/2, 0, 0, 1);
    }
    else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation])
    {
        _previewLayer.transform = CATransform3DMakeRotation(M_PI/2, 0, 0, 1);
    }
}

return _previewLayer;
}
4
mrdavenz

Fonctionne avec Swift 4, Xcode 9:

  override func viewWillTransition(to size: CGSize,
                                   with coordinator: UIViewControllerTransitionCoordinator)
  {
    super.viewWillTransition(to: size, with: coordinator)
    guard
    let conn = self.previewLayer?.connection,
      conn.isVideoOrientationSupported
      else { return }
    let deviceOrientation = UIDevice.current.orientation
    switch deviceOrientation {
    case .portrait: conn.videoOrientation = .portrait
    case .landscapeRight: conn.videoOrientation = .landscapeLeft
    case .landscapeLeft: conn.videoOrientation = .landscapeRight
    case .portraitUpsideDown: conn.videoOrientation = .portraitUpsideDown
    default: conn.videoOrientation = .portrait
    }
  }

Une subtilité à noter ici est que UIDeviceOrientation.landscapeRight est associé à AVCaptureVideoOrientation.landscapeLeft.

L’autre cas de paysage est pareillement mal assorti. Ceci est délibéré et tient compte d'un désaccord malheureux entre UIKit et AVFoundation. Si vous faites correspondre les cas en faisant correspondre les noms, cela ne fonctionnera pas et votre vidéo sera inversée dans les configurations en paysage.

3
algal

Hé les gars, merci pour toutes les réponses et commentaires à ce sujet, je suis tombé sur cela alors que je travaillais sur une application Swift. Vous pouvez obtenir la rotation de la caméra avec votre appareil en utilisant ce code:

override func shouldAutorotate() -> Bool {
        if your cameraController.previewLayer.connection != nil {
            var currentDevice: UIDevice = UIDevice.currentDevice()
            var orientation: UIDeviceOrientation = currentDevice.orientation

            var previewLayerConnection : AVCaptureConnection = your cameraController.previewLayer.connection

            if (previewLayerConnection.supportsVideoOrientation)
            {
                switch (orientation)
                {
                case .Portrait:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
                    break
                case .LandscapeRight:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
                    break
                case .LandscapeLeft:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
                    break
                default:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
                    break
                }
            }

        }
        return true
    }

J'espère que cela t'aides!

2
Pablo Segura

Un mappage correct de UIDeviceOrientation à AVCaptureVideoOrientation est nécessaire.

Si votre application prend en charge device rotation, resizing preview.frame est également nécessaire et cette func doit être appelée à partir de viewDidLayoutSubviews() et viewWillTransition().

private func configureVideoOrientation() {
    if let preview = self.previewLayer,
        let connection = preview.connection {
        let orientation = UIDevice.current.orientation

        if connection.isVideoOrientationSupported {
            var videoOrientation: AVCaptureVideoOrientation
            switch orientation {
            case .portrait:
                videoOrientation = .portrait
            case .portraitUpsideDown:
                videoOrientation = .portraitUpsideDown
            case .landscapeLeft:
                videoOrientation = .landscapeRight
            case .landscapeRight:
                videoOrientation = .landscapeLeft
            default:
                videoOrientation = .portrait
            }
            preview.frame = self.view.bounds
            connection.videoOrientation = videoOrientation
        }
    }
}
2
water

Moi aussi, je faisais face à la même chose .__C'était pour corriger l'orientation de ma caméra

override func shouldAutorotate() -> Bool {
        return false
    }

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
        return UIInterfaceOrientation.LandscapeLeft
    }

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.LandscapeLeft
    }

Pour réparer la caméra 

let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.avCaptureSession)    
previewLayer.frame = self.view.layer.frame
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
1
Cloy

Réponse sélectionnée pour Swift 4.2 - Xcode 10.0 - iOS 12.0:

var videoPreviewLayer: AVCaptureVideoPreviewLayer?

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  if let previewLayerConnection =  self.videoPreviewLayer?.connection, previewLayerConnection.isVideoOrientationSupported {
    updatePreviewLayer(layer: previewLayerConnection, orientation: UIApplication.shared.statusBarOrientation.videoOrientation)
  }
}

private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
  layer.videoOrientation = orientation
  videoPreviewLayer?.frame = self.view.bounds
}

N'oubliez pas le mappage de UIInterfaceOrientation vers AVCaptureVideoOrientation

extension UIInterfaceOrientation {

  public var videoOrientation: AVCaptureVideoOrientation {
    switch self {
    case .portrait:
      return AVCaptureVideoOrientation.portrait
    case .landscapeRight:
      return AVCaptureVideoOrientation.landscapeRight
    case .landscapeLeft:
      return AVCaptureVideoOrientation.landscapeLeft
    case .portraitUpsideDown:
      return AVCaptureVideoOrientation.portraitUpsideDown
    default:
      return AVCaptureVideoOrientation.portrait
    }
  }

}
1
juliancadi

Swift 5 Version

  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    updatePreview()
  }

  func updatePreview() {
    let orientation: AVCaptureVideoOrientation
    switch UIDevice.current.orientation {
      case .portrait:
        orientation = .portrait
      case .landscapeRight:
        orientation = .landscapeLeft
      case .landscapeLeft:
        orientation = .landscapeRight
      case .portraitUpsideDown:
        orientation = .portraitUpsideDown
      default:
        orientation = .portrait
    }
    if previewLayer?.connection?.isVideoOrientationSupported == true {
      previewLayer?.connection?.videoOrientation = orientation
    }
    previewLayer.frame = view.bounds
  }
1
Steven

Nous devons d’abord créer AVCaptureVideoPreviewLayer et:

  1. définir sa valeur videoGravity (comme dans mon cas, j'utilise une petite vue pour obtenir une sortie vidéo). 
  2. définir le cadre.

    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
    
  3. définir l'orientation initialement 

    if (_videoPreviewLayer.connection.supportsVideoOrientation) {
            _videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
        }
  4. définir l'orientation pour chaque cas en utilisant un boîtier d'interrupteur simple

    -(AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:

    (UIInterfaceOrientation)orientation {
    
        switch (orientation) {
            case UIInterfaceOrientationPortrait:
                return AVCaptureVideoOrientationPortrait;
            case UIInterfaceOrientationPortraitUpsideDown:
                return AVCaptureVideoOrientationPortraitUpsideDown;
            case UIInterfaceOrientationLandscapeLeft:
                return AVCaptureVideoOrientationLandscapeLeft ;
            case UIInterfaceOrientationLandscapeRight:
                return AVCaptureVideoOrientationLandscapeRight;
            default:
                break;
        }
        NSLog(@"Warning - Didn't recognise interface orientation (%d)",orientation);
        return AVCaptureVideoOrientationPortrait;
    

    } </ pre> </ code>

  5. Étant donné que l'appareil prend en charge landscapeLeft et landscapeRight, utilisez le délégué appelé en rotation:
    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    if (_videoPreviewLayer.connection.supportsVideoOrientation) {
        _videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:toInterfaceOrientation];
     }
    }
    
1
Maniac One

La réponse de Maselko a presque fonctionné pour moi, sauf que si l'orientation de la barre d'état bascule, la sortie de la caméra s'affiche à l'envers. J'ai résolu ce problème en appelant à nouveau la logique de Maselko lorsque la barre d'état bascule.

Voici ma solution Maselko modifiée (testée sur ios12/Swift4):

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    setCameraOrientation()
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    setCameraOrientation()
}

@objc func setCameraOrientation() {
    if let connection =  self.previewLayer?.connection  {
        let currentDevice: UIDevice = UIDevice.current
        let orientation: UIDeviceOrientation = currentDevice.orientation
        let previewLayerConnection : AVCaptureConnection = connection
        if previewLayerConnection.isVideoOrientationSupported {
            let o: AVCaptureVideoOrientation
            switch (orientation) {
            case .portrait: o = .portrait
            case .landscapeRight: o = .landscapeLeft
            case .landscapeLeft: o = .landscapeRight
            case .portraitUpsideDown: o = .portraitUpsideDown
            default: o = .portrait
            }

            previewLayerConnection.videoOrientation = o
            previewLayer!.frame = self.view.bounds
        }
    }
}
1
sttawm

Version améliorée de la réponse de Maselko

Fonctionne tout simplement génial!

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  if let connection =  previewView.connection  {
    if connection.isVideoOrientationSupported {
      let videoOrientation = AVCaptureVideoOrientation.init(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!
      connection.videoOrientation = videoOrientation
      previewView.frame = self.view.bounds
    }
  }
}
0
Kenan Karakecili

Voici la solution que j'utilise avec Swift 4. 

C'est court et fonctionne à merveille pour moi.

open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let videoLayer = self.previewLayer
    coordinator.animate(alongsideTransition: { (context: UIViewControllerTransitionCoordinatorContext) in

        guard let connection = videoLayer?.connection, connection.isVideoOrientationSupported, let orientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue) else {
            return
        }

        connection.videoOrientation = orientation
        videoLayer?.frame = self.view.bounds

    }) { (context: UIViewControllerTransitionCoordinatorContext) in
        // handle any completion logic here...
    }
}
0
digitalHound

La réponse de @Maselko est correcte, mais pour une chose: vous devriez utiliser UIApplication.shared.statusBarOrientation au lieu de UIDevice.current.orientation, car l'orientation du périphérique correspond à la position de votre périphérique physiquement. Il se casse lorsque votre appareil est en mode paysage mais votre interface utilisateur ne prend pas en charge cette orientation (comme lorsque je réalisais une application de caméra en mode paysage uniquement et que je créais la vue lorsque l'appareil était en position portrait).

private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {

    layer.videoOrientation = orientation

    previewLayer.frame = self.view.bounds

}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let connection =  self.previewLayer?.connection  {

        let currentDevice: UIDevice = UIDevice.current

        let orientation = UIApplication.shared.statusBarOrientation

        let previewLayerConnection : AVCaptureConnection = connection

        if previewLayerConnection.isVideoOrientationSupported {

            switch (orientation) {
            case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)

                break

            case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)

                break

            case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)

                break

            case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)

                break

            default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)

                break
            }
        }
    }
}
0
Teng L

La seule façon dont cela a fonctionné pour moi dans iOS 8 à 11.1 sans aucun problème est de le faire et je tiens à mentionner que dans mon cas, je n'ai chargé mon application qu'en mode paysage, mais elle devrait fonctionner dans toutes les orientations. caméra manuellement via imageview ou tout ce que vous voulez de cette façon très facilement)

@interface ViewController (){
    AVCaptureVideoPreviewLayer * previewLayer;
    AVCaptureSession* session;
}
@property (weak, nonatomic) IBOutlet UIView *cameraPreviewView;


-(void)viewDidLoad{
    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
    if (captureInput) {
        session = [[AVCaptureSession alloc] init];
        [session addInput:captureInput];
    }
    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];

    CALayer *rootLayer = [self.cameraPreviewView layer];
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[self.view bounds]];
    [rootLayer addSublayer:previewLayer];
    [session startRunning];

    //Orientation Code is in viewDidLayoutSubviews method
}
-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
            break;
        case UIInterfaceOrientationLandscapeLeft:
            [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
            break;
        case UIInterfaceOrientationLandscapeRight:
            [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
            break;
        default:break;
    }
}
0
Reza.Ab