8

I am trying to read pixels/data from an OpenGL texture which is bound to GL_TEXTURE_EXTERNAL_OES.

The reason for binding the texture to that target is because in order get live camera feed on android a SurfaceTexture needs to be created from an OpenGL texture which is bound to GL_TEXTURE_EXTERNAL_OES.

Since android uses OpenGL ES I can't use glGetTexImage() to read the image data.

Therefore I am binding the target to an FBO and then reading it using readPixels(). This is my code:

    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    //Attach 2D texture to this FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, cameraTexture, 0);
    status("glFramebufferTexture2D() returned error %d", glGetError());

However I am getting error 1282 (GL_INVALID_OPERATION) for some reason.

amirhbp
  • 185
  • 1
  • 1
  • 7

2 Answers2

2

I think this might be the problem:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_EXTERNAL_OES, cameraTexture, 0);

You should not attach the cameraTexture to the framebuffer, instead you should generate a new texture in the format of GL_TEXTURE_2D

glGenTextures(1, mTextureHandle, 0);

glBindTexture(GL_TEXTURE_2D, mTextureHandle[0]);

...

cameraTexture is the one you get from SurfaceTexture, and it is the source used for rendering. This new texture is the one you should render to (which could be used later in the rendering pipeline). Then do this:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, mTextureHandle[0], 0);

cameraTexture is drawn to the framebuffer's attached texture, using a simple shader program to draw, bind the cameraTexture when the shader program is in use:

glBindTexture(GL_TEXTURE_EXTERNAL_OES, cameraTexture); 
Yu Lu
  • 300
  • 1
  • 12
  • 1
    What solution this answer brings? – Léon Pelletier Jul 05 '15 at 11:33
  • 1
    I think the right solution need to combine the 2 answers together, first create a new framebuffer and a new texture and glFramebufferTexture2D, then you can use shader to draw the YUV data to the frame buffer and then it can be read through glReadPixels. A little bit complicated! – Wilson Chen Mar 27 '17 at 09:20
0

The GL_TEXTURE_EXTERNAL_OES texture target is usually in a YUV color space and glReadPixels() requires the target to be RGB. It probably does not do the color space conversion automatically. However, you could do the conversion in your own fragment shader which renders RGB into another texture and then use glReadPixels() to read that.

texture for YUV420 to RGB conversion in OpenGL ES

Community
  • 1
  • 1
ClayMontgomery
  • 2,786
  • 1
  • 15
  • 14
  • 3
    This is not accurate. On Android, the YUV->RGB conversion happens automatically behind the scenes. See https://stackoverflow.com/questions/46244179/android-mediacodec-output-format-gles-external-texture-yuv-nv12-to-gles-tex – tmm1 Mar 05 '18 at 23:15