简体   繁体   English

会话重启后AVcapture会话缓慢启动

[英]AVcapture session slow launch after session restart

I have a main view controller and that segues to a second view controller that has an avcapturesession. 我有一个主视图控制器,并且可以进入具有avcapturesession的第二个视图控制器。 The first time I segue from the main view controller to the capture session controller, it takes about 50ms (checked using 'instruments'). 我第一次从主视图控制器切换到捕获会话控制器,大约需要50ms(使用“仪器”检查)。 Then I segue back to the main view controller from the capture session and then back to the avcapturesession controller from the main controller. 然后我从捕获会话中回到主视图控制器,然后从主控制器返回到avcapturesession控制器。 Each time it takes longer to segue from the main view controller to the avcapturesession and by the 5th or 6th iteration the segue takes about 10 seconds. 每次从主视图控制器切换到avcapturesession需要更长的时间,并且通过第5次或第6次迭代,segue需要大约10秒。 (Compared with 50ms for first time.) I've pasted the relevant code for the avcapture session below. (与第一次50ms相比。)我已经粘贴了下面的avcapture会话的相关代码。 Can anyone help solve this? 谁能帮忙解决这个问题? Thanks 谢谢

This class (of type NSObject) manages the capture session for the second view controller 此类(类型为NSObject)管理第二个视图控制器的捕获会话
that actually implements the avcapturesession 这实际上实现了avcapturesession

#import "CaptureSessionManager.h"

@implementation CaptureSessionManager

@synthesize captureSession;
@synthesize previewLayer;

#pragma mark Capture Session Configuration

- (id)init {
    if ((self = [super init])) {
        [self setCaptureSession:[[AVCaptureSession alloc] init]];
    }
    return self;
}

- (void)addVideoPreviewLayer {
    [self setPreviewLayer:[[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self     captureSession]] autorelease]];
    [[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];

}

- (void)addVideoInput {
        AVCaptureDevice *videoDevice = [AVCaptureDevice   defaultDeviceWithMediaType:AVMediaTypeVideo];
     if (videoDevice) {
         NSError *error;
        AVCaptureDeviceInput *videoIn = [AVCaptureDeviceInput  deviceInputWithDevice:videoDevice error:&error];
        if (!error) {
           if ([[self captureSession] canAddInput:videoIn])
               [[self captureSession] addInput:videoIn];

        //else
        //  NSLog(@"Couldn't add video input");
    }

//  else
    //  NSLog(@"Couldn't create video input");
}
//else
//  NSLog(@"Couldn't create video capture device");
}

- (void)dealloc {

    [[self captureSession] stopRunning];

    [previewLayer release], previewLayer = nil;
    [captureSession release], captureSession = nil;

    [super dealloc];
}

 @end

The following is in the viewdidLoad method of the avcapture view controller: 以下是avcapture视图控制器的viewdidLoad方法:

[self setCaptureManager:[[CaptureSessionManager alloc] init]]; 

[[self captureManager] addVideoInput];

[[self captureManager] addVideoPreviewLayer];
CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),
                                                              CGRectGetMidY(layerRect))];

[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];

[[captureManager captureSession] startRunning];

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:YES];

    [[[self captureManager] previewLayer]removeFromSuperlayer];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[captureManager captureSession] stopRunning];
    });

}

内存分配

I have encounter the same problem I have found this line is the main problem 我遇到了同样的问题我发现这一行是主要问题

[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];

Just remove the previewlayer from the super layer while deallocating and there is no memory issue. 只需在解除分配时从超级层中删除预览层,并且没有内存问题。 My deallocating function is as follow 我的解除分配功能如下

 -(void)deallocSession
{
[captureVideoPreviewLayer removeFromSuperlayer];
for(AVCaptureInput *input1 in session.inputs) {
    [session removeInput:input1];
}

for(AVCaptureOutput *output1 in session.outputs) {
    [session removeOutput:output1];
}
[session stopRunning];
session=nil;
outputSettings=nil;
device=nil;
input=nil;
captureVideoPreviewLayer=nil;
stillImageOutput=nil;
self.vImagePreview=nil;

}

i called this function before popping and pushing any other view. 我在弹出并推送任何其他视图之前调用了此函数。 It solved my issue. 它解决了我的问题。

Removing session inputs and outputs seems to solve this problem for me 删除会话输入和输出似乎解决了这个问题

[captureSession stopRunning];
for(AVCaptureInput *input in captureSession.inputs) {
    [captureSession removeInput:input];
}

for(AVCaptureOutput *output in captureSession.outputs) {
    [captureSession removeOutput:output];
}

Swift version TUNER88's answer Swift版TUNER88的答案

func stopRecording() {
    captureSession.stopRunning()
    for input in captureSession.inputs {
        captureSession.removeInput(input)
    }
    for output in captureSession.outputs {
        captureSession.removeOutput(output)
    }
}

What worked for me was setting the previewLayer of type AVCaptureVideoPreviewLayer() as a weak variable, then in the stopCaptureSession() function I have: 对我previewLayer的是将AVCaptureVideoPreviewLayer()类型的previewLayer设置为弱变量,然后在stopCaptureSession()函数中我有:

func stopCaptureSession() {
    self.previewLayer?.removeFromSuperlayer()
    self.previewLayer = nil
    self.captureSession.stopRunning()
    for input in captureSession.inputs {
        self.captureSession.removeInput(input)
    }
    for output in captureSession.outputs {
        self.captureSession.removeOutput(output)
    }
}

It turned out all my problems were connected to the previewLayer 原来我的所有问题都连接到了previewLayer

You don't appear to be removing the previewLayer in the avcaptureViewController, which would keep a reference to the capture session internally. 您似乎没有删除avcaptureViewController中的previewLayer,后者将在内部保留对捕获会话的引用。 Make sure you remove the previewLayer from that view hierarchy. 确保从该视图层次结构中删除previewLayer。

Swift 3 斯威夫特3

    let session = AVCaptureSession()
    if let outputMovie = outputMovie, outputMovie.isRecording {
        outputMovie.stopRecording()
    }

    self.session.stopRunning()
    if let inputs = self.session.inputs as? [AVCaptureDeviceInput] {
        for input in inputs {
            self.session.removeInput(input)
        }
    }

    if let outputs = self.session.outputs as? [AVCaptureOutput] {
        for output in outputs {
            self.session.removeOutput(output)
        }
    }

here is the swift version of TUNER88 answer 这是TUNER88答案的快速版本

session.stopRunning()

    for(var i = 0 ; i < session.inputs.count ; i++){

        session.removeInput(session.inputs[i] as! AVCaptureInput)

    }

    for(var i = 0 ; i < session.outputs.count ; i++){

        session.removeOutput(session.outputs[i] as! AVCaptureOutput)

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM