【问题标题】:Camera freezes upon switching to the front facing camera切换到前置摄像头时相机冻结
【发布时间】:2013-01-31 09:54:37
【问题描述】:

我的问题

我使用 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 相同的exact代码,在添加的输出中稍作更改,(以满足我的需要):

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

【问题讨论】:

  • 我们能否获得更多代码,尤其是关于您在 setUpSession 中附加到视频输入的“frontFacingCamera”的设置?以及“自我”指的是什么?
  • @Spectravideo328 我已按您的要求更新了问题,感谢您的关注!

标签: iphone objective-c avfoundation


【解决方案1】:
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的回答

已编辑:这来自 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;

}

【讨论】:

  • 如果可行,我会检查并标记为答案,谢谢!
  • 好的,我检查了你的代码,它会再次像应该那样交换,正如我在问题中描述的相机在交换到正面后冻结。
  • 切换到前置摄像头后仍然卡住,有什么想法吗?
  • 修复了!您的代码运行良好,是我的错,我的一些代码与手电筒混淆,并且在切换相机时出现了一些问题,谢谢!
  • @PushpakNarasimhan 这对我来说很好用,我可以用前后摄像头录制视频,但在录制前置摄像头时,最终视频是静音(无音频),后置摄像头工作正常,请帮助我
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2013-01-12
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
相关资源
最近更新 更多