在YUV420p上有很多GREEN Color – >在iOS上的OpenGL 2.0 Shader中使用RGB

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

  • 480×320宽度和高度:
  • 512×512纹理宽度和高度

我从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); } } 

并为Y,U&V通道准备纹理。

 //: 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); 

顶点着色器和片段着色器如下。

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

请帮忙。 谢谢。

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

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

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

由于iOS支持rgb_422纹理,而不是使用三个亮度纹理使用一个rgb_422纹理。 http://www.opengl.org/registry/specs/APPLE/rgb_422.txt

编辑:哎呀YUV480P是不同于YUV422。 在这种情况下,由于其布局奇怪,您必须将YUV数据转换为RGB数据,然后才能将其作为纹理进行上传。