【问题标题】:AVCaptureSession goes to crashAVCaptureSession 崩溃
【发布时间】:2015-12-02 03:07:34
【问题描述】:

我正在使用该代码拍照我无法尽快拍照。 快速拍摄多张照片应用会崩溃。

我使用的是 Swift 1.1。

错误:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“+[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:] - NULL 样本缓冲区。'

 class ViewController: UIViewController {
    let captureSession = AVCaptureSession()
    var previewLayer : AVCaptureVideoPreviewLayer?
    var captureDevice : AVCaptureDevice?
    var captureConnection: AVCaptureConnection?
    var stillImageOutput = AVCaptureStillImageOutput()
    let targetRegion = CALayer()
    var currentImage: UIImage?

    @IBOutlet weak var cameraView: UIImageView!
    @IBOutlet weak var imageDisplayed: UIImageView!


    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.setNavigationBarHidden(true, animated: true)

        captureSession.sessionPreset = AVCaptureSessionPreset1920x1080
        let devices = AVCaptureDevice.devices()
        for device in devices {
            if device.hasMediaType(AVMediaTypeVideo) {
                if device.position == AVCaptureDevicePosition.Back {
                    captureDevice = device as? AVCaptureDevice
                }
            }
        }
        if captureDevice != nil {
            println("Device trovato")
            beginSession()
        }


    }


    func beginSession() {

        var err: NSError? = nil
        captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))

        if err != nil {
            println("err \(err?.localizedDescription)")
            return
        }

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.view.layer.addSublayer(previewLayer)

        previewLayer?.frame = CGRect(x: cameraView.frame.origin.x, y: cameraView.frame.origin.y, width: cameraView.frame.size.width, height: cameraView.frame.size.height)

        captureSetup()
        captureSession.startRunning()
    }

    func captureSetup() {

        let outputSetting = NSDictionary(dictionary: [AVVideoCodecKey: AVVideoCodecJPEG])
        self.stillImageOutput.outputSettings = outputSetting
        self.captureSession.addOutput(stillImageOutput)
        for connection:AVCaptureConnection in self.stillImageOutput.connections as [AVCaptureConnection] {

            for port:AVCaptureInputPort in connection.inputPorts! as [AVCaptureInputPort] {
                if port.mediaType == AVMediaTypeVideo {
                    captureConnection = connection as AVCaptureConnection
                    break
                }
            }
            if captureConnection != nil {
                break
            }
        }
    }


    var i = 0;

    func captureScene() {


        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
            if self.captureConnection != nil {
                self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, _) -> Void in

                    let imageDataJpeg = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer)
                    var pickedImage: UIImage = UIImage(data:imageDataJpeg)!



                    if let data = UIImagePNGRepresentation(pickedImage) {


                        let filename = self.getDocumentsDirectory().stringByAppendingPathComponent("\(self.i).png")
                        data.writeToFile(filename, atomically: true)

                        self.i++
                    }


                })
            }
        })

    }



    func getDocumentsDirectory() -> NSString {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let documentsDirectory: AnyObject = paths[0]


        return documentsDirectory as NSString
    }




    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        captureScene()
    }

}

【问题讨论】:

  • 你能解释一下同一个问题的答案吗?谢谢
  • 非常简单:检查imageSampleBuffer 是否不为零,因为有时如果你快速拍几张照片就会出现这种情况。 // 我看到您对captureStillImageAsynchronouslyFromConnection 的签名有一个非可选 imageSampleBuffer。我相信这是一个 Swift 1 的问题,在 Swift 2 中它是一个可选的,你可以检查它是否为零。使用 Swift 1,你应该寻找这个函数是否有可用的错误参数并使用它。
  • 请重新写成答案,以便我投票

标签: ios swift


【解决方案1】:

@alper 在linked answer 中解释的是,有时imageSampleBuffer 可以为零,这就是崩溃的根源。


我相信在 Swift 2 中 imageSampleBuffer 是可选的,所以为了避免这种崩溃,你可以检查 nil。示例:

if imageSampleBuffer != nil {
    let imageDataJpeg = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageSampleBuffer)
    // ...
} else {
    // handle or ignore the error
}

但是您使用的是 Swift 1,这是一个问题,因为在 Swift 1 中 imageSampleBuffer 被声明为隐式展开的可选项,这意味着它不能为 nil 并且您不能像前面的示例中那样检查。

@alper 给出的解决方案是使用

CMSampleBufferIsValid(imageSampleBuffer)

作为一种检查缓冲区是否有效的方法。


如果之前的解决方法不行,你可以试试这个。

当我查看函数签名时:

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, _) -> Void in

我看到缓冲区旁边还有另一个参数,但你忽略了它:

(imageSampleBuffer:CMSampleBuffer!, _)

我没有查找 Swift 1 文档,但如果 _ 实际上是一个错误参数,我不会感到惊讶。尝试将其替换为 error,如下所示:

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, error) -> Void in

或许

self.stillImageOutput.captureStillImageAsynchronouslyFromConnection(self.captureConnection, completionHandler:{ (imageSampleBuffer:CMSampleBuffer!, error:NSError) -> Void in

然后检查error 的内容,然后再继续imageSampleBuffer。

注意:正如我在最后一部分所说的,error 的解决方案是一个猜测,我没有测试:你必须尝试,适应,看看我的想法是否正确.如果您能找到 Swift 1 的相关文档并明确地告诉我们,那将是理想的选择。


【讨论】:

  • 完美工作的解决方案。回过头来,为什么 AVFoundation 做相机应用的方式这么慢?
  • 谢谢。不知道,我也有点惊讶这个问题没有得到更明确的处理。
  • stackoverflow.com/questions/19391300/… 检查该解决方案,我不知道如何快速翻译它。
  • 我看过了,别担心。 :) 不幸的是,我对其他问题没有答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多