a lot of GREEN Color at YUV420p --> RGB in OpenGL 2.0 Shader on iOS
ffmpeg, ios, opengl-es, yuv
Solution
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);
}
and rendering code:
// 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];
Conclusion: `u <-> v` uniforms.
Problem
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 & height: - 512x512 Texture width & height 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); } } ``` 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); ``` Rendering part is below. ``` 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 & 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 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.