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. The first time I segue from the main view controller to the capture session controller, it takes about 50ms (checked using 'instruments'). Then I segue back to the main view controller from the capture session and then back to the avcapturesession controller from the main controller. 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. (Compared with 50ms for first time.) I've pasted the relevant code for the avcapture session below. Can anyone help solve this? Thanks

This class (of type NSObject) manages the capture session for the second view controller that actually implements the 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:

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

}

Answers


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

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

You don't appear to be removing the previewLayer in the avcaptureViewController, which would keep a reference to the capture session internally. Make sure you remove the previewLayer from that view hierarchy.


Swift 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)
        }
    }

What worked for me was setting the previewLayer of type AVCaptureVideoPreviewLayer() as a weak variable, then in the stopCaptureSession() function I have:

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


here is the swift version of TUNER88 answer

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)

    }

Need Your Help

Mavericks Style Tagging

objective-c macos cocoa nstokenfield nstokenfieldcell

I'm quite new to cocoa and I'm trying to find out how I can create something similar to the new tagging UI in Mavericks:

Redirect request to public directory zend

zend-framework .htaccess web-deployment

I have a sub domain to which i have deployed my zend application, the problem is it points to the directory say abc and i cannot get it changed to point it to public directory is there a way i can ...