【问题标题】:Converting YUV420P to RGBA using OpenGL ES 2.0使用 OpenGL ES 2.0 将 YUV420P 转换为 RGBA
【发布时间】:2013-01-13 20:19:19
【问题描述】:

我正在使用 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 对隔行扫描问题进行了排序,但图片仍然损坏但是...我刚刚得知问题出在我的字节缓冲区中,因此将其标记为已回答。

【问题讨论】:

  • 如果您使用GL_LUMINANCE,红色和绿色通道都包含相同的值。如果您想遵循布拉德的回答,您应该以某种方式使 GL_RG 成为可能。我不完全确定 GL_LUMINANCE_ALPHA 做了什么,但它可能包含红色/绿色/蓝色(它们相同)和 alpha 的单独值。
  • 尝试了几种不同的组合,但除非它是 GL_LUMINANCE,否则无法使其工作。在上面的屏幕截图中,看起来上半部分具有原始视频帧下半部分的亮度级别。

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


【解决方案1】:

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

【讨论】:

  • 感谢您的回答。会试试这个。如何上传两件制服?我假设我将亮度缓冲区上传为 GL_LUMINANCE 但较小的色度缓冲区应该使用什么?还有 GL_LUMINANCE 我带吗?
  • 我用现在的样子更新了我的问题。出了点问题。
  • @BlueVoodoo - GL_LUMINANCE 应该适用于亮度平面(A5 iOS 设备有一个很好的 GL_RED_EXT 单分量格式,非常适合这种情况)。但是,对于色度纹理,您将需要多个组件,因为其中有交错的 UV 组件。 GL_LUMINANCE_ALPHA 可能是这里的方法(同样,A5 iOS 设备有 GL_RG_EXT 作为一个很好的类型)。有关更多信息,请参见此处的示例(iOS,但仍然主要适用):stackoverflow.com/a/6510542/19679
  • 为什么要选择苹果 1 和 2 组件扩展而不是标准版本?
  • @brad 你确定吗? luma/luma_alpha 与 A4/A5 上的纹理缓存一起工作正常,并且不会在内部转换为 RGBA。我观察到的苹果扩展之间的唯一区别是纹素布局......我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多