captureOutput未被调用

时间:2017-07-09 17:41:29

标签: avfoundation macos-sierra

我一直在研究这个问题太久了。

我正在尝试获取MacOS网络摄像头数据并在网络摄像头输出的帧上运行CIDetect。

我知道我需要:

  • .as-console-wrapper { max-height: 100% !important; top: 0; }(如输入中的内容)连接到AVCaptureDevice

  • AVCaptureSession(作为输出)连接到AVCaptureVideoDataOutput

  • 致电AVCaptureSession

出于某种原因,在致电.setSampleBufferDelegate(AVCaptureVideoDataOutputSampleBufferDelegate, DelegateQueue)之后(当然在.setSampleBufferDelegate(...)实例上致电.startRunning()后),我的AVCaptureSession的{​​{1}}不是被召唤。

我发现有很多人在网上遇到这个问题,但我找不到任何解决方案。

在我看来,它与AVCaptureVideoDataOutputSampleBufferDelegate

有关

captureOutput

DispatchQueue

MyDelegate.swift

class MyDelegate : NSObject {


    var context: CIContext?;
    var detector : CIDetector?;

    override init() {
        context = CIContext();
        detector = CIDetector(ofType: CIDetectorTypeFace, context: context);
        print("set up!");

    }

}
extension MyDelegate : AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection) {
        print("success?");
        var pixelBuffer : CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!;
        var image : CIImage = CIImage(cvPixelBuffer: pixelBuffer);
        var features : [CIFeature] = detector!.features(in: image);
        for feature in features {
            print(feature.type);
            print(feature.bounds);
        }
    }

    func captureOutput(_ : AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection) {
        print("fail?");
    }
}

ViewController.swift中与var captureSession : AVCaptureSession; var captureDevice : AVCaptureDevice? var previewLayer : AVCaptureVideoPreviewLayer? var vdo : AVCaptureVideoDataOutput; var videoDataOutputQueue : DispatchQueue; override func viewDidLoad() { super.viewDidLoad() camera.layer = CALayer() // Do any additional setup after loading the view, typically from a nib. captureSession.sessionPreset = AVCaptureSessionPresetLow // Get all audio and video devices on this machine let devices = AVCaptureDevice.devices() // Find the FaceTime HD camera object for device in devices! { print(device) // Camera object found and assign it to captureDevice if ((device as AnyObject).hasMediaType(AVMediaTypeVideo)) { print(device) captureDevice = device as? AVCaptureDevice } } if captureDevice != nil { do { try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice)) // vdo : AVCaptureVideoDataOutput; vdo.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: NSNumber(value: kCVPixelFormatType_32BGRA)] try captureDevice!.lockForConfiguration() captureDevice!.activeVideoMinFrameDuration = CMTimeMake(1, 30) captureDevice!.unlockForConfiguration() videoDataOutputQueue.sync{ vdo.setSampleBufferDelegate( MyDelegate, queue: videoDataOutputQueue ); vdo.alwaysDiscardsLateVideoFrames = true captureSession.addOutput(vdo) captureSession.startRunning(); } } catch { print(AVCaptureSessionErrorKey.description) } } 相关的所有必要变量都已在viewDidLoad AVFoundation内实例化。为清楚起见,我省略了这一点。

有什么想法吗?

谢谢,SO!

Kovek

编辑:    - 修正了从Viewcontrollerinit()的设置委托。

这就是我初始化self

的方式
MyDelegate

2 个答案:

答案 0 :(得分:11)

我遇到了类似的问题:在我的情况下,问题是在Swift 4中编写你必须实现以下方法:

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

而不是:

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

希望它有所帮助。

修改

此方法必须由AVCaptureMetadataOutputObjectsDelegate(例如,您的viewcontroller)实现。为了启动QRCode捕获会话,您可以尝试这样的事情:

    captureSession = AVCaptureSession()

    let videoCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video);
    var videoInput:AVCaptureDeviceInput? =  nil;

    do {
        if let v = videoCaptureDevice{
            videoInput = try AVCaptureDeviceInput(device: v)
        }
        else{
            print("Error: can't find videoCaptureDevice");
        }

    } catch {
        let ac = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "Ok", style: .default))
        present(ac, animated: true)
        return
    }

    if let videoInput = videoInput{
        if (captureSession.canAddInput(videoInput)) {
            captureSession.addInput(videoInput)
        } else {
            //Show error
            return;
        }
    }
    else{
        //Show error
        return;
    }

    let metadataOutput = AVCaptureMetadataOutput()

    if (captureSession.canAddOutput(metadataOutput)) {
        captureSession.addOutput(metadataOutput);

        metadataOutput.setMetadataObjectsDelegate(/*YOUR DELEGATE*/, queue: DispatchQueue.main);
        metadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr, AVMetadataObject.ObjectType.code128];
    } else {
        //Show error
        return;
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
    previewLayer.frame = view.layer.bounds;

    previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill;
    view.layer.addSublayer(previewLayer);

    captureSession.startRunning();

答案 1 :(得分:5)

您在声明所需的样本缓冲区委托方法时犯了错误:

captureOutput(_:didOutputSampleBuffer:from:)

请检查并确保它是:

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

PS:注意如何声明该方法的参数。所有参数都有'!'这意味着自动解包。