使用 AVFoundation 切换相机时视频冻结 [英] Video freezes on camera switch with AVFoundation

查看:24
本文介绍了使用 AVFoundation 切换相机时视频冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个具有捕捉和保存视频功能的应用.我为此使用了 AVFoundation,Apple 的 AVCam 一直是我的向导.

I made an app with a feature to capture and save video. I have used AVFoundation for that and Apple's AVCam has been my guide.

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

I hope I can make it clear:
Everything works fine until I release the videoViewController that handles the AVCamCaptureManager for the first time (In AVCam that would be AVCamViewController). After that when I create it again, the video freezes right after camera switch. Even re-run will not help, nor will clean, or device reset. (Sometimes one of the things help, but it is not a rule).

当不需要节省内存时,我会释放 videoViewController.

I release the videoViewController when not needed to save memory.

切换摄像头的代码与AVCam中基本相同:

Code for switching the camera is basically the same as in 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 的代码

Code with which I dismiss videoView

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

我目前的解决方法"是不管它,即使我不需要它.

My current "workaround" is to simply leave it be, even if I do not need it.

谁能解释为什么会发生这种情况以及如何解决它.

Can someone explain why is this happening and how to solve it.

已解决
正如 W Dyson 在他的回复中指出的那样,我应该在像这样释放我的 videoViewController 之前停止会话:

Solved
As W Dyson pointed out in his response I should have stopped the session before releasing my videoViewController like so:

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

感谢戴森.

推荐答案

你收到错误日志了吗?如果没有,您需要修复上面的代码并查看他们所说的内容.您使用的是什么版本的 AVCam?他们最近将项目更新到了 1.2 版,效率更高并且使用了块.

Are you getting error logs? If not, you need to fix the code above and see what they say. What version of AVCam are you using? They've recently updated the project to version 1.2, which is much more efficient and uses blocks.

根据我的经验,您不应该创建和重新创建会话,您可以保持打开状态.也许您需要稍微不同地构建您的应用程序.你的应用到底是关于什么的?也许我们可以帮助你.如果您的应用程序以相机为中心,那么离开会话会更容易,如果您只是以模态方式拍摄视频,那么使用 AVCam 可能是矫枉过正.

From my experience, you shouldn't be creating and recreating a session, you can just leave it on. Maybe you need to structure your app a little differently. What exactly is your app about? Maybe we can help you. If your app is centred around the camera, then it's easier to leave the session on, if your just taking video modally, then maybe using AVCam is overkill.

对我来说,您的实际问题听起来像是 AVCaptureDeviceInput.下载原始的 AVCam 包,看看您是否更改了任何保留计数或安全 if 语句.如果还有其他代码,请贴出来.

Your actual problem, to me, sounds like it's with AVCaptureDeviceInput. Download the original AVCam package and see if you've changed any retain counts, or safety if statements. If there's any other code, please post.

更新:你能改变吗

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

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

如果有错误告诉我?

此外,在释放拥有会话的视图控制器之前,请确保停止会话并将捕获管理器设置为 nil.

Also, before you release the view controller that owns the session, make sure you stop the session and set the capture manager to nil.

更新 2:试试这个切换代码.这是我一直在使用的.AVCamMirringMode 是一个结构如下:

UPDATE 2: Try this toggle code. It's what I have been using. AVCamMirringMode is a struct as follows:

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

这篇关于使用 AVFoundation 切换相机时视频冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆