title: How to properly release an AVCaptureSession
body: <p>I'm using the AVFoundation classes to capture the live video stream from the camera and to process the video samples. This works nicely. However, I do have problems properly releasing the AVFoundation instances (capture session, preview layer, input and output) once I'm done.</p>
  <p>When I no longer need the session and all associated objects, I stop the capture session and release it. This works most of the time. However, sometimes the app crashes with an <code>EXEC_BAD_ACCESS</code> signal raised in the second thread that was created by the dispatch queue (and where the video samples are processed). The crash is mainly due to my own class instance, which serves as the sample buffer delegate and is freed after I've stopped the capture session.</p>
  <p>The Apple documentation mentions the problem: Stopping the capture session is an asynchronous operation. That is: it doesn't happen immediately. In particular, the second thread continues to process video samples and access different instances like the capture session or the input and output devices.</p>
  <p>So how do I properly release the <code>AVCaptureSession</code> and all related instances? Is there a notification that reliably tells me that the <code>AVCaptureSession</code> has finished?</p>
  <p>Here's my code:</p>
  <p>Declarations:</p>
  <pre><code>AVCaptureSession* session;
  AVCaptureVideoPreviewLayer* previewLayer;
  UIView* view;
  </code></pre>
  <p>Setup of instances:</p>
  <pre><code>AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
  session = [[AVCaptureSession alloc] init];
  
  AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice: camera error: &amp;error];
  [session addInput: input];
  AVCaptureVideoDataOutput* output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
  [session addOutput: output];
  
  dispatch_queue_t queue = dispatch_queue_create(&quot;augm_reality&quot;, NULL);
  [output setSampleBufferDelegate: self queue: queue];
  dispatch_release(queue);
  
  previewLayer = [[AVCaptureVideoPreviewLayer layerWithSession: session] retain];
  previewLayer.frame = view.bounds;
  [view.layer addSublayer: previewLayer];
  
  [session startRunning];
  </code></pre>
  <p>Cleanup:</p>
  <pre><code>[previewLayer removeFromSuperlayer];
  [previewLayer release];
  [session stopRunning];
  [session release];
  </code></pre>