在YUV420p上有很多绿色 - > iOS上的OpenGL 2.0着色器中的RGB [英] a lot of GREEN Color at YUV420p --> RGB in OpenGL 2.0 Shader on iOS

查看:221
本文介绍了在YUV420p上有很多绿色 - > iOS上的OpenGL 2.0着色器中的RGB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用ffmpeg和OpenGL ES 2.0
为iOS制作电影播放器​​,但我有一些问题。输出RGB图像有很多绿色。
这是代码和图片

I want to make a movie player for iOS using ffmpeg and OpenGL ES 2.0 but I have some problem. Output RGB image has a lot of GREEN color. This is code and images


  • 480x320 width&高度:

  • 512x512纹理宽度&高度

我从ffmpeg AVFrame获得了一个YUV420p行数据。

I got a YUV420p row data from ffmpeg AVFrame.

    for (int i = 0, nDataLen = 0; i < 3; i++) {
        int nShift = (i == 0) ? 0 : 1;
        uint8_t *pYUVData = (uint8_t *)_frame->data[i];
        for (int j = 0; j < (mHeight >> nShift); j++) {
            memcpy(&pData->pOutBuffer[nDataLen], pYUVData, (mWidth >> nShift));
            pYUVData += _frame->linesize[i];
            nDataLen += (mWidth >> nShift);
        }
    }

并准备Y,U&的纹理V频道。

and prepare texture for Y, U & V channel.

//: U Texture
    if (sampler1Texture) glDeleteTextures(1, &sampler1Texture);

    glActiveTexture(GL_TEXTURE1);
    glGenTextures(1, &sampler1Texture);
    glBindTexture(GL_TEXTURE_2D, sampler1Texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // This is necessary for non-power-of-two textures
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glEnable(GL_TEXTURE_2D);

    glTexImage2D(GL_TEXTURE_2D, 
                 0, 
                 GL_LUMINANCE, 
                 texW / 2, 
                 texH / 2, 
                 0, 
                 GL_LUMINANCE, 
                 GL_UNSIGNED_BYTE,
                 NULL);

    //: V Texture
    if (sampler2Texture) glDeleteTextures(1, &sampler2Texture);

    glActiveTexture(GL_TEXTURE2);
    glGenTextures(1, &sampler2Texture);
    glBindTexture(GL_TEXTURE_2D, sampler2Texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // This is necessary for non-power-of-two textures
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glEnable(GL_TEXTURE_2D);

    glTexImage2D(GL_TEXTURE_2D, 
                 0, 
                 GL_LUMINANCE, 
                 texW / 2, 
                 texH / 2, 
                 0, 
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE,
                 NULL);

    //: Y Texture
    if (sampler0Texture) glDeleteTextures(1, &sampler0Texture);

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &sampler0Texture);
    glBindTexture(GL_TEXTURE_2D, sampler0Texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // This is necessary for non-power-of-two textures
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glEnable(GL_TEXTURE_2D);

    glTexImage2D(GL_TEXTURE_2D, 
                 0, 
                 GL_LUMINANCE, 
                 texW, 
                 texH, 
                 0, 
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE, 
                 NULL);

渲染部分如下。

int _idxU = mFrameW * mFrameH;
int _idxV = _idxU + (_idxU / 4);

// U data
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, sampler1Texture);
glUniform1i(sampler1Uniform, 1);

glTexSubImage2D(
                GL_TEXTURE_2D, 
                0, 
                0, 
                0, 
                mFrameW / 2,            // source width
                mFrameH / 2,            // source height
                GL_LUMINANCE,
                GL_UNSIGNED_BYTE, 
                &_frameData[_idxU]);

// V data
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, sampler2Texture);
glUniform1i(sampler2Texture, 2);

glTexSubImage2D(
                GL_TEXTURE_2D, 
                0, 
                0, 
                0, 
                mFrameW / 2,            // source width
                mFrameH / 2,            // source height
                GL_LUMINANCE,
                GL_UNSIGNED_BYTE,
                &_frameData[_idxV]);

// Y data
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sampler0Texture);
glUniform1i(sampler0Uniform, 0);

glTexSubImage2D(
                GL_TEXTURE_2D, 
                0, 
                0, 
                0, 
                mFrameW,            // source width
                mFrameH,            // source height
                GL_LUMINANCE,
                GL_UNSIGNED_BYTE,
                _frameData);

Vertex Shader&片段着色器在下面。

Vertex Shader & Fragment Shader is below.

attribute vec4 Position;
attribute vec2 TexCoordIn;

varying vec2 TexCoordOut;
varying vec2 TexCoordOut_UV;

uniform mat4 Projection;
uniform mat4 Modelview;

void main()
{
    gl_Position = Projection * Modelview * Position;
    TexCoordOut = TexCoordIn;
}



uniform sampler2D sampler0; // Y Texture Sampler
uniform sampler2D sampler1; // U Texture Sampler
uniform sampler2D sampler2; // V Texture Sampler

varying highp vec2 TexCoordOut;

void main()
{
    highp float y = texture2D(sampler0, TexCoordOut).r;
    highp float u = texture2D(sampler2, TexCoordOut).r - 0.5;
    highp float v = texture2D(sampler1, TexCoordOut).r - 0.5;

    //y = 0.0;
    //u = 0.0;
    //v = 0.0;

    highp float r = y + 1.13983 * v;
    highp float g = y - 0.39465 * u - 0.58060 * v;
    highp float b = y + 2.03211 * u;

    gl_FragColor = vec4(r, g, b, 1.0);
}

Y纹理(灰度)是正确的但U& V有很多绿色。
所以最终的RGB图像(Y + U + V)有很多绿色。
有什么问题?

Y Texture (Grayscale) is correct but U & V has a lot of Green Color. So final RGB image (Y+U+V) has a lot of GREEN Color. What's the problem?

请帮忙。
谢谢。

Please help. thanks.

推荐答案

更改 u v 制服(反之亦然),你会得到正确的结果。

Change u and v uniforms (vice versa) and you will have correct result.

所以像素着色器(保持不变):

So pixel shader (stays the same):

uniform sampler2D sampler0; // Y Texture Sampler
uniform sampler2D sampler1; // U Texture Sampler
uniform sampler2D sampler2; // V Texture Sampler

varying highp vec2 TexCoordOut;

void main()
{
    highp float y = texture2D(sampler0, TexCoordOut).r;
    highp float u = texture2D(sampler2, TexCoordOut).r - 0.5;
    highp float v = texture2D(sampler1, TexCoordOut).r - 0.5;

    highp float r = y + 1.13983 * v;
    highp float g = y - 0.39465 * u - 0.58060 * v;
    highp float b = y + 2.03211 * u;

    gl_FragColor = vec4(r, g, b, 1.0);
}

和渲染代码:

// RENDERING

    int _idxU = mFrameW * mFrameH;
    int _idxV = _idxU + (_idxU / 4);

    // U data
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, sampler1Texture);

    GLint sampler1Uniform = glGetUniformLocation(programStandard, "sampler2");

    glUniform1i(sampler1Uniform, 1);

    glTexSubImage2D(
                    GL_TEXTURE_2D,
                    0,
                    0,
                    0,
                    mFrameW / 2,            // source width
                    mFrameH / 2,            // source height
                    GL_LUMINANCE,
                    GL_UNSIGNED_BYTE,
                    &_frameData[_idxU]);

    // V data
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, sampler2Texture);

    GLint sampler2Uniform = glGetUniformLocation(programStandard, "sampler1");
    glUniform1i(sampler2Uniform, 2);

    glTexSubImage2D(
                    GL_TEXTURE_2D,
                    0,
                    0,
                    0,
                    mFrameW / 2,            // source width
                    mFrameH / 2,            // source height
                    GL_LUMINANCE,
                    GL_UNSIGNED_BYTE,
                    &_frameData[_idxV]);

    // Y data
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, sampler0Texture);

    GLint sampler0Uniform = glGetUniformLocation(programStandard, "sampler0");
    glUniform1i(sampler0Uniform, 0);

    glTexSubImage2D(
                    GL_TEXTURE_2D,
                    0,
                    0,
                    0,
                    mFrameW,            // source width
                    mFrameH,            // source height
                    GL_LUMINANCE,
                    GL_UNSIGNED_BYTE,
                    _frameData);


    //draw RECT
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, squareVertices);
    glEnableVertexAttribArray(ATTRIB_VERTEX);

    //ATTRIB_TEXTUREPOSITON
    glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureCoords);
    glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    free(_frameData);

    [(EAGLView *)self.view presentFramebuffer];

结论: u< - > v 制服。

这篇关于在YUV420p上有很多绿色 - &gt; iOS上的OpenGL 2.0着色器中的RGB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆