0

사진을 찍고 있습니다. 사용자가 버튼을 눌러 사진을 찍을 때 과 같은 글로벌 NSString 변수를 self.hasUserTakenAPhoto으로 설정합니다. 후방 카메라를 사용할 때 완벽하게 100 % 작동합니다. 그러나 앞면 카메라를 사용할 때만 약 50 %의 시간이 걸리며 그 이유는 모르겠습니다.전체 변수가 충분히 빠르게 업데이트되지 않습니다.

아래 코드는 중요한 코드와 기능에 대한 간단한 설명입니다.

여기 내 viewDidLoad에 있습니다 :

- (void)viewDidLoad 
{ 

    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 


    self.topHalfView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height/2); 

    self.takingPhotoView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); 

    self.afterPhotoView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); 


    self.bottomHalfView.frame = CGRectMake(0, 240, self.view.bounds.size.width, self.view.bounds.size.height/2); 



    PFFile *imageFile = [self.message objectForKey:@"file"]; 

    NSURL *imageFileURL = [[NSURL alloc]initWithString:imageFile.url]; 

    imageFile = nil; 



    self.imageData = [NSData dataWithContentsOfURL:imageFileURL]; 

    imageFileURL = nil; 

    self.topHalfView.image = [UIImage imageWithData:self.imageData]; 

    //START CREATING THE SESSION 

    self.session =[[AVCaptureSession alloc]init]; 


    [self.session setSessionPreset:AVCaptureSessionPresetPhoto]; 



    self.inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 


    NSError *error; 


    self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.inputDevice error:&error]; 



    if([self.session canAddInput:self.deviceInput]) 
     [self.session addInput:self.deviceInput]; 


    _previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session]; 




    self.rootLayer = [[self view]layer]; 


    [self.rootLayer setMasksToBounds:YES]; 


    [_previewLayer setFrame:CGRectMake(0, 240, self.rootLayer.bounds.size.width, self.rootLayer.bounds.size.height/2)]; 


    [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 


    [self.rootLayer insertSublayer:_previewLayer atIndex:0]; 




    self.videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    self.videoOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) }; 

    [self.session addOutput:self.videoOutput]; 

    dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL); 

    [self.videoOutput setSampleBufferDelegate:self queue:queue]; 



    [_session startRunning]; 

} 

나는 기본적으로 세션을 생성 한 후 실행을 시작 //START CREATING THE SESSION

의 코멘트를 남겼 viewDidLoad 시작의 중요한 부분. 이 뷰 컨트롤러를 AVCaptureVideoDataOutputSampleBufferDelegate으로 설정 했으므로 세션이 시작되면 곧 아래 메서드가 호출되기 시작합니다.

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 

    //Sample buffer data is being sent, but don't actually use it until self.hasUserTakenAPhoto has been set to YES. 


    NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto); 

    if([self.hasUserTakenAPhoto isEqualToString:@"YES"]) { 

    //Now that self.hasUserTakenAPhoto is equal to YES, grab the current sample buffer and use it for the value of self.image aka the captured photo. 

     self.image = [self imageFromSampleBuffer:sampleBuffer]; 

    } 

} 

이 코드는 매 초마다 카메라에서 비디오 출력되고 있지만 실제로 self.hasUserTakenAPhoto 때까지 그것으로 아무것도하지 않는 것은 YES 같다. 그 YES의 문자열 값이되면, 그때 self.hasUserTakenAPhoto 실제로 YES로 설정되어있는 경우 그래서, 여기에 카메라에서 현재 sampleBuffer를 사용하고 self.image

라는 내 전역 변수 안에 넣습니다.

다음은 사용자가 버튼을 눌러 사진을 찍을 때 호출되는 IBAction 코드입니다. 그래서 기본적으로 viewDidLoad 방법이 실행되고 세션이 시작되고 세션이 카메라가에보고 모두를 보내는 self.hasUserTakenAPhoto = @"YES";

-(IBAction)stillImageCapture { 


    self.hasUserTakenAPhoto = @"YES"; 

    [self.session stopRunning]; 


     if(self.inputDevice.position == 2) { 

     self.image = [self selfieCorrection:self.image]; 


    } else { 


     self.image = [self rotate:UIImageOrientationRight]; 


    } 



    CGFloat widthToHeightRatio = _previewLayer.bounds.size.width/_previewLayer.bounds.size.height; 

    CGRect cropRect; 
    // Set the crop rect's smaller dimension to match the image's smaller dimension, and 
    // scale its other dimension according to the width:height ratio. 
    if (self.image.size.width < self.image.size.height) { 
     cropRect.size.width = self.image.size.width; 
     cropRect.size.height = cropRect.size.width/widthToHeightRatio; 
    } else { 
     cropRect.size.width = self.image.size.height * widthToHeightRatio; 
     cropRect.size.height = self.image.size.height; 
    } 

    // Center the rect in the longer dimension 
    if (cropRect.size.width < cropRect.size.height) { 
     cropRect.origin.x = 0; 
     cropRect.origin.y = (self.image.size.height - cropRect.size.height)/2.0; 

     NSLog(@"Y Math: %f", (self.image.size.height - cropRect.size.height)); 


    } else { 
     cropRect.origin.x = (self.image.size.width - cropRect.size.width)/2.0; 
     cropRect.origin.y = 0; 



     float cropValueDoubled = self.image.size.height - cropRect.size.height; 


     float final = cropValueDoubled/2; 


     finalXValueForCrop = final; 


    } 



    CGRect cropRectFinal = CGRectMake(cropRect.origin.x, finalXValueForCrop, cropRect.size.width, cropRect.size.height); 

    CGImageRef imageRef = CGImageCreateWithImageInRect([self.image CGImage], cropRectFinal); 

    UIImage *image2 = [[UIImage alloc]initWithCGImage:imageRef]; 


    self.image = image2; 


    CGImageRelease(imageRef); 



    self.bottomHalfView.image = self.image; 


    if ([self.hasUserTakenAPhoto isEqual:@"YES"]) { 


     [self.takingPhotoView setHidden:YES]; 


     self.image = [self screenshot]; 


     [_afterPhotoView setHidden:NO]; 


    } 

} 

:이 코드를 실행하지만 정말 중요한 것은 모든이의 첫 번째 문이 때 많이 발생 captureOutput 메서드를 호출 한 다음 사용자가 "사진 찍기"버튼을 누르면 문자열 값 을 YES으로 설정하고 세션이 중지되고 self.hasUserTakenAPhoto이 예와 같으므로 captureOutput 메서드는 마지막 카메라 버퍼 나를 위해 self.image 개체에.

내가 뒤에서 카메라를 사용할 때 100 %의 시간 동안 작동한다고 말했기 때문에 나는 이것을 이해할 수 없다. 그러나 앞면 카메라를 사용할 때 시간의 50 % 만 작동합니다.

나는 카메라에 직면 ront를 사용하는 경우 self.hasUserTakenAPhoto이 충분히 빨리 YES에 업데이트되지 않는다는 사실까지 문제를 좁혀, 당신은 내 두번째 코드에서 보면 나는 그것이 NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto);의 문이 게시 때문에 나는 알고있다.

올바르게 작동하고 사용자가 방금 세션을 중지하는 사진을 캡처하기 위해 버튼을 누르면 방금 NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto);을 실행하면 올바른 값인 YES로 인쇄됩니다.

그러나 제대로 실행되지 않고 충분히 빠르게 업데이트되지 않으면 마지막으로 실행될 때 여전히 null 값으로 로그에 인쇄됩니다.

self.hasUserTakenAPhoto에 대한 아이디어가 전면 카메라를 사용하여 50 %의 시간 동안 충분히 빠르게 업데이트되지 않습니까? 우리가 그걸 알아 내지 못하더라도, 그건 중요하지 않습니다. 그저 다른 해결책을 찾아야합니다.

도움 주셔서 감사합니다.

답변

0

나는 스케줄링 문제라고 생각한다. 당신의 방법의 반환 시점에서

– captureOutput:didOutputSampleBuffer:fromConnection: 
– captureOutput:didDropSampleBuffer:fromConnection: 

는 도움에 대한 CFRunLoopRun()

+0

감사를 추가합니다. 내 콜백은 무엇입니까? – user3344977

+0

방금 ​​콜백 메소드를 나열하는 대답을 업데이트했습니다. –

+0

그렇다면 올바르게 이해한다면, 두 번째 코드에서 captureOutput이라는 메서드를 공유 했으므로 CFRunLoopRun(); 마지막 2 개의 중괄호 사이에 정확한? – user3344977

관련 문제