opengl es yuv转换为rgb仅显示绿色和粉红色

时间:2014-02-02 17:29:27

标签: android ios opengl-es ffmpeg yuv

我正在使用opengl着色器进行rgb转换。但它只显示绿色和粉红色的颜色。我正在使用ffmpeg来解码电影。我是初学者,所以不知道如何解决它。 ffmpeg给我三个yuv的缓冲区。我直接将这些缓冲区分配给三个纹理。

以下是我正在使用的着色器。

static const char* VERTEX_SHADER =
"attribute vec4 vPosition;                      \n"
"attribute vec2 a_texCoord;                     \n"
"varying vec2 tc;                               \n"
"uniform mat4 u_mvpMat;                         \n"
"void main()                                    \n"
"{                                              \n"
"   gl_Position = u_mvpMat * vPosition;         \n"
"   tc = a_texCoord;                            \n"
"}                                              \n";

static const char* YUV_FRAG_SHADER =
"#ifdef GL_ES                                   \n"
"precision highp float;                         \n"
"#endif                                         \n"
"varying vec2 tc;                               \n"
"uniform sampler2D TextureY;                    \n"
"uniform sampler2D TextureU;                    \n"
"uniform sampler2D TextureV;                    \n"
"uniform float imageWidth;                      \n"
"uniform float imageHeight;                     \n"

"void main(void)                                \n"
"{                                              \n"
    "float nx, ny;                              \n"
    "vec3 yuv;                                  \n"
    "vec3 rgb;                                  \n"
    "nx = tc.x;                                 \n"
    "ny = tc.y;                                 \n"

    "yuv.x = texture2D(TextureY, tc).r;         \n"
    "yuv.y = texture2D(TextureU, vec2(nx/2.0, ny/2.0)).r - 0.5;   \n"
    "yuv.z = texture2D(TextureV, vec2(nx/2.0, ny/2.0)).r - 0.5;   \n"

    // Using BT.709 which is the standard for HDTV
    "rgb = mat3( 1,              1,      1,     \n"
                "0,       -0.18732, 1.8556,     \n"
                "1.57481, -0.46813,      0)*yuv;\n"

    // BT.601, which is the standard for SDTV is provided as a reference
    //"rgb = mat3( 1,            1,     1,        \n"
    //            "0,     -0.34413, 1.772,        \n"
    //            "1.402, -0.71414,     0) * yuv; \n"
    "gl_FragColor = vec4(rgb, 1.0);             \n"
"}                                              \n";

输出:

enter image description here

我做错了什么?这个你能帮我吗。

谢谢。

更新

在调试ffmpeg解码时,我发现ffmpeg解码器给出了PIX_FMT_YUV420P输出格式。我是否需要进行一些调整以获得正确的图像颜色?

1 个答案:

答案 0 :(得分:2)

我不确定这种转变:

"rgb = mat3( 1,              1,      1,     \n"
            "0,       -0.18732, 1.8556,     \n"
            "1.57481, -0.46813,      0)*yuv;\n"

在GLSL using this page as reference中的矩阵*向量运算中刷新我的记忆时,我认为您需要转置系数矩阵,或者将yuv移动到操作的前面,即yuv * mat3(...)。以mat3(...) * yuv执行操作意味着:

r = y * 1 + u * 1 + v * 1
g = y * 0 + u * -0.18732 + v * 1.8556
b = y * 1.57481 + u * -0.46813 + v * 0

这些转换非常不正确。

作为另一个参考,这是一个小的,完整的样本GLSL着色器程序,它转换YUV - > RGB可能有一定的指导意义:http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c