[vlc-devel] [PATCH 2/2] Support for multiple video instances for android.
Paulo Vitor Magacho da Silva
pvmagacho at gmail.com
Tue Nov 25 01:31:40 CET 2014
---
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 | 19 +++++++++++++----
modules/video_output/android/utils.h | 11 ++++++++++
src/libvlc.c | 3 +++
9 files changed, 127 insertions(+), 27 deletions(-)
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
+}
+
+
/**************************************************************************
* 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..84cff7a 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_SetAndroidSurfaceSize(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 {
@@ -209,6 +211,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 +313,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);
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;
+
/* 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
#if defined (_WIN32) || defined (__OS2__)
var_Create( p_libvlc, "drawable-hwnd", VLC_VAR_INTEGER );
#endif
--
1.9.3 (Apple Git-50)
More information about the vlc-devel
mailing list