【问题标题】:Byte per row is wrong when creating a CVPixelBuffer with width multiple of 90创建宽度倍数为 90 的 CVPixelBuffer 时每行字节错误
【发布时间】:2023-04-02 08:48:01
【问题描述】:

我正在处理从网络接收的原始 yuv420 双平面帧数据,需要创建 CVPixelBuffer 以便将其处理成 Core Image 以及使用 AVAssetWriter 写入磁盘。

当我尝试使用下面的代码创建一个宽度为 120、240 或 480 的 CVPixelBuffer 时,它会分配内存并为两个平面创建一个具有正确 bytePerRow 值的正确 CVPixelBuffer(例如,宽度 120 会产生 120 bytePerRow 的值)。

但是,当我输入宽度为 90、180 或 360 的帧时,它会产生错误的 bytePerRow,例如 180 帧宽度的 192 bytePerRow。这会导致稍后在 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 一起使用时导致内存泄漏。

【问题讨论】:

    标签: ios objective-c avfoundation core-image cvpixelbuffer


    【解决方案1】:

    我已经找到了这个错误的原因,同时从 Apple DTS 收到了一个符合我直觉的答案。以下是答案:

    根据 Core Video 工程,每行字节数从 180 向上舍入到 196 的原因是需要 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;
    }
    

    【讨论】:

    • 我看到了与此类似的情况,其中前置摄像头的 CVPixelBuffer 的宽度为 1440,但每行的字节数为 1472。后者可被 64 整除;我想知道对齐要求是否增加了,或者这是否是其他原因。
    猜你喜欢
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    相关资源
    最近更新 更多