AVAssetWriter 获取原始字节会使设备上的视频损坏(在 sim 上工作)

AVAssetWriter getting raw bytes makes corrupt videos on device (works on sim)

所以我的目标是用超高速CVPixelBuffers添加到我的AVAssetWriter/AVAssetWriterInputPixelBufferAdaptor中。我以前的解决方案使用 CGContextDrawImage 但绘制速度非常慢 (0.1s)。原因似乎与颜色匹配和转换有关,但我认为这是另一个问题。

我目前的解决方案是尝试直接读取图像的字节以跳过绘图调用。我这样做:

CGImageRef cgImageRef = [image CGImage];
CGImageRetain(cgImageRef);
CVPixelBufferRef pixelBuffer = NULL;
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImageRef);
CGDataProviderRetain(dataProvider);
CFDataRef da = CGDataProviderCopyData(dataProvider);
CVPixelBufferCreateWithBytes(NULL,
                             CGImageGetWidth(cgImageRef),
                             CGImageGetHeight(cgImageRef),
                             kCVPixelFormatType_32BGRA,
                             (void*)CFDataGetBytePtr(da),
                             CGImageGetBytesPerRow(cgImageRef),
                             NULL,
                             0,
                             NULL,
                             &pixelBuffer);
[writerAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentTime];    
-- releases here --

这在我的模拟器和应用程序中很好。但是当我 运行 SpringBoard 进程中的代码时,它如下图所示。 运行 它在沙箱之外是必需的,它适用于越狱设备。

我试过玩弄例如像素格式样式,但它大多会出现不同的损坏图像。

正确的 image/video 文件看起来不错: 但这是我在破碎状态下得到的:

回答我自己的问题,因为我认为我得到了答案。分辨率差异是一个简单的代码错误,没有在后者上使用设备边界。

颜色问题。简而言之,我在沙箱外 运行 时获得的 CGImages 每个像素使用更多字节,8 个字节。我在沙箱内 运行 时得到的图像是 4 个字节。所以基本上我只是将错误的数据写入缓冲区。

因此,不是简单地将较大图像中的所有字节放入较小的缓冲区。我逐行、逐字节循环遍历像素缓冲区,然后为每个像素选择 RGBA 值。我基本上必须跳过源图像中的每隔一个字节才能将正确的数据放入缓冲区中的正确位置。