[vlc-devel] [PATCH 3/5] android: util: init ASurfaceTexture from Java
Louis Regnier
louis.videolabs at gmail.com
Mon Apr 27 23:28:53 CEST 2020
When the native SurfaceTexture API is available, construct a SurfaceTexture
object from Java through JNI calls and store the producer side
(Surface/ANativeWindow) for the AWindowHandler clients.
The SurfaceTexture constructor is only available since API 26 but the NDK
API for ASurfaceTexture already require API 28
---
modules/video_output/android/utils.c | 97 ++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 5 deletions(-)
diff --git a/modules/video_output/android/utils.c b/modules/video_output/android/utils.c
index 8a300b05bb..62d5ba16b0 100644
--- a/modules/video_output/android/utils.c
+++ b/modules/video_output/android/utils.c
@@ -77,6 +77,7 @@ struct AWindowHandler
native_window_api_t anw_api;
struct ASurfaceTextureAPI ast_api;
+ bool b_has_ast_api;
struct {
awh_events_t cb;
@@ -100,6 +101,8 @@ static struct
jmethodID setVideoLayout;
} AndroidNativeWindow;
struct {
+ jclass clazz;
+ jmethodID constructor;
jmethodID attachToGLContext;
jmethodID detachFromGLContext;
jmethodID waitAndUpdateTexImage;
@@ -284,6 +287,30 @@ LoadNativeSurfaceAPI(AWindowHandler *p_awh)
* Android ASurfaceTexture Android NDK
*/
+#define GET_CLASS(clazz, str, b_globlal) do { \
+ (clazz) = (*env)->FindClass(env, (str)); \
+ if (!(clazz)) { \
+ return -1; \
+ } \
+ if (b_globlal) { \
+ (clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \
+ if (!(clazz)) { \
+ return -1; \
+ } \
+ } \
+} while (0)
+
+static int JNI_getSurfaceTexture(JNIEnv *env)
+{
+ GET_CLASS(jfields.SurfaceTexture.clazz, "android/graphics/SurfaceTexture", true);
+
+ jfields.SurfaceTexture.constructor =
+ (*env)->GetMethodID(env, jfields.SurfaceTexture.clazz, "<init>", "(Z)V");
+ if (jfields.SurfaceTexture.constructor == NULL)
+ return -1;
+ return 0;
+}
+
static int
LoadSurfaceTextureAPI(AWindowHandler *p_awh, void *p_library)
{
@@ -327,7 +354,7 @@ LoadSurfaceTextureAPI(AWindowHandler *p_awh, void *p_library)
*/
static void
-LoadNativeWindowAPI(AWindowHandler *p_awh)
+LoadNativeWindowAPI(AWindowHandler *p_awh, JNIEnv *p_env)
{
void *p_library = dlopen("libandroid.so", RTLD_NOW);
if (!p_library)
@@ -346,7 +373,9 @@ LoadNativeWindowAPI(AWindowHandler *p_awh)
&& p_awh->anw_api.winLock && p_awh->anw_api.unlockAndPost
&& p_awh->anw_api.setBuffersGeometry)
{
- LoadSurfaceTextureAPI(p_awh, p_library);
+ if (LoadSurfaceTextureAPI(p_awh, p_library) == VLC_SUCCESS)
+ JNI_getSurfaceTexture(p_env);
+ p_awh->b_has_ast_api = false;
p_awh->p_anw_dl = p_library;
}
else
@@ -593,7 +622,7 @@ AWindowHandler_new(vout_window_t *wnd, awh_events_t *p_events)
free(p_awh);
return NULL;
}
- LoadNativeWindowAPI(p_awh);
+ LoadNativeWindowAPI(p_awh, p_env);
p_awh->b_has_video_layout_listener =
flags & AWINDOW_REGISTER_FLAGS_HAS_VIDEO_LAYOUT_LISTENER;
@@ -642,6 +671,18 @@ AWindowHandler_destroy(AWindowHandler *p_awh)
if (p_env)
{
+ if (p_awh->b_has_ast_api)
+ {
+ AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_SurfaceTexture);
+ (*p_env)->DeleteGlobalRef(p_env, p_awh->ast_api.surfacetexture);
+ if (p_awh->ast_api.p_ast != NULL)
+ {
+ p_awh->ast_api.pf_releaseAst(p_awh->ast_api.p_ast);
+ p_awh->ast_api.p_ast = NULL;
+ }
+ (*p_env)->DeleteGlobalRef(p_env, jfields.SurfaceTexture.clazz);
+ }
+
JNI_ANWCALL(CallVoidMethod, unregisterNative);
AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Video);
AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_Subtitles);
@@ -661,6 +702,46 @@ AWindowHandler_getANativeWindowAPI(AWindowHandler *p_awh)
return &p_awh->anw_api;
}
+static jobject InitSurfaceTextureNDK(AWindowHandler *p_awh, JNIEnv *p_env,
+ enum AWindow_ID id)
+{
+ jobject surfacetexture = (*p_env)->NewObject(p_env,
+ jfields.SurfaceTexture.clazz, jfields.SurfaceTexture.constructor, false);
+
+ if (surfacetexture == NULL)
+ goto error;
+
+ p_awh->ast_api.surfacetexture = (*p_env)->NewGlobalRef(p_env, surfacetexture);
+
+ p_awh->ast_api.p_ast = p_awh->ast_api.pf_astFromst(p_env,
+ p_awh->ast_api.surfacetexture);
+ if (p_awh->ast_api.p_ast == NULL)
+ goto error;
+
+ p_awh->views[id].p_anw = p_awh->ast_api.pf_acquireAnw(p_awh->ast_api.p_ast);
+ if (p_awh->views[id].p_anw == NULL)
+ goto error;
+
+ jobject jsurface = p_awh->ast_api.pf_anwToSurface(p_env, p_awh->views[id].p_anw);
+ if (jsurface == NULL)
+ goto error;
+ (*p_env)->DeleteLocalRef(p_env, surfacetexture);
+ return jsurface;
+
+error:
+ if (surfacetexture == NULL)
+ return NULL;
+ (*p_env)->DeleteLocalRef(p_env, surfacetexture);
+ p_awh->ast_api.surfacetexture = (*p_env)->NewGlobalRef(p_env, surfacetexture);
+ if (p_awh->ast_api.p_ast == NULL)
+ return NULL;
+ p_awh->ast_api.pf_releaseAst(p_awh->ast_api.p_ast);
+ if (p_awh->views[id].p_anw == NULL)
+ return NULL;
+ AWindowHandler_releaseANativeWindow(p_awh, id);
+ return NULL;
+}
+
static int
WindowHandler_NewSurfaceEnv(AWindowHandler *p_awh, JNIEnv *p_env,
enum AWindow_ID id)
@@ -676,8 +757,13 @@ WindowHandler_NewSurfaceEnv(AWindowHandler *p_awh, JNIEnv *p_env,
jsurface = JNI_ANWCALL(CallObjectMethod, getSubtitlesSurface);
break;
case AWindow_SurfaceTexture:
- jsurface = JNI_STEXCALL(CallObjectMethod, getSurface);
+ {
+ if (p_awh->b_has_ast_api)
+ jsurface = InitSurfaceTextureNDK(p_awh, p_env, id);
+ else
+ jsurface = JNI_STEXCALL(CallObjectMethod, getSurface);
break;
+ }
default:
vlc_assert_unreachable();
}
@@ -707,7 +793,8 @@ AWindowHandler_getANativeWindow(AWindowHandler *p_awh, enum AWindow_ID id)
return NULL;
assert(p_awh->views[id].jsurface != NULL);
- p_awh->views[id].p_anw = p_awh->pf_winFromSurface(p_env,
+ if (!p_awh->b_has_ast_api || id != AWindow_SurfaceTexture)
+ p_awh->views[id].p_anw = p_awh->pf_winFromSurface(p_env,
p_awh->views[id].jsurface);
return p_awh->views[id].p_anw;
}
--
2.26.2
More information about the vlc-devel
mailing list