简体   繁体   English

添加AVCaptureDeviceInput时AVCaptureSession崩溃

[英]Crash in AVCaptureSession when adding an AVCaptureDeviceInput

I have a weird crash showing on Crashlytics when setting up a camera session. 在设置摄像机会话时,我在Crashlytics上显示了一个奇怪的崩溃。 The stacktrace shows that the crash occurred at the method addInput. 堆栈跟踪显示崩溃发生在addInput方法中。

func setupCamSession(){
    self.captureSession = AVCaptureSession()
    self.cameraView.setSession(self.captureSession)
    self.sessionQueue = dispatch_queue_create("com.myapp.camera_queue", DISPATCH_QUEUE_SERIAL)
    self.setupResult = .Success
    switch AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo){
    case .Authorized:
        break //already we set it to success
    case .NotDetermined:
        // The user has not yet been presented with the option to grant video access.
        // We suspend the session queue to delay session setup until the access request has completed 
        dispatch_suspend(self.sessionQueue)
        AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted) -> Void in
            if ( !granted ) {
                self.setupResult = .CameraNotAuthorized
            }
            dispatch_resume(self.sessionQueue)
        })
    default:
        self.setupResult = .CameraNotAuthorized
    }

    dispatch_async(self.sessionQueue){
        if self.setupResult != .Success{
            return
        }
        //link input to captureSession
        guard let videoDevice = self.deviceWithMediaType(AVMediaTypeVideo, position: AVCaptureDevicePosition.Back) else{
            AppLog("Video Device Unavailable")
            self.setupResult = .SessionConfigurationFailed
            return
        }
        var videoDeviceInput: AVCaptureDeviceInput!
        do {
            videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
        }catch {
            AppLog("Could not create video device input")
        }

        /////////////////////////////////////////////////////
        self.captureSession.beginConfiguration()

        if self.captureSession.canAddInput(videoDeviceInput){
            self.captureSession.addInput(videoDeviceInput)
            self.videoDeviceInput = videoDeviceInput
            self.videoDevice = videoDevice
            dispatch_async(dispatch_get_main_queue()){
                //update the cameraView layer on the main thread
                let previewLayer : AVCaptureVideoPreviewLayer = self.cameraView.layer as! AVCaptureVideoPreviewLayer
                previewLayer.connection.videoOrientation = AVCaptureVideoOrientation(ui:UIApplication.sharedApplication().statusBarOrientation)
            }
        }else{
            AppLog("Could not add video device input to the session")
            self.setupResult = .SessionConfigurationFailed
        }

        //link output to captureSession
        let stillImageOutput = AVCaptureStillImageOutput()
        if self.captureSession.canAddOutput(stillImageOutput){
            self.captureSession.addOutput(stillImageOutput)
            self.stillImageOutput = stillImageOutput
            stillImageOutput.outputSettings = [AVVideoCodecKey : AVVideoCodecJPEG]
        }else{
            AppLog("Could not add still image output to the session")
            self.setupResult = .SessionConfigurationFailed
        }

        self.captureSession.commitConfiguration()
        /////////////////////////////////////////////////////
    }
}

func runSession(){
    dispatch_async(self.sessionQueue){
        switch self.setupResult!{
        case .Success:
            self.videoDeviceInput!.device.addObserver(self, forKeyPath: "adjustingFocus", options: NSKeyValueObservingOptions.New, context: nil)
            self.captureSession.addObserver(self, forKeyPath: "running", options: [.New], context: &SessionRunningContext)
            self.captureSession.startRunning()
            self.captureSessionRunning = self.captureSession.running
            if !self.captureSessionRunning {
                self.captureSession.removeObserver(self, forKeyPath: "running", context: &SessionRunningContext)
                self.videoDeviceInput?.device?.removeObserver(self, forKeyPath: "adjustingFocus", context: nil)
            }
       default:
       //Handle errors.
       }
  }
func stopCaptureSession(){
    dispatch_async(self.sessionQueue){
        if self.setupResult == .Success{
            if self.captureSessionRunning{
                self.captureSession.stopRunning()
                self.videoDeviceInput?.device?.removeObserver(self, forKeyPath: "adjustingFocus", context: nil)
                self.captureSession.removeObserver(self, forKeyPath: "running", context: &SessionRunningContext)
            }
            self.captureSessionRunning = false
        }
    }
}

The setupCamSession is called in viewDidLoad, the runSession in viewWillAppear and I have also a stopSession method in viewWillDisappear. 在viewDidLoad中调用setupCamSession,在viewWillAppear中调用runSession,在viewWillDisappear中我也有一个stopSession方法。 Everything related to the camera session is dispatched on a background serial queue. 与摄像机会话相关的所有内容都将在后台串行队列中调度。

The crash doesn't happen 100% of the time and I am unable to reproduce the crash on the device I use. 崩溃不会100%发生,我无法在我使用的设备上重现崩溃。 Thanks 谢谢 这是堆栈跟踪的屏幕截图

Make sure you are removing observers on deinit . 确保你在deinit上移除观察者。 I saw this occurring when coming back to the camera capture screen and I didn't remove the observer for adjustingFocus . 当我回到相机捕捉屏幕时我看到了这种情况,我没有移除观察者来adjustingFocus Once I removed that in deinit all was well. 一旦我删除了deinit一切都很好。

Had the same problem. 有同样的问题。 It was resolved after adding an usage description for the Privacy - Camera Usage Description in the Info.plist file. 在Info.plist文件中添加Privacy - Camera Usage Description的使用说明后,它已得到解决。 This answer contains tips on how to set up the description: 此答案包含有关如何设置说明的提示:

Request Permission for Camera and Library in iOS 10 - Info.plist 请求iOS 10中相机和库的权限 - Info.plist

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

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