ios pip控制器和视图控制器中的AVCaptureVideoPreviewLayer不工作

u0njafvf  于 12个月前  发布在  iOS
关注(0)|答案(1)|浏览(110)

我试图在视图控制器中集成一个画中画(画中画)控制器和相机预览。但是,相机预览仅在其首次指定的视图中可见(另一个视图变为黑色)。是否可以为两个视图使用相同的AVCaptureVideoPreviewLayer示例?或者这里需要改变什么?

class ViewController: UIViewController {

    let captureSession = AVCaptureSession()
    let captureSessionQueue = DispatchQueue(label: "Capture Session Queue")

    var pipVideoCallViewController: AVPictureInPictureVideoCallViewController!
    var pipController: AVPictureInPictureController!

    override func viewDidLoad() {
        super.viewDidLoad()

        let previewView = PreviewView(captureSession)

        let previewLayer = previewView.previewLayer
        previewLayer.frame = view.layer.bounds
        previewLayer.videoGravity = .resizeAspectFill
        previewLayer.connection?.videoOrientation = .landscapeLeft
        view.layer.addSublayer(previewLayer)

        pipVideoCallViewController = .init(previewView,
                                           preferredContentSize: CGSize(width: 1080, height: 1920))

        let pipContentSource = AVPictureInPictureController.ContentSource(
                                    activeVideoCallSourceView: view,
                                    contentViewController: pipVideoCallViewController)

        pipController = AVPictureInPictureController(contentSource: pipContentSource)
        pipController.delegate = self
        pipController.canStartPictureInPictureAutomaticallyFromInline = true

        startSession()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if !pipController.isPictureInPictureActive {
            pipController.startPictureInPicture()
        }
    }

    private func startSession() {
        captureSessionQueue.async { [unowned self] in
            let device = AVCaptureDevice.default(for: .video)!
            captureSession.addInput(try! AVCaptureDeviceInput(device: device))
            captureSession.sessionPreset = .hd1920x1080
            captureSession.isMultitaskingCameraAccessEnabled = captureSession.isMultitaskingCameraAccessSupported
            captureSession.startRunning()
        }
    }

}

extension ViewController: AVPictureInPictureControllerDelegate {

    func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
        print(error.localizedDescription)
    }
}

class PreviewView: UIView {
    override class var layerClass: AnyClass {
        AVCaptureVideoPreviewLayer.self
    }

    var previewLayer: AVCaptureVideoPreviewLayer {
        layer as! AVCaptureVideoPreviewLayer
    }

    init(_ session: AVCaptureSession) {
        super.init(frame: .zero)

        previewLayer.session = session
    }

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

extension AVPictureInPictureVideoCallViewController {

    convenience init(_ previewView: PreviewView, preferredContentSize: CGSize) {

        // Initialize.
        self.init()

        // Set the preferredContentSize.
        self.preferredContentSize = preferredContentSize

        // Configure the PreviewView.
        previewView.translatesAutoresizingMaskIntoConstraints = false
        previewView.frame = self.view.frame

        self.view.addSubview(previewView)

        NSLayoutConstraint.activate([
            previewView.topAnchor.constraint(equalTo: self.view.topAnchor),
            previewView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
            previewView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
            previewView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
        ])
    }

}
dwthyt8l

dwthyt8l1#

AVCaptureVideoPreviewLayer只能添加到单个视图,创建单个AVCaptureVideoPreviewLayer将其作为子图层添加到两个视图

var previewLayer: AVCaptureVideoPreviewLayer?

viewDidLoad将AV添加到

override func viewDidLoad() {
    super.viewDidLoad()

    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.frame = view.layer.bounds
    previewLayer.videoGravity = .resizeAspectFill
    previewLayer.connection?.videoOrientation = .landscapeLeft
    view.layer.addSublayer(previewLayer)
    self.previewLayer = previewLayer

    pipVideoCallViewController = .init(previewLayer: previewLayer,
                                       preferredContentSize: CGSize(width: 1080, height: 1920))

    let pipContentSource = AVPictureInPictureController.ContentSource(
        activeVideoCallSourceView: view,
        contentViewController: pipVideoCallViewController)

    pipController = AVPictureInPictureController(contentSource: pipContentSource)
    pipController.delegate = self
    pipController.canStartPictureInPictureAutomaticallyFromInline = true

    startSession()
}

更新控制器

convenience init(previewLayer: AVCaptureVideoPreviewLayer, preferredContentSize: CGSize) {
    self.init()
    self.preferredContentSize = preferredContentSize
    previewLayer.frame = view.frame
    view.layer.addSublayer(previewLayer)
}

相关问题