2016-08-08 4 views
0

У меня есть странная проблема,AVCaptureSession с Autolayout

В моем приложении я бегу фоновое видео (через AVCaptureSession) и приложение для iPhone устройств поэтому он должен соответствовать несколько экранов с помощью autolayout. Проблема заключается в том, что я устанавливаю сеанс в ViewDidLoad фреймы, которые еще не установлены, и если я настрою сеанс на viewDidLayoutSubviews, сеанс прекратит работу и приложение завершится с ошибкой.

Вот мой AVCaptureSession Код

- (void)setupAVCapture { 
    //Capture session 
    _session = nil; 
    _session = [[AVCaptureSession alloc] init]; 
    [_session setSessionPreset:AVCaptureSessionPresetLow]; 

    //Get the camera and set the capture device 
    AVCaptureDevice *inputDevice = [self getCamera:_camera]; // self.camera 

    //Capture device input 
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil]; 
    if ([_session canAddInput:deviceInput]) 
     [_session addInput:deviceInput]; 

    //Capture Still Image Output 
    stillImageOutput = nil; 
    stillImageOutput = [AVCaptureStillImageOutput new]; 
    [stillImageOutput addObserver:self forKeyPath:@"capturingStillImage" options:NSKeyValueObservingOptionNew context:(__bridge void *)(AVCaptureStillImageIsCapturingStillImageContext)]; 
    if ([_session canAddOutput:stillImageOutput]) 
    { 
     [_session addOutput:stillImageOutput]; 
    } 

    //Capture Video Data Output 
    videoDataOutput = nil; 
    videoDataOutput = [AVCaptureVideoDataOutput new]; 

    NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 
    [videoDataOutput setVideoSettings:rgbOutputSettings]; 
    [videoDataOutput setAlwaysDiscardsLateVideoFrames:YES]; 

    videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL); 
    [videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue]; 

    if ([_session canAddOutput:videoDataOutput]) 
    { 
     [_session addOutput:videoDataOutput]; 
    } 

    [[videoDataOutput connectionWithMediaType:AVMediaTypeVideo] setEnabled:NO]; 

    //preview view 
    self.previewLayer = nil; 
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session]; 
    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 

    CALayer *rootLayer = [_previewView layer]; 
    [rootLayer setMasksToBounds:YES]; 
    [[[self previewLayer]connection]setVideoOrientation:AVCaptureVideoOrientationPortrait]; 
    //[self.previewLayer setTransform:CATransform3DMakeAffineTransform(CGAffineTransformMakeRotation(-M_PI/2))]; 
    [self.previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height)]; 
    [rootLayer insertSublayer:self.previewLayer atIndex:0]; 

    //go 
    [_session startRunning]; 

    AVCaptureDevicePosition desiredPosition = [[self getCamera:_camera] position];//AVCaptureDevicePositionFront; 

    for (AVCaptureDevice *captureDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) 
    { 
     if ([captureDevice position] == desiredPosition) 
     { 
      [[_previewLayer session] beginConfiguration]; 
      AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil]; 

      for (AVCaptureInput *oldInput in [[_previewLayer session] inputs]) 
      { 
       [[_previewLayer session] removeInput:oldInput]; 
      } 

      [[_previewLayer session] addInput:input]; 
      [[_previewLayer session] commitConfiguration]; 
      break; 
     } 
    } 
} 

ответ

0

Ахаха, это смешно, вчера я пришел через эту проблему, с тем же грохотом. Так что, даже если это не так, вы используете этот код в фоновом режиме. Вы должны четко сказать, что вы хотите, чтобы добавить слои на главном потоке, особенно эти три строк коды:

[self.previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height)]; 
    [rootLayer insertSublayer:self.previewLayer atIndex:0]; 
    [_session startRunning]; 

сделать это вместо того, чтобы:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height)]; 
    [rootLayer insertSublayer:self.previewLayer atIndex:0]; 
    [_session startRunning]; 
}); 

Надеется, что это поможет;)

+0

I все еще получил malloc: *** ошибка для объекта 0x17004e820: неверный указатель удален из бесплатного списка *** установить точку останова в malloc_error_break для отладки – OXXY

+0

ok, попробуйте запустить сеанс в viewDidAppear, чтобы узнать, исходит ли он из макета – RomOne

+0

Кажется, что проблема, вызванная XCode 8.0 beta 4, я построил проект на XCode 7.3.1, и он отлично работает – OXXY