AVFoundation - How to control exposure

前端 未结 2 1613
Happy的楠姐
Happy的楠姐 2021-01-18 00:07

AFTER tapping to take picture, I want to lock exposure and turn off torch as soon as exposure is no longer adjusting. So, I added an observer to handle adj

相关标签:
2条回答
  • 2021-01-18 00:22

    It is almost certainly a timing issue. Call captureStillImageAsynchronouslyFromConnection:completionHandler: inside your if block. Then the capture will always be executed after exposure has been locked.

    if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) {
        dispatch_async(dispatch_get_main_queue(), 
            ^{
                NSError *error = nil;
                if ([self.inputDevice lockForConfiguration:&error]) {
                    //code to lock exposure here
                    //take photo here
                }
            });
    }
    
    0 讨论(0)
  • 2021-01-18 00:34

    I got something similar to happen by using flash instead of the torch. I have an observer for @"videoDevice.flashActive" as well. I did try using exposureModeLocked first, but it didn't work for me either.

    1. Take a photo with flash on
    2. Then instantly turn flash off and take another photo before the exposure has time to adjust

    The code below probably doesn't just work on its own, but it's simplified from what I did.

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
    {
        if (context == AdjustingExposureContext)
        {
            self.isAdjustingExposure = [change[NSKeyValueChangeNewKey] boolValue];
        }
        else if (context == FlashModeChangedContext)
        {
            self.isFlashActive = [change[NSKeyValueChangeNewKey] boolValue];
            if (!self.flashActive)
            {
                [self captureImage];  // QUICKLY! capture 2nd image without
            }                         // flash before exposure adjusts
        }
        if (!self.isAdjustingExposure && self.flashActive)
        {
            [self removeObserver:self forKeyPath:@"videoDevice.adjustingExposure" context:AdjustingExposureContext];
            [self captureImage];  // capture 1st image with the flash on
        }
    }
    

    Now in the callback for captureStillImageAsynchronouslyFromConnection:,

    if (self.isFlashActive)
        [self.videoDeviceInput.device setFlashMode:NO];
    

    However, if you need to take more than one photo without flash at the lowered exposure, this strategy may not work.

    0 讨论(0)
提交回复
热议问题