如何用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
相关产品推荐
相关产品推荐

