6

動画をキャプチャして保存する機能を備えたアプリを作成しました。私はそのためにAVFoundationを使用し、AppleのAVCamが私のガイドでした。

明確にできると
いいのですが、AVCamCaptureManagerを処理するvideoViewControllerを初めてリリースするまで(AVCamではAVCamViewControllerになります)、すべてが正常に機能します。その後、再度作成すると、カメラ切り替え直後に動画がフリーズします。再実行しても、役に立たず、クリーンアップも、デバイスのリセットも行われません。(場合によっては、1つのことが役立ちますが、それは規則ではありません)。

メモリを節約する必要がない場合は、videoViewControllerを解放します。

カメラを切り替えるためのコードは、基本的にAVCamと同じです。

NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition position = currentVideoInput.device.position;

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

if (newVideoInput != nil) {
    [session beginConfiguration];
    [session removeInput:currentVideoInput];
    if ([session canAddInput:newVideoInput]) {
        [session addInput:newVideoInput];
        [self setVideoInput:newVideoInput];
} else {
    [session addInput:currentVideoInput];
}
    [session commitConfiguration];
    [newVideoInput release];
} else if (error) {
    NSLog(@"%@",[error localizedDescription]);
}

videoViewを却下するコード

[self.videoViewController.view removeFromSuperview];
self.videoViewController = nil;

私の現在の「回避策」は、必要がない場合でも、そのままにしておくことです。

誰かがこれが起こっている理由とそれを解決する方法を説明できますか?

編集:
W Dysonが彼の応答で指摘したように、私は次のようにvideoViewControllerをリリースする前にセッションを停止する必要がありました。

[[[self.videoViewController captureManager] session] stopRunning];
[self.videoViewController.view removeFromSuperview];
self.videoViewController = nil;

WDysonに感謝します。

4

2 に答える 2

9

これを試してください—それは私にとってチャンピオンのように機能しました:

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

このコードをドロップして、VideoRecorderCaptureManager.m の元の swapCameras を置き換えることができるはずです

出典: Apple の SquareCam サンプル コード。

于 2013-01-17T14:08:37.603 に答える
3

エラーログを取得していますか? そうでない場合は、上記のコードを修正して、その内容を確認する必要があります。使用している AVCam のバージョンは何ですか? 彼らは最近、プロジェクトをバージョン 1.2 に更新しました。これは、はるかに効率的で、ブロックを使用しています。

私の経験からすると、セッションを作成して再作成するべきではなく、そのままにしておくことができます。アプリの構造を少し変える必要があるかもしれません。あなたのアプリは正確には何についてですか?多分私たちはあなたを助けることができます。アプリがカメラ中心の場合は、セッションをオンのままにしておく方が簡単です。ビデオをモーダルで撮影するだけの場合は、AVCam を使用するのはやり過ぎかもしれません。

あなたの実際の問題は、AVCaptureDeviceInput にあるように思えます。元の AVCam パッケージをダウンロードして、保持カウントや安全 if ステートメントを変更したかどうかを確認します。他のコードがある場合は、投稿してください。

更新:変更できますか

} else if (error) {
    NSLog(@"%@",[error localizedDescription]);
}

} if (error) {
    NSLog(@"%@",[error localizedDescription]);
}

エラーがあるかどうか教えてください。

また、セッションを所有するビュー コントローラーを解放する前に、必ずセッションを停止し、キャプチャ マネージャーを nil に設定してください。

更新 2: このトグル コードを試してください。それは私が使ってきたものです。AVCamMirringMode は、次のような構造体です。

enum {
    AVCamMirroringOff   = 1,
    AVCamMirroringOn    = 2,
    AVCamMirroringAuto  = 3
};
typedef NSInteger AVCamMirroringMode;


- (BOOL) toggleCamera
{
    BOOL success = NO;

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

        BOOL mirror;
        if (position == AVCaptureDevicePositionBack){
            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:&error];
            switch ([self mirroringMode]) {
                case AVCamMirroringOff:
                    mirror = NO;
                    break;
                case AVCamMirroringOn:
                    mirror = YES;
                    break;
                case AVCamMirroringAuto:
                default:
                    mirror = YES;
                    break;
            }
        }
        else if (position == AVCaptureDevicePositionFront){
            newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:&error];
            switch ([self mirroringMode]) {
                case AVCamMirroringOff:
                    mirror = NO;
                    break;
                case AVCamMirroringOn:
                    mirror = YES;
                    break;
                case AVCamMirroringAuto:
                default:
                    mirror = NO;
                    break;
            }
        }
        else
            goto bail;

        if (newVideoInput != nil) {
            [[self session] beginConfiguration];
            [[self session] removeInput:[self videoInput]];
            if ([[self session] canAddInput:newVideoInput]) {
                [[self session] addInput:newVideoInput];
                AVCaptureConnection *connection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
                if ([connection isVideoMirroringSupported]) {
                    [connection setVideoMirrored:mirror];
                }
                [self setVideoInput:newVideoInput];
            } else {
                [[self session] addInput:[self videoInput]];
            }
            [[self session] commitConfiguration];
            success = YES;
            [newVideoInput release];

        } else if (error) {
            if ([[self delegate] respondsToSelector:@selector(captureManager:didFailWithError:)]) {
                [[self delegate] captureManager:self didFailWithError:error];
            }
        }
    }

bail:
    return success;
}
于 2011-04-18T14:46:43.830 に答える