[vlc-devel] [PATCH] vout: add an OpenGL ES 2.0 vout display module for Android.

Felix Abecassis felix.abecassis at gmail.com
Tue Jan 7 16:31:20 CET 2014


This module should be preferred over the generic module provided in
gl.c since this one handles the events received from the Java code.
---
 modules/video_output/Modules.am     |   8 +-
 modules/video_output/android/gles.c | 255 ++++++++++++++++++++++++++++++++++++
 2 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100644 modules/video_output/android/gles.c

diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am
index 89304f9..5461f8b 100644
--- a/modules/video_output/Modules.am
+++ b/modules/video_output/Modules.am
@@ -43,7 +43,6 @@ if HAVE_GL
 vout_LTLIBRARIES += libgl_plugin.la
 endif
 
-
 ### XCB ###
 libvlc_xcb_events_la_SOURCES = xcb/events.c xcb/events.h
 libvlc_xcb_events_la_CPPFLAGS = -DMODULE_STRING=\"xcb\"
@@ -190,8 +189,13 @@ libandroid_native_window_plugin_la_SOURCES = android/nativewindow.c
 libandroid_native_window_plugin_la_CFLAGS = $(AM_CFLAGS)
 libandroid_native_window_plugin_la_LIBADD = -ldl
 
+libandroid_gles_plugin_la_SOURCES = opengl.c opengl.h android/gles.c
+libandroid_gles_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES=2
+libandroid_gles_plugin_la_LIBADD = $(GLES2_LIBS)
+libandroid_gles_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
+
 if HAVE_ANDROID
-vout_LTLIBRARIES += libandroid_native_window_plugin.la
+vout_LTLIBRARIES += libandroid_native_window_plugin.la libandroid_gles_plugin.la
 if HAVE_EGL
 vout_LTLIBRARIES += libegl_android_plugin.la
 endif
diff --git a/modules/video_output/android/gles.c b/modules/video_output/android/gles.c
new file mode 100644
index 0000000..4601575
--- /dev/null
+++ b/modules/video_output/android/gles.c
@@ -0,0 +1,255 @@
+/*****************************************************************************
+ * Copyright (C) 2014 VLC authors and VideoLAN
+ *
+ * Author: Felix Abecassis <felix.abecassis 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
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_display.h>
+#include <vlc_opengl.h>
+#include "opengl.h"
+
+static int Open (vlc_object_t *);
+static void Close (vlc_object_t *);
+
+vlc_module_begin ()
+# define API VLC_OPENGL_ES2
+# define MODULE_VARNAME "gles2"
+    set_shortname (N_("Android OpenGL ES2"))
+    set_description (N_("Android OpenGL ES2 video output"))
+    set_capability ("vout display", 150)
+    set_callbacks (Open, Close)
+    add_shortcut ("android_opengles2", "gles2")
+vlc_module_end ()
+
+struct vout_display_sys_t
+{
+    vout_display_opengl_t *vgl;
+
+    vout_window_t *window;
+    vlc_gl_t *gl;
+    picture_pool_t *pool;
+};
+
+static picture_pool_t *Pool (vout_display_t *, unsigned);
+static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
+static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
+static int Control (vout_display_t *, int, va_list);
+static void Manage (vout_display_t *vd);
+
+/* JNI prototypes */
+extern int jni_GetFrameDimensions (int *width, int *height);
+extern bool jni_IsEventSurfaceAttached ();
+extern bool jni_IsEventSurfaceDetached ();
+
+static vout_window_t *MakeWindow (vout_display_t *vd)
+{
+    vout_window_cfg_t cfg = {
+        .x = var_InheritInteger (vd, "video-x"),
+        .y = var_InheritInteger (vd, "video-y"),
+        .width = vd->cfg->display.width,
+        .height = vd->cfg->display.height,
+        .type = VOUT_WINDOW_TYPE_ANDROID_NATIVE
+    };
+    vout_window_t *wnd = vout_display_NewWindow (vd, &cfg);
+    if (wnd != NULL)
+        return wnd;
+
+    msg_Err (vd, "parent window not available");
+    return NULL;
+}
+
+static int Open (vlc_object_t *obj)
+{
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *sys = malloc (sizeof (*sys));
+    if (sys == NULL)
+        return VLC_ENOMEM;
+
+    sys->gl = NULL;
+    sys->pool = NULL;
+
+    sys->window = MakeWindow (vd);
+    if (sys->window == NULL)
+        goto error;
+
+    sys->gl = vlc_gl_Create (sys->window, API, "$" MODULE_VARNAME);
+    if (sys->gl == NULL)
+        goto error;
+
+    if (vlc_gl_MakeCurrent (sys->gl))
+        goto error;
+
+    sys->vgl = vout_display_opengl_New (&vd->fmt, &vd->info.subpicture_chromas, sys->gl);
+    if (!sys->vgl)
+    {
+        vlc_gl_ReleaseCurrent (sys->gl);
+        goto error;
+    }
+
+    vd->sys = sys;
+    vd->info.has_pictures_invalid = false;
+    vd->info.has_event_thread = false;
+    vd->pool = Pool;
+    vd->prepare = PictureRender;
+    vd->display = PictureDisplay;
+    vd->control = Control;
+    vd->manage = Manage;
+
+    bool is_fullscreen = vd->cfg->is_fullscreen;
+    vout_display_SendEventFullscreen (vd, is_fullscreen);
+
+    return VLC_SUCCESS;
+
+error:
+    if (sys->gl != NULL)
+        vlc_gl_Destroy (sys->gl);
+    if (sys->window != NULL)
+        vout_display_DeleteWindow (vd, sys->window);
+    free (sys);
+    return VLC_EGENERIC;
+}
+
+static void Close (vlc_object_t *obj)
+{
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *sys = vd->sys;
+
+    vout_display_opengl_Delete (sys->vgl);
+    vlc_gl_ReleaseCurrent (sys->gl);
+
+    vlc_gl_Destroy (sys->gl);
+    vout_display_DeleteWindow (vd, sys->window);
+    free (sys);
+}
+
+static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (!sys->pool)
+        sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
+    return sys->pool;
+}
+
+static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
+}
+
+static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    vout_display_opengl_Display (sys->vgl, &vd->source);
+    picture_Release (pic);
+    if (subpicture)
+        subpicture_Delete(subpicture);
+}
+
+static int Control (vout_display_t *vd, int query, va_list ap)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    switch (query)
+    {
+      case VOUT_DISPLAY_CHANGE_FULLSCREEN:
+      {
+        const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
+        return vout_window_SetFullScreen (sys->window, c->is_fullscreen);
+      }
+
+      case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
+      {
+        unsigned state = va_arg (ap, unsigned);
+        return vout_window_SetState (sys->window, state);
+      }
+
+      case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
+      case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+      case VOUT_DISPLAY_CHANGE_ZOOM:
+      {
+        const vout_display_cfg_t *cfg = va_arg (ap, const vout_display_cfg_t *);
+        const video_format_t *src = &vd->source;
+
+        if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE && va_arg (ap, int))
+        {
+            vout_window_SetSize (sys->window,
+                                 cfg->display.width, cfg->display.height);
+            return VLC_EGENERIC;
+        }
+
+        vout_display_place_t place;
+        vout_display_PlacePicture (&place, src, cfg, false);
+
+        vout_window_SetSize (sys->window,
+                             place.width, place.height);
+        glViewport (0, 0, place.width, place.height);
+
+        return VLC_SUCCESS;
+      }
+
+      case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
+      case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+      {
+        const vout_display_cfg_t *cfg = vd->cfg;
+        const video_format_t *src = va_arg (ap, const video_format_t *);
+
+        vout_display_place_t place;
+        vout_display_PlacePicture (&place, src, cfg, false);
+
+        glViewport (0, 0, place.width, place.height);
+
+        return VLC_SUCCESS;
+      }
+
+      case VOUT_DISPLAY_GET_OPENGL:
+      {
+        vlc_gl_t **pgl = va_arg (ap, vlc_gl_t **);
+        *pgl = sys->gl;
+        return VLC_SUCCESS;
+      }
+
+      case VOUT_DISPLAY_HIDE_MOUSE:
+          return VLC_SUCCESS;
+
+      default:
+        msg_Err (vd, "Unknown request %d", query);
+        return VLC_EGENERIC;
+    }
+}
+
+static void Manage(vout_display_t *vd)
+{
+    if (jni_IsEventSurfaceAttached ())
+    {
+        int width, height;
+        jni_GetFrameDimensions (&width, &height);
+        vout_display_SendEventDisplaySize (vd, width, height, vd->cfg->is_fullscreen);
+    }
+    if (jni_IsEventSurfaceDetached ())
+        vout_display_SendEventClose (vd);
+}
-- 
1.8.3.2




More information about the vlc-devel mailing list