[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