Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change camera capture device while recording a video

I am developing an iPhone App. In that, there is a requirement for Pausing and resuming the camera. So i used AVFoundation for that instead of using UIImagePickerController.

My code is :

 - (void) startup :(BOOL)isFrontCamera
    {

        if (_session == nil)
        {
            NSLog(@"Starting up server");

            self.isCapturing = NO;
            self.isPaused = NO;
            _currentFile = 0;
            _discont = NO;

            // create capture device with video input
            _session = [[AVCaptureSession alloc] init];
            AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

        if(isFrontCamera)
        {
            NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
            AVCaptureDevice *captureDevice = nil;
            for (AVCaptureDevice *device in videoDevices)
            {
                if (device.position == AVCaptureDevicePositionFront)
                {
                    captureDevice = device;
                    break;  
                }  
            }

            cameraDevice = captureDevice;

        }


            cameraDevice=[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:nil];

            [_session addInput:input];

            // audio input from default mic
            AVCaptureDevice* mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
            AVCaptureDeviceInput* micinput = [AVCaptureDeviceInput deviceInputWithDevice:mic error:nil];
            [_session addInput:micinput];

            // create an output for YUV output with self as delegate
            _captureQueue = dispatch_queue_create("uk.co.gdcl.cameraengine.capture", DISPATCH_QUEUE_SERIAL);
            AVCaptureVideoDataOutput* videoout = [[AVCaptureVideoDataOutput alloc] init];
            [videoout setSampleBufferDelegate:self queue:_captureQueue];
            NSDictionary* setcapSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                            [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], kCVPixelBufferPixelFormatTypeKey,
                                            nil];
            videoout.videoSettings = setcapSettings;
            [_session addOutput:videoout];
            _videoConnection = [videoout connectionWithMediaType:AVMediaTypeVideo];

            [_videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];

            NSDictionary* actual = videoout.videoSettings;
            _cy = [[actual objectForKey:@"Width"] integerValue];
            _cx = [[actual objectForKey:@"Height"] integerValue];
     AVCaptureAudioDataOutput* audioout = [[AVCaptureAudioDataOutput alloc] init];
            [audioout setSampleBufferDelegate:self queue:_captureQueue];
            [_session addOutput:audioout];
            _audioConnection = [audioout connectionWithMediaType:AVMediaTypeAudio];
     [_session startRunning];

            _preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];
            _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
        }
    }

Here i am facing the problem when i change the camera to Front. when i calling the above method by changing the camera to front, the preview layer is getting stuck and no preview is coming. My doubt is "Can we change the capture device in the middle of capture session ?". Please guide me where i am going wrong (or) Suggest me with a solution on how to navigate between front and back camera while recording.

Thanks in Advance.

like image 413
KUMAR.A Avatar asked Mar 23 '23 15:03

KUMAR.A


2 Answers

Yes, you can. There are just a few of things you need to cater to.

  1. Need to be using AVCaptureVideoDataOutput and its delegate for recording.
  2. Make sure you remove the previous deviceInput before adding the new deviceInput.
  3. You must remove and recreate the AVCaptureVideoDataOutput as well.

I am using these two functions for it right now and it works while the session is running.

- (void)configureVideoWithDevice:(AVCaptureDevice *)camera {

    [_session beginConfiguration];
    [_session removeInput:_videoInputDevice];
    _videoInputDevice = nil;

    _videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:camera error:nil];
    if ([_session canAddInput:_videoInputDevice]) {
        [_session addInput:_videoInputDevice];
    }

    [_session removeOutput:_videoDataOutput];
    _videoDataOutput = nil;

    _videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    [_videoDataOutput setSampleBufferDelegate:self queue:_outputQueueVideo];
    NSDictionary* setcapSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], kCVPixelBufferPixelFormatTypeKey, nil];

    _videoDataOutput.videoSettings = setcapSettings;
    [_session addOutput:_videoDataOutput];
    _videoConnection = [_videoDataOutput connectionWithMediaType:AVMediaTypeVideo];

    if([_videoConnection isVideoOrientationSupported]) {
        [_videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
    }  

    [_session commitConfiguration];
}

- (void)configureAudioWithDevice:(AVCaptureDevice *)microphone {
    [_session beginConfiguration];
    _audioInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:microphone error:nil];
    if ([_session canAddInput:_audioInputDevice]) {
        [_session addInput:_audioInputDevice];
    }

    [_session removeOutput:_audioDataOutput];
    _audioDataOutput = nil;

    _audioDataOutput = [[AVCaptureAudioDataOutput alloc] init];
    [_audioDataOutput setSampleBufferDelegate:self queue:_outputQueueAudio];
    [_session addOutput:_audioDataOutput];
    _audioConnection = [_audioDataOutput connectionWithMediaType:AVMediaTypeAudio];

    [_session commitConfiguration];
}
like image 160
mylegfeelsfunny Avatar answered Apr 09 '23 07:04

mylegfeelsfunny


You can't change the captureDevice mid-session. And you can only have one capture session running at a time. You could end the current session and create a new one. There will be a slight lag (maybe a second or two depending on your cpu load).

I wish Apple would allow multiple sessions or at least multiple devices per session... but they do not... yet.

like image 32
Nick Terry Avatar answered Apr 09 '23 07:04

Nick Terry