Question

I have an iPhone camera app in which I use the AVCaptureVideoPreviewLayer. When someone takes a picture/stillImage this is shown in a new ViewController. The magic happens once this view controller is dismissed.

The whole app rotates properly, both viewcontroller; but for one exception. If I take a picture in one orientation, rotate the device in the new ViewController and then go back to the AVCaptureVideoPreviewLayer the whole layer rotates along just fine, except for the image, so suddenly the input is presented sideways through the previewLayer.

I have checked, and tried setting the frame for the PreviewLayer, but this all seems fine, the values I see when debugging are all correct. It is just the image that is displayed that is skewed. Rotating the device back and forth fixes this issue during use.

Has anyone seen this before, and does anyone have a clue how to fix this?

Was it helpful?

Solution

You could change the previewLayer's connection's videoOrientation when the interface rotates

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    self.previewLayer.connection.videoOrientation = self.interfaceOrientation;
}

OTHER TIPS

Since didRotateFromInterfaceOrientation: is deprecated in iOS 8, I change the video orientation of the connection in viewDidLayoutSubviews

switch ([UIApplication sharedApplication].statusBarOrientation) {
    case UIInterfaceOrientationPortrait:
        self.captureVideoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
        break;
    case UIInterfaceOrientationPortraitUpsideDown:
        self.captureVideoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
        break;
    case UIInterfaceOrientationLandscapeLeft:
        self.captureVideoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
        break;
    case UIInterfaceOrientationLandscapeRight:
        self.captureVideoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
        break;
    default:
        break;
}

I had a similar problem in the past. Once dismissed camera controller you could refresh view rotation with this:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *topView = [window.subviews objectAtIndex:0];
[topView removeFromSuperview];
[window addSubview:topView];        

So, removing top most view on shown window and resetting it on window, it should refresh view rotation properly.

Hope it helps

Maybe, instead of changing AVCaptureVideoPreviewLayer frame, you could try to put it in a container UIView, and set this container's frame. (I fixed a 'sizing' bug on ÀVCaptureVideoPreviewLayerthis way : sizing directly PreviewLayer had no effect, but sizing its containingUIView` worked).

Or, maybe you can force orientation in your viewController viewWillAppear (or viewDidAppear ?)

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // try and force current orientation
    UIApplication *application = [UIApplication sharedApplication];
    UIInterfaceOrientation currentOrientation = application.statusBarOrientation;
    [application setStatusBarOrientation:currentOrientation animated:animated];
}

Good luck !

Since the interfaceOrientation is deprecated, the up to date swift 2.0 solution shall be:

let previewLayerConnection = self.previewLayer.connection
let orientation = AVCaptureVideoOrientation(rawValue: UIApplication.sharedApplication().statusBarOrientation.rawValue)
previewLayerConnection.videoOrientation = orientation!
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top