Ravi Ravi - 9 months ago 490
Swift Question

AVCaptureVideoDataOutput captureOutput not being called

I'm trying screen capture on a Mac with AVCaptureScreenInput, but AVCaptureVideoDataOutput delegate captureOutput is never called, and I'm not sure why. I do get a notification saying the capture session was started.

import Cocoa
import AVFoundation

class ViewController: NSViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

var captureSession: AVCaptureSession!

override func viewDidLoad() {
// Do any additional setup after loading the view.

override func viewWillAppear() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.errorNotif), name: AVCaptureSessionRuntimeErrorNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.startedNotif), name: AVCaptureSessionDidStartRunningNotification, object: nil)

override func viewWillDisappear() {

func captureOutput(captureOutput: AVCaptureOutput!, didDropSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
print("drop frame")

func startScreenCapture() {

let displayId = CGMainDisplayID()
captureSession = AVCaptureSession()
if captureSession.canSetSessionPreset(AVCaptureSessionPresetHigh) {
captureSession.sessionPreset = AVCaptureSessionPresetHigh
let captureScreenInput = AVCaptureScreenInput(displayID: displayId)
if captureSession.canAddInput(captureScreenInput) {
} else {
print("Could not add main display to capture input")

let output = AVCaptureVideoDataOutput()

let queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)
output.setSampleBufferDelegate(self, queue: queue)
output.alwaysDiscardsLateVideoFrames = true

output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as NSString: NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)]

func errorNotif() {
print("error starting capture")
func startedNotif() {
print("started screen capture")


You need to define the didOutputSampleBuffer delegate callback to actually receive the captured frames:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
    print("captured \(sampleBuffer)")

p.s. I don't sure about macOS, but viewWillAppear may not be a good place to do initialisation because on iOS at least it can be called multiple times.