Switching between front and back cameras

I’d like to switch between the front and back cameras while an app is running, say on iPhone 4 or iPad 2. I can’t use setDeviceID() because it can only be called before initGrabber(), and I’d like the switch to be controlled by the user while video is being grabbed, much the same way as Photo Booth. Would I be required to maintain 2 different grabbers? Is there another way? Thanks.

You can switch between front and back cameras, though you’ll need to use Objective-C.

Here’s a function (found online somewhere) that returns the front facing camera if available:

  
  
- (AVCaptureDevice *)frontFacingCameraIfAvailable  
{  
    //  look at all the video devices and get the first one that's on the front  
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];  
    AVCaptureDevice *captureDevice = nil;  
    for (AVCaptureDevice *device in videoDevices)  
    {  
        if (device.position == AVCaptureDevicePositionFront)  
        {  
            captureDevice = device;  
            break;  
        }  
    }  
      
    //  couldn't find one on the front, so just get the default video device.  
    if ( ! captureDevice)  
    {  
        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
    }  
      
    return captureDevice;  
}  
  

And a method that returns the back camera:

  
  
- (AVCaptureDevice *)backCamera  
{  
    //  look at all the video devices and get the first one that's on the front  
    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];  
    AVCaptureDevice *captureDevice = nil;  
    for (AVCaptureDevice *device in videoDevices)  
    {  
        if (device.position == AVCaptureDevicePositionBack)  
        {  
            captureDevice = device;  
            break;  
        }  
    }  
      
    //  couldn't find one on the front, so just get the default video device.  
    if ( ! captureDevice)  
    {  
        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
    }  
      
    return captureDevice;  
}  
  

To switch between the two cameras, I keep track with a boolean and recall the initCapture function. Here’s a the snippet of a few lines I modified in initCapture in ofxiPhoneVideoGrabber.mm – these just define which camera to use via AVCaptureDevice:

  
  
    AVCaptureDevice *captureDevice;  
      
    if(frontCamera == true){  
        captureDevice = [self frontFacingCameraIfAvailable];  
    } else {  
        captureDevice = [self backCamera];  
  
    }  
          
    captureInput = [AVCaptureDeviceInput   
				deviceInputWithDevice:captureDevice   
				error:nil];   
  

Hope that helps!

thanks for your answer. i didn’t see it in time for my app which i’ve already completed. i accomplished camera switching by maintaining 2 grabbers and exposing/using AVFoundationVideoGrabber’s startCapture() and stopCapture(). this way i can run the correct grabber depending on which camera is chosen.

Hi, I encountered the same problem. How did you implement startCapture() and stopCapture() in AVFoundationVideoGrabber? It seemed that there are no startCapture() and stopCapture() methods, so I guessed that you implemented them. I’ll be much appreciated if you can reply.

Hi. This is five-year old code & has not been kept up-to-date, so refer to it with caution.

I added to AVFoundationVideoGrabber.h:

class AVFoundationVideoGrabber{
    public:
        ...
        void startCapture();
        void stopCapture();
        ...
}

and to AVFoundationVideoGrabber.mm:

void AVFoundationVideoGrabber::startCapture(){
    [grabber startCapture];
}

void AVFoundationVideoGrabber::stopCapture(){
    [grabber stopCapture];
}

That’s all. In my app setup, I init 2 grabbers for front & back cams, with the back grabber being the default one at startup:

void myApp::setup() {
    ...
    grabberFront.setDeviceID(1);
    grabberFront.setUseTexture(false);
    grabberFront.initGrabber(vidW, vidH, OF_PIXELS_BGRA); // vidW & vidH are my vars
    grabberFront.stopCapture();
    grabberBack.setDeviceID(0);
    grabberBack.setUseTexture(false);
    grabberBack.initGrabber(vidW, vidH, OF_PIXELS_BGRA); // vidW & vidH are my vars
    ...
}

When you wish to switch, you just call stopCapture() and startCapture() on the appropriate grabbers.

Many thanks to reply!!! I’ve solved that last night. Get hint from your last reply. It helps a lot. Still, I’m very appreciated you answered me!