视频在AVFoundation的相机开关上冻结 [英] Video freezes on camera switch with AVFoundation

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

问题描述

我制作了一款具有拍摄和保存视频功能的应用。
我已经使用AVFoundation并 Apple的AVCam 我的向导。



我希望我能说清楚:

一切正常,直到我发布第一次处理AVCamCaptureManager的videoViewController(在AVCam中,这将是AVCamViewController)。之后,当我再次创建它时,视频在摄像机切换后立即冻结。即使重新运行也无济于事,也无法清理或重置设备。 (有时候其中一个有帮助,但这不是一个规则)。



我不需要保存内存时释放videoViewController。



切换相机的代码与AVCam基本相同:

  NSError *错误; 
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;

即使我不需要,我现在的解决方法就是保留它。 / p>

有人可以解释为什么会发生这种情况以及如何解决它。



编辑:已解决

正如W Dyson在他的回答中指出的那样,我应该在释放我的videoViewController之前停止会话,如下所示:

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

谢谢W Dyson。

解决方案

您收到错误日志了吗?如果没有,您需要修复上面的代码,看看他们说了什么。
您使用的是什么版本的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镜像;
if(position == AVCaptureDevicePositionBack){
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:& error];
switch([self mirroringMode]){
case AVCamMirroringOff:
mirror = NO;
休息;
case AVCamMirroringOn:
mirror = YES;
休息;
case AVCamMirroringAuto:
默认值:
mirror = YES;
休息;
}
}
else if(position == AVCaptureDevicePositionFront){
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:& error];
switch([self mirroringMode]){
case AVCamMirroringOff:
mirror = NO;
休息;
case AVCamMirroringOn:
mirror = YES;
休息;
case AVCamMirroringAuto:
默认值:
mirror = NO;
休息;
}
}
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];

}否则如果(错误){
if([[self delegate] respondsToSelector:@selector(captureManager:didFailWithError :)]){
[[self delegate] captureManager: self didFailWithError:error];
}
}
}

保释金:
返回成功;
}


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.

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).

I release the videoViewController when not needed to save memory.

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

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.

EDIT: 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;

Thanks W Dyson.

解决方案

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.

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.

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.

UPDATE: Can you change

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

to

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

and tell me if there's an error?

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

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天全站免登陆