         return bottomBar
     }()
     
+    private var _startingOfSession: SessionStarting
+    
     // MARK: Initializer.
-    public init?(previewView: CaptureVideoPreviewView? = nil, session: AVCaptureSession? = nil, input: AVCaptureDeviceInput? = nil) {
-        guard let __input = input ?? (try? AVCaptureDeviceInput(device: AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo))) else {
-            return nil
-        }
-        _session = session ?? previewView?.previewLayer.session ?? AVCaptureSession()
-        if previewView?.previewLayer.session === _session {
-            _previewView = previewView
-        }
-        _input = __input
-        _output = AVCapturePhotoOutput()
-        
+    public init?(session: AVCaptureSession? = nil, starting: SessionStarting = .never) throws {
+        self._startingOfSession = starting
+        self._session = session
         super.init(nibName: nil, bundle: nil)
-        _initializer()
+        try _initSession()
+        // Start the session immediately if the starting mode is `.immediately`.
+        switch _startingOfSession {
+        case .immediately:
+            if !_session.isRunning {
+                _session.startRunning()
+            }
+        default: break
+        }
+    }
+    
+    public init() {
+        fatalError("Using designated initializer to create instance.")
     }
     
     override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
-        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
-        _initializer()
+        fatalError("Using designated initializer to create instance.")
     }
     
     required public init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _initializer()
-    }
-    
-    private func _initializer() {
-        _configureSession()
-        if _previewView == nil {
-            _previewView = PreviewView(session: _session)
+        fatalError("Using designated initializer to create instance.")
+    }
+    
+    deinit {
+        switch _startingOfSession {
+        case .immediately: fallthrough
+        case .at(_)  :
+            if  _session.isRunning, stopSessionWhenDisposed {
+                _session.stopRunning()
+            }
+        default: break
         }
     }
     

    }
}

// MARK: Actions.

extension CameraViewController {

    
    override open func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Start the session immediately if the starting mode is `.at(.willAppear)`.
        switch _startingOfSession {
        case .at(.willAppear):
            if !_session.isRunning {
                _session.startRunning()
            }
        default: break
        }
    }
    
    open override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // Start the session immediately if the starting mode is `.at(.didAppear)`.
        switch _startingOfSession {
        case .at(.didAppear):
            if !_session.isRunning {
                _session.startRunning()
            }
        default: break
        }
    }
    
    override open func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Stop the session when view did disappear.
        /* if stopSessionWhenDisposed {
            _session.stopRunning()
        } */
    }
    
    // MARK: Private.
    
    /// Create session and device input if session is nil and device inputs of session is empty.
    private func _initSession() throws {
        func create_add_input() throws {
            var adevice:  AVCaptureDevice!
            if #available(iOS 10.0, *) {
                adevice = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back)
            } else {
                adevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
            }
            guard let device = adevice else { throw CameraError.initializing(.noneOfCaptureDevice) }
            
            _input = try AVCaptureDeviceInput(device: device)
            _session =  AVCaptureSession()
            if  _session.canAddInput (_input) {
                _session.addInput    (_input)
            } else { throw CameraError.initializing(.sessionCannotAddInput) }
        }
        // Configure the display out put.
        _displayOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: kCVPixelFormatType_32BGRA]
        _displayOutput.setSampleBufferDelegate(self, queue: _displayQueue)
        _displayOutput.alwaysDiscardsLateVideoFrames = true
        // Initialize and configure the session of the capture.
        if  _session == nil {
            // Initialize the device input for the session.
            try create_add_input()
        } else {
            // Find the available device inputs.
            let deviceInputs = _session.inputs.flatMap({ ($0 is AVCaptureDeviceInput && ($0 as! AVCaptureDeviceInput).device.hasMediaType(AVMediaTypeVideo)) ? $0 : nil }) as! [AVCaptureDeviceInput]
            if  deviceInputs.isEmpty {
                try create_add_input()
            } else if deviceInputs.startIndex == deviceInputs.index(before: deviceInputs.endIndex) {
                // Has only one video device inputs.
                _input = deviceInputs.first
            }
        }
        _initPreviewView() // Call the initialzer of preview view obviously.
        // Configure session.
        if #available(iOS 10.0, *) {
            if  _session.canAddOutput(capturePhotoOutput) {
                _session.addOutput   (capturePhotoOutput)
            } else { throw CameraError.initializing(.sessionCannotAddOutput) }
        }
        if  _session.canAddOutput(_displayOutput) {
            _session.addOutput   (_displayOutput)
        } else { throw CameraError.initializing(.sessionCannotAddOutput) }
    }
    /// Initialize the preview view if the session is not nil and inputs of the session is not empty.
    private func _initPreviewView() {
        guard _previewView?.previewLayer.session !== _session && _session != nil && !_session.inputs.filter({ ($0 is AVCaptureDeviceInput && ($0 as! AVCaptureDeviceInput).device.hasMediaType(AVMediaTypeVideo)) }).isEmpty else { return }
        
        _previewView = PreviewView(session: _session)
    }
    
    private func _setupTopBar() {
