1

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

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

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

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

UPDATE3:好的,这里有什么不妥。

在此处输入图像描述

我将它用于纹理。这个对吗?

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

UPDATE4:使用GL_LUMINANCE_ALPHA对隔行扫描问题进行排序,但图片仍然损坏但是...我刚刚了解到问题出在我的字节缓冲区中,因此将其标记为已回答。

4

1 回答 1

2

Apple has a couple of examples for iOS where they convert from YUV420 planar data to RGBA in an OpenGL ES 2.0 shader. While not specifically for Android, you should still be able to use this GLSL shader code to accomplish what you want.

This is what I use in a conversion fragment shader based on their example:

 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 is the Y plane of your image as a texture, and chrominanceTexture is the UV plane.

I believe the above is tuned for video range YUV, so you may need to adjust these values for full range YUV. This shader runs in a fraction of a millisecond for 1080p video frames on an iPhone 4S.

于 2013-01-12T22:01:36.247 回答