Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: webrtc/api/android/java/src/org/webrtc/YuvConverter.java

Issue 2436653003: Android YuvConverter: Use OpenGL Framebuffer instead of EGL pixel buffer (Closed)
Patch Set: Rebase against VideoFileRenderer Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/api/android/java/src/org/webrtc/VideoFileRenderer.java ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/api/android/java/src/org/webrtc/YuvConverter.java
diff --git a/webrtc/api/android/java/src/org/webrtc/YuvConverter.java b/webrtc/api/android/java/src/org/webrtc/YuvConverter.java
index 1203d86515840db873750cf555b3196844ec3812..050d69de8edbaa3c95d37cd8f1750bf740e974d9 100644
--- a/webrtc/api/android/java/src/org/webrtc/YuvConverter.java
+++ b/webrtc/api/android/java/src/org/webrtc/YuvConverter.java
@@ -16,13 +16,10 @@ import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
/**
- * Class for converting OES textures to a YUV ByteBuffer.
+ * Class for converting OES textures to a YUV ByteBuffer. It should be constructed on a thread with
+ * an active EGL context, and only be used from that thread.
*/
class YuvConverter {
- private final EglBase eglBase;
- private final GlShader shader;
- private boolean released = false;
-
// Vertex coordinates in Normalized Device Coordinates, i.e.
// (-1, -1) is bottom-left and (1, 1) is top-right.
private static final FloatBuffer DEVICE_RECTANGLE = GlUtil.createFloatBuffer(new float[] {
@@ -83,14 +80,40 @@ class YuvConverter {
+ "}\n";
// clang-format on
- private int texMatrixLoc;
- private int xUnitLoc;
- private int coeffsLoc;
+ private final int frameBufferId;
+ private final int frameTextureId;
+ private final GlShader shader;
+ private final int texMatrixLoc;
+ private final int xUnitLoc;
+ private final int coeffsLoc;
+ private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker();
+ private int frameBufferWidth;
+ private int frameBufferHeight;
+ private boolean released = false;
+
+ /**
+ * This class should be constructed on a thread that has an active EGL context.
+ */
+ public YuvConverter() {
+ threadChecker.checkIsOnValidThread();
+ frameTextureId = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
+ this.frameBufferWidth = 0;
+ this.frameBufferHeight = 0;
- public YuvConverter(EglBase.Context sharedContext) {
- eglBase = EglBase.create(sharedContext, EglBase.CONFIG_PIXEL_RGBA_BUFFER);
- eglBase.createDummyPbufferSurface();
- eglBase.makeCurrent();
+ // Create framebuffer object and bind it.
+ final int frameBuffers[] = new int[1];
+ GLES20.glGenFramebuffers(1, frameBuffers, 0);
+ frameBufferId = frameBuffers[0];
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
+ GlUtil.checkNoGLES2Error("Generate framebuffer");
+
+ // Attach the texture to the framebuffer as color attachment.
+ GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
+ GLES20.GL_TEXTURE_2D, frameTextureId, 0);
+ GlUtil.checkNoGLES2Error("Attach texture to framebuffer");
+
+ // Restore normal framebuffer.
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
shader = new GlShader(VERTEX_SHADER, FRAGMENT_SHADER);
shader.useProgram();
@@ -104,11 +127,11 @@ class YuvConverter {
// If the width is not a multiple of 4 pixels, the texture
// will be scaled up slightly and clipped at the right border.
shader.setVertexAttribArray("in_tc", 2, TEXTURE_RECTANGLE);
- eglBase.detachCurrent();
}
- synchronized public void convert(
- ByteBuffer buf, int width, int height, int stride, int textureId, float[] transformMatrix) {
+ public void convert(ByteBuffer buf, int width, int height, int stride, int srcTextureId,
+ float[] transformMatrix) {
+ threadChecker.checkIsOnValidThread();
if (released) {
throw new IllegalStateException("YuvConverter.convert called on released object");
}
@@ -163,20 +186,28 @@ class YuvConverter {
transformMatrix =
RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.verticalFlipMatrix());
- // Create new pBuffferSurface with the correct size if needed.
- if (eglBase.hasSurface()) {
- if (eglBase.surfaceWidth() != stride / 4 || eglBase.surfaceHeight() != total_height) {
- eglBase.releaseSurface();
- eglBase.createPbufferSurface(stride / 4, total_height);
+ // Bind our framebuffer.
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
+ GlUtil.checkNoGLES2Error("glBindFramebuffer");
+
+ if (frameBufferWidth != stride / 4 || frameBufferHeight != total_height) {
+ frameBufferWidth = stride / 4;
+ frameBufferHeight = total_height;
+ // (Re)-Allocate texture.
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureId);
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, frameBufferWidth,
+ frameBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
+
+ // Check that the framebuffer is in a good state.
+ final int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
+ if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
+ throw new IllegalStateException("Framebuffer not complete, status: " + status);
}
- } else {
- eglBase.createPbufferSurface(stride / 4, total_height);
}
- eglBase.makeCurrent();
-
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
- GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
+ GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, srcTextureId);
GLES20.glUniformMatrix4fv(texMatrixLoc, 1, false, transformMatrix, 0);
// Draw Y
@@ -203,20 +234,26 @@ class YuvConverter {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glReadPixels(
- 0, 0, stride / 4, total_height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
+ 0, 0, frameBufferWidth, frameBufferHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkNoGLES2Error("YuvConverter.convert");
+ // Restore normal framebuffer.
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
+
// Unbind texture. Reportedly needed on some devices to get
// the texture updated from the camera.
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
- eglBase.detachCurrent();
}
- synchronized public void release() {
+ public void release() {
+ threadChecker.checkIsOnValidThread();
released = true;
- eglBase.makeCurrent();
shader.release();
- eglBase.release();
+ GLES20.glDeleteTextures(1, new int[] {frameTextureId}, 0);
+ GLES20.glDeleteFramebuffers(1, new int[] {frameBufferId}, 0);
+ frameBufferWidth = 0;
+ frameBufferHeight = 0;
}
}
« no previous file with comments | « webrtc/api/android/java/src/org/webrtc/VideoFileRenderer.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698