简体   繁体   English

Android使用着色器将YUV转换为RGB转换

[英]Android opengl es YUV to RGB conversion using shaders

I am working on a video player for android device, in which I am using ffmpeg for decoding and opengl es for rendering. 我正在研究Android设备的视频播放器,其中我使用ffmpeg进行解码,并使用opengl进行渲染。 I am stuck at one point where I am using opengl es shaders for YUV to RGB conversion. 我被困在一个地方,我正在使用opengl es着色器进行YUV到RGB的转换。 Application is able to display image but its not displaying correct colors. 应用程序能够显示图像但不显示正确的颜色。 After conervting from YUV to RGB, image only displays green and pink colors. 从YUV到RGB后,图像仅显示绿色和粉红色。 I did searched on google, but no solution found. 我在谷歌搜索过,但没有找到解决方案。 Can any one please help me on this topic? 任何人都可以帮我解决这个话题吗?

I am getting three different buffers (y, u, v) from ffmpeg and then I am passing these buffers to 3 textures as it is. 我从ffmpeg得到三个不同的缓冲区(y,u,v),然后我将这些缓冲区传递给3个纹理。

Here are shaders I am using. 这是我正在使用的着色器。

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
    };

Here is another person who had asked same question: Camera frame yuv to rgb conversion using GL shader language 这是另一个提出相同问题的人: 使用GL着色器语言对相框进行rgb转换

Thank You. 谢谢。

UPDATE : 更新

ClayMontgomery's shaders. 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);\
}";

Here is output: 这是输出:

在此输入图像描述

The pink and green colors indicate that your input luma and chroma values are not being normalized correctly before the CSC matrix calculations and some of your constants look wrong. 粉红色和绿色表示在CSC矩阵计算和某些常量看起来错误之前,您的输入亮度和色度值未正确归一化。 Also, you should probably be scaling your texture coordinates for the chroma because it's typically sub-sampled with respect to the luma. 此外,您可能应该缩放色度的纹理坐标,因为它通常相对于亮度进行子采样。 There is a good guide to this here: 这里有一个很好的指南:

http://fourcc.org/fccyvrgb.php http://fourcc.org/fccyvrgb.php

Here is an implementation in GLSL that I coded and tested on the Freescale i.MX53. 这是我在飞思卡尔i.MX53上编码和测试的GLSL实现。 I recommend you try this code. 我建议你试试这个代码。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM