我正在处理从网络收到的原始yuv420双翼飞机帧数据,需要创建CVPixelBuffer以便将其处理为Core Image以及使用AVAssetWriter写入磁盘。
当我尝试使用宽度(如120,240或480)创建一个代码如下的CVPixelBuffer时,它会分配内存并为两个平面创建一个正确的bytePerRow值的CVPixelBuffer(例如,宽度120产生的值为120 bytePerRow)。
但是,当我输入一个宽度为90,180或360的帧时,它会产生一个错误的bytePerRow,例如192字节的PerRow,帧宽为180.这会导致稍后在CoreImage或AVAssetWriter中绘制问题。
请参阅以下代码以创建CVPixelBuffer。
CGSize frameSize = CGSizeMake(180,240);
CVPixelBufferRef pixelBuffer = NULL;
NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey : (id)kCFBooleanTrue,
(id)kCVPixelBufferIOSurfaceCoreAnimationCompatibilityKey : (id)kCFBooleanTrue,
(id)kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey : (id)kCFBooleanTrue,
(id)kCVPixelBufferOpenGLESCompatibilityKey: (id)kCFBooleanTrue};
CVReturn result = CVPixelBufferCreate(NULL, frameSize.width, frameSize.height, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, (__bridge CFDictionaryRef _Nullable)(pixelAttributes), &pixelBuffer);
请注意,我不能使用CVPixelBufferCreateWithPlanarBytes,这会强制我自己分配内存,并在与Core Image一起使用时导致内存泄漏,这不是此问题的主题。
答案 0 :(得分:1)
我已经找到了这个错误的原因并同时收到Apple DTS的答案,这符合我的直觉。以下是答案:
根据核心视频工程,每行字节从180向上舍入的原因是由于所需的16字节对齐。 180/16 = 11.25; 192/16 = 12.0。
有很多方法可以强制每行精确的字节数,但这听起来不错。所需对齐的原因是图形卡具有硬件限制。听起来你想要使用CoreImage。使用未对齐的CVPixelBuffers将无法正常工作,或在某处强制使用额外的副本。
我们建议逐行填充缓冲区。像这样:
int srcRowbytes = 180; // Or whatever it is from wherever
int dstRowbytes = CVPixelBufferGetBytesPerRowOfPlane( dstBuffer, plane );
void * dstBytes = CVPixelBufferGetBaseAddressOfPlane( dstBuffer, plane );
for( int line = 0; line < height; line++ ) {
memcpy( dstBytes, srcBytes, srcRowbytes );
srcBytes += srcRowbytes;
dstBytes += dstRowbytes;
}