AVCapture превью зависает / застревает при разблокировке телефона

ios objective-c avcapturesession avcapture

853 просмотра

2 ответа

Приложение iOS для камеры, написанное на Objective C, замораживает слой предварительного просмотра при возврате с экрана блокировки / при разблокировке телефона.

Все настройки камеры вызываются в viewWillAppear. До сих пор я был успешным, за исключением единственной проблемы, которая заключается в том, что слой предварительного просмотра камеры зависает или застревает при возвращении с экрана блокировки. Раздел камеры моего кода приведен ниже.

Буду признателен за любую оказанную помощь. Спасибо. PS: Пожалуйста, не стесняйтесь указывать на любую ошибку в моем коде, так как я только новичок.

- (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];
});
}
Автор: sreejesh Источник Размещён: 08.11.2019 10:59

Ответы (2)


1 плюс

попробуйте наблюдать UIApplicationDidEnterBackgroundNotification/UIApplicationWillEnterForegroundNotification,UIApplicationWillResignActiveNotification/UIApplicationDidBecomeActiveNotificationуведомления, чтобы остановить / начать сеанс захвата соответственно

Автор: Frog Tan Размещён: 20.08.2016 08:37

0 плюса

Существует большое различие между жизненным циклом приложенияViewDidLoad ViewWillAppear и ViewDidAppearметода приложения .

Создание UIViews или выполнение какой-либо тяжелой задачи довольно дорого вызывает замораживание, и вам следует избегать, насколько это возможно, использования метода ViewWillAppear.

посмотри:

  1. ViewDidLoad : всякий раз, когда я добавляю элементы управления в представление, которое должно отображаться вместе с представлением, сразу же я помещаю его в метод ViewDidLoad. В основном этот метод вызывается всякий раз, когда представление загружается в память. Например, если мое представление представляет собой форму с 3 метками, я бы добавил сюда метки; представление никогда не будет существовать без этих форм.
  2. ViewWillAppear : ViewWillAppear обычно просто для обновления данных в форме. Итак, для примера выше, я бы использовал это для загрузки данных из моего домена в форму. Создание UIViews довольно дорого, и вам следует избегать, насколько это возможно, использования метода ViewWillAppear, поскольку при его вызове это означает, что iPhone уже готов показать UIView пользователю и все, что вы здесь делаете. будет влиять на производительность очень заметным образом (например, задержка анимации и т. д.).
  3. ViewDidAppear : ViewDidAppear для запуска новых потоков с вещами, выполнение которых может занять много времени, например, например, вызовом веб- службы для получения дополнительных данных для формы выше. Хорошая вещь заключается в том, что представление уже существует и отображается для пользователь, вы можете показать приятное сообщение "Ожидание" пользователю, пока вы получаете данные.
Автор: vaibhav Размещён: 20.08.2016 07:35
Вопросы из категории :
32x32