YUV420p上有很多绿色-->;iOS上OpenGL 2.0着色器中的RGB

YUV420p上有很多绿色-->;iOS上OpenGL 2.0着色器中的RGB,ios,opengl-es,ffmpeg,yuv,Ios,Opengl Es,Ffmpeg,Yuv,我想使用ffmpeg和OpenGL ES 2.0为iOS制作一个电影播放器 但是我有一些问题。输出的RGB图像有很多绿色。 这是代码和图像 480x320宽度和高度: 512x512纹理宽度和高度 我从ffmpeg AVFrame获取了YUV420p行数据 for (int i = 0, nDataLen = 0; i < 3; i++) { int nShift = (i == 0) ? 0 : 1; uint8_t *pYUVData = (

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

  • 480x320宽度和高度:
  • 512x512纹理宽度和高度
我从ffmpeg AVFrame获取了YUV420p行数据

    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);
        }
    }
下面是渲染部分

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);
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);
}
顶点着色器和片段着色器位于下面

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);
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)有很多绿色。 有什么问题吗

请帮忙。
谢谢。

因为iOS支持rgb_422纹理,所以不要使用三种亮度纹理,而是使用一种rgb_422纹理

编辑:
哎呀,YUV480p和YUV422不一样。在这种情况下,由于其奇怪的布局,在作为纹理上载之前,您必须将YUV数据转换为RGB数据。

更改
u
v
制服(反之亦然),您将获得正确的结果

因此像素着色器(保持不变):

和渲染代码:

// 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
制服

“u&v有很多绿色”是什么意思?U和V没有颜色。它们是U和V。最终图像中的绿色来自“浮点g”计算。你用CPU验证过公式吗?尝试将YUV数据转换为RGB,以查看公式是否正确。还有-为什么从采样器2读取浮点u,而从采样器1读取浮点v?取样器定义后的注释说取样器1是u,取样器2是v。我知道u&v没有绿色。但当我这样做时,y=0.0;&v=0.0;然后输出屏幕有很多绿色。我弄错了你说的话。取样器1为u,取样器2为v。但结果是一样的。嗯,我试着通过ffmpeg函数中的sws_比例将YUV转换成RGB。结果是好的。但问题是速度(或性能)。您好,您找到解决问题的方法了吗?我正试着做同样的事情,但是运气不好。。。