captureOutput函数未使用setSampleBufferDelegate调用

问题描述:

我开始开发iOS应用程序,这是我的第一篇SO帖子。我正在尝试实现UI视图,该视图可以显示后置摄像头的预览视频并处理捕获的帧。我的预览图层完美地工作,我可以在我的用户界面视图中看到图片显示。但是,captureOutput函数永远不会被调用。captureOutput函数未使用setSampleBufferDelegate调用

我已经在网上搜索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 
     }) 
    } 
} 

这里有一些链接,我进去看了看,没有一个相关的解决我的问题:

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

我也看到你有多个点,你可以在会话开始运行之前返回false。您是否检查过您是否在其中一个位置过早退出?简单地说,一个控制台输出或返回语句中的一个断点可以给你一些信息。

+0

嗨Canis,谢谢你的回复!我已经测试过,并且可以确认该函数在会话开始运行之前不会返回false。在开始运行会话之前,我会考虑提交配置,看看它是如何工作的。再次感谢! – CMao

+0

我试图使用startConfiguration和commitConfiguration函数,但它没有解决问题... – CMao

+0

@Cooao如果以下教程不起作用,那么我也不知所措。我的开发环境不允许我在此刻自己测试你的代码......你可以尝试在一个单独的viewcontroller中一步一步地按照教程吗? 哦,另一个虽然,你正在一个真实的设备上而不是在模拟器上测试? – Canis

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

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) 

func captureOutput(_ output: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) 

我用的是雨燕语法旧版本和编译器没有提醒我的问题!修正函数签名后,captureOutput函数被调用精美:-)

+0

我感谢您发布此解决方案,即使您自己发现它。这样其他人可能会找到他们需要的答案!做得好! – Canis

+1

谢谢你,卡尼斯,真是太好了! :-) – CMao

+0

这应该被标记为正确的答案。谢谢@CMao。我仍然感到震惊,苹果公司并没有将这种方法标记为“已弃用”,花了我很长时间才发现问题。 – Victor

从斯威夫特4:

func captureOutput(_ captureOutput: AVCaptureOutput!, 
didOutputMetadataObjects metadataObjects: [Any]!, from connection: 
AVCaptureConnection!) 

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

已更改为以下:当我改变dualCamera到AVCaptureDeviceType.builtInWideAngleCamera迅速4. 希望它可以帮助有需要的人

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) 

的问题得到了解决。