[vlc-devel] [PATCH 1/3] Android utils, OpenGL: load ASurfaceTexture NDK API

Louis Regnier louis.videolabs at gmail.com
Mon Apr 6 11:51:58 CEST 2020


Implement a new Android NDK API library to manage surfacetexture natively.
If device is not recent enough to support this API it will fallback to the
previous JNI API.

To avoid JNI, we need an access to the SurfaceTexture which is
initialized in the AWindow.java class in the Android bindings.

Currently only a Surface (weak reference to the producer side)
is returned by the AWindow JNI API preventing using the NDK API
directly.

First, add those new method bindings from the AWindow object.

Then, if method exist, dynamically bind the NDK SurfaceTexture API
to a pointer structure to determine whether it is available.
Fallback to JNI behaviour if they are not available.

refs videolan/vlc#20344
---
 modules/video_output/android/utils.c | 99 ++++++++++++++++++++++++----
 modules/video_output/android/utils.h |  1 +
 2 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/modules/video_output/android/utils.c b/modules/video_output/android/utils.c
index 2010f13976..7158ec6658 100644
--- a/modules/video_output/android/utils.c
+++ b/modules/video_output/android/utils.c
@@ -25,11 +25,39 @@
 #include <jni.h>
 #include <pthread.h>
 #include <assert.h>
+#include <android/surface_texture.h>
+#include <android/surface_texture_jni.h>
 
 typedef ANativeWindow* (*ptr_ANativeWindow_fromSurface)(JNIEnv*, jobject);
 typedef ANativeWindow* (*ptr_ANativeWindow_fromSurfaceTexture)(JNIEnv*, jobject);
 typedef void (*ptr_ANativeWindow_release)(ANativeWindow*);
 
+typedef void (*ptr_ASurfaceTexture_getTransformMatrix)
+                                        (ASurfaceTexture *st, float mtx[16]);
+typedef ASurfaceTexture* (*ptr_ASurfaceTexture_fromSurfaceTexture)
+                                        (JNIEnv* env, jobject surfacetexture);
+typedef int (*ptr_ASurfaceTexture_updateTexImage)(ASurfaceTexture* st);
+typedef int (*ptr_ASurfaceTexture_detachFromGLContext)
+                                        (ASurfaceTexture *st);
+typedef int (*ptr_ASurfaceTexture_attachToGLContext)
+                                        (ASurfaceTexture *st, uint32_t texName);
+typedef void (*ptr_ASurfaceTexture_release)(ASurfaceTexture *st);
+
+struct ASurfaceTextureAPI
+{
+    float   transMat[16];
+
+    jobject surfacetexture;
+    ASurfaceTexture *p_ast;
+
+    ptr_ASurfaceTexture_updateTexImage pf_updateTexImage;
+    ptr_ASurfaceTexture_fromSurfaceTexture pf_astFromst;
+    ptr_ASurfaceTexture_attachToGLContext pf_attachToGL;
+    ptr_ASurfaceTexture_detachFromGLContext pf_detachFromGL;
+    ptr_ASurfaceTexture_getTransformMatrix pf_getTransMatrix;
+    ptr_ASurfaceTexture_release pf_releaseAst;
+};
+
 struct AWindowHandler
 {
     JavaVM *p_jvm;
@@ -46,6 +74,9 @@ struct AWindowHandler
     ptr_ANativeWindow_release pf_winRelease;
     native_window_api_t anw_api;
 
+    struct SurfaceTextureHandler st;
+    struct ASurfaceTextureAPI ast_api;
+
     struct {
         awh_events_t cb;
     } event;
@@ -57,20 +88,6 @@ struct AWindowHandler
     } stex;
 };
 
-struct SurfaceTexture
-{
-    JavaVM *p_jvm;
-
-    void *p_anw_dl;
-    ptr_ANativeWindow_fromSurface pf_winFromSurface;
-    ptr_ANativeWindow_release pf_winRelease;
-
-    jobject thiz;
-    jobject jsurface;
-    ANativeWindow *p_anw;
-
-};
-
 static struct
 {
     struct {
@@ -86,6 +103,8 @@ static struct
         jmethodID detachFromGLContext;
         jmethodID waitAndUpdateTexImage;
         jmethodID getSurface;
+        jmethodID getSurfaceTexture;
+        jmethodID removeFrameAvailableListener;
     } SurfaceTexture;
 } jfields;
 
@@ -262,6 +281,53 @@ LoadNativeSurfaceAPI(AWindowHandler *p_awh)
     p_awh->anw_api.setBuffersGeometry = NULL;
 }
 
+/*
+ * Android ASurfaceTexture Android NDK
+ */
+
+static int
+ASurfaceTexture_attachToGLContext(AWindowHandler *p_awh, uint32_t texName);
+static int
+ASurfaceTexture_updateTexImage(AWindowHandler *p_awh, const float **pp_transform_mtx);
+static void
+ASurfaceTexture_detachFromGLContext(AWindowHandler *p_awh);
+static int
+JNISurfaceTexture_waitAndUpdateTexImage(AWindowHandler *p_awh,
+                                            const float **pp_transform_mtx);
+static void
+JNISurfaceTexture_detachFromGLContext(AWindowHandler *p_awh);
+static int
+JNISurfaceTexture_attachToGLContext(AWindowHandler *p_awh, uint32_t tex_name);
+
+static int
+LoadSurfaceTextureAPI(AWindowHandler *p_awh, void *p_library)
+{
+    if (jfields.SurfaceTexture.removeFrameAvailableListener
+            && jfields.SurfaceTexture.getSurfaceTexture)
+    {
+        p_awh->ast_api.pf_astFromst = (ptr_ASurfaceTexture_fromSurfaceTexture)
+            dlsym(p_library, "ASurfaceTexture_fromSurfaceTexture");
+        p_awh->ast_api.pf_updateTexImage = (ptr_ASurfaceTexture_updateTexImage)
+            dlsym(p_library, "ASurfaceTexture_updateTexImage");
+        p_awh->ast_api.pf_attachToGL = (ptr_ASurfaceTexture_attachToGLContext)
+            dlsym(p_library, "ASurfaceTexture_attachToGLContext");
+        p_awh->ast_api.pf_detachFromGL = (ptr_ASurfaceTexture_detachFromGLContext)
+            dlsym(p_library, "ASurfaceTexture_detachFromGLContext");
+        p_awh->ast_api.pf_getTransMatrix = (ptr_ASurfaceTexture_getTransformMatrix)
+            dlsym(p_library, "ASurfaceTexture_getTransformMatrix");
+        p_awh->ast_api.pf_releaseAst = (ptr_ASurfaceTexture_release)
+            dlsym(p_library, "ASurfaceTexture_release");
+
+        if (p_awh->ast_api.pf_astFromst && p_awh->ast_api.pf_updateTexImage
+                && p_awh->ast_api.pf_attachToGL && p_awh->ast_api.pf_detachFromGL
+                && p_awh->ast_api.pf_getTransMatrix && p_awh->ast_api.pf_releaseAst)
+        {
+            return VLC_SUCCESS;
+        }
+    }
+    return VLC_EGENERIC;
+}
+
 /*
  * Android NativeWindow (post android 2.3)
  */
@@ -286,6 +352,7 @@ LoadNativeWindowAPI(AWindowHandler *p_awh)
      && p_awh->anw_api.winLock && p_awh->anw_api.unlockAndPost
      && p_awh->anw_api.setBuffersGeometry)
     {
+        LoadSurfaceTextureAPI(p_awh, p_library);
         p_awh->p_anw_dl = p_library;
     }
     else
@@ -435,6 +502,10 @@ InitJNIFields(JNIEnv *env, vlc_object_t *p_obj, jobject *jobj)
                true);
     GET_METHOD(SurfaceTexture.getSurface,
                "SurfaceTexture_getSurface", "()Landroid/view/Surface;", true);
+    GET_METHOD(SurfaceTexture.getSurfaceTexture,
+               "SurfaceTexture_getSurfaceTexture", "()Landroid/graphics/SurfaceTexture;", true);
+    GET_METHOD(SurfaceTexture.removeFrameAvailableListener,
+               "SurfaceTexture_removeFrameAvailableListener", "()V", true);
 
     if ((*env)->RegisterNatives(env, clazz, jni_callbacks, 2) < 0)
     {
diff --git a/modules/video_output/android/utils.h b/modules/video_output/android/utils.h
index 35ccc41906..28aed6c6a1 100644
--- a/modules/video_output/android/utils.h
+++ b/modules/video_output/android/utils.h
@@ -34,6 +34,7 @@
 #include <vlc_common.h>
 
 typedef struct AWindowHandler AWindowHandler;
+typedef struct ASurfaceTexture ASurfaceTexture;
 
 enum AWindow_ID {
     AWindow_Video,
-- 
2.26.0



More information about the vlc-devel mailing list