2

I'm trying to implement a View which can show the preview video of the rear camera and process the captured frames. I would like to use two outputs: one to save the video and one to process each frame.

let movieOutput = AVCaptureMovieFileOutput()
let videoDataOutput = AVCaptureVideoDataOutput()

I have added the delegates to my view controller:

class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate, AVCaptureVideoDataOutputSampleBufferDelegate

Also I have added my outputs to the AVCaptureSession:

do {
    videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable as! String: NSNumber(value: kCVPixelFormatType_32BGRA)]
    videoDataOutput.alwaysDiscardsLateVideoFrames = true
    let queue = DispatchQueue(label: "videosamplequeue")
    videoDataOutput.setSampleBufferDelegate(self, queue: queue)
    guard captureSession.canAddOutput(videoDataOutput) else {
        fatalError()
    }
    if captureSession.canAddOutput(videoDataOutput){
        captureSession.addOutput(videoDataOutput)
    }

    videoConnection = videoDataOutput.connection(withMediaType:AVMediaTypeVideo)
}

if captureSession.canAddOutput(movieOutput) {
    captureSession.addOutput(movieOutput)
}

My preview layer works perfectly and I can see the picture display in my UI view. But captureOutput is never called. If I comment:

//if captureSession.canAddOutput(movieOutput) {
//        captureSession.addOutput(movieOutput)
//    }

then, my captureOutput is called and works fine, but I would like to save my video in a file. I'm working with swift 3, so I'm using:

func captureOutput(_ output: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)
Ricardo
  • 2,086
  • 25
  • 35

1 Answers1

0

Currently, when you remove the other source, it's still calling captureOutput maybe with fake data, but still for videoDataOutput, because you set sampleBufferDelegate for it. But captureOutput isn't meant for movieOutput.

movieOutput is AVCaptureMovieFileOutput, which is a subclass of AVCaptureFileOutput.

AVCaptureFileOutput implements two protocols: AVCaptureFileOutputDelegate and AVCaptureFileOutputRecordingDelegate

You should implement one of them (read the documentation to decide which one fits your requirement), and implement their methods, and expect them to be invoked, rather than captureOutput to be called twice.

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89
  • Yes, I'm calling: videoDataOutput.setSampleBufferDelegate(self, queue: queue) and works, the problem is when I add the second output to the capture session: captureSession.addOutput(movieOutput) – Ricardo Jul 02 '18 at 07:52
  • There is one more delegate involved, see edited answer. – Nirav Bhatt Jul 02 '18 at 07:54
  • I'm getting "Value of type 'AVCaptureMovieFileOutput' has no member 'delegate'". This implementation works if I remove captureSession.addOutput(videoDataOutput). Each output works if I remove the other – Ricardo Jul 02 '18 at 08:02
  • Have you tried doing this? movieOutput.setSampleBufferDelegate(self, queue: queue) Do it along with videoDataOutput.setSampleBufferDelegate(self, queue: queue). Not one way or the other. – Nirav Bhatt Jul 02 '18 at 08:11
  • Yes, but movieOutput is AVCaptureMovieFileOutput and has no member called setSampleBufferDelegate – Ricardo Jul 02 '18 at 08:17
  • ok, so movieOutput is AVCaptureMovieFileOutput, which is a subclass of AVCaptureFileOutput. AVCaptureFileOutput has a delegate (AVCaptureFileOutputDelegate) and that has 2 methods called: fileOutputShouldProvideSampleAccurateRecordingStart and fileOutput - look here: https://developer.apple.com/documentation/avfoundation/avcapturefileoutputdelegate - so you expecting ´captureOutput´ to be called twice is probably wrong. When you remove the other, its still calling it maybe with fake data because you set sampleBufferDelegate. But captureOutput isn't meant for movieOutput. – Nirav Bhatt Jul 02 '18 at 08:26
  • the method you are looking for is here: https://developer.apple.com/documentation/avfoundation/avcapturefileoutputdelegate/1390096-fileoutput – Nirav Bhatt Jul 02 '18 at 08:30
  • It sounds good but I'm getting 'AVCaptureFileOutputDelegate' is unavailable. I'm using swift 3 – Ricardo Jul 02 '18 at 09:26