为什么AVFoundation不能在iOS设备上接受我的平面像素缓冲区?

我一直在努力弄清楚我的代码有什么问题。 我正在创build一个平面CVPixelBufferRef写入AVAssetWriter 。 这个像素缓冲区是通过一些其他的过程手动创build的(也就是说,我没有从相机或类似的东西那里得到这些样本)。 在iOS模拟器上,添加示例并创build有效的输出影片没有任何问题。

但是,在设备上,它立即在第一个样本失败,并提供less于无用的错误信息:

AVAssetWriterError: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x12fd2c670 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed}

我对像素格式很陌生,如果我以某种方式创build了无效的像素缓冲区,我不会感到惊讶,但在模拟器(即OS X)上工作得很好的事实让我感到困惑。

这是我的代码:

 const int pixelBufferWidth = img->get_width(); const int pixelBufferHeight = img->get_height(); size_t planeWidths[3]; size_t planeHeights[3]; size_t planeBytesPerRow[3]; void* planeBaseAddresses[3]; for (int c=0;c<3;c++) { int stride; const uint8_t* p = de265_get_image_plane(img, c, &stride); int width = de265_get_image_width(img,c); int height = de265_get_image_height(img, c); planeWidths[c] = width; planeHeights[c] = height; planeBytesPerRow[c] = stride; planeBaseAddresses[c] = const_cast<uint8_t*>(p); } void* descriptor = calloc(1, sizeof(CVPlanarPixelBufferInfo_YCbCrPlanar)); CVPixelBufferRef pixelBufferRef; CVReturn result = CVPixelBufferCreateWithPlanarBytes(NULL, pixelBufferWidth, pixelBufferHeight, kCVPixelFormatType_420YpCbCr8Planar, NULL, 0, 3, planeBaseAddresses, planeWidths, planeHeights, planeBytesPerRow, &pixelBufferReleaseCallback, NULL, NULL, &pixelBufferRef); CMFormatDescriptionRef formatDescription = NULL; CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBufferRef, &formatDescription); if (assetWriter == nil) { // ... create output file path in Caches directory assetWriter = [AVAssetWriter assetWriterWithURL:fileOutputURL fileType:AVFileTypeMPEG4 error:nil]; NSDictionary *videoSettings = @{AVVideoCodecKey : AVVideoCodecH264, AVVideoWidthKey : @(pixelBufferWidth), AVVideoHeightKey : @(pixelBufferHeight), AVVideoCompressionPropertiesKey : @{AVVideoMaxKeyFrameIntervalKey : @1}}; assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings sourceFormatHint:formatDescription]; [assetWriter addInput:assetWriterInput]; NSDictionary *pixelBufferAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8Planar), (id)kCVPixelBufferWidthKey : @(pixelBufferWidth), (id)kCVPixelBufferHeightKey : @(pixelBufferHeight)}; pixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:assetWriterInput sourcePixelBufferAttributes:pixelBufferAttributes]; [assetWriter startWriting]; [assetWriter startSessionAtSourceTime:kCMTimeZero]; } samplePresentationTime = CMTimeMake(frameIndex++, framesPerSecond); BOOL success = [pixelBufferAdaptor appendPixelBuffer:pixelBufferRef withPresentationTime:samplePresentationTime]; 

success永远是NO ,而资产编写者的错误就是我上面贴的。

我也尝试手动创build示例缓冲区,而不是使用AVAssetWriterInputPixelBufferAdaptor只是为了消除这个可能的问题,但结果是一样的。

再次,这在模拟器工作,所以我知道我的像素缓冲区确实包含正确的数据。

另外,我证实我可以写入文件目的地。 我试图在该位置创build一个虚拟文件,并成功。

我想避免将我的缓冲区转换为RGB,因为我不应该。 我有Y'CbCr缓冲区开始,我想只是将它们编码为支持Y'CbCr的H.264video。

正在创build这些缓冲区的源声明如下:

The image is currently always 3-channel YCbCr, with 4:2:0 chroma.

我确认它总是进入处理8位YUV通道的循环逻辑。

我究竟做错了什么?

所以,我不能正式确认这一点,但似乎AVAssetWriter不喜欢iOS上的3平面像素格式(即, kCVPixelFormatType_420YpCbCr8Planar )。 在OS X上,它似乎可以与任何东西一起工作。 当我将我的3平面缓冲区转换为双平面像素缓冲区格式时,这个工作在iOS上。 这并不令人惊讶,因为相机本身以kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange像素格式捕捉,因此AV Foundation可能也会使用该格式。

尽pipevImageConvert_PlanarToChunky8有助于将Cb和Cr平面交叉到一个平面,但如果我不需要自己完成这个明确的转换步骤,那将会很好。