使用OpenGL ES 2.0将YUV420P转换为RGBA

时间:2013-01-12 21:15:54

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

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

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

更新:进一步感谢Brad Larsson的回答,但看起来并不正确。

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

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

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

1 个答案:

答案 0 :(得分:2)

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

这是我在转换片段着色器中使用的基于它们的示例:

 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视频帧,该着色器在几分之一毫秒内运行。