2
votes

In my App I'm capturing images using AVFoundation

I made a button to switch between front and back cameras but it won't work.

Here's the code I used :

if (captureDevice.position == AVCaptureDevicePositionFront) {
        for ( AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] ) {
            if ( device.position == AVCaptureDevicePositionBack) {


                NSError * error;
                AVCaptureDeviceInput * newDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:device error:&error];
                [captureSesion beginConfiguration];
                for (AVCaptureDeviceInput *oldInput in [captureSesion inputs]) {
                    [captureSesion removeInput:oldInput];
                }

                if ([captureSesion canAddInput:newDeviceInput]) {
                    [captureSesion addInput:newDeviceInput];
                }                
                [captureSesion commitConfiguration];
                break;
            }
        }
    }

THX.

2

2 Answers

7
votes

If your captureSession's sessionPreset is not compatible with the camera you're switching to it will fail the canAddInput test. I always reset to AVCaptureSessionPresetHigh before toggling cameras then try to switch it to whatever preset I have preferred. Here's the code I use:

- (void)toggleCamera {
  AVCaptureDevicePosition newPosition = self.currentCameraPossition == AVCaptureDevicePositionBack ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
  AVCaptureDevice *device = [self videoDeviceWithPosition:newPosition];
  AVCaptureDeviceInput *deviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:nil];

  [_captureSession beginConfiguration];
  [_captureSession removeInput:self.deviceInput];
  [_captureSession setSessionPreset:AVCaptureSessionPresetHigh]; //Always reset preset before testing canAddInput because preset will cause it to return NO

  if ([_captureSession canAddInput:deviceInput]) {
    [_captureSession addInput:deviceInput];
    self.deviceInput = deviceInput;
    self.currentCameraPossition = newPosition;
  } else {
      [_captureSession addInput:self.deviceInput];
  }

  if ([device supportsAVCaptureSessionPreset:self.sessionPreset]) {
    [_captureSession setSessionPreset:self.sessionPreset];
  }

  if ([device lockForConfiguration:nil]) {
    [device setSubjectAreaChangeMonitoringEnabled:YES];
    [device unlockForConfiguration];
  }

  [_captureSession commitConfiguration];
} 
2
votes

I have seen issues with toggle code not working if it is not run on the main thread. Can you try wrapping your code with the following block:

dispatch_async(dispatch_get_main_queue(), ^{
   // Your camera toggle code goes here
});