Подтвердить что ты не робот

Невозможно захватить видеоданные на Swift Playgrounds, captureOutput AVCaptureVideoDataOutputSampleBufferDelegate метод делегирования не вызван

Я хочу получить доступ к iPad-iPad в приложении Swift Playgrounds iPad. Я обнаружил, что невозможно захватить видеоданные, хотя моя игровая площадка работает нормально.

captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!), метод делегата протокола AVCaptureVideoDataOutputSampleBufferDelegate не вызван (вероятно, из-за отсутствия видеоданных), в то время как он находится в моем приложении iOS.

Предполагается, что на моей игровой площадке будет отображаться вид камеры FaceTime. Почему я не могу отобразить вывод камеры, даже если Apple явно говорит, что это разрешено делать? Кроме того, приложение Playground запрашивает у меня разрешения на камеру, как только я открою свою игровую площадку, поэтому это должно быть разрешено каким-то образом.

import UIKit
import CoreImage
import AVFoundation
import ImageIO
import PlaygroundSupport

class Visage: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {

    var visageCameraView : UIView = UIView()
    fileprivate var faceDetector : CIDetector?
    fileprivate var videoDataOutput : AVCaptureVideoDataOutput?
    fileprivate var videoDataOutputQueue : DispatchQueue?
    fileprivate var cameraPreviewLayer : AVCaptureVideoPreviewLayer?
    fileprivate var captureSession : AVCaptureSession = AVCaptureSession()
    fileprivate let notificationCenter : NotificationCenter = NotificationCenter.default

    override init() {
        super.init()

        self.captureSetup(AVCaptureDevicePosition.front)
        var faceDetectorOptions : [String : AnyObject]?
        faceDetectorOptions = [CIDetectorAccuracy : CIDetectorAccuracyHigh as AnyObject]
        self.faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: faceDetectorOptions)
    }

    func beginFaceDetection() {
        self.captureSession.startRunning()
    }

    func endFaceDetection() {
        self.captureSession.stopRunning()
    }

    fileprivate func captureSetup (_ position : AVCaptureDevicePosition) {
        var captureError : NSError?
        var captureDevice : AVCaptureDevice!

        for testedDevice in AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo){
            if ((testedDevice as AnyObject).position == position) {
                captureDevice = testedDevice as! AVCaptureDevice
            }
        }

        if (captureDevice == nil) {
            captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
        }

        var deviceInput : AVCaptureDeviceInput?
        do {
            deviceInput = try AVCaptureDeviceInput(device: captureDevice)
        } catch let error as NSError {
            captureError = error
            deviceInput = nil
        }
        captureSession.sessionPreset = AVCaptureSessionPresetHigh

        if (captureError == nil) {
            if (captureSession.canAddInput(deviceInput)) {
                captureSession.addInput(deviceInput)
            }

            self.videoDataOutput = AVCaptureVideoDataOutput()
            self.videoDataOutput!.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: Int(kCVPixelFormatType_32BGRA)]
            self.videoDataOutput!.alwaysDiscardsLateVideoFrames = true
            self.videoDataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue", attributes: [])
            self.videoDataOutput!.setSampleBufferDelegate(self, queue: self.videoDataOutputQueue!)

            if (captureSession.canAddOutput(self.videoDataOutput)) {
                captureSession.addOutput(self.videoDataOutput)
            }
        }

        visageCameraView.frame = UIScreen.main.bounds
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer?.frame = UIScreen.main.bounds
        previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        visageCameraView.layer.addSublayer(previewLayer!)
    }

    // NOT CALLED
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {            
        print("delegate method called!")
    }
}

class SmileView: UIView {
    let smileView = UIView()
    var smileRec: Visage!

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(smileView)
        self.translatesAutoresizingMaskIntoConstraints = false
        smileRec = Visage()
        smileRec.beginFaceDetection()
        let cameraView = smileRec.visageCameraView
        self.addSubview(cameraView)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
let sView = SmileView(frame: frame)
PlaygroundPage.current.liveView = sView
4b9b3361

Ответ 1

Изменить: это должно быть исправлено:)

-

Изменить: это подтвердило ошибку Apple.

Я опубликовал отчет об ошибке, и я обновлю этот ответ, когда придет новая официальная информация.

Ответ 2

Мне кажется, вам нужно установить свойство needsIndefiniteExecution, чтобы выполнение не прекращалось после завершения вашего кода. Из яблока:

По умолчанию выполняется весь код верхнего уровня, а затем выполняется прекращается. При работе с асинхронным кодом включите неопределенный выполнение, чтобы продолжить выполнение после завершения Достигнут код верхнего уровня игровых площадок. Это, в свою очередь, дает темы и обратный вызов времени для выполнения.

Редактирование игровой площадки автоматически прекращает выполнение, даже если неограниченное выполнение.

Устанавливает requireIndefiniteExecution в true для продолжения выполнения после конец кода верхнего уровня. установите для него значение false, чтобы остановить выполнение при этом точка.

Таким образом, возможный код в конце будет:

let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
let sView = SmileView(frame: frame)
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = sView