2

私の問題

AVFoundation を使用して、5 秒ごとにビデオ出力のフレームをキャプチャしています。ユーザーがボタンをタップすると、入力カメラが前面から背面、およびその反対に切り替わる必要があります。問題は、バックカメラフロントカメラに切り替えるたびにフリーズすることです(奇妙なことに、逆に動作します-つまり、フロントカメラからバックカメラへ)!

私が使用するコード

カメラを切り替えるには、Apple のAVCam サンプル コードから取得した正確なコードを使用し、変数名を少し変更します (コードと一致するようにします)。

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

をセットアップするには、 AVCam サンプル コードとまったく同じコードAVCaptureSessionを使用しますが、出力を少し変更します (私のニーズに合わせるため)。

- (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 サンプル コードから取得したものです。

// 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];
}
4

1 に答える 1

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

回答はこちらから

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;

}
于 2013-03-07T09:00:49.893 に答える