像素格式、CVPixelBufferRefs 和 glReadPixels

发布于 2024-12-12 04:43:33 字数 576 浏览 0 评论 0原文

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

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

这是我到目前为止所尝试过的:

  • 按照 argb = (rgba >> 8) | 行进行位操作(rgba << 24)
  • 使用 CGImageRef 作为中间步骤

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

I'm using glReadPixels to read data into a CVPixelBufferRef. I use the CVPixelBufferRef as the input into an AVAssetWriter. Unfortunately the pixel formats seem to be mismatched.

I think glReadPixels is returning pixel data in RGBA format while AVAssetWriter wants pixel data in ARGB format. What's the best way to convert RGBA to ARGB?

Here's what I've tried so far:

  • bit manipulation along the lines of argb = (rgba >> 8) | (rgba << 24)
  • using a CGImageRef as an intermediate step

The bit manipulation didn't work because CVPixelBufferRef doesn't seem to support subscripts. The CGImageRef intermediate step does work... but I'd prefer not to have 50 extra lines of code that could potentially be a performance hit.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

话少心凉 2024-12-19 04:43:34

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

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

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

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

GLCameraRippleRosyWriter

头文件本身包含很好的文档,并且 mac等效项非常相似(CVOpenGLTextureCache),因此您应该有足够的知识来帮助您入门。

Better than using the CPU to swap the components would be to write a simple fragment shader to efficiently do it on the GPU as you render the image.

And the best bestest way is to completely remove the copying stage by using an iOS5 CoreVideo CVOpenGLESTextureCache which allows you to render straight to the CVPixelBufferRef, eliminating the call to glReadPixels.

p.s. I'm pretty sure AVAssetWriter wants data in BGRA format (actually it probably wants it in yuv, but that's another story).

UPDATE: as for links, the doco seems to still be under NDA, but there are two pieces of freely downloadable example code available:

GLCameraRipple and RosyWriter

The header files themselves contain good documentation, and the mac equivalent is very similar (CVOpenGLTextureCache), so you should have plenty to get you started.

彩虹直至黑白 2024-12-19 04:43:34

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

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);

Regarding the bit manipulation, you can get a pointer to the pixel buffer's raw data:

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);
深海里的那抹蓝 2024-12-19 04:43:34

这有点盲目,但您是否尝试过将 GL_BGRA 用于 glReadPixels 并使用 kCVPixelFormatType_32BGRA 用于 CVPixelBufferCreate

我建议这样做是因为 技术问答 QA1501 没有列出支持的所有 RGBA 格式。

It's kind of a shot in the dark, but have you tried GL_BGRA for glReadPixels with kCVPixelFormatType_32BGRA for CVPixelBufferCreate?

I suggest this because Technical Q&A QA1501 doesn't list any RGBA format as supported.

知足的幸福 2024-12-19 04:43:34

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

在 glReadPixels 中使用 GL_BGRA。
确实有效,刚刚亲自尝试过。

glReadPixels(0, 0, w*s, h*s, GL_BGRA, GL_UNSIGNED_BYTE, buffer);

Use GL_BGRA in glReadPixels.
It works, just tried it myself.

千纸鹤 2024-12-19 04:43:34
    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);
    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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文