[vlc-devel] [PATCH 3/5] android: util: init ASurfaceTexture from Java

Thomas Guillem thomas at gllm.fr
Tue Apr 28 16:30:54 CEST 2020



On Tue, Apr 28, 2020, at 12:57, Thomas Guillem wrote:
> 
> 
> On Mon, Apr 27, 2020, at 23:28, Louis Regnier wrote:
> > 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;
> 
> This variable name is confusing. It seem to be used to identify if the 
> NDK API is present. Why not adding ndk in the var name ?
> Also, when is this variable set to true ?
> 
> >  
> >      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;
> 
> This is misleading but it is my fault.
> The methods from the SurfaceTexture struct are methods of the AWindow 
> class.
> The methods from the AndroidNativeWindow struct are methods of the 
> AWindow class.
> Therefore, both struct should be first merged and name AWindow.
> 
> Then you could add clazz and constructor on the SurfaceTexture struct 
> that will be methods/class of the SurfaceTexture class.
> 
> > @@ -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)); \
> 
> You leak a local ref, you should call (*env)->DeleteLocalRef(env, 
> clazz); after getting the global ref (and use an other class var).
> 
> 
> > +        if (!(clazz)) { \
> > +            return -1; \
> > +        } \
> > +    } \
> > +} while (0)
> 
> THis macro is used only one time, and could be removed.
> 
> > +
> > +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;
> 
> I think you could put direcly the content of this function in 
> LoadSurfaceTextureAPI().
> 
> > +}
> > +
> >  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);
> 
> You leak a local ref, you should call (*env)->DeleteLocalRef(env, 
> surfacetexture); after getting the global ref.

Ah no, you release it at the end of this function.

> 
> > +
> > +    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
> > 
> > _______________________________________________
> > vlc-devel mailing list
> > To unsubscribe or modify your subscription options:
> > https://mailman.videolan.org/listinfo/vlc-devel
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list