【问题标题】:Android opengl es YUV to RGB conversion using shadersAndroid opengl es YUV到RGB转换使用着色器
【发布时间】:2014-02-25 04:26:17
【问题描述】:

我正在为 android 设备开发视频播放器,其中我使用 ffmpeg 进行解码并使用 opengl es 进行渲染。我被困在使用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
    };

这是另一个问同样问题的人:Camera frame yuv to rgb conversion using GL shader language

谢谢。

更新

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);\
}";

这是输出:

【问题讨论】:

    标签: android c++ opengl-es ffmpeg


    【解决方案1】:

    粉红色和绿色表示您的输入亮度和色度值在 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);\
        }";
    

    【讨论】:

    • 首先非常感谢您的回复。我很感激你的帮助。我会试试你的建议。如果可行,我将接受它作为最终解决方案。
    • 您好,我尝试了您的解决方案,但仍然无法正常工作。我确实使用了您的着色器,只从顶点着色器中删除了矩阵;因为我没有使用 MVPmatrix。它仍然在图片中显示绿色和粉红色。
    • 使用 ClayMontgomery 建议的着色器和屏幕截图更新问题。
    猜你喜欢
    • 2016-04-18
    • 2014-02-26
    • 2013-06-10
    • 2019-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多