AVCaptureSession with multiple orientations issue

半城伤御伤魂 提交于 2019-12-03 21:10:04

Ah fixed it with the following

-(void) orientationChanged {
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (deviceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        [_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];

    else if (deviceOrientation == UIInterfaceOrientationPortrait)
        [_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];

    else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft)
        [_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];

    else
        [_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}

To reflect device orientation changes in your captured media you need to set the videoOrientation property of a output capture connection.

AVCaptureOutput* output = <# Your capture output device #>; //reference to your device output, possibly of AVCaptureStillImageOutput or AVCaptureMovieFileOutput type
AVCaptureConnection* connection = [output connectionWithMediaType:AVMediaTypeVideo];
if ([connection isVideoOrientationSupported]) {
    connection.videoOrientation = [self videoOrientationFromDeviceOrientation];
}

And the method below returns video orientation based on device orientation:

-(AVCaptureVideoOrientation)videoOrientationFromDeviceOrientation {
    AVCaptureVideoOrientation result = [UIDevice currentDevice].orientation;
    if ( result == UIDeviceOrientationLandscapeLeft )
        result = AVCaptureVideoOrientationLandscapeRight;
    else if ( result == UIDeviceOrientationLandscapeRight )
        result = AVCaptureVideoOrientationLandscapeLeft;
    return result;
}

Hope you would find it helpful.

I don't have new informations on this issue, but I think both provided answers are good and still just the half story. I worked on this issue quite a long time today and didn't find the right answer for my situation. But almost.

Actually you'd need to comply with both solutions. You definitely need to rotate the preview layer correspondingly. But if you want to have the footage in the same orientation (and not somehow cut off), you'd need to do a combination.

Also I'm including a fix: -[UIDevice orientation] gets you with the real orientation of the device in the room. But you'd probably better rely on the interface orientation of the application as seen in the code below.

In my case I only support landscape (both) and have a video recorder which writes to disk. Here I'm using a block for the notifications, since I like 'em a lot ;)

// @property (nonatomic, retain) AVCaptureMovieFileOutput *videoFileOutput;
// @property (nonatomic, retain) AVCaptureVideoPreviewLayer *videoPreviewLayer;

- (void)viewDidLoad {
    [super viewDidLoad];

    void (^observerHandler)(NSNotification *) = ^(NSNotification *note) {
        switch ([[UIApplication sharedApplication] statusBarOrientation]) {
            case UIInterfaceOrientationLandscapeRight:
                [[[self videoPreviewLayer] connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
                [[[self videoFileOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
                break;

            case UIInterfaceOrientationLandscapeLeft:
                [[[self videoPreviewLayer] connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
                [[[self videoFileOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
                break;

            default:
                break;
        }
    };

    [self setOrientationObserver:[[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceOrientationDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:observerHandler]];
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!