录制视频时更改摄像头捕获设备

时间:2013-08-27 13:38:04

标签: iphone ios objective-c avfoundation

我正在开发一款iPhone App。其中,需要暂停和恢复相机。所以我使用了AVFoundation而不是UIImagePickerController

我的代码是:

 - (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;
        }
    }

当我将相机更改为Front时,我遇到了问题。当我通过将相机更改为前面来调用上述方法时,预览图层卡住了,没有预览。我怀疑是“我们可以在捕获会话中更改捕获设备吗?”。请指导我出错的地方(或)建议我在录制时如何在前后摄像头之间导航。

先谢谢。

3 个答案:

答案 0 :(得分:4)

是的,你可以。您需要满足一些需要的东西。

  1. 需要使用AVCaptureVideoDataOutput及其代表进行录制。
  2. 确保在添加新的deviceInput之前删除先前的deviceInput。
  3. 您还必须删除并重新创建AVCaptureVideoDataOutput。
  4. 我现在正在使用这两个函数,它在会话运行时有效。

    - (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];
    }
    

答案 1 :(得分:1)

您无法在会话中途更改captureDevice。而且您一次只能运行一个捕获会话。您可以结束当前会话并创建一个新会话。会有轻微的延迟(可能是一两秒,具体取决于你的CPU负载)。

我希望Apple能够在每个会话中允许多个会话或至少多个设备......但是他们还没有......但是。

答案 2 :(得分:0)

您是否考虑过多个会话,然后处理视频文件以将它们合并为一个?