解码ProresRAW为原生拜耳表示时出现AVFoundation -11821错误如何解决?
ProRes RAW解码失败原因与解决方案
你遇到的错误码-11821(无法解码)底层对应-12137,本质是AVAssetReader的输出配置不符合ProRes RAW的解码要求。
常见失败原因
- 输出配置错误:你当前使用的
outputSettings没有指定输出原生拜耳CFA数据,AVFoundation会默认尝试将ProRes RAW解码为渲染后的彩色帧,而ProRes RAW解码器不支持通过普通AVAssetReader路径输出渲染后帧,直接触发解码错误。 - 资源未完成加载:直接同步调用
movieAsset.tracks时可能AVAsset还未完成元数据加载,读取到的轨道信息不完整,导致解码链路初始化失败。 - 运行环境不支持:ProRes RAW原生拜耳输出仅支持macOS 10.15及以上版本,且需要设备带有ProRes硬件解码能力(M系列芯片Mac、带硬件解码模块的Intel Mac),iOS/iPadOS暂不支持原生拜耳数据输出。
代码调整方案
首先修改outputSettings配置,仅指定输出拜耳像素格式,不要加其他转换类参数:
// 请根据你的ProRes RAW实际拜耳排列选择对应格式,可选值包括kCVPixelFormatType_14Bayer_RGGB、kCVPixelFormatType_14Bayer_BGGR等 let outputSettings = [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_14Bayer_RGGB ] as [String : Any]
然后调整AVAsset初始化逻辑,等待资源加载完成再初始化读取器:
class Decoder { private let assetReader: AVAssetReader? private let output: AVAssetReaderTrackOutput init(fileURL: URL) async throws { VTRegisterProfessionalVideoWorkflowVideoDecoders() // 配置asset,开启精确时序,等待轨道加载完成 let movieAsset = AVURLAsset(url: fileURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true]) let tracks = try await movieAsset.load(.tracks).filter { $0.mediaType == .video } guard let firstTrack = tracks.first else { print("No video tracks found") throw NSError(domain: "DecoderError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无可用视频轨道"]) } let out = AVAssetReaderTrackOutput(track: firstTrack, outputSettings: outputSettings) out.alwaysCopiesSampleData = false // 无需额外拷贝,降低内存开销 let assetReader = try AVAssetReader(asset: movieAsset) guard assetReader.canAdd(out) else { throw NSError(domain: "DecoderError", code: -2, userInfo: [NSLocalizedDescriptionKey: "不支持的输出配置"]) } assetReader.add(out) self.assetReader = assetReader self.output = out } func run(){ guard let assetReader = assetReader, assetReader.startReading() else { print("Failed to start asset reader: \(assetReader?.error ?? NSError())") return } while assetReader.status == .reading { guard let sampleBuffer = output.copyNextSampleBuffer() else { if let error = assetReader.error { print("Decode error: \(error)") } break } print("Decoding success!") // 此处处理拿到的原生拜耳SampleBuffer即可 CMSampleBufferInvalidate(sampleBuffer) } if assetReader.status == .completed { print("全部帧解码完成") } } }
额外说明
解码得到的SampleBuffer中附带了ProRes RAW的所有元数据(黑电平、白电平、色彩矩阵、拜耳排列等),可以通过CMGetAttachment接口从SampleBuffer中读取,无需硬编码参数。
内容的提问来源于stack exchange,提问作者JaSHin
相关产品推荐
相关产品推荐

