IOS 5 - adjust focus and focus mode AVCaptureDevice freezes the image in real time

I use the following method to set the focus point with iOS 4:

- (void) focusAtPoint:(CGPoint)point { AVCaptureDevice *device = [[self captureInput] device]; NSError *error; if ([device isFocusModeSupported:AVCaptureFocusModeAutoFocus] && [device isFocusPointOfInterestSupported]) { if ([device lockForConfiguration:&error]) { [device setFocusPointOfInterest:point]; [device setFocusMode:AVCaptureFocusModeAutoFocus]; [device unlockForConfiguration]; } else { NSLog(@"Error: %@", error); } } } 

On iOS 4 devices, this works without problems. But on iOS 5, the live camera channel freezes and after a few seconds turns completely black. An exception or error is not thrown.

The error does not occur if I comment on either setFocusPointOfInterest or setFocusMode. Thus, their combination will lead to this behavior.

+4
source share
2 answers

The point you specified for the setFocusPointOfInterest: function is invalid. This is the reason it is crumbling.

Add this method to your program and use the value returned by this function

  - (CGPoint)convertToPointOfInterestFromViewCoordinates:(CGPoint)viewCoordinates { CGPoint pointOfInterest = CGPointMake(.5f, .5f); CGSize frameSize = [[self videoPreviewView] frame].size; AVCaptureVideoPreviewLayer *videoPreviewLayer = [self prevLayer]; if ([[self prevLayer] isMirrored]) { viewCoordinates.x = frameSize.width - viewCoordinates.x; } if ( [[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResize] ) { pointOfInterest = CGPointMake(viewCoordinates.y / frameSize.height, 1.f - (viewCoordinates.x / frameSize.width)); } else { CGRect cleanAperture; for (AVCaptureInputPort *port in [[[[self captureSession] inputs] lastObject] ports]) { if ([port mediaType] == AVMediaTypeVideo) { cleanAperture = CMVideoFormatDescriptionGetCleanAperture([port formatDescription], YES); CGSize apertureSize = cleanAperture.size; CGPoint point = viewCoordinates; CGFloat apertureRatio = apertureSize.height / apertureSize.width; CGFloat viewRatio = frameSize.width / frameSize.height; CGFloat xc = .5f; CGFloat yc = .5f; if ( [[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResizeAspect] ) { if (viewRatio > apertureRatio) { CGFloat y2 = frameSize.height; CGFloat x2 = frameSize.height * apertureRatio; CGFloat x1 = frameSize.width; CGFloat blackBar = (x1 - x2) / 2; if (point.x >= blackBar && point.x <= blackBar + x2) { xc = point.y / y2; yc = 1.f - ((point.x - blackBar) / x2); } } else { CGFloat y2 = frameSize.width / apertureRatio; CGFloat y1 = frameSize.height; CGFloat x2 = frameSize.width; CGFloat blackBar = (y1 - y2) / 2; if (point.y >= blackBar && point.y <= blackBar + y2) { xc = ((point.y - blackBar) / y2); yc = 1.f - (point.x / x2); } } } else if ([[videoPreviewLayer videoGravity] isEqualToString:AVLayerVideoGravityResizeAspectFill]) { if (viewRatio > apertureRatio) { CGFloat y2 = apertureSize.width * (frameSize.width / apertureSize.height); xc = (point.y + ((y2 - frameSize.height) / 2.f)) / y2; yc = (frameSize.width - point.x) / frameSize.width; } else { CGFloat x2 = apertureSize.height * (frameSize.height / apertureSize.width); yc = 1.f - ((point.x + ((x2 - frameSize.width) / 2)) / x2); xc = point.y / frameSize.height; } } pointOfInterest = CGPointMake(xc, yc); break; } } } return pointOfInterest; } 
+8
source

I want to give more information for @Louis's answer.

According to Apple docs (pay attention to the highlighted part):

In addition, the device may support a focus point of interest. You are testing support using focusPointOfInterestSupported. If supported, you set focus using focusPointOfInterest. You pass CGPoint, where {0,0} represents the upper left of the image area, and {1,1} represents the lower right in landscape mode, while the home button on the right is applied even if the device is in portrait mode.

We must include orientation when calculating FocusPointOfInterest .

+1
source

All Articles