android - 使用 OpenGL ES 2.0 将 YUV420P 转换为 RGBA

标签 android opengl-es opengl-es-2.0 yuv

我正致力于在 Android 上使用 OpenGL ES 2.0 处理视频。图片数据被提取为 YUV420P,我需要在我的 OpenGL fragment 着色器中以某种方式在 RGBA 中处理它们。

如何将 YUV420P 数据转换为 RGBA? (鉴于它是视频,性能是关键)

更新:感谢 Brad Larsson 的回答,但它看起来不正确。

更新 2:呃,我还在使用我的 RGBA fragment 着色器。当然看起来不对。现在我有另一个问题。让我进一步挖掘。

更新 3:好的,这里有些事情不对劲。

enter image description here

我将其用于纹理。这是正确的吗?

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, luminanceBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, chrominanceBuffer);

更新 4:使用 GL_LUMINANCE_ALPHA 解决了隔行扫描问题,但图片仍然损坏但是...我刚刚得知问题出在我的字节缓冲区中,因此将此标记为已回答。

最佳答案

Apple 有几个适用于 iOS 的示例,它们在 OpenGL ES 2.0 着色器中将 YUV420 平面数据转换为 RGBA。虽然不是专门针对 Android 的,但您仍然应该能够使用此 GLSL 着色器代码来完成您想要的。

这是我根据他们的示例在转换 fragment 着色器中使用的:

 varying highp vec2 textureCoordinate;

 uniform sampler2D luminanceTexture;
 uniform sampler2D chrominanceTexture;

 void main()
 {
     mediump vec3 yuv;
     lowp vec3 rgb;

     yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
     yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);

     // BT.601, which is the standard for SDTV is provided as a reference
     /*
      rgb = mat3(      1,       1,       1,
      0, -.39465, 2.03211,
      1.13983, -.58060,       0) * yuv;
      */

     // Using BT.709 which is the standard for HDTV
     rgb = mat3(      1,       1,       1,
                0, -.21482, 2.12798,
                1.28033, -.38059,       0) * yuv;

     gl_FragColor = vec4(rgb, 1);
 }

luminanceTexture 是作为纹理的图像的 Y 平面,chrominanceTexture 是 UV 平面。

我相信以上是针对视频范围 YUV 进行调整的,因此您可能需要针对全范围 YUV 调整这些值。对于 iPhone 4S 上的 1080p 视频帧,此着色器的运行时间不到一毫秒。

关于android - 使用 OpenGL ES 2.0 将 YUV420P 转换为 RGBA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14298028/

相关文章:

android - backstack 中的 fragment 可以被杀死吗?

android - 在 PC 的 Firefox 上模拟 Android 的 Webview?

cocoa-touch - iPhone SDK 有没有像样的 OpenGL 文本绘图库?

iphone - glDrawElements VAO/VBO 在 iOS 上崩溃

java - 调用具有来自另一个 Activity 的值的 "void"方法

java - 即使指定了 subscribeOn,代码也在主线程上运行

android - 着色器代码中的 for 循环使用硬编码数字但不使用统一变量

ios - MTKView清晰显示

android - glDrawElements 不绘制任何东西

opengl-es - android OpenGLES 1.x CameraPreview 到 Surfacetexture