[vlc-devel] [PATCH 2/3] Support for multiple video instances for android.

Thomas Guillem thomas at gllm.fr
Tue Nov 25 11:43:56 CET 2014



On Tue, Nov 25, 2014, at 08:30, Paulo Vitor Magacho da Silva wrote:
> Support for multiple video instances for android.
> ---
>  include/vlc/libvlc_media_player.h           | 17 +++++++++++++++
>  lib/media_player.c                          | 32
>  +++++++++++++++++++++++++++++
>  modules/codec/omxil/android_mediacodec.c    | 30
>  +++++++++++++++++++--------
>  modules/codec/omxil/omxil.c                 | 25 +++++++++++++++-------
>  modules/codec/omxil/omxil.h                 |  3 +++
>  modules/video_output/android/nativewindow.c | 14 ++++++-------
>  modules/video_output/android/surface.c      | 29
>  ++++++++++++++++++--------
>  modules/video_output/android/utils.h        | 11 ++++++++++
>  src/libvlc.c                                |  3 +++
>  9 files changed, 133 insertions(+), 31 deletions(-)

Again, It won't apply on up to date master, since there is now a new
android_vout.

> 
> diff --git a/include/vlc/libvlc_media_player.h
> b/include/vlc/libvlc_media_player.h
> index 1c73cf2..e3f925f 100644
> --- a/include/vlc/libvlc_media_player.h
> +++ b/include/vlc/libvlc_media_player.h
> @@ -437,6 +437,23 @@ LIBVLC_API void libvlc_media_player_set_nsobject (
> libvlc_media_player_t *p_mi,
>  LIBVLC_API void * libvlc_media_player_get_nsobject (
>  libvlc_media_player_t *p_mi );
>  
>  /**
> + * Set the android_surface_value_t structure handler holding the Android
> surface information where
> + * the media player should render its video output.
> + *
> + * \param p_mi the Media Player
> + * \param object the android_surface_value_t structure to set.
> + */
> +LIBVLC_API void libvlc_media_player_set_surfacevalue (
> libvlc_media_player_t *p_mi, void * object );
> +
> +/**
> + * Gets a handler to the android_surface_value_t structure holding
> Android Surface object information.
> + *
> + * \param p_mi the Media Player
> + * \return the android_surface_value_t pointer or 0 if none where set
> + */
> +LIBVLC_API void * libvlc_media_player_get_surfacevalue (
> libvlc_media_player_t *p_mi );
> +
> +/**
>   * Set the agl handler where the media player should render its video
>   output.
>   *
>   * \param p_mi the Media Player
> diff --git a/lib/media_player.c b/lib/media_player.c
> index 698f8d2..f2b388e 100644
> --- a/lib/media_player.c
> +++ b/lib/media_player.c
> @@ -515,6 +515,9 @@ libvlc_media_player_new( libvlc_instance_t *instance
> )
>      var_Create (mp, "drawable-agl", VLC_VAR_INTEGER);
>      var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
>  #endif
> +#ifdef __ANDROID__
> +    var_Create (mp, "drawable-surfacevalue", VLC_VAR_ADDRESS);
> +#endif
>  
>      var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
>      var_SetBool (mp, "keyboard-events", true);
> @@ -1017,6 +1020,35 @@ void * libvlc_media_player_get_nsobject(
> libvlc_media_player_t *p_mi )
>  #endif
>  }
>  
> +
> +/**************************************************************************
> + * set_surfacevalue
> +
> **************************************************************************/
> +void libvlc_media_player_set_surfacevalue( libvlc_media_player_t *p_mi,
> +                                           void * object )
> +{
> +    assert (p_mi != NULL);
> +#ifdef __ANDROID__
> +    var_SetAddress (p_mi, "drawable-surfacevalue", object);
> +#else
> +    (void) p_mi; (void)object;
> +#endif
> +}
> +
> +/**************************************************************************
> + * get_surfacevalue
> +
> **************************************************************************/
> +void * libvlc_media_player_get_surfacevalue( libvlc_media_player_t *p_mi
> )
> +{
> +    assert (p_mi != NULL);
> +#ifdef __ANDROID__
> +    return var_GetAddress (p_mi, "drawable-surfacevalue");
> +#else
> +    return NULL;
> +#endif
> +}
> +
> +

This should be done in a separate commit that touch only libvlc.

>  /**************************************************************************
>   * set_agl
>   **************************************************************************/
> diff --git a/modules/codec/omxil/android_mediacodec.c
> b/modules/codec/omxil/android_mediacodec.c
> index 00bea88..de2ba86 100644
> --- a/modules/codec/omxil/android_mediacodec.c
> +++ b/modules/codec/omxil/android_mediacodec.c
> @@ -50,13 +50,15 @@
>  
>  #define THREAD_NAME "android_mediacodec"
>  
> +typedef struct android_surf_value_t android_surf_value_t;
> +
>  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
>  extern void jni_detach_thread();
>  /* JNI functions to get/set an Android Surface object. */
> -extern jobject jni_LockAndGetAndroidJavaSurface();
> -extern void jni_UnlockAndroidSurface();
> -extern void jni_EventHardwareAccelerationError();
> -extern bool jni_IsVideoPlayerActivityCreated();
> +extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t
> *object);
> +extern void jni_UnlockAndroidSurface(android_surf_value_t *object);
> +extern void jni_EventHardwareAccelerationError(android_surf_value_t
> *android_surface);
> +extern bool jni_IsVideoPlayerActivityCreated(android_surf_value_t
> *android_surface);
>  
>  /* Implementation of a circular buffer of timestamps with overwriting
>   * of older values. MediaCodec has only one type of timestamp, if a
> @@ -172,6 +174,8 @@ struct decoder_sys_t
>      picture_t** inflight_picture; /**< stores the inflight picture for
>      each output buffer or NULL */
>  
>      timestamp_fifo_t *timestamp_fifo;
> +
> +    android_surf_value_t *object;
>  };
>  
>  enum Types
> @@ -325,6 +329,12 @@ static int OpenDecoder(vlc_object_t *p_this)
>      if ((p_dec->p_sys = p_sys = calloc(1, sizeof(*p_sys))) == NULL)
>          return VLC_ENOMEM;
>  
> +    p_sys->object = var_CreateGetAddress (p_dec,
> "drawable-surfacevalue");
> +    if (!p_sys->object) {
> +        msg_Warn(p_dec, "No android_surf_value_t set.");
> +        return VLC_EGENERIC;
> +    }
> +
>      p_dec->pf_decode_video = DecodeVideo;
>  
>      p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
> @@ -504,16 +514,16 @@ static int OpenDecoder(vlc_object_t *p_this)
>      /* If the VideoPlayerActivity is not started, MediaCodec opaque
>         direct rendering should be disabled since no surface will be
>         attached to the JNI. */
> -    p_sys->direct_rendering = jni_IsVideoPlayerActivityCreated() &&
> var_InheritBool(p_dec, CFG_PREFIX "dr");
> +    p_sys->direct_rendering =
> jni_IsVideoPlayerActivityCreated(p_sys->object) && var_InheritBool(p_dec,
> CFG_PREFIX "dr");
>      if (p_sys->direct_rendering) {
> -        jobject surf = jni_LockAndGetAndroidJavaSurface();
> +        jobject surf = jni_LockAndGetAndroidJavaSurface(p_sys->object);
>          if (surf) {
>              // Configure MediaCodec with the Android surface.
>              (*env)->CallVoidMethod(env, p_sys->codec, p_sys->configure,
>              format, surf, NULL, 0);
>              if ((*env)->ExceptionOccurred(env)) {
>                  msg_Warn(p_dec, "Exception occurred in
>                  MediaCodec.configure with an output surface.");
>                  (*env)->ExceptionClear(env);
> -                jni_UnlockAndroidSurface();
> +                jni_UnlockAndroidSurface(p_sys->object);
>                  goto error;
>              }
>              p_dec->fmt_out.i_codec = VLC_CODEC_ANDROID_OPAQUE;
> @@ -521,7 +531,7 @@ static int OpenDecoder(vlc_object_t *p_this)
>              msg_Warn(p_dec, "Failed to get the Android Surface,
>              disabling direct rendering.");
>              p_sys->direct_rendering = false;
>          }
> -        jni_UnlockAndroidSurface();
> +        jni_UnlockAndroidSurface(p_sys->object);
>      }
>      if (!p_sys->direct_rendering) {
>          (*env)->CallVoidMethod(env, p_sys->codec, p_sys->configure,
>          format, NULL, NULL, 0);
> @@ -576,6 +586,8 @@ static void CloseDecoder(vlc_object_t *p_this)
>      if (!p_sys)
>          return;
>  
> +    var_Destroy (p_dec, "drawable-surfacevalue");
> +
>      /* Invalidate all pictures that are currently in flight in order
>       * to prevent the vout from using destroyed output buffers. */
>      if (p_sys->direct_rendering)
> @@ -885,7 +897,7 @@ static picture_t *DecodeVideo(decoder_t *p_dec,
> block_t **pp_block)
>          block_Release(p_block);
>          if (!p_sys->error_event_sent) {
>              /* Signal the error to the Java. */
> -            jni_EventHardwareAccelerationError();
> +            jni_EventHardwareAccelerationError(p_sys->object);
>              p_sys->error_event_sent = true;
>          }
>          return NULL;
> diff --git a/modules/codec/omxil/omxil.c b/modules/codec/omxil/omxil.c
> index 03814d0..82cc6f2 100644
> --- a/modules/codec/omxil/omxil.c
> +++ b/modules/codec/omxil/omxil.c
> @@ -70,9 +70,9 @@
>  #define THREAD_NAME "omxil"
>  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
>  extern void jni_detach_thread();
> -extern jobject jni_LockAndGetAndroidJavaSurface();
> -extern void jni_UnlockAndroidSurface();
> -extern bool jni_IsVideoPlayerActivityCreated();
> +extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t
> *object);
> +extern void jni_UnlockAndroidSurface(android_surf_value_t *object);
> +extern bool jni_IsVideoPlayerActivityCreated(android_surf_value_t
> *android_surface);
>  #endif
>  
>  /*****************************************************************************
> @@ -1056,6 +1056,15 @@ static int OpenGeneric( vlc_object_t *p_this, bool
> b_encode )
>          return VLC_ENOMEM;
>      }
>  
> +#if defined(USE_IOMX)
> +    p_sys->object = var_CreateGetAddress (p_dec,
> "drawable-surfacevalue");
> +    if (!p_sys->object) {
> +        msg_Warn(p_dec, "No android_surf_value_t set.");
> +        DeinitOmxCore();
> +        return VLC_EGENERIC;
> +    }
> +#endif
> +
>      /* Initialise the thread properties */
>      if(!b_encode)
>      {
> @@ -1078,7 +1087,7 @@ static int OpenGeneric( vlc_object_t *p_this, bool
> b_encode )
>      p_sys->in.p_fmt = &p_dec->fmt_in;
>      OMX_FIFO_INIT (&p_sys->out.fifo, pInputPortPrivate );
>  #if defined(USE_IOMX)
> -    p_sys->out.b_direct = jni_IsVideoPlayerActivityCreated() &&
> var_InheritBool(p_dec, CFG_PREFIX "dr");
> +    p_sys->out.b_direct =
> jni_IsVideoPlayerActivityCreated(p_sys->object) && var_InheritBool(p_dec,
> CFG_PREFIX "dr");
>  #else
>      p_sys->out.b_direct = false;
>  #endif
> @@ -1913,6 +1922,8 @@ static void CloseGeneric( vlc_object_t *p_this )
>      OMX_FIFO_DESTROY( &p_sys->in.fifo );
>      OMX_FIFO_DESTROY( &p_sys->out.fifo );
>  
> +    var_Destroy (p_dec, "drawable-surfacevalue");
> +
>      free( p_sys );
>  }
>  
> @@ -2089,9 +2100,9 @@ static void HwBuffer_Init( decoder_t *p_dec,
> OmxPort *p_port )
>          goto error;
>      }
>  
> -    surf = jni_LockAndGetAndroidJavaSurface();
> +    surf = jni_LockAndGetAndroidJavaSurface(p_dec->p_sys->object);
>      if( !surf ) {
> -        jni_UnlockAndroidSurface();
> +        jni_UnlockAndroidSurface(p_dec->p_sys->object);
>          msg_Warn( p_dec, "jni_LockAndGetAndroidJavaSurface failed" );
>          goto error;
>      }
> @@ -2100,7 +2111,7 @@ static void HwBuffer_Init( decoder_t *p_dec,
> OmxPort *p_port )
>      p_port->p_hwbuf->window =
>      p_port->p_hwbuf->native_window.winFromSurface( p_env, surf );
>      jni_detach_thread();
>  
> -    jni_UnlockAndroidSurface();
> +    jni_UnlockAndroidSurface(p_dec->p_sys->object);
>      if( !p_port->p_hwbuf->window ) {
>          msg_Warn( p_dec, "winFromSurface failed" );
>          goto error;
> diff --git a/modules/codec/omxil/omxil.h b/modules/codec/omxil/omxil.h
> index 911f5f6..02279a3 100644
> --- a/modules/codec/omxil/omxil.h
> +++ b/modules/codec/omxil/omxil.h
> @@ -138,4 +138,7 @@ struct decoder_sys_t
>      size_t i_nal_size_length; /* Length of the NAL size field for H264
>      */
>      int b_use_pts;
>  
> +#if defined(USE_IOMX)
> +    android_surf_value_t *object;
> +#endif
>  };
> diff --git a/modules/video_output/android/nativewindow.c
> b/modules/video_output/android/nativewindow.c
> index 98c03fa..584bdec 100644
> --- a/modules/video_output/android/nativewindow.c
> +++ b/modules/video_output/android/nativewindow.c
> @@ -40,9 +40,9 @@
>  #define THREAD_NAME "ANativeWindow"
>  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
>  extern void jni_detach_thread();
> -extern jobject jni_LockAndGetAndroidJavaSurface();
> -extern void jni_UnlockAndroidSurface();
> -extern void  jni_SetSurfaceLayout(int width, int height, int
> visible_width, int visible_height, int sar_num, int sar_den);
> +extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t
> *object);
> +extern void jni_UnlockAndroidSurface(android_surf_value_t *object);
> +extern void  jni_SetSurfaceLayout(android_surf_value_t *object, int
> width, int height, int visible_width, int visible_height, int sar_num,
> int sar_den);
>  
>  static int Open(vout_window_t *, const vout_window_cfg_t *);
>  static void Close(vout_window_t *);
> @@ -90,7 +90,7 @@ static int Open(vout_window_t *wnd, const
> vout_window_cfg_t *cfg)
>      }
>  
>      // Create the native window by first getting the Java surface.
> -    jobject javaSurface = jni_LockAndGetAndroidJavaSurface();
> +    jobject javaSurface = jni_LockAndGetAndroidJavaSurface(NULL);
>      if (javaSurface == NULL)
>          goto error;
>  
> @@ -99,7 +99,7 @@ static int Open(vout_window_t *wnd, const
> vout_window_cfg_t *cfg)
>      p_sys->window = p_sys->native_window.winFromSurface(p_env,
>      javaSurface); // ANativeWindow_fromSurface call.
>      jni_detach_thread();
>  
> -    jni_UnlockAndroidSurface();
> +    jni_UnlockAndroidSurface(NULL);
>  
>      if (p_sys->window == NULL)
>          goto error;
> @@ -110,7 +110,7 @@ static int Open(vout_window_t *wnd, const
> vout_window_cfg_t *cfg)
>      wnd->sys = p_sys;
>  
>      // Set the Java surface size.
> -    jni_SetSurfaceLayout(cfg->width, cfg->height, cfg->width,
> cfg->height, 1, 1);
> +    jni_SetSurfaceLayout(NULL, cfg->width, cfg->height, cfg->width,
> cfg->height, 1, 1);
>  
>      return VLC_SUCCESS;
>  
> @@ -144,7 +144,7 @@ static int Control(vout_window_t *wnd, int cmd,
> va_list ap)
>          {
>              unsigned width = va_arg(ap, unsigned);
>              unsigned height = va_arg(ap, unsigned);
> -            jni_SetSurfaceLayout(width, height, width, height, 1, 1);
> +            jni_SetSurfaceLayout(NULL, width, height, width, height, 1,
> 1);
>              break;
>          }
>          case VOUT_WINDOW_SET_STATE:
> diff --git a/modules/video_output/android/surface.c
> b/modules/video_output/android/surface.c
> index bd10618..32a8772 100644
> --- a/modules/video_output/android/surface.c
> +++ b/modules/video_output/android/surface.c
> @@ -76,11 +76,11 @@ vlc_module_end()
>  #define THREAD_NAME "AndroidSurface"
>  extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
>  extern void jni_detach_thread();
> -extern jobject jni_LockAndGetAndroidJavaSurface();
> -extern void  jni_UnlockAndroidSurface();
> +extern jobject jni_LockAndGetAndroidJavaSurface(android_surf_value_t
> *object);
> +extern void  jni_UnlockAndroidSurface(android_surf_value_t *object);
>  extern void *jni_AndroidJavaSurfaceToNativeSurface(jobject *surf);
> -extern void  jni_SetSurfaceLayout(int width, int height, int
> visible_width, int visible_height, int sar_num, int sar_den);
> -extern int jni_ConfigureSurface(jobject jsurf, int width, int height,
> int hal, bool *configured);
> +extern void  jni_SetSurfaceLayout(android_surf_value_t *object, int
> width, int height, int visible_width, int visible_height, int sar_num,
> int sar_den);
> +extern int jni_ConfigureSurface(jobject jsurf, android_surf_value_t
> *object, int width, int height, int hal, bool *configured);
>  
>  // _ZN7android7Surface4lockEPNS0_11SurfaceInfoEb
>  typedef void (*Surface_lock)(void *, void *, int);
> @@ -124,6 +124,8 @@ struct vout_display_sys_t {
>      unsigned int i_alloc_height;
>  
>      video_format_t fmt;
> +
> +    android_surf_value_t *object;
>  };
>  
>  struct picture_sys_t {
> @@ -186,7 +188,8 @@ static void UpdateLayout(vout_display_sys_t *sys)
>          i_height = sys->fmt.i_height;
>      }
>  
> -    jni_SetSurfaceLayout(i_width, i_height,
> +    jni_SetSurfaceLayout(sys->object,
> +                         i_width, i_height,
>                           sys->fmt.i_visible_width,
>                           sys->fmt.i_visible_height,
>                           i_sar_num,
> @@ -209,6 +212,13 @@ static int Open(vlc_object_t *p_this)
>      if (!sys)
>          goto error;
>  
> +    sys->object = var_CreateGetAddress (vd, "drawable-surfacevalue");
> +    if (!sys->object) {
> +        free(sys);
> +        msg_Err(vd, "No android_surf_value_t set.");
> +        return VLC_EGENERIC;
> +    }
> +
>      /* */
>      sys->p_library = InitLibrary(sys);
>      if (!sys->p_library) {
> @@ -304,6 +314,8 @@ static void Close(vlc_object_t *p_this)
>      vout_display_t *vd = (vout_display_t *)p_this;
>      vout_display_sys_t *sys = vd->sys;
>  
> +    var_Destroy (vd, "drawable-surfacevalue");
> +
>      if (sys) {
>          if (sys->pool)
>              picture_pool_Release(sys->pool);
> @@ -328,13 +340,13 @@ static int  AndroidLockSurface(picture_t *picture)
>      uint32_t sw, sh;
>  
>      if (!sys->native_surface) {
> -        picsys->surf = jni_LockAndGetAndroidJavaSurface();
> +        picsys->surf = jni_LockAndGetAndroidJavaSurface(sys->object);
>          if (unlikely(!picsys->surf)) {
> -            jni_UnlockAndroidSurface();
> +            jni_UnlockAndroidSurface(sys->object);
>              return VLC_EGENERIC;
>          }
>          sys->native_surface =
>          jni_AndroidJavaSurfaceToNativeSurface(picsys->surf);
> -        jni_UnlockAndroidSurface();
> +        jni_UnlockAndroidSurface(sys->object);
>  
>          if (!sys->native_surface)
>              return VLC_EGENERIC;
> @@ -349,6 +361,7 @@ static int  AndroidLockSurface(picture_t *picture)
>      if (aligned_width != sys->i_alloc_width || sh !=
>      sys->i_alloc_height) {
>          bool configured;
>          if (jni_ConfigureSurface(picsys->surf,
> +                                 sys->object,
>                                   aligned_width,
>                                   sh,
>                                   sys->i_android_hal,
> diff --git a/modules/video_output/android/utils.h
> b/modules/video_output/android/utils.h
> index 96d4f86..11274b8 100644
> --- a/modules/video_output/android/utils.h
> +++ b/modules/video_output/android/utils.h
> @@ -24,6 +24,7 @@
>  # include "config.h"
>  #endif
>  
> +#include <pthread.h>
>  #include <android/native_window.h>
>  #include <jni.h>
>  #include <android/native_window_jni.h>
> @@ -46,6 +47,16 @@ typedef struct
>      ptr_ANativeWindow_setBuffersGeometry setBuffersGeometry;
>  } native_window_api_t;
>  
> +typedef struct android_surf_value_t {
> +    pthread_mutex_t vout_android_lock;
> +    pthread_cond_t vout_android_surf_attached;
> +    void *vout_android_surf;
> +    void *vout_android_gui;
> +    jobject vout_android_java_surf;
> +    jobject vout_android_subtitles_surf;
> +    bool vout_video_player_activity_created;
> +} android_surf_value_t;

You don't have to specify again this struct, you can do:
typedef struct android_surf_value_t android_surf_value_t;
vlc shouldn't have access to android_surf_value_t members.

> +
>  /* Fill the structure passed as parameter and return a library handle
>     that should be destroyed with dlclose. */
>  void *LoadNativeWindowAPI(native_window_api_t *native);
> diff --git a/src/libvlc.c b/src/libvlc.c
> index 946ce2e..9d1bcd8 100644
> --- a/src/libvlc.c
> +++ b/src/libvlc.c
> @@ -485,6 +485,9 @@ dbus_out:
>      var_Create( p_libvlc, "drawable-clip-right", VLC_VAR_INTEGER );
>      var_Create( p_libvlc, "drawable-nsobject", VLC_VAR_ADDRESS );
>  #endif
> +#ifdef __ANDROID__
> +    var_Create( p_libvlc, "drawable-vlcobject", VLC_VAR_ADDRESS);
> +#endif

why not merging that with "drawable-surfacevalue" ? ANd why not calling
it "drawable-androidobject" ?

>  #if defined (_WIN32) || defined (__OS2__)
>      var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_INTEGER );
>  #endif
> -- 
> 1.9.3 (Apple Git-50)
> 
> _______________________________________________
> 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