2014-12-02 22 views
8

L'app Mac OS X che sto codificando sta acquisendo una foto utilizzando la fotocamera facetime incorporata macbook.AVCaptureDevice adjustingExposure è False ma l'immagine acquisita è scura

Su MacBookAir3,2, MacBookPro8,2 e MacBookPro10,2 funziona bene ma sui nuovi macbook ci vogliono foto "scure". Capisco che è a causa di esposizione automatica, ma ho problemi a farlo funzionare. Lo AVCaptureDeviceadjustingExposure è impostato su NO ma la foto scattata è ancora completamente scura.

Il codice: setupCamera viene chiamato una volta durante il lancio dell'app

-(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 { 
     // ... 
    } 
} 

... poi ognuno cliccare sul bottone a pressione nell'interfaccia utente chiama la funzione shootPhoto:

-(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 ... 
    }]; 
} 

L'idea è per verificare se il dispositivo della fotocamera sta regolando la messa a fuoco, l'esposizione o il bilanciamento del bianco. Se non chiamare il actuallyCapture subito. Se si sta regolando - aggiungi osservatori e chiama lo actuallyCapture dallo observeValueForKeyPath.

Il problema è che le chiamate addObserver non vengono mai chiamate perché il dispositivo restituisce tutte adjustingX==NO - ma la foto catturata è ancora scura.

Quale potrebbe essere il motivo? Sto aspettando correttamente il bilanciamento del bianco e le regolazioni dell'esposizione?

È difficile eseguire il debug per me perché possiedo solo quei dispositivi che funzionano correttamente.

risposta

2

Sono riuscito a risolvere da solo questo problema. Ecco come ho fatto:

Set osservatori per adjustingExposure, adjustingFocus e 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]; 

Per catturare foto inizializzare un AVCaptureSession ma impostare un timer di ritardo 1s e in realtà catturare dopo spara:

-(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]; 
      }); 
     } 
    }); 
} 

Nel observeValueForKeyPath:ofObject:change:context controllare se tutte e tre le regolazioni sono già state fatte e se lo sono - annullare il timer impostato sopra e scattare la foto:

- (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

Che cos'è MyAdjustingWhiteBalanceObservationContext? – confile