2014-12-02 29 views
8

Aplikacja Mac OS X, którą koduję, wykonuje zdjęcie przy użyciu wbudowanej kamery Mac Facebook.Ustawienie AVCapture Adjusting Exposure jest fałszywe, ale przechwycony obraz jest ciemny

Na MacBookAir3,2, MacBookPro8,2 i MacBookPro10,2 to działa dobrze, ale na nowych MacBooków trwa „ciemny” zdjęć. Rozumiem, że jest to spowodowane automatyczną ekspozycją, ale mam problem z jej działaniem. Ustawienie adjustingExposure jest ustawione na NO, ale zrobione zdjęcie jest nadal całkowicie ciemne.

Kod: setupCamera nazywa raz podczas uruchomienia aplikacji

-(void) setupCamera 
{ 
    session = [[AVCaptureSession alloc] init]; 
    session.sessionPreset = AVCaptureSessionPresetPhoto; 

    sessionInitialized = YES; 

    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    [device lockForConfiguration:NULL]; 
    if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) 
     [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure]; 

    if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) 
     [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; 

    if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) 
     [device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]; 

    [device unlockForConfiguration]; 


    NSError *error = nil; 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; 
    if(error != nil) { 
     // ... 
    } 

    if([session canAddInput:input]) { 
     [session addInput:input]; 
    } else { 
     // ... 
    } 

    output = [[AVCaptureStillImageOutput alloc] init]; 
    NSDictionary *outputSettings = @{ AVVideoCodecKey : AVVideoCodecJPEG }; 
    [output setOutputSettings:outputSettings]; 

    if([session canAddOutput:output]) { 
     [session addOutput:output]; 
    } else { 
     // ... 
    } 
} 

... wtedy każde kliknięcie na przycisk snap w interfejsie wywołuje shootPhoto funkcję:

-(void) shootPhoto 
{ 
    [session startRunning]; 

    if([device lockForConfiguration:NULL]) { 
     if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) 
      [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure]; 

     if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) 
      [device setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; 

     if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) 
      [device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]; 

     [device unlockForConfiguration]; 
    } 

    if(device.adjustingFocus == NO && device.adjustingExposure == NO && device.adjustingWhiteBalance == NO) { 
     [self actuallyCapture]; 
    } else { 
     [device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext]; 
     [device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:MyAdjustingFocusObservationContext]; 
     [device addObserver:self forKeyPath:@"adjustingWhiteBalance" options:NSKeyValueObservingOptionNew context:MyAdjustingWhiteBalanceObservationContext]; 
    } 
} 

-(void) actuallyCapture 
{ 
    if ([session isRunning] == NO) 
     return; 

    connection = [output connectionWithMediaType:AVMediaTypeVideo]; 
    [output captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { 
     // save file etc ... 
    }]; 
} 

pomysł jest aby sprawdzić, czy urządzenie aparatu reguluje ostrość, ekspozycję lub balans bieli. Jeśli nie, natychmiast zadzwoń pod numer actuallyCapture. Jeśli się dostosowuje - dodaj obserwatorów i zadzwoń pod numer actuallyCapture z observeValueForKeyPath.

Problem polega na tym, że połączenia addObserver nigdy nie są wywoływane, ponieważ urządzenie zwraca wszystkie adjustingX==NO - ale mimo to przechwycone zdjęcie jest ciemne.

Jaki może być tego powód? Czy właściwie czekam na regulację balansu bieli i ekspozycji?

Ciężko mi debugować, ponieważ posiadam tylko te urządzenia, które działają dobrze.

Odpowiedz

2

Udało mi się rozwiązać ten problem osobiście. Oto jak to zrobiłem:

Set obserwatorzy dla adjustingExposure, adjustingFocus i adjustingWhiteBalance:

[self.device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext]; 
[self.device addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:MyAdjustingFocusObservationContext]; 
[self.device addObserver:self forKeyPath:@"adjustingWhiteBalance" options:NSKeyValueObservingOptionNew context:MyAdjustingWhiteBalanceObservationContext]; 

się uchwycić na zdjęciu inicjalizacji AVCaptureSession ale ustawić 1s opóźnienia samowyzwalacza i rzeczywiście uchwycić po pożary:

-(void) shootPhoto 
{ 
    dispatch_async(self.sessionQueue, ^{ 
     if([self setupCamera]) { 
      self.sessionInitialized = YES; 
      [self.session startRunning]; 

      self.isWaitingToCaptureImage = YES; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       self.captureDelayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 
                      target:self 
                     selector:@selector(actuallyCapture) 
                     userInfo:nil 
                     repeats:NO]; 
      }); 
     } 
    }); 
} 

W czeku observeValueForKeyPath:ofObject:change:context jeśli wszystkie trzy korekty są już wykonane i czy są one - anulować timer ustawiony wyżej i zrób zdjęcie:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if(!self.sessionInitialized || !self.isWaitingToCaptureImage) { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
     return; 
    } 

    if (context != MyAdjustingExposureObservationContext && context != MyAdjustingFocusObservationContext && context != MyAdjustingWhiteBalanceObservationContext) { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
     return; 
    } else { 
     if (self.device.adjustingExposure || self.device.adjustingFocus || self.device.adjustingWhiteBalance) { 
      NSLog(@"not ready to capture yet"); 
      return; 
     } else { 
      NSLog(@"ready to capture"); 
      if (self.captureDelayTimer && self.captureDelayTimer.isValid) { 
       [self.captureDelayTimer invalidate]; 
       self.captureDelayTimer = nil; 
      } 
      [self actuallyCaptureDispatch]; 
     } 
    } 
} 
+0

Co to jest MyAdjustingWhiteBalanceObservationContext? – confile