6

我制作了一个具有捕获和保存视频功能的应用程序。我为此使用了 AVFoundation,Apple 的 AVCam一直是我的指南。

我希望我能说清楚:
在我第一次发布处理 AVCamCaptureManager 的 videoViewController 之前,一切正常(在 AVCam 中,这将是 AVCamViewController)。之后,当我再次创建它时,视频在相机切换后立即冻结。即使重新运行也无济于事,清理或设备重置也无济于事。(有时其中一件事会有所帮助,但这不是规则)。

当不需要节省内存时,我会释放 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;

谢谢戴森。

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 回答