Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVCapture preview freezes/stuck when unlocking the phone

My iOS camera app written in Objective C freezes its preview layer when coming back from the lock screen/when unlocking the phone.

All the camera configurations settings are being called in the viewWillAppear. I have been successful so far, except for the only problem, which is the camera preview layer freezes or stuck when coming back from the lock screen. The camera section of my code is given below.

Any help is much appreciated. Thank you. ps: Please feel free to point out any mistake in my code as i am just a newbie.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    dispatch_async(dispatch_get_main_queue(), ^{
    [self setGUIBasedOnMode];
    });
}


-(void) setGUIBasedOnMode
{
if (![self isStreamStarted]) {
if (shutterActionMode == SnapCamSelectionModeLiveStream)
{
    _flashButton.hidden = true;
    _cameraButton.hidden = true;
    _liveSteamSession = [[VCSimpleSession alloc] initWithVideoSize:[[UIScreen mainScreen]bounds].size frameRate:30 bitrate:1000000 useInterfaceOrientation:YES];
    [_liveSteamSession.previewView removeFromSuperview];
    AVCaptureVideoPreviewLayer  *ptr;
    [_liveSteamSession getCameraPreviewLayer:(&ptr)];
    _liveSteamSession.previewView.frame = self.view.bounds;
    _liveSteamSession.delegate = self;
}
else{
    [_liveSteamSession.previewView removeFromSuperview];
    _liveSteamSession.delegate = nil;
    _cameraButton.hidden = false;
    if(flashFlag == 0){
        _flashButton.hidden = false;
    }
    else if(flashFlag == 1){
        _flashButton.hidden = true;
    }
    self.session = [[AVCaptureSession alloc] init];
    self.previewView.hidden = false;
    self.previewView.session = self.session;

    [self configureCameraSettings]; //All The Camera Configuration Settings.

    dispatch_async( self.sessionQueue, ^{
        switch ( self.setupResult )
        {
            case AVCamSetupResultSuccess:
            {
                [self addObservers];

                [self.session startRunning];

                self.sessionRunning = self.session.isRunning;
                if(loadingCameraFlag == false){
                    [self hidingView];
                }
                break;
            }
            case AVCamSetupResultCameraNotAuthorized:
            {
                dispatch_async( dispatch_get_main_queue(), ^{
                    NSString *message = NSLocalizedString( @"MyApp doesn't have permission to use the camera, please change privacy settings", @"Alert message when the user has denied access to the camera");
                    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"AVCam" message:message preferredStyle:UIAlertControllerStyleAlert];
                    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"OK", @"Alert OK button" ) style:UIAlertActionStyleCancel handler:nil];
                    [alertController addAction:cancelAction];

                    UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Settings", @"Alert button to open Settings" ) style:UIAlertActionStyleDefault handler:^( UIAlertAction *action ) {
                        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                    }];
                    [alertController addAction:settingsAction];
                    [self presentViewController:alertController animated:YES completion:nil];
                } );
                break;
            }
            case AVCamSetupResultSessionConfigurationFailed:
            {
                dispatch_async( dispatch_get_main_queue(), ^{
                    NSString *message = NSLocalizedString( @"Unable to capture media", @"Alert message when something goes wrong during capture session configuration" );
                    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"MyApp" message:message preferredStyle:UIAlertControllerStyleAlert];
                    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"OK", @"Alert OK button" ) style:UIAlertActionStyleCancel handler:nil];
                    [alertController addAction:cancelAction];
                    [self presentViewController:alertController animated:YES completion:nil];
                } );
                break;
            }
        }
    });
}
}

-(void)configureCameraSettings
{
self.sessionQueue = dispatch_queue_create( "session queue",      DISPATCH_QUEUE_SERIAL );
self.setupResult = AVCamSetupResultSuccess;
switch ( [AVCaptureDevice     authorizationStatusForMediaType:AVMediaTypeVideo] )
{
    case AVAuthorizationStatusAuthorized:
    {
        break;
    }
    case AVAuthorizationStatusNotDetermined:
    {
        dispatch_suspend( self.sessionQueue);
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^( BOOL granted ) {
            if ( ! granted ) {
                self.setupResult = AVCamSetupResultCameraNotAuthorized;
            }
            dispatch_resume( self.sessionQueue );
        }];
        break;
    }
    default:
    {
        self.setupResult = AVCamSetupResultCameraNotAuthorized;
        break;
    }
}

dispatch_async( self.sessionQueue, ^{
if ( self.setupResult != AVCamSetupResultSuccess ) {
    return;
}
self.backgroundRecordingID = UIBackgroundTaskInvalid;
NSError *error = nil;

AVCaptureDevice *videoDevice = [IPhoneCameraViewController deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack];
AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];

[self.session beginConfiguration];

if ( [self.session canAddInput:videoDeviceInput] ) {
    [self.session addInput:videoDeviceInput];
    self.videoDeviceInput = videoDeviceInput;

    dispatch_async( dispatch_get_main_queue(), ^{
        UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
        AVCaptureVideoOrientation initialVideoOrientation = AVCaptureVideoOrientationPortrait;
        if ( statusBarOrientation != UIInterfaceOrientationUnknown ) {
            initialVideoOrientation = (AVCaptureVideoOrientation)statusBarOrientation;
        }
        AVCaptureVideoPreviewLayer *previewLayer = (AVCaptureVideoPreviewLayer *)self.previewView.layer;
        if (shutterActionMode == SnapCamSelectionModeVideo)
        {
            [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
            if([self.session canSetSessionPreset:AVCaptureSessionPresetMedium]){
                [self.session setSessionPreset:AVCaptureSessionPresetMedium];
            }
        }
        previewLayer.connection.videoOrientation = initialVideoOrientation;
    } );
}
else {
    self.setupResult = AVCamSetupResultSessionConfigurationFailed;
}

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];

if ( ! audioDeviceInput ) {
}

if ( [self.session canAddInput:audioDeviceInput] ) {
    [self.session addInput:audioDeviceInput];
}
else {
}

AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];

Float64 TotalSeconds = 10*60;
int32_t preferredTimeScale = 30;
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);           movieFileOutput.maxRecordedDuration = maxDuration;
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024 * 100;

if ( [self.session canAddOutput:movieFileOutput] ) {
    [self.session addOutput:movieFileOutput];
    AVCaptureConnection *connection = [movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    if ( connection.isVideoStabilizationSupported ) {
        connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
    self.movieFileOutput = movieFileOutput;
}
else {
    self.setupResult = AVCamSetupResultSessionConfigurationFailed;
}

AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
if ( [self.session canAddOutput:stillImageOutput] ) {
    stillImageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG};
    [self.session addOutput:stillImageOutput];
    self.stillImageOutput = stillImageOutput;
}
else {
    self.setupResult = AVCamSetupResultSessionConfigurationFailed;
}
[self.session commitConfiguration];
});
}
like image 651
sreejesh Avatar asked Aug 20 '16 07:08

sreejesh


1 Answers

try to observe UIApplicationDidEnterBackgroundNotification/UIApplicationWillEnterForegroundNotification,UIApplicationWillResignActiveNotification/UIApplicationDidBecomeActiveNotification notifications to stop/start your capture session correspondingly

like image 92
Frog Tan Avatar answered Nov 02 '22 23:11

Frog Tan