You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用AVCaptureVideoDataOutput获取10bit P3色彩空间的CMSampleBuffers(≥30fps)?

好问题!答案是肯定的——你确实可以通过AVCaptureVideoDataOutput获取10bit P3色彩空间的CMSampleBuffer,且帧率维持在30fps以上,但需要满足硬件支持+正确的配置步骤,我来一步步给你拆解:

核心前提:设备硬件支持

首先得明确:不是所有iOS/iPadOS设备都能捕获10bit P3视频。你需要搭载A12仿生及以上芯片的设备(比如iPhone XS/XR及以后、iPad Pro 2018及以后),这类设备的图像信号处理器(ISP)原生支持10bit色彩深度和P3色彩空间的硬件级捕获。

配置步骤详解

1. 筛选支持10bit P3的设备格式

你不能直接依赖默认的session preset,得手动遍历设备的可用格式,找到同时支持10bit深度和P3色彩空间的选项:

guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
    fatalError("No back camera available")
}

// 遍历所有支持的格式,筛选10bit P3的选项
var targetFormat: AVCaptureDevice.Format?
for format in device.formats {
    let supportedColorSpaces = format.supportedColorSpaces
    // 检查是否支持P3色彩空间,且像素格式为10bit YUV(视频捕获常用格式)
    if supportedColorSpaces.contains(.displayP3),
       format.mediaSubType == kCVPixelFormatType_420YpCbCr10BiPlanarFullRange {
        // 额外确认该格式支持30fps及以上的帧率
        let ranges = format.videoSupportedFrameRateRanges
        for range in ranges {
            if range.minFrameRate <= 30, range.maxFrameRate >= 30 {
                targetFormat = format
                break
            }
        }
        if targetFormat != nil { break }
    }
}

guard let format = targetFormat else {
    // 设备不支持10bit P3,fallback到8bit P3或默认格式
    print("Device doesn't support 10bit P3 capture, falling back to 8bit")
    // 这里可以设置8bit P3的格式,比如kCVPixelFormatType_420YpCbCr8BiPlanarFullRange + .displayP3
    return
}

// 激活选中的格式和色彩空间
do {
    try device.lockForConfiguration()
    device.activeFormat = format
    device.activeColorSpace = .displayP3
    // 设置帧率为30fps(或更高,比如60fps,如果格式支持)
    device.activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: 30)
    device.activeVideoMaxFrameDuration = CMTimeMake(value: 1, timescale: 30)
    device.unlockForConfiguration()
} catch {
    print("Failed to configure device: \(error)")
}

2. 配置AVCaptureVideoDataOutput以输出10bit数据

接下来要给AVCaptureVideoDataOutput指定明确的10bit像素格式,不能用默认设置:

let videoOutput = AVCaptureVideoDataOutput()
// 设置输出格式为10bit YUV P3
videoOutput.videoSettings = [
    kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr10BiPlanarFullRange,
    kCVPixelBufferColorSpaceKey as String: CGColorSpace(name: CGColorSpace.displayP3)!.cfRepresentation
]

// 开启丢弃延迟帧,保证帧率稳定
videoOutput.alwaysDiscardsLateVideoFrames = true

// 设置代理队列(建议用串行队列避免线程问题)
let queue = DispatchQueue(label: "VideoCaptureQueue")
videoOutput.setSampleBufferDelegate(self, queue: queue)

// 将输出添加到session
if captureSession.canAddOutput(videoOutput) {
    captureSession.addOutput(videoOutput)
}

3. 验证回调中的CMSampleBuffer

在captureOutput(_:didOutput:from:)代理方法中,你可以验证拿到的buffer是否是10bit P3:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    guard let formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer) else { return }
    let mediaSubType = CMFormatDescriptionGetMediaSubType(formatDesc)
    let colorSpace = CMFormatDescriptionGetColorSpace(formatDesc)
    
    // 检查是否是10bit YUV和P3色彩空间
    if mediaSubType == kCVPixelFormatType_420YpCbCr10BiPlanarFullRange,
       colorSpace?.name == CGColorSpace.displayP3 {
        print("Successfully received 10bit P3 CMSampleBuffer")
        // 这里处理你的buffer数据
    }
}

常见坑点

  • 设备兼容性:如果你的测试设备是A12以下的,比如iPhone X或更早,无论怎么配置都拿不到10bit数据,只能fallback到8bit。
  • Preset冲突:不要给session设置过于严格的preset(比如.photo),优先用.hd1920x1080或.4K这类视频类preset,否则可能会覆盖你手动设置的格式。
  • 性能考量:10bit数据量比8bit大50%,要确保你的处理逻辑能跟上帧率,避免丢帧。

内容的提问来源于stack exchange,提问作者Deepak Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:44:07