diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 40c8b284e6..0fb77fabef 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -766,11 +766,11 @@ rtc_android_library("video_api_java") { "api/org/webrtc/JavaI420Buffer.java", "api/org/webrtc/RendererCommon.java", "api/org/webrtc/SurfaceTextureHelper.java", + "api/org/webrtc/TextureBufferImpl.java", "api/org/webrtc/YuvConverter.java", "api/org/webrtc/YuvHelper.java", "src/java/org/webrtc/EglBase10.java", "src/java/org/webrtc/EglBase14.java", - "src/java/org/webrtc/TextureBufferImpl.java", ] deps = [ diff --git a/sdk/android/api/org/webrtc/SurfaceTextureHelper.java b/sdk/android/api/org/webrtc/SurfaceTextureHelper.java index eefc153ff2..700a7b9138 100644 --- a/sdk/android/api/org/webrtc/SurfaceTextureHelper.java +++ b/sdk/android/api/org/webrtc/SurfaceTextureHelper.java @@ -320,12 +320,7 @@ public class SurfaceTextureHelper { * buffer calls returnTextureFrame() when it is released. */ public TextureBuffer createTextureBuffer(int width, int height, Matrix transformMatrix) { - return new TextureBufferImpl( - width, height, TextureBuffer.Type.OES, oesTextureId, transformMatrix, this, new Runnable() { - @Override - public void run() { - returnTextureFrame(); - } - }); + return new TextureBufferImpl(width, height, TextureBuffer.Type.OES, oesTextureId, + transformMatrix, handler, yuvConverter, this ::returnTextureFrame); } } diff --git a/sdk/android/src/java/org/webrtc/TextureBufferImpl.java b/sdk/android/api/org/webrtc/TextureBufferImpl.java similarity index 64% rename from sdk/android/src/java/org/webrtc/TextureBufferImpl.java rename to sdk/android/api/org/webrtc/TextureBufferImpl.java index 9ad2ae2d14..19036589ec 100644 --- a/sdk/android/src/java/org/webrtc/TextureBufferImpl.java +++ b/sdk/android/api/org/webrtc/TextureBufferImpl.java @@ -11,31 +11,32 @@ package org.webrtc; import android.graphics.Matrix; -import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; +import android.os.Handler; /** - * Android texture buffer backed by a SurfaceTextureHelper's texture. The buffer calls - * |releaseCallback| when it is released. + * Android texture buffer that glues together the necessary information together with a generic + * release callback. ToI420() is implemented by providing a Handler and a YuvConverter. */ -class TextureBufferImpl implements VideoFrame.TextureBuffer { +public class TextureBufferImpl implements VideoFrame.TextureBuffer { private final int width; private final int height; private final Type type; private final int id; private final Matrix transformMatrix; - private final SurfaceTextureHelper surfaceTextureHelper; + private final Handler toI420Handler; + private final YuvConverter yuvConverter; private final RefCountDelegate refCountDelegate; public TextureBufferImpl(int width, int height, Type type, int id, Matrix transformMatrix, - SurfaceTextureHelper surfaceTextureHelper, @Nullable Runnable releaseCallback) { + Handler toI420Handler, YuvConverter yuvConverter, @Nullable Runnable releaseCallback) { this.width = width; this.height = height; this.type = type; this.id = id; this.transformMatrix = transformMatrix; - this.surfaceTextureHelper = surfaceTextureHelper; + this.toI420Handler = toI420Handler; + this.yuvConverter = yuvConverter; this.refCountDelegate = new RefCountDelegate(releaseCallback); } @@ -66,7 +67,8 @@ class TextureBufferImpl implements VideoFrame.TextureBuffer { @Override public VideoFrame.I420Buffer toI420() { - return surfaceTextureHelper.textureToYuv(this); + return ThreadUtils.invokeAtFrontUninterruptibly( + toI420Handler, () -> yuvConverter.convert(this)); } @Override @@ -82,17 +84,12 @@ class TextureBufferImpl implements VideoFrame.TextureBuffer { @Override public VideoFrame.Buffer cropAndScale( int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth, int scaleHeight) { - retain(); - Matrix newMatrix = new Matrix(transformMatrix); - newMatrix.postScale(cropWidth / (float) width, cropHeight / (float) height); - newMatrix.postTranslate(cropX / (float) width, cropY / (float) height); + final Matrix newMatrix = new Matrix(transformMatrix); + newMatrix.preTranslate(cropX / (float) width, cropY / (float) height); + newMatrix.preScale(cropWidth / (float) width, cropHeight / (float) height); + retain(); return new TextureBufferImpl( - scaleWidth, scaleHeight, type, id, newMatrix, surfaceTextureHelper, new Runnable() { - @Override - public void run() { - release(); - } - }); + scaleWidth, scaleHeight, type, id, newMatrix, toI420Handler, yuvConverter, this ::release); } } diff --git a/sdk/android/api/org/webrtc/VideoRenderer.java b/sdk/android/api/org/webrtc/VideoRenderer.java index f10ad20f58..402f261f39 100644 --- a/sdk/android/api/org/webrtc/VideoRenderer.java +++ b/sdk/android/api/org/webrtc/VideoRenderer.java @@ -171,10 +171,10 @@ public class VideoRenderer { yuvStrides[1], yuvPlanes[2], yuvStrides[2], () -> { VideoRenderer.renderFrameDone(this); }); } else { - // Note: surfaceTextureHelper being null means calling toI420 will crash. + // Note: No Handler or YuvConverter means calling toI420 will crash. buffer = new TextureBufferImpl(width, height, VideoFrame.TextureBuffer.Type.OES, textureId, - RendererCommon.convertMatrixToAndroidGraphicsMatrix(samplingMatrix), - null /* surfaceTextureHelper */, () -> { VideoRenderer.renderFrameDone(this); }); + RendererCommon.convertMatrixToAndroidGraphicsMatrix(samplingMatrix), null /* handler */, + null /* yuvConverter */, () -> VideoRenderer.renderFrameDone(this)); } return new VideoFrame(buffer, rotationDegree, 0 /* timestampNs */); } diff --git a/sdk/android/api/org/webrtc/YuvConverter.java b/sdk/android/api/org/webrtc/YuvConverter.java index 31db0dd610..2d8e54882c 100644 --- a/sdk/android/api/org/webrtc/YuvConverter.java +++ b/sdk/android/api/org/webrtc/YuvConverter.java @@ -18,8 +18,8 @@ import org.webrtc.VideoFrame.I420Buffer; import org.webrtc.VideoFrame.TextureBuffer; /** - * 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 for converting OES textures to a YUV ByteBuffer. It can be constructed on any thread, but + * should only be operated from a single thread with an active EGL context. */ public class YuvConverter { // Vertex coordinates in Normalized Device Coordinates, i.e. @@ -111,7 +111,7 @@ public class YuvConverter { // clang-format on private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker(); - private final GlTextureFrameBuffer textureFrameBuffer; + private final GlTextureFrameBuffer textureFrameBuffer = new GlTextureFrameBuffer(GLES20.GL_RGBA); private TextureBuffer.Type shaderTextureType; private GlShader shader; private int texMatrixLoc; @@ -123,8 +123,7 @@ public class YuvConverter { * This class should be constructed on a thread that has an active EGL context. */ public YuvConverter() { - threadChecker.checkIsOnValidThread(); - textureFrameBuffer = new GlTextureFrameBuffer(GLES20.GL_RGBA); + threadChecker.detachThread(); } /** Converts the texture buffer to I420. */