iOS: captureOutput function isn't called using AVCaptureMovieFileOutput and AVCaptureVideoDataOutput

391 Views Asked by At

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)
1

There are 1 best solutions below

8
Nirav Bhatt On

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.