2017-08-11 65 views
3

我開始開發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 
     }) 
    } 
} 

這裏有一些鏈接,我進去看了看,沒有一個相關的解決我的問題:

回答

0

根據this教程,您需要在開始運行會議之前提交您的配置。

我也看到你有多個點,你可以在會話開始運行之前返回false。您是否檢查過您是否在其中一個位置過早退出?簡單地說,一個控制檯輸出或返回語句中的一個斷點可以給你一些信息。

+0

嗨Canis,謝謝你的回覆!我已經測試過,並且可以確認該函數在會話開始運行之前不會返回false。在開始運行會話之前,我會考慮提交配置,看看它是如何工作的。再次感謝! – CMao

+0

我試圖使用startConfiguration和commitConfiguration函數,但它沒有解決問題... – CMao

+0

@Cooao如果以下教程不起作用,那麼我也不知所措。我的開發環境不允許我在此刻自己測試你的代碼......你可以嘗試在一個單獨的viewcontroller中一步一步地按照教程嗎? 哦,另一個雖然,你正在一個真實的設備上而不是在模擬器上測試? – Canis

9

我終於找到了問題的原因。您需要確保爲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

5

從斯威夫特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) 
0

的問題得到了解決。