[vlc-commits] vout/opengl: add converter_android

Thomas Guillem git at videolan.org
Mon Dec 19 12:06:44 CET 2016


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Dec 15 11:35:48 2016 +0100| [10028ddeecc43506194a5a0b264beb8c55cdda5b] | committer: Thomas Guillem

vout/opengl: add converter_android

This converter handle the chroma ANDROID_OPAQUE. It creates a Java
SurfaceTexture from an OpenGL texture name. MediaCodec will be able to render
directly to the ANativeWindow* that is created from this SurfaceTexture.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=10028ddeecc43506194a5a0b264beb8c55cdda5b
---

 modules/video_output/Makefile.am                |   3 +
 modules/video_output/opengl/converter_android.c | 253 ++++++++++++++++++++++++
 modules/video_output/opengl/internal.h          |   6 +
 modules/video_output/opengl/vout_helper.c       |   3 +
 4 files changed, 265 insertions(+)

diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 5d5fffe..fefdf2f 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -37,6 +37,9 @@ endif
 
 ### OpenGL ###
 libgles2_plugin_la_SOURCES = $(OPENGL_DISPLAY_SRCS) video_output/opengl/display.c
+if HAVE_ANDROID
+libgles2_plugin_la_SOURCES += video_output/opengl/converter_android.c
+endif
 libgles2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GLES2_CFLAGS) -DUSE_OPENGL_ES2
 libgles2_plugin_la_LIBADD = $(GLES2_LIBS) $(LIBM)
 libgles2_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
diff --git a/modules/video_output/opengl/converter_android.c b/modules/video_output/opengl/converter_android.c
new file mode 100644
index 0000000..255c60b
--- /dev/null
+++ b/modules/video_output/opengl/converter_android.c
@@ -0,0 +1,253 @@
+/*****************************************************************************
+ * converter_android.c: OpenGL Android opaque converter
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * 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
+
+#ifndef __ANDROID__
+# error this file must be built from android
+#endif
+
+#include <GLES2/gl2ext.h>
+#include "internal.h"
+#include "../android/display.h"
+#include "../android/utils.h"
+
+struct priv
+{
+    SurfaceTexture *stex;
+    const float *transform_mtx;
+};
+
+static int
+tc_anop_gen_textures(const opengl_tex_converter_t *tc,
+                     const GLsizei *tex_width, const GLsizei *tex_height,
+                     GLuint *textures)
+{
+    (void) tex_width; (void) tex_height;
+
+    glActiveTexture(GL_TEXTURE0);
+    glClientActiveTexture(GL_TEXTURE0);
+
+    glGenTextures(1, textures);
+    glBindTexture(tc->tex_target, textures[0]);
+
+    glTexParameteri(tc->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(tc->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(tc->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(tc->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    return VLC_SUCCESS;
+}
+
+static void
+tc_anop_del_textures(const opengl_tex_converter_t *tc, const GLuint *textures)
+{
+    (void) tc;
+    glDeleteTextures(1, textures);
+}
+
+static int
+pool_lock_pic(picture_t *p_pic)
+{
+    picture_sys_t *p_picsys = p_pic->p_sys;
+
+    p_picsys->b_locked = true;
+    return 0;
+}
+
+static void
+pool_unlock_pic(picture_t *p_pic)
+{
+    picture_sys_t *p_picsys = p_pic->p_sys;
+    if (p_picsys->b_locked)
+    {
+        AndroidOpaquePicture_Release(p_picsys, false);
+        p_picsys->b_locked  = false;
+    }
+}
+
+static picture_pool_t *
+tc_anop_get_pool(const opengl_tex_converter_t *tc, const video_format_t *fmt,
+                 unsigned requested_count, const GLuint *textures)
+{
+    struct priv *priv = tc->priv;
+    priv->stex = SurfaceTexture_create(tc->parent, textures[0]);
+    if (priv->stex == NULL)
+        return NULL;
+
+#define FORCED_COUNT 31
+    requested_count = FORCED_COUNT;
+    picture_t *picture[FORCED_COUNT] = {NULL, };
+    unsigned count;
+
+    for (count = 0; count < requested_count; count++)
+    {
+        picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys));
+        if (unlikely(p_picsys == NULL))
+            break;
+        picture_resource_t rsc = {
+            .p_sys = p_picsys,
+            .pf_destroy = AndroidOpaquePicture_DetachVout,
+        };
+
+        p_picsys->hw.b_vd_ref = true;
+        p_picsys->hw.p_surface = SurfaceTexture_getANativeWindow(priv->stex);
+        p_picsys->hw.p_jsurface = SurfaceTexture_getSurface(priv->stex);
+        p_picsys->hw.i_index = -1;
+        vlc_mutex_init(&p_picsys->hw.lock);
+
+        picture[count] = picture_NewFromResource(fmt, &rsc);
+        if (!picture[count])
+        {
+            free(p_picsys);
+            break;
+        }
+    }
+    if (count <= 0)
+        goto error;
+
+    /* Wrap the pictures into a pool */
+    picture_pool_configuration_t pool_cfg = {
+        .picture_count = requested_count,
+        .picture       = picture,
+        .lock          = pool_lock_pic,
+        .unlock        = pool_unlock_pic,
+    };
+    picture_pool_t *pool = picture_pool_NewExtended(&pool_cfg);
+    if (!pool)
+        goto error;
+
+    return pool;
+error:
+    SurfaceTexture_release(priv->stex);
+    return NULL;
+}
+
+static int
+tc_anop_update(const opengl_tex_converter_t *tc, const GLuint *textures,
+               unsigned width, unsigned height,
+               const picture_t *pic, const size_t *plane_offset)
+{
+    (void) width; (void) height; (void) plane_offset;
+
+    if (plane_offset != NULL)
+        return VLC_EGENERIC;
+
+    if (!pic->p_sys->b_locked)
+        return VLC_SUCCESS;
+
+    struct priv *priv = tc->priv;
+
+    AndroidOpaquePicture_Release(pic->p_sys, true);
+
+    if (SurfaceTexture_waitAndUpdateTexImage(priv->stex, &priv->transform_mtx)
+        != VLC_SUCCESS)
+    {
+        priv->transform_mtx = NULL;
+        return VLC_EGENERIC;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(tc->tex_target, textures[0]);
+
+    return VLC_SUCCESS;
+}
+
+static void
+tc_anop_prepare_shader(const opengl_tex_converter_t *tc,
+                       GLuint program, float alpha)
+{
+    (void) alpha;
+    struct priv *priv = tc->priv;
+    if (priv->transform_mtx != NULL)
+    {
+        GLint handle = tc->api->GetUniformLocation(program, "uSTMatrix");
+        tc->api->UniformMatrix4fv(handle, 1, GL_FALSE, priv->transform_mtx);
+    }
+}
+
+static void
+tc_anop_release(const opengl_tex_converter_t *tc)
+{
+    tc->api->DeleteShader(tc->fragment_shader);
+
+    struct priv *priv = tc->priv;
+    if (priv->stex != NULL)
+        SurfaceTexture_release(priv->stex);
+
+    free(priv);
+}
+
+int
+opengl_tex_converter_anop_init(const video_format_t *fmt,
+                               opengl_tex_converter_t *tc)
+{
+    if (fmt->i_chroma != VLC_CODEC_ANDROID_OPAQUE)
+        return VLC_EGENERIC;
+
+    tc->priv = malloc(sizeof(struct priv));
+    if (unlikely(tc->priv == NULL))
+        return VLC_ENOMEM;
+
+    struct priv *priv = tc->priv;
+    priv->stex = NULL;
+    priv->transform_mtx = NULL;
+
+    tc->pf_gen_textures   = tc_anop_gen_textures;
+    tc->pf_del_textures   = tc_anop_del_textures;
+    tc->pf_get_pool       = tc_anop_get_pool;
+    tc->pf_update         = tc_anop_update;
+    tc->pf_prepare_shader = tc_anop_prepare_shader;
+    tc->pf_release        = tc_anop_release;
+
+    /* fake plane_count to 1 */
+    static const vlc_chroma_description_t desc = {
+        .plane_count = 1,
+        .p[0].w.num = 1,
+        .p[0].w.den = 1,
+        .p[0].h.num = 1,
+        .p[0].h.den = 1,
+        .pixel_size = 0,
+        .pixel_bits = 0,
+    };
+
+    tc->chroma       = VLC_CODEC_ANDROID_OPAQUE;
+    tc->desc         = &desc;
+    tc->tex_target   = GL_TEXTURE_EXTERNAL_OES;
+    tc->orientation  = ORIENT_VFLIPPED;
+
+    static const char *code =
+        "#version " GLSL_VERSION "\n"
+        "#extension GL_OES_EGL_image_external : require\n"
+        PRECISION
+        "varying vec4 TexCoord0;"
+        "uniform samplerExternalOES sTexture;"
+        "uniform mat4 uSTMatrix;"
+        "void main()"
+        "{ "
+        "  gl_FragColor = texture2D(sTexture, (uSTMatrix * TexCoord0).xy);"
+        "}";
+    tc->fragment_shader = tc->api->CreateShader(GL_FRAGMENT_SHADER);
+    tc->api->ShaderSource(tc->fragment_shader, 1, &code, NULL);
+    tc->api->CompileShader(tc->fragment_shader);
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/video_output/opengl/internal.h b/modules/video_output/opengl/internal.h
index 2ec127e..e65ff05 100644
--- a/modules/video_output/opengl/internal.h
+++ b/modules/video_output/opengl/internal.h
@@ -254,4 +254,10 @@ extern int
 opengl_tex_converter_xyz12_init(const video_format_t *,
                                 opengl_tex_converter_t *);
 
+#ifdef __ANDROID__
+extern int
+opengl_tex_converter_anop_init(const video_format_t *,
+                               opengl_tex_converter_t *);
+#endif
+
 #endif /* include-guard */
diff --git a/modules/video_output/opengl/vout_helper.c b/modules/video_output/opengl/vout_helper.c
index 017c335..19c6d3a 100644
--- a/modules/video_output/opengl/vout_helper.c
+++ b/modules/video_output/opengl/vout_helper.c
@@ -52,6 +52,9 @@ static opengl_tex_converter_init_cb opengl_tex_converter_init_cbs[] =
 {
     opengl_tex_converter_yuv_init,
     opengl_tex_converter_xyz12_init,
+#ifdef __ANDROID__
+    opengl_tex_converter_anop_init,
+#endif
 };
 
 typedef struct {



More information about the vlc-commits mailing list