[vlc-commits] android: vout: re-use the same SurfaceTexture
Thomas Guillem
git at videolan.org
Fri Apr 21 16:32:57 CEST 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Apr 20 18:47:40 2017 +0200| [c547de6f215a6b98041f44d193ae3f2e432bb94c] | committer: Thomas Guillem
android: vout: re-use the same SurfaceTexture
Call attachToGLContext/detachFromGLContext on a same SurfaceTexture instance.
That way, we don't have to re-configure MediaCodec in order to setup the new
Surface when the video size change mid-stream (and when a new OpenGL vout is
created).
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c547de6f215a6b98041f44d193ae3f2e432bb94c
---
modules/video_output/android/utils.c | 217 ++++++++----------------
modules/video_output/android/utils.h | 36 ++--
modules/video_output/opengl/converter_android.c | 26 +--
3 files changed, 106 insertions(+), 173 deletions(-)
diff --git a/modules/video_output/android/utils.c b/modules/video_output/android/utils.c
index db462e0c16..d944e499ba 100644
--- a/modules/video_output/android/utils.c
+++ b/modules/video_output/android/utils.c
@@ -51,6 +51,11 @@ struct AWindowHandler
awh_events_t cb;
} event;
bool b_has_video_layout_listener;
+
+ struct {
+ jfloatArray jtransform_mtx_array;
+ jfloat *jtransform_mtx;
+ } stex;
};
struct SurfaceTexture
@@ -65,8 +70,6 @@ struct SurfaceTexture
jobject jsurface;
ANativeWindow *p_anw;
- jfloatArray jtransform_mtx_array;
- jfloat *jtransform_mtx;
};
static struct
@@ -81,11 +84,11 @@ static struct
jmethodID setVideoLayout;
} AndroidNativeWindow;
struct {
- jmethodID create;
- jmethodID release;
+ jmethodID attachToGLContext;
+ jmethodID detachFromGLContext;
jmethodID waitAndUpdateTexImage;
jmethodID getSurface;
- } SurfaceTextureThread;
+ } SurfaceTexture;
} jfields;
/*
@@ -441,10 +444,6 @@ InitJNIFields(JNIEnv *env, vlc_object_t *p_obj, jobject *jobj)
jfields.id = (*env)->GetMethodID(env, clazz, (str), (args)); \
CHECK_EXCEPTION("GetMethodID("str")", critical); \
} while( 0 )
-#define GET_SMETHOD(id, str, args, critical) do { \
- jfields.id = (*env)->GetStaticMethodID(env, clazz, (str), (args)); \
- CHECK_EXCEPTION("GetMethodID("str")", critical); \
-} while( 0 )
clazz = (*env)->GetObjectClass(env, jobj);
CHECK_EXCEPTION("AndroidNativeWindow clazz", true);
@@ -461,21 +460,15 @@ InitJNIFields(JNIEnv *env, vlc_object_t *p_obj, jobject *jobj)
GET_METHOD(AndroidNativeWindow.setVideoLayout,
"setVideoLayout", "(IIIIII)V", true);
- GET_SMETHOD(SurfaceTextureThread.create,
- "SurfaceTextureThread_create",
- "(I)Lorg/videolan/libvlc/AWindow$SurfaceTextureThread;", true);
- GET_SMETHOD(SurfaceTextureThread.release,
- "SurfaceTextureThread_release",
- "(Lorg/videolan/libvlc/AWindow$SurfaceTextureThread;)V",
- true);
- GET_SMETHOD(SurfaceTextureThread.waitAndUpdateTexImage,
- "SurfaceTextureThread_waitAndUpdateTexImage",
- "(Lorg/videolan/libvlc/AWindow$SurfaceTextureThread;[F)Z",
- true);
- GET_SMETHOD(SurfaceTextureThread.getSurface,
- "SurfaceTextureThread_getSurface",
- "(Lorg/videolan/libvlc/AWindow$SurfaceTextureThread;)"
- "Landroid/view/Surface;", true);
+ GET_METHOD(SurfaceTexture.attachToGLContext,
+ "SurfaceTexture_attachToGLContext", "(I)Z", true);
+ GET_METHOD(SurfaceTexture.detachFromGLContext,
+ "SurfaceTexture_detachFromGLContext", "()V", true);
+ GET_METHOD(SurfaceTexture.waitAndUpdateTexImage,
+ "SurfaceTexture_waitAndUpdateTexImage", "([F)Z",
+ true);
+ GET_METHOD(SurfaceTexture.getSurface,
+ "SurfaceTexture_getSurface", "()Landroid/view/Surface;", true);
if ((*env)->RegisterNatives(env, clazz, jni_callbacks, 2) < 0)
{
@@ -503,7 +496,7 @@ end:
#define JNI_ANWCALL(what, method, ...) \
(*p_env)->what(p_env, p_awh->jobj, jfields.AndroidNativeWindow.method, ##__VA_ARGS__)
#define JNI_STEXCALL(what, method, ...) \
- (*p_env)->what(p_env, jfields.AndroidNativeWindow.clazz, jfields.SurfaceTextureThread.method, ##__VA_ARGS__)
+ (*p_env)->what(p_env, p_awh->jobj, jfields.SurfaceTexture.method, ##__VA_ARGS__)
static JNIEnv*
AWindowHandler_getEnv(AWindowHandler *p_awh)
@@ -552,12 +545,24 @@ AWindowHandler_new(vout_window_t *wnd, awh_events_t *p_events)
p_awh->wnd = wnd;
p_awh->event.cb = *p_events;
+ jfloatArray jarray = (*p_env)->NewFloatArray(p_env, 16);
+ if ((*p_env)->ExceptionCheck(p_env))
+ {
+ (*p_env)->ExceptionClear(p_env);
+ free(p_awh);
+ return NULL;
+ }
+ p_awh->stex.jtransform_mtx_array = (*p_env)->NewGlobalRef(p_env, jarray);
+ (*p_env)->DeleteLocalRef(p_env, jarray);
+ p_awh->stex.jtransform_mtx = NULL;
+
const jint flags = JNI_ANWCALL(CallIntMethod, registerNative,
(jlong)(intptr_t)p_awh);
if ((flags & AWINDOW_REGISTER_FLAGS_SUCCESS) == 0)
{
msg_Err(wnd, "AWindow already registered");
(*p_env)->DeleteGlobalRef(p_env, p_awh->jobj);
+ (*p_env)->DeleteGlobalRef(p_env, p_awh->stex.jtransform_mtx_array);
free(p_awh);
return NULL;
}
@@ -604,6 +609,7 @@ AWindowHandler_destroy(AWindowHandler *p_awh)
if (p_awh->p_anw_dl)
dlclose(p_awh->p_anw_dl);
+ (*p_env)->DeleteGlobalRef(p_env, p_awh->stex.jtransform_mtx_array);
free(p_awh);
}
@@ -619,10 +625,18 @@ WindowHandler_NewSurfaceEnv(AWindowHandler *p_awh, JNIEnv *p_env,
{
jobject jsurface;
- if (id == AWindow_Video)
- jsurface = JNI_ANWCALL(CallObjectMethod, getVideoSurface);
- else
- jsurface = JNI_ANWCALL(CallObjectMethod, getSubtitlesSurface);
+ switch (id)
+ {
+ case AWindow_Video:
+ jsurface = JNI_ANWCALL(CallObjectMethod, getVideoSurface);
+ break;
+ case AWindow_Subtitles:
+ jsurface = JNI_ANWCALL(CallObjectMethod, getSubtitlesSurface);
+ break;
+ case AWindow_SurfaceTexture:
+ jsurface = JNI_STEXCALL(CallObjectMethod, getSurface);
+ break;
+ }
if (!jsurface)
return VLC_EGENERIC;
@@ -742,155 +756,62 @@ AWindowHandler_setVideoLayout(AWindowHandler *p_awh,
return VLC_SUCCESS;
}
-SurfaceTexture *
-SurfaceTexture_create(vlc_object_t *p_obj, int i_tex_name)
+int
+SurfaceTexture_attachToGLContext(AWindowHandler *p_awh, int tex_name)
{
- if (jfields.SurfaceTextureThread.create == NULL)
- return NULL;
-
- JavaVM *p_jvm = var_InheritAddress(p_obj, "android-jvm");
- if (p_jvm == NULL)
- return NULL;
-
- JNIEnv *p_env = android_getEnvCommon(NULL, p_jvm, "SurfaceTexture");
+ JNIEnv *p_env = android_getEnvCommon(NULL, p_awh->p_jvm, "SurfaceTexture");
if (!p_env)
- return NULL;
-
- SurfaceTexture *p_stex = malloc(sizeof(SurfaceTexture));
- if (p_stex == NULL)
- return NULL;
-
- void *p_library = dlopen("libandroid.so", RTLD_NOW);
- if (!p_library)
- goto error;
-
- p_stex->pf_winFromSurface = dlsym(p_library, "ANativeWindow_fromSurface");
- p_stex->pf_winRelease = dlsym(p_library, "ANativeWindow_release");
- if (p_stex->pf_winFromSurface == NULL || p_stex->pf_winRelease == NULL)
- goto error;
- p_stex->p_anw_dl = p_library;
- p_stex->p_jvm = p_jvm;
- p_stex->p_anw = NULL;
- p_stex->jsurface = NULL;
-
- jfloatArray jarray = (*p_env)->NewFloatArray(p_env, 16);
- if ((*p_env)->ExceptionCheck(p_env))
- {
- (*p_env)->ExceptionClear(p_env);
- goto error;
- }
- p_stex->jtransform_mtx_array = (*p_env)->NewGlobalRef(p_env, jarray);
- (*p_env)->DeleteLocalRef(p_env, jarray);
- p_stex->jtransform_mtx = NULL;
-
- jobject thiz = JNI_STEXCALL(CallStaticObjectMethod, create, i_tex_name);
- if ((*p_env)->ExceptionCheck(p_env))
- {
- (*p_env)->ExceptionClear(p_env);
- (*p_env)->DeleteGlobalRef(p_env, p_stex->jtransform_mtx_array);
- goto error;
- }
- p_stex->thiz = (*p_env)->NewGlobalRef(p_env, thiz);
- (*p_env)->DeleteLocalRef(p_env, thiz);
-
- return p_stex;
+ return VLC_EGENERIC;
-error:
- free(p_stex);
- if (p_library != NULL)
- dlclose(p_library);
- return NULL;
+ return JNI_STEXCALL(CallBooleanMethod, attachToGLContext, tex_name) ?
+ VLC_SUCCESS : VLC_EGENERIC;
}
void
-SurfaceTexture_release(SurfaceTexture *p_stex)
+SurfaceTexture_detachFromGLContext(AWindowHandler *p_awh)
{
- JNIEnv *p_env = android_getEnvCommon(NULL, p_stex->p_jvm, "SurfaceTexture");
+ JNIEnv *p_env = android_getEnvCommon(NULL, p_awh->p_jvm, "SurfaceTexture");
if (!p_env)
return;
- if (p_stex->p_anw != NULL)
- p_stex->pf_winRelease(p_stex->p_anw);
-
- if (p_stex->jsurface != NULL)
- (*p_env)->DeleteGlobalRef(p_env, p_stex->jsurface);
-
- JNI_STEXCALL(CallStaticVoidMethod, release, p_stex->thiz);
- (*p_env)->DeleteGlobalRef(p_env, p_stex->thiz);
-
- if (p_stex->jtransform_mtx != NULL)
- (*p_env)->ReleaseFloatArrayElements(p_env, p_stex->jtransform_mtx_array,
- p_stex->jtransform_mtx,
- JNI_ABORT);
- (*p_env)->DeleteGlobalRef(p_env, p_stex->jtransform_mtx_array);
-
- dlclose(p_stex->p_anw_dl);
- free(p_stex);
-}
-
-jobject
-SurfaceTexture_getSurface(SurfaceTexture *p_stex)
-{
- JNIEnv *p_env = android_getEnvCommon(NULL, p_stex->p_jvm, "SurfaceTexture");
- if (!p_env)
- return NULL;
-
- if (p_stex->jsurface == NULL)
- {
- jobject jsurface =
- JNI_STEXCALL(CallStaticObjectMethod, getSurface, p_stex->thiz);
- if ((*p_env)->ExceptionCheck(p_env))
- {
- (*p_env)->ExceptionClear(p_env);
- return NULL;
- }
- p_stex->jsurface = (*p_env)->NewGlobalRef(p_env, jsurface);
- (*p_env)->DeleteLocalRef(p_env, jsurface);
- }
- return p_stex->jsurface;
-}
+ JNI_STEXCALL(CallVoidMethod, detachFromGLContext);
-ANativeWindow *
-SurfaceTexture_getANativeWindow(SurfaceTexture *p_stex)
-{
- JNIEnv *p_env = android_getEnvCommon(NULL, p_stex->p_jvm, "SurfaceTexture");
- if (!p_env)
- return NULL;
+ AWindowHandler_releaseANativeWindowEnv(p_awh, p_env, AWindow_SurfaceTexture);
- if (p_stex->p_anw == NULL)
+ if (p_awh->stex.jtransform_mtx != NULL)
{
- jobject jsurface = SurfaceTexture_getSurface(p_stex);
- if (jsurface != NULL)
- p_stex->p_anw = p_stex->pf_winFromSurface(p_env, jsurface);
+ (*p_env)->ReleaseFloatArrayElements(p_env, p_awh->stex.jtransform_mtx_array,
+ p_awh->stex.jtransform_mtx,
+ JNI_ABORT);
+ p_awh->stex.jtransform_mtx = NULL;
}
- return p_stex->p_anw;
}
int
-SurfaceTexture_waitAndUpdateTexImage(SurfaceTexture *p_stex,
+SurfaceTexture_waitAndUpdateTexImage(AWindowHandler *p_awh,
const float **pp_transform_mtx)
{
- JNIEnv *p_env = android_getEnvCommon(NULL, p_stex->p_jvm, "SurfaceTexture");
+ JNIEnv *p_env = android_getEnvCommon(NULL, p_awh->p_jvm, "SurfaceTexture");
if (!p_env)
return VLC_EGENERIC;
- if (p_stex->jtransform_mtx != NULL)
- (*p_env)->ReleaseFloatArrayElements(p_env, p_stex->jtransform_mtx_array,
- p_stex->jtransform_mtx,
+ if (p_awh->stex.jtransform_mtx != NULL)
+ (*p_env)->ReleaseFloatArrayElements(p_env, p_awh->stex.jtransform_mtx_array,
+ p_awh->stex.jtransform_mtx,
JNI_ABORT);
- bool ret = JNI_STEXCALL(CallStaticBooleanMethod, waitAndUpdateTexImage,
- p_stex->thiz, p_stex->jtransform_mtx_array);
+ bool ret = JNI_STEXCALL(CallBooleanMethod, waitAndUpdateTexImage,
+ p_awh->stex.jtransform_mtx_array);
if (ret)
{
- p_stex->jtransform_mtx = (*p_env)->GetFloatArrayElements(p_env,
- p_stex->jtransform_mtx_array, NULL);
- *pp_transform_mtx = p_stex->jtransform_mtx;
+ p_awh->stex.jtransform_mtx = (*p_env)->GetFloatArrayElements(p_env,
+ p_awh->stex.jtransform_mtx_array, NULL);
+ *pp_transform_mtx = p_awh->stex.jtransform_mtx;
return VLC_SUCCESS;
}
else
{
- p_stex->jtransform_mtx = NULL;
+ p_awh->stex.jtransform_mtx = NULL;
return VLC_EGENERIC;
}
}
diff --git a/modules/video_output/android/utils.h b/modules/video_output/android/utils.h
index 704755da44..87b0d9cc67 100644
--- a/modules/video_output/android/utils.h
+++ b/modules/video_output/android/utils.h
@@ -34,11 +34,11 @@
#include <vlc_common.h>
typedef struct AWindowHandler AWindowHandler;
-typedef struct SurfaceTexture SurfaceTexture;
enum AWindow_ID {
AWindow_Video,
AWindow_Subtitles,
+ AWindow_SurfaceTexture,
AWindow_Max,
};
@@ -177,35 +177,43 @@ int AWindowHandler_setVideoLayout(AWindowHandler *p_awh,
int i_sar_num, int i_sar_den);
/**
- * Construct a new Java SurfaceTexture to stream images to a given OpenGL
- * texture
+ * Attach a SurfaceTexture to the OpenGL ES context that is current on the
+ * calling thread.
*
* See SurfaceTexture Android documentation.
+ * \return 0 on success, -1 on error.
*/
-SurfaceTexture *
-SurfaceTexture_create(vlc_object_t *p_obj, int tex_name);
+int
+SurfaceTexture_attachToGLContext(AWindowHandler *p_awh, int tex_name);
/**
- * Release a SurfaceTexture
+ * Detach a SurfaceTexture from the OpenGL ES context that owns the OpenGL ES
+ * texture object.
*/
void
-SurfaceTexture_release(SurfaceTexture *p_stex);
+SurfaceTexture_detachFromGLContext(AWindowHandler *p_awh);
/**
- * Get a Java Surface from the SurfaceTexture
+ * Get a Java Surface from the attached SurfaceTexture
*
* This object can be used with mediacodec_jni.
*/
-jobject
-SurfaceTexture_getSurface(SurfaceTexture *p_stex);
+static inline jobject
+SurfaceTexture_getSurface(AWindowHandler *p_awh)
+{
+ return AWindowHandler_getSurface(p_awh, AWindow_SurfaceTexture);
+}
/**
- * Get a ANativeWindow from the SurfaceTexture
+ * Get a ANativeWindow from the attached SurfaceTexture
*
* This pointer can be used with mediacodec_ndk.
*/
-ANativeWindow *
-SurfaceTexture_getANativeWindow(SurfaceTexture *p_stex);
+static inline ANativeWindow *
+SurfaceTexture_getANativeWindow(AWindowHandler *p_awh)
+{
+ return AWindowHandler_getANativeWindow(p_awh, AWindow_SurfaceTexture);
+}
/**
* Wait for a new frame and update it
@@ -221,5 +229,5 @@ SurfaceTexture_getANativeWindow(SurfaceTexture *p_stex);
* \return VLC_SUCCESS or a VLC error
*/
int
-SurfaceTexture_waitAndUpdateTexImage(SurfaceTexture *p_stex,
+SurfaceTexture_waitAndUpdateTexImage(AWindowHandler *p_awh,
const float **pp_transform_mtx);
diff --git a/modules/video_output/opengl/converter_android.c b/modules/video_output/opengl/converter_android.c
index db55cf03ef..3e0f03c0da 100644
--- a/modules/video_output/opengl/converter_android.c
+++ b/modules/video_output/opengl/converter_android.c
@@ -33,8 +33,9 @@
struct priv
{
- SurfaceTexture *stex;
+ AWindowHandler *awh;
const float *transform_mtx;
+ bool stex_attached;
struct {
GLint uSTMatrix;
@@ -68,12 +69,12 @@ tc_anop_allocate_textures(const opengl_tex_converter_t *tc, GLuint *textures,
(void) tex_width; (void) tex_height;
struct priv *priv = tc->priv;
assert(textures[0] != 0);
- priv->stex = SurfaceTexture_create(VLC_OBJECT(tc->gl), textures[0]);
- if (priv->stex == NULL)
+ if (SurfaceTexture_attachToGLContext(priv->awh, textures[0]) != 0)
{
- msg_Err(tc->gl, "tc_anop_get_pool: SurfaceTexture_create failed");
+ msg_Err(tc->gl, "SurfaceTexture_attachToGLContext failed");
return VLC_EGENERIC;
}
+ priv->stex_attached = true;
return VLC_SUCCESS;
}
@@ -98,8 +99,8 @@ tc_anop_get_pool(const opengl_tex_converter_t *tc, const video_format_t *fmt,
};
p_picsys->hw.b_vd_ref = true;
- p_picsys->hw.p_surface = SurfaceTexture_getANativeWindow(priv->stex);
- p_picsys->hw.p_jsurface = SurfaceTexture_getSurface(priv->stex);
+ p_picsys->hw.p_surface = SurfaceTexture_getANativeWindow(priv->awh);
+ p_picsys->hw.p_jsurface = SurfaceTexture_getSurface(priv->awh);
p_picsys->hw.i_index = -1;
vlc_mutex_init(&p_picsys->hw.lock);
@@ -147,7 +148,7 @@ tc_anop_update(const opengl_tex_converter_t *tc, GLuint *textures,
AndroidOpaquePicture_Release(pic->p_sys, true);
- if (SurfaceTexture_waitAndUpdateTexImage(priv->stex, &priv->transform_mtx)
+ if (SurfaceTexture_waitAndUpdateTexImage(priv->awh, &priv->transform_mtx)
!= VLC_SUCCESS)
{
priv->transform_mtx = NULL;
@@ -184,8 +185,9 @@ static void
tc_anop_release(const opengl_tex_converter_t *tc)
{
struct priv *priv = tc->priv;
- if (priv->stex != NULL)
- SurfaceTexture_release(priv->stex);
+
+ if (priv->stex_attached)
+ SurfaceTexture_detachFromGLContext(priv->awh);
free(priv);
}
@@ -194,7 +196,8 @@ GLuint
opengl_tex_converter_anop_init(const video_format_t *fmt,
opengl_tex_converter_t *tc)
{
- if (fmt->i_chroma != VLC_CODEC_ANDROID_OPAQUE)
+ if (fmt->i_chroma != VLC_CODEC_ANDROID_OPAQUE
+ || !tc->gl->surface->handle.anativewindow)
return 0;
tc->priv = malloc(sizeof(struct priv));
@@ -202,8 +205,9 @@ opengl_tex_converter_anop_init(const video_format_t *fmt,
return 0;
struct priv *priv = tc->priv;
- priv->stex = NULL;
+ priv->awh = tc->gl->surface->handle.anativewindow;
priv->transform_mtx = NULL;
+ priv->stex_attached = false;
tc->pf_allocate_textures = tc_anop_allocate_textures;
tc->pf_get_pool = tc_anop_get_pool;
More information about the vlc-commits
mailing list