 extension CameraViewController {
     public final class DisplayView: CaptureVideoDisplayView {}
 }
+
+// MARK: - Sample buffer delegates.
+
+extension CameraViewController {
+    /// Get all the sample buffer delegate as `[AVCaptureVideoDataOutputSampleBufferDelegate]`.
+    /// Do not add or remove delegates using the the result since the result is copied.
+    ///
+    public var  sampleBufferDelegates: [AVCaptureVideoDataOutputSampleBufferDelegate] { return _sampleBufferDelegates.allObjects }
+    /// Replace the old managed sample buffer delegates with the new delegates.
+    /// 
+    /// - Parameter sampleBufferDelegates: The new delegates queue to replace with.
+    ///
+    public func set(sampleBufferDelegates delegates: [AVCaptureVideoDataOutputSampleBufferDelegate]) {
+        removeAllSampleBufferDelegates()
+        add(sampleBufferDelegates: delegates)
+    }
+    /// Add a delegates queue to the managed delegates queue without changing the orders.
+    ///
+    /// - Parameter sampleBufferDelegates: The new delegates queue to add.
+    ///
+    public func add(sampleBufferDelegates delegates: [AVCaptureVideoDataOutputSampleBufferDelegate]) {
+        delegates.forEach({ [unowned self] in self._sampleBufferDelegates.add($0) })
+    }
+    /// Add a new sample buffer delegate to the managed delegates queue.
+    ///
+    /// - Parameter sampleBufferDelegate: A instance of AVCaptureVideoDataOutputSampleBufferDelegate to be added.
+    ///
+    public func add(sampleBufferDelegate delegate: AVCaptureVideoDataOutputSampleBufferDelegate?) {
+        _sampleBufferDelegates.add(delegate)
+    }
+    /// Remove a sample buffer from the managed delegates queue.
+    ///
+    /// - Parameter sampleBufferDelegate: A instance of AVCaptureVideoDataOutputSampleBufferDelegate to be removed.
+    ///
+    public func remove(sampleBufferDelegate delegate: AVCaptureVideoDataOutputSampleBufferDelegate?) {
+        _sampleBufferDelegates.remove(delegate)
+    }
+    /// Remove all the managed sample buffer delegates.
+    public func removeAllSampleBufferDelegates() {
+        _sampleBufferDelegates.removeAllObjects()
+    }
+}
+
+// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate.
+
+extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
+    public func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
+        sampleBufferDelegates.forEach({ $0.captureOutput?(captureOutput, didOutputSampleBuffer: sampleBuffer, from: connection) })
+    }
+    
+    public func captureOutput(_ captureOutput: AVCaptureOutput!, didDrop sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
+        sampleBufferDelegates.forEach({ $0.captureOutput?(captureOutput, didDrop: sampleBuffer, from: connection) })
+    }
+}

    
    // MARK: Private.
    
    private func _configureSession() {
        if _session.inputs.isEmpty || _session.canAddInput(_input) {
            _session.addInput(_input)
        }
        if _session.outputs.isEmpty || _session.canAddOutput(_output) {
            _session.addOutput(_output)
        }
    }
    
    private func _setupTopBar() {

@available(iOS 9.0, *)
open class CameraViewController: UIViewController {
    open weak var delegate: CameraViewControllerDelegate?
    open   var stopSessionWhenDisposed: Bool = false
    public var configurationQueue: DispatchQueue { return _sessionQueue }
    /// Sample buffer delegates queue.
    fileprivate
    var _sampleBufferDelegates: NSHashTable<AVCaptureVideoDataOutputSampleBufferDelegate> = NSHashTable.weakObjects()
    
    private var _session: AVCaptureSession!
    private var _input  : AVCaptureDeviceInput!
