不使用setSampleBufferDelegate调用captureOutput函数

CMa*_*Mao 14 swift

我开始开发iOS应用程序,这是我的第一篇SO帖子.我正在尝试实现一个UI视图,它可以显示后置摄像头的预览视频并处理捕获的帧.我的预览图层效果很好,我可以在UI视图中看到图片显示.但是,永远不会调用captureOutput函数.

我已经在网上搜索了一段时间的silimar问题和解决方案,并试图调整不同的东西,包括输出,连接和调度队列设置,但没有一个工作.任何人都可以帮助我或分享一些见解和方向吗?非常感谢提前!

这里是我的代码,我使用的是Xcode 11 betaiOS 10作为构建目标.

class ThreeDScanningViewController: UIViewController, 
AVCaptureVideoDataOutputSampleBufferDelegate {

    @IBOutlet weak var imageView: UIImageView!

    var session : AVCaptureSession!
    var device : AVCaptureDevice!
    var output : AVCaptureVideoDataOutput!
    var previewLayer : AVCaptureVideoPreviewLayer!

    override func viewDidLoad() {
        super.viewDidLoad()
                //NotificationCenter.default.addObserver(self, selector: #selector(self.startedNotif), name: NSNotification.name.CaptureSessionDidStartRunningNotification, object: nil)

    func initCamera() -> Bool {
        session = AVCaptureSession()
        session.sessionPreset = AVCaptureSession.Preset.medium

        let devices = AVCaptureDevice.devices()

        for d in devices { 
            if ((d as AnyObject).position == AVCaptureDevice.Position.back) {
                device = d as! AVCaptureDevice
            }
        }
        if device == nil {
            return false
        }

        do {
            // Set up the input

            let input : AVCaptureDeviceInput!
            try input = AVCaptureDeviceInput(device: device)

            if session.canAddInput(input) {
                session.addInput(input)
            } else {
                return false
            }

            // Set up the device

            try device.lockForConfiguration()
            device.activeVideoMinFrameDuration = CMTimeMake(1, 15)
            device.unlockForConfiguration()

            // Set up the preview layer

            previewLayer = AVCaptureVideoPreviewLayer(session: session)
            previewLayer.frame = imageView.bounds
            imageView.layer.addSublayer(previewLayer)

            // Set up the output

            output = AVCaptureVideoDataOutput()
            output.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) as String: kCVPixelFormatType_32BGRA]

            let queue = DispatchQueue(label: "myqueue")
            output!.setSampleBufferDelegate(self, queue: queue)

            output.alwaysDiscardsLateVideoFrames = true

            if session.canAddOutput(output) {
                session.addOutput(output)
            } else {
                return false
            }

            for connection in output.connections {
                if let conn = connection as? AVCaptureConnection {
                    if conn.isVideoOrientationSupported {
                        conn.videoOrientation = AVCaptureVideoOrientation.portrait
                    }
                }
            }

            session.startRunning()

        } catch let error as NSError {
            print(error)
            return false
        }

        return true
    }

    func captureOutput (captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        print("captureOutput!\n");
        DispatchQueue.main.async(execute: {
            // Do stuff
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我查看的一些链接,没有一个与解决我的问题相关:

CMa*_*Mao 37

我终于找到了问题的原因.您需要确保为swift 3语法的captureOutput函数使用正确的函数签名.

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
Run Code Online (Sandbox Code Playgroud)

func captureOutput(_ output: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
Run Code Online (Sandbox Code Playgroud)

我使用的是旧版本的Swift语法,编译器没有警告我这个问题!纠正功能签名后,captureOutput函数被称为精美:-)

  • 这应该标记为正确答案。谢谢@CMao。苹果公司没有将该方法标记为“不推荐使用”,这让我很震惊,我花了很长时间才发现问题。 (2认同)

Aja*_*ddy 13

来自Swift 4:

func captureOutput(_ captureOutput: AVCaptureOutput!, 
didOutputMetadataObjects metadataObjects: [Any]!, from connection: 
AVCaptureConnection!)  
Run Code Online (Sandbox Code Playgroud)

将不会被调用,因为它不再存在.

它已更改为以下内容:

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) 
Run Code Online (Sandbox Code Playgroud)


Can*_*nis 2

根据教程,您需要在开始运行会话之前提交配置。

我还发现在会话开始运行之前,您有多个返回 false 的地方。您是否检查过自己是否在这些地点之一过早退出?只需控制台输出或返回语句上的断点即可为您提供一些信息。