Я слишком долго занимался этим.
Я пытаюсь получить данные веб-камеры MacOS и запустить CIDetect для кадров, выводимых веб-камерой.
Я знаю, что мне нужно:
подключите
AVCaptureDevice
(как на входе) кAVCaptureSession
подключите
AVCaptureVideoDataOutput
(как выход к) вAVCaptureSession
позвонить
.setSampleBufferDelegate(AVCaptureVideoDataOutputSampleBufferDelegate, DelegateQueue)
По какой-то причине после вызова .setSampleBufferDelegate(...)
(и, конечно, после вызова .startRunning()
в экземпляре AVCaptureSession
) мой 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
, были созданы внутри Viewcontroller
init()
. Я опустил это для ясности.
Любые идеи?
Спасибо, ТАК!
Ковек
РЕДАКТИРОВАТЬ: - Фиксированная настройка делегата от self
до MyDelegate
.
И вот как я инициализирую videoDataOutputQueue
:
videoDataOutputQueue = DispatchQueue(
label: "VideoDataOutputQueue"
);