【问题标题】:Pixel formats, CVPixelBufferRefs and glReadPixels像素格式,CVPixelBufferRefs 和 glReadPixels
【发布时间】:2023-03-10 06:26:02
【问题描述】:

我正在使用glReadPixels 将数据读入CVPixelBufferRef。我使用CVPixelBufferRef 作为AVAssetWriter 的输入。不幸的是,像素格式似乎不匹配。

我认为glReadPixels 正在返回 RGBA 格式的像素数据,而 AVAssetWriter 想要 ARGB 格式的像素数据。将 RGBA 转换为 ARGB 的最佳方法是什么?

这是我迄今为止尝试过的:

  • 沿 argb = (rgba >> 8) | 行的位操作(rgba
  • 使用CGImageRef 作为中间步骤

位操作不起作用,因为 CVPixelBufferRef 似乎不支持下标。 CGImageRef 中间步骤确实有效...但我不希望有 50 行额外的代码可能会影响性能。

【问题讨论】:

  • 您是如何获得 CVPixelBufferRef 的?你是在调用 CVPixelBufferCreate 吗?如果是这样,您将传递什么作为 pixelFormatType 参数?你传递给 glReadPixels 的格式是什么?
  • 我将kCVPixelFormatType_32ARGB 传递给CVPixelBufferCreate。我将GL_RBGA 传递给glReadPixels。我尝试将 RBGA 格式传递给 CVPixelBufferCreate,但它不起作用(颜色不好或应用程序崩溃)。

标签: ios avassetwriter glreadpixels


【解决方案1】:

比使用 CPU 交换组件更好的是编写一个简单的片段着色器,以便在渲染图像时在 GPU 上高效地执行此操作。

最好的最好方法是使用 iOS5 CoreVideo CVOpenGLESTextureCache 完全删除复制阶段,它允许您直接渲染到 CVPixelBufferRef,从而消除对 glReadPixels 的调用。

附言我很确定 AVAssetWriter 想要 BGRA 格式的数据(实际上它可能想要 yuv 格式的数据,但那是另一回事了)。

更新:至于链接,doco 似乎仍在 NDA 下,但有两段可免费下载的示例代码:

GLCameraRippleRosyWriter

头文件本身包含很好的文档,与 mac 等效文件 (CVOpenGLTextureCache) 非常相似,所以你应该有很多东西可以帮助你开始。

【讨论】:

  • OpenGLTextureCache 听起来很棒。有相关文档的链接吗?
  • 如果你有 ADC 登录,你可以获得文档,添加一些示例代码来回答
  • 看起来真的很有趣!谢谢:-)
  • 他们就是这样,你再也不会以同样的方式看待 glReadPixels 和 glTexImage2D 了。一个警告,有点大:我很确定这些东西在 iPad2 上具有硬件支持(可能也在 4S 上),在较小的硬件上,时间表明它依赖于 glReadPixels/glTexImage2D。
  • “最好的最好方法是使用 iOS5 CoreVideo CVOpenGLESTextureCache 完全删除复制阶段,它允许您直接渲染到 CVPixelBufferRef,从而消除对 glReadPixels 的调用。” - 找不到任何关于这个非常需要的功能的文档
【解决方案2】:

关于位操作,您可以获得指向像素缓冲区原始数据的指针:

CVPixelBufferLockBaseAddress(buffer, 0);
size_t stride = CVPixelBufferGetBytesPerRow(buffer);
char *data = (char *)CVPixelBufferGetBaseAddress(buffer);
for (size_t y = 0; y < CVPixelBufferGetHeight(buffer); ++y) {
    uint32_t *pixels = (uint32_t *)(data + stride * y);
    for (size_t x = 0; x < CVPixelBufferGetWidth(buffer); ++x)
        pixels[x] = (pixels[x] >> 8) | (pixels[x] << 24);
}
CVPixelBufferUnlockBaseAddress(buffer, 0);

【讨论】:

    【解决方案3】:

    这有点像在黑暗中拍摄,但是您是否尝试过将GL_BGRA 用于glReadPixelskCVPixelFormatType_32BGRA 用于CVPixelBufferCreate

    我建议这样做是因为Technical Q&A QA1501 没有列出任何支持的 RGBA 格式。

    【讨论】:

    • 不幸的是,将 GL_BGRA 传递给 glReadPixels 会导致输出像素数据全为零:-(
    【解决方案4】:

    glReadPixels(0, 0, w*s, h*s, GL_BGRA, GL_UNSIGNED_BYTE, 缓冲区);

    在 glReadPixels 中使用 GL_BGRA。 好用,自己试了一下。

    【讨论】:

    • 输出缓冲区中是否有非零数据?
    【解决方案5】:
        glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, _buffer);
        CVPixelBufferRef buffer = NULL;
        CVReturn ret = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,_size.width,_size.height,kCVPixelFormatType_32BGRA,glubyte,_size.width*4,NULL,NULL,NULL,&buffer);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多