【问题标题】:CVPixelBufferGetBaseAddress returns null VTDecompressionSessionDecodeFrame callbackCVPixelBufferGetBaseAddress 返回空 VTDecompressionSessionDecodeFrame 回调
【发布时间】:2016-06-17 17:59:53
【问题描述】:

我正在使用 VTDecompressionSession 通过网络解码 H.264 流。我需要从给定的图像缓冲区复制 YUV 缓冲区。我已经验证给定的 imageBuffer 的 typeID 等于CVPixelBufferGetTypeID()

但每当我尝试检索缓冲区或任何平面的基地址时,它们总是返回 NULL。 iOS 传递的 OSStatus 为 0,所以我的假设是这里没有任何问题。也许我不知道如何提取数据。有人可以帮忙吗?

void decompressionCallback(void * CM_NULLABLE decompressionOutputRefCon,
                           void * CM_NULLABLE sourceFrameRefCon,
                           OSStatus status,
                           VTDecodeInfoFlags infoFlags,
                           CM_NULLABLE CVImageBufferRef imageBuffer,
                           CMTime presentationTimeStamp, 
                           CMTime presentationDuration )
{
    CFShow(imageBuffer);
    size_t dataSize = CVPixelBufferGetDataSize(imageBuffer);
    void * decodedBuffer = CVPixelBufferGetBaseAddress(imageBuffer);
    memcpy(pYUVBuffer, decodedBuffer, dataSize);
}

编辑:这里也是 CVImageBufferRef 对象的转储。看起来可疑的一件事是我希望有 3 个平面(Y、U 和 V)。但是只有两架飞机。我的期望是使用CVPixelBufferGetBaseAddressOfPlane 来提取每个数据平面。我正在实现它以消除对单独软件编解码器的依赖,因此我需要以这种方式提取每个平面,因为我的渲染管道的其余部分需要它。

{类型 = 不可变 dict, count = 5, entries => 0 : {contents = "PixelFormatDescription"} = {type = immutable dict, count = 10, entries => 0 : {contents = "Planes"} = {type = mutable-small, count = 2, 值 = ( 0 : {类型 = 可变 dict, count = 3, entries => 0 : {contents = "FillExtendedPixelsCallback"} = {length = 24, capacity = 24, bytes = 0x0000000000000000030139783010000000000000000000000} 1:{内容=“BitsPerBlock”}={值=+8,类型= kCFNumberSInt32Type} 2 : {contents = "BlackBlock"} = {length = 1, capacity = 1, bytes = 0x10} }

1 : {type = 可变字典, 计数 = 5,条目 => 2:{contents = "Horizo​​ntalSubsampling"} = {value = +2,type = kCFNumberSInt32Type} 3 : {contents = "BlackBlock"} = {length = 2, capacity = 2, bytes = 0x8080} 4 : {内容 = “BitsPerBlock”} = {值 = +16,类型 = kCFNumberSInt32Type} 5 : {contents = "VerticalSubsampling"} = {value = +2, type = kCFNumberSInt32Type} 6 : {contents = "FillExtendedPixelsCallback"} = {length = 24, capacity = 24, bytes = 0x0000000000000000ac119783010000000000000000000000} }

)} 2 : {内容 = "IOSurfaceOpenGLESFBOCompatibility"} = {value = true} 3: {contents = "ContainsYCbCr"} = {value = true} 4: {contents = "IOSurfaceOpenGLESTextureCompatibility"} = {value = true} 5:{contents = "ComponentRange"} = {contents = "VideoRange"} 6:{contents = "PixelFormat"} = {value = +875704438,类型 = kCFNumberSInt32Type} 7 : {contents = "IOSurfaceCoreAnimationCompatibility"} = {value = true} 9:{contents = "ContainsAlpha"} = {value = false} 10:{contents = "ContainsRGB"} = {value = false} 11:{contents = "OpenGLESCompatibility"} = {value = true} }

2 : {内容 = “ExtendedPixelsRight”} = {value = +8,type = kCFNumberSInt32Type} 3:{contents = “ExtendedPixelsTop”} = {value = +0,type = kCFNumberSInt32Type} 4 : {contents = "ExtendedPixelsLeft"} = {value = +0, type = kCFNumberSInt32Type} 5 : {contents = "ExtendedPixelsBottom"} = {value = +0, type = kCFNumberSInt32Type} } 传播附件 = {类型 = 可变字典,计数 = 7,条目 => 0 : {内容= “CVImageBufferChromaLocationTopField”} = 左 1:{contents = “CVImageBufferYCbCrMatrix”} = {内容 = “ITU_R_601_4”} 2: {contents = "ColorInfoGuessedBy"} = {contents = "VideoToolbox"} 5 : {contents = “CVImageBufferColorPrimaries”} = SMPTE_C 8:{contents = “CVImageBufferTransferFunction”} = {contents = “ITU_R_709_2”} 10:{contents = "CVImageBufferChromaLocationBottomField"} = 左 12 : {contents = "CVFieldCount"} = {value = +1, type = kCFNumberSInt32Type} } nonPropagatedAttachments={type = mutable dict, count = 0, entries => }

【问题讨论】:

    标签: ios api codec


    【解决方案1】:

    所以你的格式是kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v',两个平面对 4:2:0 YUV 数据有意义,因为第一个平面是全尺寸 Y 单通道位图,第二个是半宽半高 UV 双通道位图.

    你是对的,对于平面数据你应该调用CVPixelBufferGetBaseAddressOfPlane,虽然你应该能够使用CVPixelBufferGetBaseAddress,将其结果解释为CVPlanarPixelBufferInfo_YCbCrBiPlanar,所以问题可能是你没有调用@987654325 @ 之前是 CVPixelBufferGetBaseAddress* 也不是 CVPixelBufferUnlockBaseAddress 之后。

    通过编写一些有趣的 YUV->RGB 着色器代码,您可以使用 Metal 或 OpenGL 有效地显示 2 个 YUV 平面。

    【讨论】:

    • 我确实希望根据我的应用程序的当前实现提取 3 个平面。但是我注意到我可以在目标缓冲区信息中设置 kCVPixelBufferPixelFormatTypeKey : kCVPixelFormatType_420YpCbCr8Planar ,这会导致 CVPixelBuffer 有 3 个平面。我没有明确调用 CVPixelBufferLockBaseAddress,你是对的。有必要这样做吗?
    • 明白了。不敢相信我在文档中错过了这一点。非常感谢。
    • 不客气!我会使用 GetBaseAddress 的平面版本来获取数据,它会为您处理一些烦恼。
    • 我的问题不同。基本上我没有在 CVPixelBufferBaseAddress(pixelBuf) 之前执行 CVPixelBufferLockBaseAddress(pixelBuf),所以它总是返回 。如果你先锁定基地址,它会从 CVPixelBufferBaseAddress(pixelBuf) 返回一个基地址。
    • 你的问题听起来完全一样:“每当我尝试检索缓冲区或任何平面的基地址时,它们总是返回 NULL”
    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 2016-07-26
    • 2020-04-24
    • 2011-02-18
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多