vlc | branch: master | Thomas Guillem <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
