切换到前置摄像头后,摄像头会冻结

时间:2013-02-15 12:08:50

标签: iphone objective-c avfoundation

我的问题

我使用AVFoundation每5秒捕获一次视频输出帧。当用户点击一个按钮时,输入摄像头应该从前面一个切换到后面一个,反之亦然。问题是,每当我将后置摄像头切换到前置摄像头时,它就会冻结(奇怪的是,它的工作方式相反 - 意思是前置摄像头到后置摄像头)!

我使用的代码

要在相机之间切换,我使用从Apple的AVCam sample code获取的完全代码,稍微更改一下变量名称(因此它会匹配我的代码):

- (BOOL)toggleCamera
{
    BOOL success = NO;

    if ([self cameraCount] > 1) {
        NSError *error;
        AVCaptureDeviceInput *newVideoInput;
        AVCaptureDevicePosition position = [[self.videoInput device] position];

        if (position == AVCaptureDevicePositionBack)
            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:&error];

        else if (position == AVCaptureDevicePositionFront)
            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:&error];

        else
            goto bail;

        if (newVideoInput != nil) {

            // Start configuring the session.
            [[self captureSession] beginConfiguration];

            // Remove the current video input device.
            [[self captureSession] removeInput:[self videoInput]];

            if ([[self captureSession] canAddInput:newVideoInput]) {
                [[self captureSession] addInput:newVideoInput];
                [self setVideoInput:newVideoInput];
            }

            else {
                [[self captureSession] addInput:[self videoInput]];
            }

            [[self captureSession] commitConfiguration];

            success = YES;
            [newVideoInput release];
        }

        else if (error) {
            NSLog(@"PICTURE TAKER: Failed to toggle cameras."
                  @"\nError: %@", error.localizedDescription);
        }
    }

bail:
    return success;
}

再次设置AVCaptureSession,我使用AVCam sample code中的完全相同代码,添加的输出略有变化(以满足我的需求) ):

- (BOOL) setupSession
{
    BOOL success = NO;

    // Set torch and flash mode to auto
    if ([[self backFacingCamera] hasFlash]) {
        if ([[self backFacingCamera] lockForConfiguration:nil]) {
            if ([[self backFacingCamera] isFlashModeSupported:AVCaptureFlashModeAuto]) {
                [[self backFacingCamera] setFlashMode:AVCaptureFlashModeAuto];
            }
            [[self backFacingCamera] unlockForConfiguration];
        }
    }
    if ([[self backFacingCamera] hasTorch]) {
        if ([[self backFacingCamera] lockForConfiguration:nil]) {
            if ([[self backFacingCamera] isTorchModeSupported:AVCaptureTorchModeAuto]) {
                [[self backFacingCamera] setTorchMode:AVCaptureTorchModeAuto];
            }
            [[self backFacingCamera] unlockForConfiguration];
        }
    }

    // Init the device inputs
    AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:nil];

    // Create a video output & configure it.
    AVCaptureVideoDataOutput *newVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
    newVideoDataOutput.videoSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)};

    // Set the output's delegate.
    dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
    [newVideoDataOutput setSampleBufferDelegate:self queue:queue];
    dispatch_release(queue);

    // Create session (use default AVCaptureSessionPresetHigh)
    AVCaptureSession *newCaptureSession = [[AVCaptureSession alloc] init];

    // Add inputs and output to the capture session
    if ([newCaptureSession canAddInput:newVideoInput]) {
        [newCaptureSession addInput:newVideoInput];
    }

    if ([newCaptureSession canAddOutput:newVideoDataOutput]) {
        [newCaptureSession addOutput:newVideoDataOutput];
    }

    [self setVideoOutput:newVideoDataOutput];
    [self setVideoInput:newVideoInput];
    [self setCaptureSession:newCaptureSession];

    [newVideoDataOutput release];
    [newVideoInput release];
    [newCaptureSession release];

    // Get our view's layer.
    CALayer *viewLayer = self.view.layer;

    // Add the the session's preview layer.
    AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    captureVideoPreviewLayer.frame = self.view.bounds;
    [viewLayer insertSublayer:captureVideoPreviewLayer below:self.imageViewOverlay.layer];
    [captureVideoPreviewLayer release];

    success = YES;

    return success;
}

* 重要提示:在调用输出代表后,相机会立即冻结。

任何人都可以帮我解决这个问题吗?似乎我几乎尝试了所有东西!

更新#1

根据要求,self指的是一个视图控制器,它提供会话的预览图层并管理与摄像头相关的所有内容。另外,我发布代码处理frontFacingCamera部分,这是(就像我到目前为止发布的所有代码一样)取自Apple的AVCam sample code

// Find a camera with the specificed AVCaptureDevicePosition, returning nil if one is not found
- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if ([device position] == position) {
            return device;
        }
    }
    return nil;
}

// Find a front facing camera, returning nil if one is not found
- (AVCaptureDevice *) frontFacingCamera
{
    return [self cameraWithPosition:AVCaptureDevicePositionFront];
}

1 个答案:

答案 0 :(得分:6)

BOOL isUsingFrontFacingCamera;



- (BOOL) swapCameras
{
    if ([self cameraCount] > 1) {
    AVCaptureDevicePosition desiredPosition;
    if (isUsingFrontFacingCamera) {
        desiredPosition = AVCaptureDevicePositionBack;
    } else {
        desiredPosition = AVCaptureDevicePositionFront;
    }

    for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]) {
        if ([d position] == desiredPosition) {
            [[self session] beginConfiguration];
            AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
            for (AVCaptureInput *oldInput in [[self session] inputs]) {
                [[self session] removeInput:oldInput];
            }
            [[self session] addInput:input];
            [[self session] commitConfiguration];
            break;
        }
    }
    isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
    return YES;
}
return NO;
}

来自here

的回答

EDITED:来自Square Cam Apple示例代码。工作良好。测试也。 http://developer.apple.com/library/ios/#samplecode/SquareCam/Listings/SquareCam_SqareCamViewController_m.html

//使用前/后相机

- (IBAction)switchCameras:(id)sender

{

AVCaptureDevicePosition desiredPosition;

if (isUsingFrontFacingCamera)

    desiredPosition = AVCaptureDevicePositionBack;

else

    desiredPosition = AVCaptureDevicePositionFront;



for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {

    if ([d position] == desiredPosition) {

        [[previewLayer session] beginConfiguration];

        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];

        for (AVCaptureInput *oldInput in [[previewLayer session] inputs]) {

            [[previewLayer session] removeInput:oldInput];

        }

        [[previewLayer session] addInput:input];

        [[previewLayer session] commitConfiguration];

        break;

    }

}

isUsingFrontFacingCamera = !isUsingFrontFacingCamera;

}