【问题标题】:Multiple AVCaptureSession on macOS. What is the right approach?macOS 上的多个 AVCaptureSession。什么是正确的方法?
【发布时间】:2023-03-24 10:02:01
【问题描述】:

我想使用 AVFoundation 在 macOS 上预览和录制多个 AVCaptureDevice。我有一个测试应用程序,我在其中为要预览和记录的每个设备输入创建 AVCaptureSession。我将 AVCaptureInput、AVCaptureMovieFileOutput 和 AVCaptureVideoPreviewLayer 添加到每个 AVCaptureSession。我有一个全局对象“MyAVSessionManager”,它管理所有会话。所有会话仅共享一个 'dispatch_queue_create("sr_capture_queue_video", DISPATCH_QUEUE_SERIAL);'。一切正常,但是当我连接两个设备时(它们的帧速率是否相同并不重要),GPU 帧速率从 50fps 翻倍到 100fps 左右(两个输入都连接到不同的信号(但格式相同。我使用 1080p50用于测试)。我的结论(我可能完全错了)是来自捕获的视频缓冲区的 blit 在会话之间不同步,因此每个会话在到达时都会写入其视频缓冲区。我没有找到如何同步它的选项( AVCaptureSession?),因此视频缓冲区将立即与我的预览层同步,与显示同步。我想尝试为所有设备使用一个通用的 AVCapture 会话,具有多个 AVCaptureVideoPreviewLayers 和 AVCaptureMovieFileOutputs(连接到适当的输入)。我希望在这种情况下,可以同步来自不同视频缓冲区的 blit。如果失败,我看到的唯一选择是拥有多个 AVCaptureVideoDataOutputs,使用 Metal 从传入的 CVImageBuffer 创建纹理并同步commandBuffer.commit() 用于所有缓冲区。我的问题:哪种方法最好?更好的是:为每个设备(使用共享队列或自己的队列?)或为所有设备创建单独的 AVCaptureSession?显示(和同步)多个预览的正确方法是什么?谢谢。

【问题讨论】:

  • 测试应用程序只有一个 AVCaptureSession 和多个 AVCaptureDevice 输入连接到多个 AVCaptureVideoPreviewLayers 工作正常(与每个设备的 3 x AVCaptureSessions 相比,CPU 利用率约为三分之一),但 FPS 仍然存在90FPS(三个设备,每个 1080i50)。也许我不明白 Debug Gauges 中的 FPS 数字实际上代表什么……是:每秒发送到 GPU 的帧数,还是 GPU 随机(显示)的每秒帧数?

标签: macos avfoundation avcapturesession


【解决方案1】:

修复:手动添加所有连接。我做错的是:

       let previewOutput = AVCapturePhotoOutput()
    
        // Add a previewOutput.
        guard session.canAddOutput(previewOutput) else {
            print("Could not add previewOutput to the session")
            setupResult = .configurationFailed
            session.commitConfiguration()
            return
        }
        
        session.addOutput(previewOutput)
        
        let previewLayer  = AVCaptureVideoPreviewLayer(sessionWithNoConnection: session)
        let previewLayerConnection = AVCaptureConnection(inputPort: devicePort, videoPreviewLayer: previewLayer)
        
        guard session.canAddConnection(previewLayerConnection) else
        {   print("Could not add preview layer connection to the session")
            setupResult = .configurationFailed
            session.commitConfiguration()
            return
        }
        
        session.addConnection(previewLayerConnection)

这是错误的:session.addOutput(previewOutput) 它必须是: session.addOutputWithNoConnections(previewOutput) 然后手动创建连接:

        let previewLayer  = AVCaptureVideoPreviewLayer(sessionWithNoConnection: session)
        let previewLayerConnection = AVCaptureConnection(inputPort: devicePort, videoPreviewLayer: previewLayer)
        
        guard session.canAddConnection(previewLayerConnection) else
        {   print("Could not add preview layer connection to the session")
            setupResult = .configurationFailed
            session.commitConfiguration()
            return
        }
        
        session.addConnection(previewLayerConnection)

我创建了这个连接两次。当我检查会话时,连接数正确(通过打印描述)。我不知道我使用 session.addOutput() 创建的连接会发生什么(它没有在 session.connections 中列出),但是我在仪表中注意到的 FPS 问题消失了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多