[vlc-devel] [PATCH] vout: Overlay for Parrot Asteroid devices
Rémi Denis-Courmont
remi at remlab.net
Fri Jun 21 14:25:16 CEST 2013
Hello,
I do not maintain this plugin but... I think that this exceed the code
overhead ratio above which a new plugin should be created instead of large
#ifdef's. Not counting the legal and plugin boilerplate, this patch almost
doubles the lines count of androidsurface.c.
Also comments inline.
diff --git a/modules/video_output/androidsurface.c
b/modules/video_output/androidsurface.c
index 6784ab9..a6485b9 100644
--- a/modules/video_output/androidsurface.c
+++ b/modules/video_output/androidsurface.c
@@ -6,6 +6,7 @@
* Authors: Ming Hu <tewilove at gmail.com>
* Ludovic Fauvet <etix at l0cal.com>
* Sébastien Toque <xilasz at gmail.com>
+ * Andrei Mandychev <andron.mobi at gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -43,6 +44,22 @@
# define ANDROID_SYM_S_UNLOCK "_ZN7android7Surface13unlockAndPostEv"
#endif
+#ifdef PARROT_MEDIA_OUT
+
+#define SCREEN_PRIMARY_LCD 0
+#define SCREEN_SECONDARY_LCD_ 1
Why the trailing underscore?
+#define SCREEN_COMPOSITE_TV 2
+
+#define NUM_BUFFERS_TO_BE_QUEUED_FOR_OPTIMAL_PERFORMANCE 3
+
+#define ANDROID_SYM_OVR_DESTROY "_ZN7android7Overlay7destroyEv"
+#define ANDROID_SYM_OVR_DEQUEUE_BUF "_ZN7android7Overlay13dequeueBufferEPPv"
+#define ANDROID_SYM_OVR_QUEUE_BUF "_ZN7android7Overlay11queueBufferEPv"
+#define ANDROID_SYM_OVR_GET_BUF_ADDR "_ZN7android7Overlay16getBufferAddressEPv"
+#define ANDROID_SYM_OVR_GET_BUF_COUNT "_ZNK7android7Overlay14getBufferCountEv"
+
+#endif /* PARROT_MEDIA_OUT */
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
@@ -81,6 +98,45 @@ typedef void (*Surface_lock2)(void *, void *, void *);
// _ZN7android7Surface13unlockAndPostEv
typedef void (*Surface_unlockAndPost)(void *);
+#ifdef PARROT_MEDIA_OUT
+
+/* possible overlay formats */
+enum {
+ OVERLAY_FORMAT_RGBA_8888 = 1,
+ OVERLAY_FORMAT_RGB_565 = 4,
+ OVERLAY_FORMAT_BGRA_8888 = 5,
+ OVERLAY_FORMAT_YCbCr_422_SP = 0x10, // NV16
+ OVERLAY_FORMAT_YCbYCr_422_I = 0x14,
+ OVERLAY_FORMAT_YCbYCr_420_I = 0x15,
+ OVERLAY_FORMAT_CbYCrY_422_I = 0x16,
+ OVERLAY_FORMAT_CbYCrY_420_I = 0x17,
+ OVERLAY_FORMAT_YCbCr_420_SP = 0x21,
+ OVERLAY_FORMAT_YCbCr_420_SP_SEQ_TB = 0x24, //NV12 Interlaced (Sequential
Top-Bottom)
+ OVERLAY_FORMAT_DEFAULT = 99, // The actual color format is
determined by the overlay
+};
+
+typedef void ISurface;
+typedef void Overlay;
IMHO, if you want opaque types, you'd better use an incomplete struct. At
least the compiler will perform basic type safety checks:
typedef struct ISurface ISurface;
+typedef int32_t status_t;
+
+typedef ISurface* (*getISurface)(void *);
+typedef Overlay* (*createOverlay)(void *, uint32_t, uint32_t, int32_t,
int32_t);
+typedef void (*releaseOverlay)();
+typedef void (*setDisplay)(void *, int);
+
+// _ZN7android7Overlay7destroyEv
+typedef void (*Overlay_destroy)(void *);
+// ZN7android7Overlay13dequeueBufferEPPv
+typedef status_t (*Overlay_dequeueBuffer)(void *, int *);
+// ZN7android7Overlay11queueBufferEPv
+typedef status_t (*Overlay_queueBuffer)(void *, int);
+// ZN7android7Overlay16getBufferAddressEPv
+typedef void* (*Overlay_getBufferAddress)(void *, int);
+// ZNK7android7Overlay14getBufferCountEv
+typedef int32_t (*Overlay_getBufferCount)(void *);
+
+#endif /* PARROT_MEDIA_OUT */
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
@@ -113,6 +169,32 @@ struct vout_display_sys_t {
/* density */
int i_sar_num;
int i_sar_den;
+
+#ifdef PARROT_MEDIA_OUT
+ // libsurfacehelper.so library and its methods.
+ void *p_libsurfacehelper;
+ getISurface getISurface;
+ createOverlay createOverlay;
+ releaseOverlay releaseOverlay;
+ setDisplay setDisplay;
+
+ // libui.so library and its overlay methods.
+ void *p_libui;
+ Overlay_destroy o_destroy;
+ Overlay_dequeueBuffer o_dequeueBuffer;
+ Overlay_queueBuffer o_queueBuffer;
+ Overlay_getBufferAddress o_getBufferAddress;
+ Overlay_getBufferCount o_getBufferCount;
+
+ // Android framework/base/include/ui/Overlay.h object
+ Overlay* overlay;
+
+ // Overlay's buffer information
+ int buffer_count;
+ int buffer_queued_count;
+ void** buffer_ptrs;
+ int buffer_idx;
+#endif /* PARROT_MEDIA_OUT */
};
struct picture_sys_t {
@@ -126,6 +208,90 @@ static void AndroidUnlockSurface(picture_t *);
static vlc_mutex_t single_instance = VLC_STATIC_MUTEX;
+#ifdef PARROT_MEDIA_OUT
+
+typedef struct {
+ int fd;
+ unsigned int length;
+ uint32_t offset;
+ void *ptr;
+} mapping_data_t;
+
+static inline void *LoadSurfaceHelper(const char *psz_lib, vout_display_sys_t
*sys) {
+ void *p_library = dlopen(psz_lib, RTLD_NOW);
+ if (!p_library)
+ return NULL;
+
+ sys->getISurface = (getISurface)(dlsym(p_library, "getISurface"));
+ sys->createOverlay = (createOverlay)(dlsym(p_library, "createOverlay"));
+ sys->releaseOverlay = (releaseOverlay)(dlsym(p_library,
"releaseOverlay"));
+ sys->setDisplay = (setDisplay)(dlsym(p_library, "setDisplay"));
+
+ if (sys->getISurface && sys->createOverlay && sys->setDisplay)
+ return p_library;
+
+ dlclose(p_library);
+ return NULL;
+}
+
+static inline void *LoadOverlay(const char *psz_lib, vout_display_sys_t *sys)
+{
+ void *p_library = dlopen(psz_lib, RTLD_NOW);
+ if (!p_library)
+ return NULL;
+
+ sys->o_destroy = (Overlay_destroy)(dlsym(p_library,
ANDROID_SYM_OVR_DESTROY));
+ sys->o_dequeueBuffer = (Overlay_dequeueBuffer)(dlsym(p_library,
ANDROID_SYM_OVR_DEQUEUE_BUF));
+ sys->o_queueBuffer = (Overlay_queueBuffer)(dlsym(p_library,
ANDROID_SYM_OVR_QUEUE_BUF));
+ sys->o_getBufferAddress = (Overlay_getBufferAddress)(dlsym(p_library,
ANDROID_SYM_OVR_GET_BUF_ADDR));
+ sys->o_getBufferCount = (Overlay_getBufferCount)(dlsym(p_library,
ANDROID_SYM_OVR_GET_BUF_COUNT));
+
+ if (sys->o_destroy && sys->o_dequeueBuffer && sys->o_queueBuffer &&
+ sys->o_getBufferAddress && sys->o_getBufferCount)
+ return p_library;
+
+ dlclose(p_library);
+ return NULL;
+}
+
+static int OpenOverlay(vout_display_t *vd, video_format_t *fmt) {
+
+ vout_display_sys_t *sys = vd->sys;
+
+ void* surf = jni_LockAndGetAndroidSurface();
+ if (unlikely(!surf)) {
+ msg_Err(vd, "surface is not set");
+ jni_UnlockAndroidSurface();
Why do you free something you presumably just failed to allocate?
+ return VLC_EGENERIC;
+ }
+ msg_Dbg(vd, "Creating overlay... w=%d, h=%d", fmt->i_width, fmt-
>i_height);
+ sys->overlay = sys->createOverlay(surf, fmt->i_width, fmt->i_height,
OVERLAY_FORMAT_CbYCrY_422_I, 0);
+ if (!sys->overlay) {
+ msg_Err(vd, "Can't create overlay");
+ jni_UnlockAndroidSurface();
+ return VLC_EGENERIC;
+ }
+ sys->buffer_count = sys->o_getBufferCount(sys->overlay);
+ if (sys->buffer_count <= 0) {
+ msg_Err(vd, "There is no any overlay buffer");
+ jni_UnlockAndroidSurface();
Does this not leak the overlay?
+ return VLC_EGENERIC;
+ }
+ sys->buffer_idx = 0;
+ sys->buffer_queued_count = 0;
+ sys->buffer_ptrs = calloc(sys->buffer_count, sizeof(void*));
No need to memset(), so use malloc().
+ for (int i = 0; i < sys->buffer_count; i++) {
+ mapping_data_t* data = sys->o_getBufferAddress(sys->overlay, i);
+ sys->buffer_ptrs[i] = data->ptr;
+ }
+ sys->setDisplay(surf, SCREEN_PRIMARY_LCD);
+ jni_UnlockAndroidSurface();
+
+ return VLC_SUCCESS;
+}
+
+#endif /* PARROT_MEDIA_OUT */
+
static inline void *LoadSurface(const char *psz_lib, vout_display_sys_t *sys)
{
void *p_library = dlopen(psz_lib, RTLD_NOW);
@@ -186,9 +352,28 @@ static int Open(vlc_object_t *p_this)
return VLC_EGENERIC;
}
+#ifdef PARROT_MEDIA_OUT
+ // Load libsurfacehelper.so to get ISurface and create/destroy Overlay.
+ sys->p_libsurfacehelper =
LoadSurfaceHelper("/data/data/org.videolan.vlc/lib/libsurfacehelper.so", sys);
+ if (!sys->p_libsurfacehelper) {
+ msg_Err(vd, "libsurfacehelper.so library is not loaded");
+ return VLC_EGENERIC;
+ }
+
+ // Load libui.so to have an access to overlay methods.
+ sys->p_libui = LoadOverlay("libui.so", sys);
+ if (!sys->p_libui) {
+ msg_Err(vd, "libui.so library is not loaded");
+ return VLC_EGENERIC;
+ }
+#endif /* PARROT_MEDIA_OUT */
+
/* Setup chroma */
video_format_t fmt = vd->fmt;
+#ifdef PARROT_MEDIA_OUT
+ fmt.i_chroma = VLC_CODEC_UYVY;
+#else
char *psz_fcc = var_InheritString(vd, CFG_PREFIX "chroma");
if( psz_fcc ) {
fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_fcc);
@@ -220,6 +405,7 @@ static int Open(vlc_object_t *p_this)
return VLC_EGENERIC;
}
video_format_FixRgb(&fmt);
+#endif /* PARROT_MEDIA_OUT */
msg_Dbg(vd, "Pixel format %4.4s", (char*)&fmt.i_chroma);
@@ -268,6 +454,20 @@ static int Open(vlc_object_t *p_this)
sys->i_sar_num = vd->source.i_sar_num;
sys->i_sar_den = vd->source.i_sar_den;
+#ifdef PARROT_MEDIA_OUT
+ if (OpenOverlay(vd, &fmt) != VLC_SUCCESS) {
+ msg_Err(vd, "Could not open overlay");
+ picture_pool_Delete(sys->pool);
+ dlclose(sys->p_libsurfacehelper);
+ dlclose(sys->p_libui);
+ dlclose(sys->p_library);
+ free(sys);
+ vlc_mutex_unlock(&single_instance);
+ return VLC_EGENERIC;
+ }
+ jni_SetAndroidSurfaceSize(fmt.i_width, fmt.i_height, sys->i_sar_num, sys-
>i_sar_den);
+#endif /* PARROT_MEDIA_OUT */
+
return VLC_SUCCESS;
enomem:
@@ -284,6 +484,13 @@ static void Close(vlc_object_t *p_this)
vout_display_sys_t *sys = vd->sys;
picture_pool_Delete(sys->pool);
+#ifdef PARROT_MEDIA_OUT
+ sys->o_destroy(sys->overlay);
+ sys->releaseOverlay();
+ free(sys->buffer_ptrs);
+ dlclose(sys->p_libsurfacehelper);
+ dlclose(sys->p_libui);
+#endif /* PARROT_MEDIA_OUT */
dlclose(sys->p_library);
free(sys);
vlc_mutex_unlock(&single_instance);
@@ -326,6 +533,13 @@ static void SetupPictureYV12( SurfaceInfo* p_surfaceInfo,
picture_t *p_picture )
static int AndroidLockSurface(picture_t *picture)
{
+#ifdef PARROT_MEDIA_OUT
+ vout_display_sys_t *sys = picture->p_sys->sys;
+
+ picture->p[0].p_pixels = sys->buffer_ptrs[sys->buffer_idx]; // Set a
picture buffer
+ picture->p[0].i_lines = picture->p[0].i_visible_lines;
+ picture->p[0].i_pitch = picture->p[0].i_visible_pitch;
+#else
picture_sys_t *picsys = picture->p_sys;
vout_display_sys_t *sys = picsys->sys;
SurfaceInfo *info;
@@ -367,17 +581,23 @@ static int AndroidLockSurface(picture_t *picture)
if (info->format == 0x32315659 /*ANDROID_IMAGE_FORMAT_YV12*/)
SetupPictureYV12(info, picture);
+#endif /* PARROT_MEDIA_OUT */
+
return VLC_SUCCESS;
}
static void AndroidUnlockSurface(picture_t *picture)
{
+#ifdef PARROT_MEDIA_OUT
+ picture->p[0].p_pixels = NULL;
+#else
picture_sys_t *picsys = picture->p_sys;
vout_display_sys_t *sys = picsys->sys;
if (likely(picsys->surf))
sys->s_unlockAndPost(picsys->surf);
jni_UnlockAndroidSurface();
+#endif /* PARROT_MEDIA_OUT */
}
static void Display(vout_display_t *vd, picture_t *picture, subpicture_t
*subpicture)
@@ -385,6 +605,39 @@ static void Display(vout_display_t *vd, picture_t
*picture, subpicture_t *subpic
VLC_UNUSED(vd);
VLC_UNUSED(subpicture);
+#ifdef PARROT_MEDIA_OUT
+ vout_display_sys_t *sys = vd->sys;
+
+ if (sys->buffer_count > 0 && sys->buffer_queued_count < sys->buffer_count) {
+ int nBuffers_queued_to_dss = vd->sys->o_queueBuffer(sys->overlay, sys-
>buffer_idx);
+ if (nBuffers_queued_to_dss < 0) {
+ msg_Err(vd, "Failed queue buffer#%d to overlay!", sys->buffer_idx);
+ } else {
+ sys->buffer_queued_count++;
+ if (nBuffers_queued_to_dss != sys->buffer_queued_count) {
+ msg_Warn(vd, "Found some buffers discarded by DSS upon STREAM
OFF!");
+ sys->buffer_queued_count = 1; // discard previously queued
buffers.
+ }
+ sys->buffer_idx++;
+ if (sys->buffer_idx == sys->buffer_count)
+ sys->buffer_idx = 0;
+ }
+ }
+
+ if (sys->buffer_queued_count >=
NUM_BUFFERS_TO_BE_QUEUED_FOR_OPTIMAL_PERFORMANCE) {
+ int i;
+ status_t status = vd->sys->o_dequeueBuffer(sys->overlay, &i);
+ if (status == 0) {
+ sys->buffer_queued_count--;
+ //msg_Dbg(vd, "dequeue buffer[%d]", i);
+ } else {
+ msg_Err(vd, "no buffer to dequeue in overlay");
+ }
+ } else {
+ //msg_Dbg(vd, "skip dequeue buffer, there are not enough queued
buffers");
+ }
+#endif /* PARROT_MEDIA_OUT */
+
/* refcount lowers to 0, and pool_cfg.unlock is called */
picture_Release(picture);
--
1.7.9.5
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list