Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS NSInternalInconsistencyException while taking a photo while app is using iOS9 picture in picture mode

I am having a crash when trying to take a photo (front facing camera), that only fails when the user is using picture in picture mode for a separate apps video. Everything works fine if the user doesn't have a video in picture in picture. The crash occurs on this line:

[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {

with the error

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVCaptureStillImageOutput captureStillImageAsynchronouslyFromConnection:completionHandler:] - inconsistent state.'

I tried checking if the phone just couldn't take a photo in general while using picture in picture mode, but the default iOS camera app is able to take a picture fine (although maybe it uses a different method of taking the photo). stillImageOutput and videoConnection seem to be set up fine and are not nil.

Here is the code leading up to this crash in case it helps.

avCaptureSession = [[AVCaptureSession alloc] init];
AVCaptureDevice* cameraDevice = [GS60_FriendFeed_ScreenshotSelfie_Preview_View frontFacingCameraIfAvailable];
avCaptureSession.sessionPreset = avCaptureSessionPresetString;

NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:&error];
if (!input) {
    NSLog(@"ERROR: trying to open camera: %@", error);
}
[avCaptureSession addInput:input];
AVCaptureStillImageOutput* stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[avCaptureSession addOutput:stillImageOutput];
[avCaptureSession startRunning];

and later

AVCaptureConnection* videoConnection = nil;
AVCaptureStillImageOutput* stillImageOutput = [[avCaptureSession outputs] objectAtIndex:0];
for (AVCaptureConnection* connection in stillImageOutput.connections) {
    for (AVCaptureInputPort *port in [connection inputPorts]) {
        if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
            videoConnection = connection;
            break;
        }
    }
    if (videoConnection) { break; }
}

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
AVCaptureVideoOrientation avcaptureOrientation = AVCaptureVideoOrientationPortrait;
if(orientation == UIInterfaceOrientationUnknown) {
    avcaptureOrientation = AVCaptureVideoOrientationPortrait;
} else if(orientation == UIInterfaceOrientationPortrait) {
    avcaptureOrientation = AVCaptureVideoOrientationPortrait;
} else if(orientation == UIInterfaceOrientationPortraitUpsideDown) {
    avcaptureOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
} else if(orientation == UIInterfaceOrientationLandscapeLeft) {
    avcaptureOrientation = AVCaptureVideoOrientationLandscapeLeft;
} else if(orientation == UIInterfaceOrientationLandscapeRight) {
    avcaptureOrientation = AVCaptureVideoOrientationLandscapeRight;
}
[videoConnection setVideoOrientation:avcaptureOrientation];

//this line flips the image so it uses exactly what the preview shows
[videoConnection setVideoMirrored:YES];
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
...

I would prefer to be able to take the photo but if that is not possible while picture in picture is open, knowing how to detect that we won't be able to take it would be still be helpful.

Thanks for any help.

like image 475
ksiit Avatar asked Aug 26 '16 00:08

ksiit


People also ask

How to take a selfie in portrait mode on iPhone?

Take a selfie in Portrait mode. With an iPhone X and later, you can take selfies in Portrait mode. Here's how: Open the Camera app. Swipe to Portrait mode and tap the front-facing camera button . Hold your iPhone in front of your face. Snap your selfie with one of the volume buttons.

How to change lighting on iPhone portrait mode photos?

Change Lighting on iPhone 1 Open the Photos app, then select the Portrait mode photo that you want to change. 2 Tap Edit. Lighting effects appear in the bottom part of the photo. 3 Swipe the lighting effects to choose the one you want. 4 Tap Done. See More....

How do I take a picture in portrait mode on Android?

Take photos in Portrait mode. To capture the perfect shot: Open the Camera app and swipe to Portrait mode. Follow the tips on your screen, such as moving further away. When Portrait mode is ready, the lighting effect, like Natural Light, turns yellow. Tap the shutter button .

Does the iPhone XR camera support portrait mode?

The rear-facing iPhone XR camera supports only Natural Light, Studio Light, and Contour Light. With an iPhone X and later, you can take selfies in Portrait mode. Here's how: Open the Camera app.


2 Answers

Make sure the connection is there and enabled

if (!videoConnection || !videoConnection.enabled || !videoConnection.active) {
    // Raise error here / warn user... 
    return;
}
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
AVCaptureVideoOrientation avcaptureOrientation = AVCaptureVideoOrientationPortrait;
like image 174
Evtim Georgiev Avatar answered Oct 19 '22 20:10

Evtim Georgiev


This can happen when the capture session is interrupted and unable to start, which can be triggered by a phone call, alarm, the app being in split screen on the iPad, or another app using picture-in-picture mode.

It's a good idea to add an observer for the AVCaptureSessionWasInterrupted notification so your app can respond and alert the user according to the reason.

You can check for the reason in the notification callback:

notification.userInfo[AVCaptureSessionInterruptionReasonKey];

Furthermore, you should add an observer for AVCaptureSessionInterruptionEnded to restart the session when the interruption has ended.

Apple has a great example on how this works.

like image 31
Antipex Avatar answered Oct 19 '22 18:10

Antipex