[英]YUV to RGB conversion and display using opengl es 2.0 from android ndk using shaders
[英]Android opengl es YUV to RGB conversion using shaders
我正在研究Android设备的视频播放器,其中我使用ffmpeg进行解码,并使用opengl进行渲染。 我被困在一个地方,我正在使用opengl es着色器进行YUV到RGB的转换。 应用程序能够显示图像但不显示正确的颜色。 从YUV到RGB后,图像仅显示绿色和粉红色。 我在谷歌搜索过,但没有找到解决方案。 任何人都可以帮我解决这个话题吗?
我从ffmpeg得到三个不同的缓冲区(y,u,v),然后我将这些缓冲区传递给3个纹理。
这是我正在使用的着色器。
static const char kVertexShader[] =
"attribute vec4 vPosition; \n"
"attribute vec2 vTexCoord; \n"
"varying vec2 v_vTexCoord; \n"
"void main() { \n"
"gl_Position = vPosition; \n"
"v_vTexCoord = vTexCoord; \n"
"} \n";
static const char kFragmentShader[] =
"precision mediump float; \n"
"varying vec2 v_vTexCoord; \n"
"uniform sampler2D yTexture; \n"
"uniform sampler2D uTexture; \n"
"uniform sampler2D vTexture; \n"
"void main() { \n"
"float y=texture2D(yTexture, v_vTexCoord).r;\n"
"float u=texture2D(uTexture, v_vTexCoord).r - 0.5;\n"
"float v=texture2D(vTexture, v_vTexCoord).r - 0.5;\n"
"float r=y + 1.13983 * v;\n"
"float g=y - 0.39465 * u - 0.58060 * v;\n"
"float b=y + 2.03211 * u;\n"
"gl_FragColor = vec4(r, g, b, 1.0);\n"
"}\n";
static const GLfloat kVertexInformation[] =
{
-1.0f, 1.0f, // TexCoord 0 top left
-1.0f,-1.0f, // TexCoord 1 bottom left
1.0f,-1.0f, // TexCoord 2 bottom right
1.0f, 1.0f // TexCoord 3 top right
};
static const GLshort kTextureCoordinateInformation[] =
{
0, 0, // TexCoord 0 top left
0, 1, // TexCoord 1 bottom left
1, 1, // TexCoord 2 bottom right
1, 0 // TexCoord 3 top right
};
static const GLuint kStride = 0;//COORDS_PER_VERTEX * 4;
static const GLshort kIndicesInformation[] =
{
0, 1, 2,
0, 2, 3
};
这是另一个提出相同问题的人: 使用GL着色器语言对相框进行rgb转换
谢谢。
更新 :
ClayMontgomery的着色器。
const char* VERTEX_SHADER = "\
attribute vec4 a_position;\
attribute vec2 a_texCoord;\
varying vec2 gsvTexCoord;\
varying vec2 gsvTexCoordLuma;\
varying vec2 gsvTexCoordChroma;\
\
void main()\
{\
gl_Position = a_position;\
gsvTexCoord = a_texCoord;\
gsvTexCoordLuma.s = a_texCoord.s / 2.0;\
gsvTexCoordLuma.t = a_texCoord.t / 2.0;\
gsvTexCoordChroma.s = a_texCoord.s / 4.0;\
gsvTexCoordChroma.t = a_texCoord.t / 4.0;\
}";
const char* YUV_FRAGMENT_SHADER = "\
precision highp float;\
uniform sampler2D y_texture;\
uniform sampler2D u_texture;\
uniform sampler2D v_texture;\
varying vec2 gsvTexCoord;\
varying vec2 gsvTexCoordLuma;\
varying vec2 gsvTexCoordChroma;\
\
void main()\
{\
float y = texture2D(y_texture, gsvTexCoordLuma).r;\
float u = texture2D(u_texture, gsvTexCoordChroma).r;\
float v = texture2D(v_texture, gsvTexCoordChroma).r;\
u = u - 0.5;\
v = v - 0.5;\
vec3 rgb;\
rgb.r = y + (1.403 * v);\
rgb.g = y - (0.344 * u) - (0.714 * v);\
rgb.b = y + (1.770 * u);\
gl_FragColor = vec4(rgb, 1.0);\
}";
这是输出:
粉红色和绿色表示在CSC矩阵计算和某些常量看起来错误之前,您的输入亮度和色度值未正确归一化。 此外,您可能应该缩放色度的纹理坐标,因为它通常相对于亮度进行子采样。 这里有一个很好的指南:
http://fourcc.org/fccyvrgb.php
这是我在飞思卡尔i.MX53上编码和测试的GLSL实现。 我建议你试试这个代码。
const char* pVertexShaderSource = "\
uniform mat4 gsuMatModelView;\
uniform mat4 gsuMatProj;\
attribute vec4 gsaVertex;\
attribute vec2 gsaTexCoord;\
varying vec2 gsvTexCoord;\
varying vec2 gsvTexCoordLuma;\
varying vec2 gsvTexCoordChroma;\
\
void main()\
{\
vec4 vPosition = gsuMatModelView * gsaVertex;\
gl_Position = gsuMatProj * vPosition;\
gsvTexCoord = gsaTexCoord;\
gsvTexCoordLuma.s = gsaTexCoord.s / 2.0;\
gsvTexCoordLuma.t = gsaTexCoord.t / 2.0;\
gsvTexCoordChroma.s = gsaTexCoord.s / 4.0;\
gsvTexCoordChroma.t = gsaTexCoord.t / 4.0;\
}";
const char* pFragmentShaderSource = "\
precision highp float;\
uniform sampler2D gsuTexture0;\
uniform sampler2D gsuTexture1;\
uniform sampler2D gsuTexture2;\
varying vec2 gsvTexCoordLuma;\
varying vec2 gsvTexCoordChroma;\
\
void main()\
{\
float y = texture2D(gsuTexture0, gsvTexCoordLuma).r;\
float u = texture2D(gsuTexture1, gsvTexCoordChroma).r;\
float v = texture2D(gsuTexture2, gsvTexCoordChroma).r;\
u = u - 0.5;\
v = v - 0.5;\
vec3 rgb;\
rgb.r = y + (1.403 * v);\
rgb.g = y - (0.344 * u) - (0.714 * v);\
rgb.b = y + (1.770 * u);\
gl_FragColor = vec4(rgb, 1.0);\
}";
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.