From 0cb34dcd1ccb5b9534b47030de495e7b5bf5e9d6 Mon Sep 17 00:00:00 2001 From: hoangtc Date: Wed, 23 May 2018 08:53:08 -0700 Subject: [PATCH] Add SurfaceCapturer base class, and provide the first implementation Use PixelCopy API for the first SurfaceCapturer implementation. This supports devices from API 24+. Github: #3609. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=197732711 --- .../assets/bitmap/image_256_256.png | Bin 0 -> 1976 bytes .../androidTest/assets/bitmap/image_80_60.bmp | Bin 0 -> 19338 bytes .../surfacecapturer/SurfaceCapturer.java | 84 ++++++++++++++++++ .../exoplayer2/util/EGLSurfaceTexture.java | 48 ++++++++-- .../exoplayer2/testutil/DummyMainThread.java | 0 5 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 library/core/src/androidTest/assets/bitmap/image_256_256.png create mode 100644 library/core/src/androidTest/assets/bitmap/image_80_60.bmp create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/surfacecapturer/SurfaceCapturer.java rename {testutils_robolectric => testutils}/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java (100%) diff --git a/library/core/src/androidTest/assets/bitmap/image_256_256.png b/library/core/src/androidTest/assets/bitmap/image_256_256.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1403eebde00da4a0b231fb5a284c66841422e2 GIT binary patch literal 1976 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFtdQTU}kczms*BAvE6nG9F zIJZAT;L|}yZ~f`Fzg;WV7pR^7cbhkZ$^S3?kNp{bFuby_X5c*VES~YfA7KW&2Cf5g z4on+u4~ICJEZ* zod4Ute~`X#zu&I69+*ex|112*$sq5*n!vBXc;k;Y!<>4i1MC5eH<&#b%>HvRJfF|- zfiZ;P8-q~8+5JoheyTInFo-tTHn1doUe8c4s&zD&Mw0~1b58xeTmR%Oqry~xH8O*z LtDnm{r-UW|OO3#d literal 0 HcmV?d00001 diff --git a/library/core/src/androidTest/assets/bitmap/image_80_60.bmp b/library/core/src/androidTest/assets/bitmap/image_80_60.bmp new file mode 100644 index 0000000000000000000000000000000000000000..440c80f1b53ba3c578825ea677d82749fd9e94d9 GIT binary patch literal 19338 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 Wh}=;It constructs a {@link Surface}, which can be used as the output surface for an image producer + * to draw images to. As images are being drawn into this surface, this capturer will capture these + * images, and return them via {@link Callback}. The output images will have a fixed frame size of + * (width, height), and any image drawn into the surface will be stretched to fit this frame size. + */ +public abstract class SurfaceCapturer { + + /** The callback to be notified of the image capturing result. */ + public interface Callback { + + /** + * Called when the surface capturer has been able to capture its surface into a {@link Bitmap}. + * This will happen whenever the producer updates the image on the wrapped surface. + */ + void onSurfaceCaptured(Bitmap bitmap); + + /** Called when the surface capturer couldn't capture its surface due to an error. */ + void onSurfaceCaptureError(Exception e); + } + + /** The callback to be notified of the image capturing result. */ + private final Callback callback; + /** The width of the output images. */ + private final int outputWidth; + /** The height of the output images. */ + private final int outputHeight; + + /** + * Constructs a new instance. + * + * @param callback See {@link #callback}. + * @param outputWidth See {@link #outputWidth}. + * @param outputHeight See {@link #outputHeight}. + */ + protected SurfaceCapturer(Callback callback, int outputWidth, int outputHeight) { + this.callback = callback; + this.outputWidth = outputWidth; + this.outputHeight = outputHeight; + } + + /** Returns the callback to be notified of the image capturing result. */ + protected Callback getCallback() { + return callback; + } + + /** Returns the width of the output images. */ + public int getOutputWidth() { + return outputWidth; + } + + /** Returns the height of the output images. */ + public int getOutputHeight() { + return outputHeight; + } + + /** Returns a {@link Surface} that image producers (camera, video codec etc...) can draw to. */ + public abstract Surface getSurface(); + + /** Releases all kept resources. This instance cannot be used after this call. */ + public abstract void release(); +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java index 6fe76b9b2cc..552a0f224da 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java @@ -33,6 +33,12 @@ @TargetApi(17) public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableListener, Runnable { + /** Listener to be called when the texture image on {@link SurfaceTexture} has been updated. */ + public interface TextureImageListener { + /** Called when the {@link SurfaceTexture} receives a new frame from its image producer. */ + void onFrameAvailable(); + } + /** Secure mode to be used by the EGL surface and context. */ @Retention(RetentionPolicy.SOURCE) @IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER}) @@ -45,6 +51,9 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL /** Creating a secure surface backed by a pixel buffer. */ public static final int SECURE_MODE_PROTECTED_PBUFFER = 2; + private static final int EGL_SURFACE_WIDTH = 1; + private static final int EGL_SURFACE_HEIGHT = 1; + private static final int[] EGL_CONFIG_ATTRIBUTES = new int[] { EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, @@ -69,6 +78,7 @@ private GlException(String msg) { private final Handler handler; private final int[] textureIdHolder; + private final @Nullable TextureImageListener callback; private @Nullable EGLDisplay display; private @Nullable EGLContext context; @@ -82,7 +92,21 @@ private GlException(String msg) { * looper. */ public EGLSurfaceTexture(Handler handler) { + this(handler, /* callback= */ null); + } + + /** + * @param handler The {@link Handler} that will be used to call {@link + * SurfaceTexture#updateTexImage()} to update images on the {@link SurfaceTexture}. Note that + * {@link #init(int)} has to be called on the same looper thread as the looper of the {@link + * Handler}. + * @param callback The {@link TextureImageListener} to be called when the texture image on {@link + * SurfaceTexture} has been updated. This callback will be called on the same handler thread + * as the {@code handler}. + */ + public EGLSurfaceTexture(Handler handler, @Nullable TextureImageListener callback) { this.handler = handler; + this.callback = callback; textureIdHolder = new int[1]; } @@ -142,8 +166,20 @@ public void onFrameAvailable(SurfaceTexture surfaceTexture) { @Override public void run() { + // Run on the provided handler thread when a new image frame is available. + dispatchOnFrameAvailable(); if (texture != null) { - texture.updateTexImage(); + try { + texture.updateTexImage(); + } catch (RuntimeException e) { + // Ignore + } + } + } + + private void dispatchOnFrameAvailable() { + if (callback != null) { + callback.onFrameAvailable(); } } @@ -220,9 +256,9 @@ private static EGLSurface createEGLSurface( pbufferAttributes = new int[] { EGL14.EGL_WIDTH, - 1, + EGL_SURFACE_WIDTH, EGL14.EGL_HEIGHT, - 1, + EGL_SURFACE_HEIGHT, EGL_PROTECTED_CONTENT_EXT, EGL14.EGL_TRUE, EGL14.EGL_NONE @@ -230,8 +266,10 @@ private static EGLSurface createEGLSurface( } else { pbufferAttributes = new int[] { - EGL14.EGL_WIDTH, 1, - EGL14.EGL_HEIGHT, 1, + EGL14.EGL_WIDTH, + EGL_SURFACE_WIDTH, + EGL14.EGL_HEIGHT, + EGL_SURFACE_HEIGHT, EGL14.EGL_NONE }; } diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java similarity index 100% rename from testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java rename to testutils/src/main/java/com/google/android/exoplayer2/testutil/DummyMainThread.java