From 09116bf10d515d50bdd1e9a20278be816cb762aa Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Tue, 15 Apr 2014 17:58:34 +0100 Subject: [PATCH] egl/eglglessink: remove since EGLImage and iOS support have been added in glimagesink https://bugzilla.gnome.org/show_bug.cgi?id=703343 --- configure.ac | 269 +-- docs/plugins/Makefile.am | 1 - ext/Makefile.am | 8 - ext/eglgles/Android.mk | 71 - ext/eglgles/Makefile.am | 39 - ext/eglgles/TODO | 11 - ext/eglgles/gstegladaptation.c | 707 -------- ext/eglgles/gstegladaptation.h | 216 --- ext/eglgles/gstegladaptation_eagl.m | 349 ---- ext/eglgles/gstegladaptation_egl.c | 927 ----------- ext/eglgles/gsteglglessink.c | 2259 -------------------------- ext/eglgles/gsteglglessink.h | 145 -- ext/eglgles/video_platform_wrapper.c | 706 -------- ext/eglgles/video_platform_wrapper.h | 61 - gst-libs/gst/Makefile.am | 7 +- gst-libs/gst/egl/Makefile.am | 95 -- gst-libs/gst/egl/egl.c | 624 ------- gst-libs/gst/egl/egl.h | 110 -- pkgconfig/Makefile.am | 6 - win32/common/config.h | 3 - 20 files changed, 70 insertions(+), 6544 deletions(-) delete mode 100644 ext/eglgles/Android.mk delete mode 100644 ext/eglgles/Makefile.am delete mode 100644 ext/eglgles/TODO delete mode 100644 ext/eglgles/gstegladaptation.c delete mode 100644 ext/eglgles/gstegladaptation.h delete mode 100644 ext/eglgles/gstegladaptation_eagl.m delete mode 100644 ext/eglgles/gstegladaptation_egl.c delete mode 100644 ext/eglgles/gsteglglessink.c delete mode 100644 ext/eglgles/gsteglglessink.h delete mode 100644 ext/eglgles/video_platform_wrapper.c delete mode 100644 ext/eglgles/video_platform_wrapper.h delete mode 100644 gst-libs/gst/egl/Makefile.am delete mode 100644 gst-libs/gst/egl/egl.c delete mode 100644 gst-libs/gst/egl/egl.h diff --git a/configure.ac b/configure.ac index 1e4b8698f5..592fc767ea 100644 --- a/configure.ac +++ b/configure.ac @@ -242,7 +242,7 @@ PKG_CHECK_MODULES(GMODULE_EXPORT, gmodule-export-2.0, HAVE_GMODULE_EXPORT=yes, H dnl Needed by plugins that use g_module_*() API PKG_CHECK_MODULES(GMODULE_NO_EXPORT, gmodule-no-export-2.0) -dnl x11 is optional for librfb and eglglessink +dnl x11 is optional for librfb HAVE_X11=NO PKG_CHECK_MODULES(X11, x11, HAVE_X11=yes, HAVE_X11=no) AC_SUBST(X11_LIBS) @@ -458,163 +458,6 @@ else AG_GST_DISABLE_PLUGIN(dccp) fi -dnl *** gst-libs/gst/egl *** -AC_ARG_WITH([egl-window-system], - AS_HELP_STRING([--with-egl-window-system],[EGL window system to use (x11, mali-fb, rpi, none)]), - [EGL_WINDOW_SYSTEM="$withval"], - [EGL_WINDOW_SYSTEM="auto"]) - -if test x"$EGL_WINDOW_SYSTEM" = x"auto"; then - dnl Mali - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - LIBS="$LIBS -lUMP $EGL_LIBS" - CFLAGS="$CFLAGS $EGL_CFLAGS" - AC_CHECK_LIB([Mali], [mali_image_create], [EGL_WINDOW_SYSTEM="mali-fb"], [EGL_WINDOW_SYSTEM="auto"]) - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - - dnl RPi - if test x"$EGL_WINDOW_SYSTEM" = x"auto"; then - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - LIBS="$LIBS -lvcos -lvchiq_arm" - CFLAGS="$CFLAGS" - AC_CHECK_LIB([bcm_host], [bcm_host_init], - [ - LIBS="$LIBS -lbcm_host" - AC_CHECK_HEADER([bcm_host.h], [EGL_WINDOW_SYSTEM="rpi"], [EGL_WINDOW_SYSTEM="auto"]) - ]) - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - fi - - if test x"$EGL_WINDOW_SYSTEM" = x"auto"; then - if test x"$HAVE_X11" = x"yes"; then - EGL_WINDOW_SYSTEM="x11" - fi - fi - - if test x"$EGL_WINDOW_SYSTEM" = x"auto"; then - EGL_WINDOW_SYSTEM="auto" - fi -fi - -case "$EGL_WINDOW_SYSTEM" in - x11|auto) - PKG_CHECK_MODULES(EGL, egl, HAVE_EGL="yes", [ - HAVE_EGL="no" - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - - AC_CHECK_LIB([EGL], [eglGetProcAddress], - [ - AC_CHECK_HEADER([EGL/egl.h], - [ - HAVE_EGL="yes" - EGL_LIBS="-lEGL" - EGL_CFLAGS="" - ] - ) - ] - ) - - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - ]) - - dnl X11 specific part, above is auto and X11 - if test x"$HAVE_EGL" = x"yes" -a x"$EGL_WINDOW_SYSTEM" = x"x11"; then - if test x"$HAVE_X11" != x"yes"; then - AC_MSG_ERROR([libX11 not found and is required for EGL X11 window system]) - else - AC_DEFINE(USE_EGL_X11, [1], [Use X11 EGL window system]) - EGL_CFLAGS="$EGL_CFLAGS $X11_CFLAGS" - EGL_LIBS="$EGL_LIBS $X11_LIBS" - fi - fi - ;; - mali-fb) - dnl FIXME: Mali EGL depends on GLESv1 or GLESv2 - HAVE_EGL="no" - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - AC_CHECK_HEADER([EGL/fbdev_window.h], - [ - LIBS="$LIBS -lUMP" - AC_CHECK_LIB([Mali], [mali_image_create], - [ - LIBS="$LIBS -lMali" - AC_CHECK_LIB([GLESv2], [glEnable], - [ - AC_CHECK_HEADER([GLES2/gl2.h], - [ - AC_CHECK_LIB([EGL], [eglGetProcAddress], - [ - AC_CHECK_HEADER([EGL/egl.h], - [ - HAVE_EGL="yes" - EGL_LIBS="-lGLESv2 -lEGL -lMali -lUMP" - EGL_CFLAGS="" - AC_DEFINE(USE_EGL_MALI_FB, [1], [Use Mali FB EGL window system]) - ]) - ]) - ]) - ]) - ]) - ]) - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - ;; - rpi) - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - - dnl FIXME: EGL of RPi depends on GLESv1 or GLESv2 - dnl FIXME: GLESv2 of RPi depends on EGL... WTF! - LIBS="$LIBS -lvcos -lvchiq_arm" - AC_CHECK_LIB([bcm_host], [bcm_host_init], - [ - LIBS="$LIBS -lbcm_host" - AC_CHECK_HEADER(bcm_host.h, - [ - LIBS="$LIBS -lGLESv2" - AC_CHECK_LIB([EGL], [eglGetProcAddress], - [ - LIBS="$LIBS -lEGL" - AC_CHECK_HEADER([EGL/egl.h], - [ - AC_CHECK_LIB([GLESv2], [glEnable], - [ - AC_CHECK_HEADER([GLES2/gl2.h], - [ - HAVE_EGL="yes" - EGL_LIBS="-lGLESv2 -lEGL -lbcm_host -lvcos -lvchiq_arm" - EGL_CFLAGS="" - AC_DEFINE(USE_EGL_RPI, [1], [Use RPi EGL window system]) - ]) - ]) - ]) - ]) - ]) - ]) - - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - ;; - none|no) - HAVE_EGL="no" - AC_MSG_WARN([No EGL window system specified, will not build gstreamer-egl]) - ;; - *) - AC_MSG_ERROR([invalid EGL window system specified]) - ;; -esac - -AC_SUBST(EGL_LIBS) -AC_SUBST(EGL_CFLAGS) -AM_CONDITIONAL(HAVE_EGL, test x"$HAVE_EGL" = x"yes") - dnl *** opengl *** AC_ARG_ENABLE([opengl], [ --enable-opengl Enable Desktop OpenGL support @<:@default=auto@:>@], @@ -707,10 +550,7 @@ HAVE_GLU=no HAVE_GNUSTEP_COCOA=no HAVE_WAYLAND_EGL=no -HAVE_EGL_RPI="no" -if test x"$HAVE_EGL" = x"yes" -a x"$EGL_WINDOW_SYSTEM" = x"rpi"; then -HAVE_EGL_RPI="yes" -fi +HAVE_EGL_RPI=no case $host in *-mingw32* ) @@ -729,6 +569,70 @@ case $host in AG_GST_CHECK_LIBHEADER(GLU, GLU, gluSphere,, GL/glu.h) AG_GST_CHECK_LIBHEADER(GLES2, GLESv2, glTexImage2D,, GLES2/gl2.h) + old_LIBS=$LIBS + old_CFLAGS=$CFLAGS + + dnl FIXME: Mali EGL depends on GLESv1 or GLESv2 + AC_CHECK_HEADER([EGL/fbdev_window.h], + [ + LIBS="$LIBS -lUMP" + AC_CHECK_LIB([Mali], [mali_image_create], + [ + LIBS="$LIBS -lMali" + AC_CHECK_LIB([GLESv2], [glEnable], + [ + AC_CHECK_HEADER([GLES2/gl2.h], + [ + AC_CHECK_LIB([EGL], [eglGetProcAddress], + [ + AC_CHECK_HEADER([EGL/egl.h], + [ + HAVE_EGL=yes + HAVE_GLES2=yes + EGL_LIBS="-lMali -lUMP" + EGL_CFLAGS="" + AC_DEFINE(USE_EGL_MALI_FB, [1], [Use Mali FB EGL platform]) + ]) + ]) + ]) + ]) + ]) + ]) + + dnl FIXME: EGL of RPi depends on GLESv1 or GLESv2 + dnl FIXME: GLESv2 of RPi depends on EGL... WTF! + LIBS="$LIBS -lvcos -lvchiq_arm" + AC_CHECK_LIB([bcm_host], [bcm_host_init], + [ + LIBS="$LIBS -lbcm_host" + AC_CHECK_HEADER(bcm_host.h, + [ + LIBS="$LIBS -lGLESv2" + AC_CHECK_LIB([EGL], [eglGetProcAddress], + [ + LIBS="$LIBS -lEGL" + AC_CHECK_HEADER([EGL/egl.h], + [ + AC_CHECK_LIB([GLESv2], [glEnable], + [ + AC_CHECK_HEADER([GLES2/gl2.h], + [ + HAVE_EGL=yes + HAVE_GLES2=yes + HAVE_EGL_RPI=yes + EGL_LIBS="-lbcm_host -lvcos -lvchiq_arm" + EGL_CFLAGS="" + AC_DEFINE(USE_EGL_RPI, [1], [Use RPi platform]) + ]) + ]) + ]) + ]) + ]) + ]) + + LIBS=$old_LIBS + CFLAGS=$old_CFLAGS + PKG_CHECK_MODULES(WAYLAND_EGL, wayland-client >= 1.0 wayland-cursor >= 1.0 wayland-egl >= 9.0, HAVE_WAYLAND_EGL=yes, HAVE_WAYLAND_EGL=no) ;; esac @@ -1200,6 +1104,7 @@ if test "x$GL_APIS" = "x" -o "x$GL_PLATFORMS" = "x" -o "x$GL_WINDOWS" = "x"; the USE_EGL=no USE_WGL=no USE_COCOA=no + USE_EGL_MALI=no USE_EGL_RPI=no USE_EAGL=no @@ -1232,6 +1137,7 @@ AM_CONDITIONAL(USE_GLX, test "x$USE_GLX" = "xyes") AM_CONDITIONAL(USE_EGL, test "x$USE_EGL" = "xyes") AM_CONDITIONAL(USE_WGL, test "x$USE_WGL" = "xyes") AM_CONDITIONAL(USE_COCOA, test "x$USE_COCOA" = "xyes") +AM_CONDITIONAL(USE_EGL_MALI, test "x$USE_EGL_MALI" = "xyes") AM_CONDITIONAL(USE_EGL_RPI, test "x$USE_EGL_RPI" = "xyes") AM_CONDITIONAL(USE_EAGL, test "x$USE_EAGL" = "xyes") @@ -2599,39 +2505,6 @@ AG_GST_CHECK_FEATURE(RSVG, [rsvg decoder], rsvg, [ AC_SUBST(RSVG_LIBS) ]) -dnl *** eglgles *** -translit(dnm, m, l) AM_CONDITIONAL(USE_EGLGLES, true) -AG_GST_CHECK_FEATURE(EGLGLES, [eglgles sink], eglgles, [ - HAVE_EGLGLES="no" - - if test x"$HAVE_EGL" = x"yes"; then - PKG_CHECK_MODULES(EGLGLES, egl glesv2, HAVE_EGLGLES="yes", [ - HAVE_EGLGLES="no" - old_LIBS=$LIBS - old_CFLAGS=$CFLAGS - - LIBS="$LIBS $EGL_LIBS" - CFLAGS="$CFLAGS $EGL_CFLAGS" - AC_CHECK_LIB([GLESv2], [glEnable], - [ - AC_CHECK_HEADER([GLES2/gl2.h], - [ - HAVE_EGLGLES="yes" - EGLGLES_LIBS="-lGLESv2" - EGLGLES_CFLAGS="" - ]) - ]) - LIBS=$old_LIBS - CFLAGS=$old_CFLAGS - ]) - elif test x"$HAVE_IOS" = x"yes"; then - HAVE_EGLGLES="yes" - fi - - AC_SUBST(EGLGLES_CFLAGS) - AC_SUBST(EGLGLES_LIBS) -]) - dnl *** gl *** translit(dnm, m, l) AM_CONDITIONAL(USE_GL, true) AG_GST_CHECK_FEATURE(GL, [gl elements], gl, [ @@ -3056,8 +2929,6 @@ AM_CONDITIONAL(USE_OPENJPEG, false) AM_CONDITIONAL(USE_OPENNI2, false) AM_CONDITIONAL(USE_OPUS, false) AM_CONDITIONAL(USE_PVR, false) -AM_CONDITIONAL(USE_RSVG, false) -AM_CONDITIONAL(USE_EGLGLES, false) AM_CONDITIONAL(USE_LIBVISUAL, false) AM_CONDITIONAL(USE_TIMIDITY, false) AM_CONDITIONAL(USE_WILDMIDI, false) @@ -3237,7 +3108,6 @@ gst/yadif/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/basecamerabinsrc/Makefile -gst-libs/gst/egl/Makefile gst-libs/gst/gl/Makefile gst-libs/gst/gl/android/Makefile gst-libs/gst/gl/cocoa/Makefile @@ -3308,7 +3178,6 @@ ext/directfb/Makefile ext/wayland/Makefile ext/daala/Makefile ext/dts/Makefile -ext/eglgles/Makefile ext/gl/Makefile ext/faac/Makefile ext/faad/Makefile @@ -3371,8 +3240,6 @@ pkgconfig/gstreamer-codecparsers.pc pkgconfig/gstreamer-codecparsers-uninstalled.pc pkgconfig/gstreamer-insertbin.pc pkgconfig/gstreamer-insertbin-uninstalled.pc -pkgconfig/gstreamer-egl.pc -pkgconfig/gstreamer-egl-uninstalled.pc pkgconfig/gstreamer-gl.pc pkgconfig/gstreamer-gl-uninstalled.pc pkgconfig/gstreamer-mpegts.pc diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 8758cf39e7..b093bcfe56 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -72,7 +72,6 @@ EXTRA_HFILES = \ $(top_srcdir)/ext/dc1394/gstdc1394.h \ $(top_srcdir)/ext/directfb/dfbvideosink.h \ $(top_srcdir)/ext/dts/gstdtsdec.h \ - $(top_srcdir)/ext/eglgles/gsteglglessink.h \ $(top_srcdir)/ext/faac/gstfaac.h \ $(top_srcdir)/ext/faad/gstfaad.h \ $(top_srcdir)/ext/kate/gstkateenc.h \ diff --git a/ext/Makefile.am b/ext/Makefile.am index c32ce0dd2e..5701057fb8 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -76,12 +76,6 @@ else DTS_DIR= endif -if USE_EGLGLES -EGLGLES_DIR=eglgles -else -EGLGLES_DIR= -endif - if USE_GL GL_DIR=gl else @@ -416,7 +410,6 @@ SUBDIRS=\ $(DAALA_DIR) \ $(DTS_DIR) \ $(RESINDVD_DIR) \ - $(EGLGLES_DIR) \ $(GL_DIR) \ $(FAAC_DIR) \ $(FAAD_DIR) \ @@ -492,7 +485,6 @@ DIST_SUBDIRS = \ lv2 \ daala \ dts \ - eglgles \ gl \ modplug \ mimic \ diff --git a/ext/eglgles/Android.mk b/ext/eglgles/Android.mk deleted file mode 100644 index 6f8db387a4..0000000000 --- a/ext/eglgles/Android.mk +++ /dev/null @@ -1,71 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -# ------------------------------------- -# gsteglglessink library -# -include $(CLEAR_VARS) - -LOCAL_ARM_MODE := arm - -gsteglglessink_FILES := gsteglglessink.c - -LOCAL_SRC_FILES := $(gsteglglessink_FILES) -LOCAL_C_INCLUDES = $(LOCAL_PATH) \ - $(LOCAL_PATH)/include - -ifneq ($(NDK_BUILD), true) -LOCAL_C_INCLUDES += $(TOP)/frameworks/base -else -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../android_headers -endif - -LOCAL_CFLAGS += -DHAVE_CONFIG_H -LOCAL_CFLAGS += -Wall -Wdeclaration-after-statement -g -O2 -LOCAL_CFLAGS += -DANDROID_USE_GSTREAMER \ - $(shell $(PKG_CONFIG) gstreamer-plugins-bad-0.10 --cflags) \ - $(shell $(PKG_CONFIG) gstreamer-audio-0.10 --cflags) - -ifeq ($(USE_AUDIO_PURE_CODEC),true) -LOCAL_CFLAGS += -DAUDIO_PURE_CODEC -endif - -LOCAL_SHARED_LIBRARIES += libdl -LOCAL_SHARED_LIBRARIES += \ - libgstreamer-0.10 \ - libgstbase-0.10 \ - libglib-2.0 \ - libgthread-2.0 \ - libgmodule-2.0 \ - libgobject-2.0 \ - libgstvideo-0.10 \ - libgstinterfaces-0.10 - -ifneq ($(NDK_BUILD), true) -LOCAL_LDFLAGS := -L$(SYSROOT)/usr/lib -llog -else -LOCAL_LDFLAGS := -L$(SYSROOT)/usr/lib -llog -lmedia -lutils -endif - -LOCAL_LDFLAGS += -lEGL -lGLESv2 - -LOCAL_SHARED_LIBRARIES += \ - libutils \ - libcutils \ - libui \ - libhardware \ - libandroid_runtime \ - libmedia - - -LOCAL_MODULE:= libgsteglglessink -LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 - -# -# define LOCAL_PRELINK_MODULE to false to not use pre-link map -# -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_TAGS := eng debug - -include $(BUILD_SHARED_LIBRARY) - -#endif # USE_HARDWARE_MM == true diff --git a/ext/eglgles/Makefile.am b/ext/eglgles/Makefile.am deleted file mode 100644 index c6a7c5e2cc..0000000000 --- a/ext/eglgles/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -plugin_LTLIBRARIES = libgsteglglessink.la - -if HAVE_IOS -DISTRO_SRC = gstegladaptation_eagl.m -else -DISTRO_SRC = gstegladaptation_egl.c video_platform_wrapper.c -GST_EGL_LIBS = $(top_builddir)/gst-libs/gst/egl/libgstegl-$(GST_API_VERSION).la -endif - -libgsteglglessink_la_SOURCES = gsteglglessink.c gstegladaptation.c $(DISTRO_SRC) - -libgsteglglessink_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) \ - $(GST_CFLAGS) \ - $(EGL_CFLAGS) \ - $(EGLGLES_CFLAGS) -libgsteglglessink_la_OBJCFLAGS = $(GST_PLUGINS_BAD_OBJCFLAGS) \ - $(GST_PLUGINS_BASE_OBJCFLAGS) \ - $(GST_BASE_OBJCFLAGS) \ - $(GST_OBJCFLAGS) \ - $(EGLGLES_OBJCFLAGS) \ - -fobjc-abi-version=2 -fobjc-legacy-dispatch - -libgsteglglessink_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) $(EGL_LIBS) $(EGLGLES_LIBS) \ - -lgstvideo-$(GST_API_VERSION) $(GST_EGL_LIBS) - -if HAVE_IOS -libgsteglglessink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -Wl,-framework,OpenGLES -Wl,-framework,QuartzCore -Wl,-framework,UIKit -Wl,-framework,CoreGraphics -Wl,-framework,CoreFoundation -Wl,-framework,Foundation -W -else -libgsteglglessink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -endif - -libgsteglglessink_la_LIBTOOLFLAGS = --tag=CC $(GST_PLUGIN_LIBTOOLFLAGS) - -noinst_HEADERS = gsteglglessink.h gstegladaptation.h video_platform_wrapper.h - -EXTRA_DIST = gsteglglessink.c gstegladaptation.c gstegladaptation_egl.c video_platform_wrapper.c gstegladaptation_eagl.m $(noinst_HEADERS) diff --git a/ext/eglgles/TODO b/ext/eglgles/TODO deleted file mode 100644 index 4c194733b5..0000000000 --- a/ext/eglgles/TODO +++ /dev/null @@ -1,11 +0,0 @@ -- Correctly handle upstream surface region size changes. Test and debug - set_render_rect -- Make sure we are considering DAR on all scaling/rendering cases -- Test and debug caps renegotiation -- Drop android specifics like the default window h/w -- Move EGL/GLES context to it's own struct. Proly move GLSL stuff to it's - own header too -- Optimize shading routines if possible. -- Either finish implementing or drop fast rendering path logic -- Implement buffer pool -- Finish code documentation diff --git a/ext/eglgles/gstegladaptation.c b/ext/eglgles/gstegladaptation.c deleted file mode 100644 index 3d9cc03bf8..0000000000 --- a/ext/eglgles/gstegladaptation.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * GStreamer EGL/GLES Sink Adaptation - * Copyright (C) 2012-2013 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * @author: Sebastian Dröge - * @author: Thiago Santos - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gstegladaptation.h" - -#include -#include - -#define GST_CAT_DEFAULT egladaption_debug -GST_DEBUG_CATEGORY (egladaption_debug); - -/* GLESv2 GLSL Shaders - * - * OpenGL ES Standard does not mandate YUV support. This is - * why most of these shaders deal with Packed/Planar YUV->RGB - * conversion. - */ - -/* *INDENT-OFF* */ -/* Direct vertex copy */ -static const char *vert_COPY_prog = { - "attribute vec3 position;" - "attribute vec2 texpos;" - "varying vec2 opos;" - "void main(void)" - "{" - " opos = texpos;" - " gl_Position = vec4(position, 1.0);" - "}" -}; - -static const char *vert_COPY_prog_no_tex = { - "attribute vec3 position;" - "void main(void)" - "{" - " gl_Position = vec4(position, 1.0);" - "}" -}; - -/* Paint all black */ -static const char *frag_BLACK_prog = { - "precision mediump float;" - "void main(void)" - "{" - " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);" - "}" -}; - -/* Direct fragments copy with stride-scaling */ -static const char *frag_COPY_prog = { - "precision mediump float;" - "varying vec2 opos;" - "uniform sampler2D tex;" - "uniform vec2 tex_scale0;" - "uniform vec2 tex_scale1;" - "uniform vec2 tex_scale2;" - "void main(void)" - "{" - " vec4 t = texture2D(tex, opos / tex_scale0);" - " gl_FragColor = vec4(t.rgb, 1.0);" - "}" -}; - -/* Channel reordering for XYZ <-> ZYX conversion */ -static const char *frag_REORDER_prog = { - "precision mediump float;" - "varying vec2 opos;" - "uniform sampler2D tex;" - "uniform vec2 tex_scale0;" - "uniform vec2 tex_scale1;" - "uniform vec2 tex_scale2;" - "void main(void)" - "{" - " vec4 t = texture2D(tex, opos / tex_scale0);" - " gl_FragColor = vec4(t.%c, t.%c, t.%c, 1.0);" - "}" -}; - -/* Packed YUV converters */ - -/** AYUV to RGB conversion */ -static const char *frag_AYUV_prog = { - "precision mediump float;" - "varying vec2 opos;" - "uniform sampler2D tex;" - "uniform vec2 tex_scale0;" - "uniform vec2 tex_scale1;" - "uniform vec2 tex_scale2;" - "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" - "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" - "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" - "const vec3 bcoeff = vec3(1.164, 2.018, 0.000);" - "void main(void) {" - " float r,g,b;" - " vec3 yuv;" - " yuv = texture2D(tex,opos / tex_scale0).gba;" - " yuv += offset;" - " r = dot(yuv, rcoeff);" - " g = dot(yuv, gcoeff);" - " b = dot(yuv, bcoeff);" - " gl_FragColor=vec4(r,g,b,1.0);" - "}" -}; - -/* Planar YUV converters */ - -/** YUV to RGB conversion */ -static const char *frag_PLANAR_YUV_prog = { - "precision mediump float;" - "varying vec2 opos;" - "uniform sampler2D Ytex,Utex,Vtex;" - "uniform vec2 tex_scale0;" - "uniform vec2 tex_scale1;" - "uniform vec2 tex_scale2;" - "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" - "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" - "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" - "const vec3 bcoeff = vec3(1.164, 2.018, 0.000);" - "void main(void) {" - " float r,g,b;" - " vec3 yuv;" - " yuv.x=texture2D(Ytex,opos / tex_scale0).r;" - " yuv.y=texture2D(Utex,opos / tex_scale1).r;" - " yuv.z=texture2D(Vtex,opos / tex_scale2).r;" - " yuv += offset;" - " r = dot(yuv, rcoeff);" - " g = dot(yuv, gcoeff);" - " b = dot(yuv, bcoeff);" - " gl_FragColor=vec4(r,g,b,1.0);" - "}" -}; - -/** NV12/NV21 to RGB conversion */ -static const char *frag_NV12_NV21_prog = { - "precision mediump float;" - "varying vec2 opos;" - "uniform sampler2D Ytex,UVtex;" - "uniform vec2 tex_scale0;" - "uniform vec2 tex_scale1;" - "uniform vec2 tex_scale2;" - "const vec3 offset = vec3(-0.0625, -0.5, -0.5);" - "const vec3 rcoeff = vec3(1.164, 0.000, 1.596);" - "const vec3 gcoeff = vec3(1.164,-0.391,-0.813);" - "const vec3 bcoeff = vec3(1.164, 2.018, 0.000);" - "void main(void) {" - " float r,g,b;" - " vec3 yuv;" - " yuv.x=texture2D(Ytex,opos / tex_scale0).r;" - " yuv.yz=texture2D(UVtex,opos / tex_scale1).%c%c;" - " yuv += offset;" - " r = dot(yuv, rcoeff);" - " g = dot(yuv, gcoeff);" - " b = dot(yuv, bcoeff);" - " gl_FragColor=vec4(r,g,b,1.0);" - "}" -}; -/* *INDENT-ON* */ - -void -gst_egl_adaption_init (void) -{ - GST_DEBUG_CATEGORY_INIT (egladaption_debug, "egladaption", 0, - "EGL adaption layer"); -} - -static GstCaps * -_gst_video_format_new_template_caps (GstVideoFormat format) -{ - return gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (format), - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); -} - -GstCaps * -gst_egl_adaptation_fill_supported_fbuffer_configs (GstEglAdaptationContext * - ctx) -{ - GstCaps *caps = NULL, *copy1, *copy2; - guint i, n; - - GST_DEBUG_OBJECT (ctx->element, - "Building initial list of wanted eglattribs per format"); - - /* Init supported format/caps list */ - if (_gst_egl_choose_config (ctx, TRUE, NULL)) { - - caps = gst_caps_new_empty (); - - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBA)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGRA)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_ARGB)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_ABGR)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBx)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGRx)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_xRGB)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_xBGR)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_AYUV)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y444)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_BGR)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_I420)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_YV12)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_NV12)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_NV21)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y42B)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_Y41B)); - gst_caps_append (caps, - _gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB16)); - - copy1 = gst_caps_copy (caps); - copy2 = gst_caps_copy (caps); - -#ifndef HAVE_IOS - n = gst_caps_get_size (caps); - for (i = 0; i < n; i++) { - GstCapsFeatures *features = - gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE, NULL); - gst_caps_set_features (caps, i, features); - } -#endif - - n = gst_caps_get_size (copy1); - for (i = 0; i < n; i++) { - GstCapsFeatures *features = - gst_caps_features_new - (GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL); - gst_caps_set_features (copy1, i, features); - } - - gst_caps_append (caps, copy1); - gst_caps_append (caps, copy2); - } else { - GST_INFO_OBJECT (ctx->element, - "EGL display doesn't support RGBA8888 config"); - } - - return caps; -} - -void -gst_egl_adaptation_cleanup (GstEglAdaptationContext * ctx) -{ - gint i; - - glUseProgram (0); - - if (ctx->have_vbo) { - glDeleteBuffers (1, &ctx->position_buffer); - glDeleteBuffers (1, &ctx->index_buffer); - ctx->have_vbo = FALSE; - } - - if (ctx->have_texture) { - glDeleteTextures (ctx->n_textures, ctx->texture); - ctx->have_texture = FALSE; - ctx->n_textures = 0; - } - - for (i = 0; i < 2; i++) { - if (ctx->glslprogram[i]) { - glDetachShader (ctx->glslprogram[i], ctx->fragshader[i]); - glDetachShader (ctx->glslprogram[i], ctx->vertshader[i]); - glDeleteProgram (ctx->glslprogram[i]); - glDeleteShader (ctx->fragshader[i]); - glDeleteShader (ctx->vertshader[i]); - ctx->glslprogram[i] = 0; - ctx->fragshader[i] = 0; - ctx->vertshader[i] = 0; - } - } - - gst_egl_adaptation_context_make_current (ctx, FALSE); - - gst_egl_adaptation_destroy_surface (ctx); - gst_egl_adaptation_destroy_context (ctx); -} - -gboolean -got_gl_error (const char *wtf) -{ - GLuint error = GL_NO_ERROR; - - if ((error = glGetError ()) != GL_NO_ERROR) { - GST_CAT_ERROR (GST_CAT_DEFAULT, "GL ERROR: %s returned 0x%04x", wtf, error); - return TRUE; - } - return FALSE; -} - -static gboolean -create_shader_program (GstEglAdaptationContext * ctx, GLuint * prog, - GLuint * vert, GLuint * frag, const gchar * vert_text, - const gchar * frag_text) -{ - GLint test; - GLchar *info_log; - - /* Build shader program for video texture rendering */ - *vert = glCreateShader (GL_VERTEX_SHADER); - GST_DEBUG_OBJECT (ctx->element, "Sending %s to handle %d", vert_text, *vert); - glShaderSource (*vert, 1, &vert_text, NULL); - if (got_gl_error ("glShaderSource vertex")) - goto HANDLE_ERROR; - - glCompileShader (*vert); - if (got_gl_error ("glCompileShader vertex")) - goto HANDLE_ERROR; - - glGetShaderiv (*vert, GL_COMPILE_STATUS, &test); - if (test != GL_FALSE) - GST_DEBUG_OBJECT (ctx->element, "Successfully compiled vertex shader"); - else { - GST_ERROR_OBJECT (ctx->element, "Couldn't compile vertex shader"); - glGetShaderiv (*vert, GL_INFO_LOG_LENGTH, &test); - info_log = g_new0 (GLchar, test); - glGetShaderInfoLog (*vert, test, NULL, info_log); - GST_INFO_OBJECT (ctx->element, "Compilation info log:\n%s", info_log); - g_free (info_log); - goto HANDLE_ERROR; - } - - *frag = glCreateShader (GL_FRAGMENT_SHADER); - GST_DEBUG_OBJECT (ctx->element, "Sending %s to handle %d", frag_text, *frag); - glShaderSource (*frag, 1, &frag_text, NULL); - if (got_gl_error ("glShaderSource fragment")) - goto HANDLE_ERROR; - - glCompileShader (*frag); - if (got_gl_error ("glCompileShader fragment")) - goto HANDLE_ERROR; - - glGetShaderiv (*frag, GL_COMPILE_STATUS, &test); - if (test != GL_FALSE) - GST_DEBUG_OBJECT (ctx->element, "Successfully compiled fragment shader"); - else { - GST_ERROR_OBJECT (ctx->element, "Couldn't compile fragment shader"); - glGetShaderiv (*frag, GL_INFO_LOG_LENGTH, &test); - info_log = g_new0 (GLchar, test); - glGetShaderInfoLog (*frag, test, NULL, info_log); - GST_INFO_OBJECT (ctx->element, "Compilation info log:\n%s", info_log); - g_free (info_log); - goto HANDLE_ERROR; - } - - *prog = glCreateProgram (); - if (got_gl_error ("glCreateProgram")) - goto HANDLE_ERROR; - glAttachShader (*prog, *vert); - if (got_gl_error ("glAttachShader vertices")) - goto HANDLE_ERROR; - glAttachShader (*prog, *frag); - if (got_gl_error ("glAttachShader fragments")) - goto HANDLE_ERROR; - glLinkProgram (*prog); - glGetProgramiv (*prog, GL_LINK_STATUS, &test); - if (test != GL_FALSE) { - GST_DEBUG_OBJECT (ctx->element, "GLES: Successfully linked program"); - } else { - GST_ERROR_OBJECT (ctx->element, "Couldn't link program"); - goto HANDLE_ERROR; - } - - return TRUE; - -HANDLE_ERROR: - { - if (*frag && *prog) - glDetachShader (*prog, *frag); - if (*vert && *prog) - glDetachShader (*prog, *vert); - if (*prog) - glDeleteProgram (*prog); - if (*frag) - glDeleteShader (*frag); - if (*vert) - glDeleteShader (*vert); - *prog = 0; - *frag = 0; - *vert = 0; - - return FALSE; - } -} - -gboolean -gst_egl_adaptation_init_surface (GstEglAdaptationContext * ctx, - GstVideoFormat format) -{ - GLboolean ret; - const gchar *texnames[3] = { NULL, }; - gchar *frag_prog = NULL; - gboolean free_frag_prog = FALSE; - gint i; - - GST_DEBUG_OBJECT (ctx->element, "Enter EGL surface setup"); - - if (!gst_egl_adaptation_create_surface (ctx)) { - GST_ERROR_OBJECT (ctx->element, "Can't create surface"); - goto HANDLE_ERROR_LOCKED; - } - - if (!gst_egl_adaptation_context_make_current (ctx, TRUE)) - goto HANDLE_ERROR_LOCKED; - - gst_egl_adaptation_query_buffer_preserved (ctx); - - gst_egl_adaptation_init_exts (ctx); - - /* Save surface dims */ - gst_egl_adaptation_update_surface_dimensions (ctx); - - /* Save display's pixel aspect ratio - * - * DAR is reported as w/h * EGL_DISPLAY_SCALING wich is - * a constant with value 10000. This attribute is only - * supported if the EGL version is >= 1.2 - * XXX: Setup this as a property. - * or some other one time check. Right now it's being called once - * per frame. - */ - gst_egl_adaptation_query_par (ctx); - - /* We have a surface! */ - ctx->have_surface = TRUE; - - /* Init vertex and fragment GLSL shaders. - * Note: Shader compiler support is optional but we currently rely on it. - */ - - glGetBooleanv (GL_SHADER_COMPILER, &ret); - if (ret == GL_FALSE) { - GST_ERROR_OBJECT (ctx->element, "Shader compiler support is unavailable!"); - goto HANDLE_ERROR; - } - - /* Build shader program for video texture rendering */ - - switch (format) { - case GST_VIDEO_FORMAT_AYUV: - frag_prog = (gchar *) frag_AYUV_prog; - free_frag_prog = FALSE; - ctx->n_textures = 1; - texnames[0] = "tex"; - break; - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y41B: - frag_prog = (gchar *) frag_PLANAR_YUV_prog; - free_frag_prog = FALSE; - ctx->n_textures = 3; - texnames[0] = "Ytex"; - texnames[1] = "Utex"; - texnames[2] = "Vtex"; - break; - case GST_VIDEO_FORMAT_NV12: - frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'r', 'a'); - free_frag_prog = TRUE; - ctx->n_textures = 2; - texnames[0] = "Ytex"; - texnames[1] = "UVtex"; - break; - case GST_VIDEO_FORMAT_NV21: - frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'a', 'r'); - free_frag_prog = TRUE; - ctx->n_textures = 2; - texnames[0] = "Ytex"; - texnames[1] = "UVtex"; - break; - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_BGRA: - frag_prog = g_strdup_printf (frag_REORDER_prog, 'b', 'g', 'r'); - free_frag_prog = TRUE; - ctx->n_textures = 1; - texnames[0] = "tex"; - break; - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_ARGB: - frag_prog = g_strdup_printf (frag_REORDER_prog, 'g', 'b', 'a'); - free_frag_prog = TRUE; - ctx->n_textures = 1; - texnames[0] = "tex"; - break; - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_ABGR: - frag_prog = g_strdup_printf (frag_REORDER_prog, 'a', 'b', 'g'); - free_frag_prog = TRUE; - ctx->n_textures = 1; - texnames[0] = "tex"; - break; - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_RGB16: - frag_prog = (gchar *) frag_COPY_prog; - free_frag_prog = FALSE; - ctx->n_textures = 1; - texnames[0] = "tex"; - break; - default: - g_assert_not_reached (); - break; - } - - if (!create_shader_program (ctx, - &ctx->glslprogram[0], - &ctx->vertshader[0], - &ctx->fragshader[0], vert_COPY_prog, frag_prog)) { - if (free_frag_prog) - g_free (frag_prog); - frag_prog = NULL; - goto HANDLE_ERROR; - } - if (free_frag_prog) - g_free (frag_prog); - frag_prog = NULL; - - ctx->position_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "position"); - ctx->texpos_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "texpos"); - ctx->tex_scale_loc[0][0] = - glGetUniformLocation (ctx->glslprogram[0], "tex_scale0"); - ctx->tex_scale_loc[0][1] = - glGetUniformLocation (ctx->glslprogram[0], "tex_scale1"); - ctx->tex_scale_loc[0][2] = - glGetUniformLocation (ctx->glslprogram[0], "tex_scale2"); - - glEnableVertexAttribArray (ctx->position_loc[0]); - if (got_gl_error ("glEnableVertexAttribArray")) - goto HANDLE_ERROR; - - glEnableVertexAttribArray (ctx->texpos_loc[0]); - if (got_gl_error ("glEnableVertexAttribArray")) - goto HANDLE_ERROR; - - for (i = 0; i < ctx->n_textures; i++) { - ctx->tex_loc[0][i] = - glGetUniformLocation (ctx->glslprogram[0], texnames[i]); - } - - if (!ctx->buffer_preserved) { - /* Build shader program for black borders */ - if (!create_shader_program (ctx, - &ctx->glslprogram[1], - &ctx->vertshader[1], - &ctx->fragshader[1], vert_COPY_prog_no_tex, frag_BLACK_prog)) - goto HANDLE_ERROR; - - ctx->position_loc[1] = - glGetAttribLocation (ctx->glslprogram[1], "position"); - - glEnableVertexAttribArray (ctx->position_loc[1]); - if (got_gl_error ("glEnableVertexAttribArray")) - goto HANDLE_ERROR; - } - - /* Generate textures */ - if (!ctx->have_texture) { - GST_INFO_OBJECT (ctx->element, "Performing initial texture setup"); - - glGenTextures (ctx->n_textures, ctx->texture); - if (got_gl_error ("glGenTextures")) - goto HANDLE_ERROR_LOCKED; - - for (i = 0; i < ctx->n_textures; i++) { - glBindTexture (GL_TEXTURE_2D, ctx->texture[i]); - if (got_gl_error ("glBindTexture")) - goto HANDLE_ERROR; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - /* If these are not set the texture image unit will return - * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * frames. For a deeper explanation take a look at the OpenGL ES - * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto HANDLE_ERROR_LOCKED; - } - - ctx->have_texture = TRUE; - } - - glUseProgram (0); - - return TRUE; - - /* Errors */ -HANDLE_ERROR_LOCKED: -HANDLE_ERROR: - GST_ERROR_OBJECT (ctx->element, "Couldn't setup EGL surface"); - return FALSE; -} - -gboolean -gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx) -{ - gint egl_configs; - - if (!_gst_egl_choose_config (ctx, FALSE, &egl_configs)) { - GST_ERROR_OBJECT (ctx->element, "eglChooseConfig failed"); - goto HANDLE_ERROR; - } - - if (egl_configs < 1) { - GST_ERROR_OBJECT (ctx->element, - "Could not find matching framebuffer config"); - goto HANDLE_ERROR; - } - - if (!gst_egl_adaptation_create_egl_context (ctx)) { - GST_ERROR_OBJECT (ctx->element, "Error getting context, eglCreateContext"); - goto HANDLE_ERROR; - } - - return TRUE; - - /* Errors */ -HANDLE_ERROR: - GST_ERROR_OBJECT (ctx->element, "Couldn't choose an usable config"); - return FALSE; -} - -GstEglAdaptationContext * -gst_egl_adaptation_context_new (GstElement * element) -{ - GstEglAdaptationContext *ctx = g_new0 (GstEglAdaptationContext, 1); - - ctx->element = gst_object_ref (element); - - gst_egl_adaptation_init (ctx); - return ctx; -} - -void -gst_egl_adaptation_context_free (GstEglAdaptationContext * ctx) -{ - gst_egl_adaptation_deinit (ctx); - gst_object_unref (ctx->element); - g_free (ctx); -} diff --git a/ext/eglgles/gstegladaptation.h b/ext/eglgles/gstegladaptation.h deleted file mode 100644 index 48b31eb7fe..0000000000 --- a/ext/eglgles/gstegladaptation.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * GStreamer EGL/GLES Sink Adaptation - * Copyright (C) 2012-2013 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * @author: Sebastian Dröge - * @author: Thiago Santos - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_EGL_ADAPTATION_H__ -#define __GST_EGL_ADAPTATION_H__ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#ifndef __VCCOREVER__ -#define __VCCOREVER__ 0x04000000 -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC optimize ("gnu89-inline") -#endif - -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#ifdef HAVE_IOS -#include -#else -#include -#include -#include -#include -#include -#endif - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#pragma GCC reset_options -#pragma GCC diagnostic pop -#endif - -G_BEGIN_DECLS - -typedef struct _GstEglAdaptationContext GstEglAdaptationContext; -typedef struct _GstEglGlesImageFmt GstEglGlesImageFmt; - -#ifdef HAVE_IOS -typedef struct _GstEaglContext GstEaglContext; -#else -typedef struct _GstEglGlesRenderContext GstEglGlesRenderContext; -#endif - -typedef struct _coord5 -{ - float x; - float y; - float z; - float a; /* texpos x */ - float b; /* texpos y */ -} coord5; - -typedef struct -{ - GLuint texture; -} GstEGLGLESImageData; - -/* - * GstEglAdaptationContext: - * @have_vbo: Set if the GLES VBO setup has been performed - * @have_texture: Set if the GLES texture setup has been performed - * @have_surface: Set if the EGL surface setup has been performed - * - * The #GstEglAdaptationContext data structure. - */ -struct _GstEglAdaptationContext -{ - GstElement *element; - -#ifdef HAVE_IOS - GstEaglContext *eaglctx; - void * window, *used_window; -#else - GstEglGlesRenderContext *eglglesctx; - GstEGLDisplay *display, *set_display; - EGLNativeWindowType window, used_window; -#endif - - GLuint fragshader[2]; /* frame, border */ - GLuint vertshader[2]; /* frame, border */ - GLuint glslprogram[2]; /* frame, border */ - GLuint texture[3]; /* RGB/Y, U/UV, V */ - /* shader vars */ - GLuint position_loc[2]; /* frame, border */ - GLuint texpos_loc[1]; /* frame */ - GLuint tex_scale_loc[1][3]; /* [frame] RGB/Y, U/UV, V */ - GLuint tex_loc[1][3]; /* [frame] RGB/Y, U/UV, V */ - coord5 position_array[16]; /* 4 x Frame x-normal,y-normal, 4x Frame x-normal,y-flip, 4 x Border1, 4 x Border2 */ - unsigned short index_array[4]; - unsigned int position_buffer, index_buffer; - gint n_textures; - - gint surface_width; - gint surface_height; - gint pixel_aspect_ratio_n; - gint pixel_aspect_ratio_d; - - gboolean have_vbo; - gboolean have_texture; - gboolean have_surface; - gboolean buffer_preserved; -}; - -GST_DEBUG_CATEGORY_EXTERN (egladaption_debug); - -void gst_egl_adaption_init (void); - -GstEglAdaptationContext * gst_egl_adaptation_context_new (GstElement * element); -void gst_egl_adaptation_context_free (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_init (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_deinit (GstEglAdaptationContext * ctx); - -gboolean gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx); -void gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx); - -gboolean -gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx); - -#ifndef HAVE_IOS -EGLContext gst_egl_adaptation_context_get_egl_context (GstEglAdaptationContext * ctx); -#endif - -/* platform window */ -gboolean gst_egl_adaptation_create_native_window (GstEglAdaptationContext -* ctx, gint width, gint height, gpointer * own_window_data); -void gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, gpointer * own_window_data); - -GstCaps *gst_egl_adaptation_fill_supported_fbuffer_configs (GstEglAdaptationContext * ctx); -gboolean gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx); -gboolean gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx); -gboolean gst_egl_adaptation_init_surface (GstEglAdaptationContext * ctx, GstVideoFormat format); -void gst_egl_adaptation_init_exts (GstEglAdaptationContext * ctx); -gboolean gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext * ctx); -gboolean _gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, gint * num_configs); - -gboolean got_gl_error (const char *wtf); -gboolean got_egl_error (const char *wtf); - -void gst_egl_adaptation_set_window (GstEglAdaptationContext * ctx, guintptr window); - -gboolean gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, gboolean bind); -void gst_egl_adaptation_cleanup (GstEglAdaptationContext * ctx); - -void gst_egl_adaptation_bind_API (GstEglAdaptationContext * ctx); - -gboolean gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx); - -#ifndef HAVE_IOS -/* TODO: The goal is to move this function to gstegl lib (or - * splitted between gstegl lib and gstgl lib) in order to be used in - * webkitVideoSink - * So it has to be independent of GstEglAdaptationContext */ -GstBuffer * -gst_egl_image_allocator_alloc_eglimage (GstAllocator * allocator, - GstEGLDisplay * display, EGLContext eglcontext, GstVideoFormat format, - gint width, gint height); -#endif - -G_END_DECLS - -#endif /* __GST_EGL_ADAPTATION_H__ */ diff --git a/ext/eglgles/gstegladaptation_eagl.m b/ext/eglgles/gstegladaptation_eagl.m deleted file mode 100644 index 2da420308a..0000000000 --- a/ext/eglgles/gstegladaptation_eagl.m +++ /dev/null @@ -1,349 +0,0 @@ -/* - * GStreamer EGL/GLES Sink Adaptation for IOS - * Copyright (C) 2013 Collabora Ltd. - * @author: Thiago Santos - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#import -#import -#import -#include - -#include "gstegladaptation.h" - -#define GST_CAT_DEFAULT egladaption_debug - -struct _GstEaglContext -{ - EAGLContext *eagl_context; - GLuint framebuffer; - GLuint color_renderbuffer; - GLuint depth_renderbuffer; - - UIView *window; - UIView *used_window; -}; - -static gboolean -gst_egl_adaptation_update_surface (GstEglAdaptationContext * ctx); - -void -gst_egl_adaptation_init (GstEglAdaptationContext * ctx) -{ - ctx->eaglctx = g_new0 (GstEaglContext, 1); -} - -void -gst_egl_adaptation_deinit (GstEglAdaptationContext * ctx) -{ - g_free (ctx->eaglctx); -} - -gboolean -gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx) -{ - /* NOP - the display should be initialized by the application */ - return TRUE; -} - -void -gst_egl_adaptation_bind_API (GstEglAdaptationContext * ctx) -{ - /* NOP */ -} - -gboolean -gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx, gint width, gint height, gpointer * own_window_data) -{ - return FALSE; -} - -void -gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, gpointer * own_window_data) -{ -} - -gboolean -gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx) -{ - __block EAGLContext *context; - - dispatch_sync(dispatch_get_main_queue(), ^{ - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - if (context == nil) { - GST_ERROR_OBJECT (ctx->element, "Failed to create EAGL GLES2 context"); - } - }); - - ctx->eaglctx->eagl_context = context; - if (context == nil) - return FALSE; - - /* EAGL needs the context to be set here to allow surface creation */ - return gst_egl_adaptation_context_make_current (ctx, TRUE); -} - -gboolean -gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, - gboolean bind) -{ - __block EAGLContext *ctx_to_set = nil; - if (bind && ctx->eaglctx->eagl_context) { - EAGLContext *cur_ctx = [EAGLContext currentContext]; - - if (cur_ctx == ctx->eaglctx->eagl_context) { - GST_DEBUG_OBJECT (ctx->element, - "Already attached the context to thread %p", g_thread_self ()); - return TRUE; - } - - GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p", - g_thread_self ()); - if ([EAGLContext setCurrentContext: ctx->eaglctx->eagl_context] == NO) { - got_gl_error ("setCurrentContext"); - GST_ERROR_OBJECT (ctx->element, "Couldn't bind context"); - return FALSE; - } - ctx_to_set = ctx->eaglctx->eagl_context; - } else { - GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p", - g_thread_self ()); - if ([EAGLContext setCurrentContext: nil] == NO) { - got_gl_error ("setCurrentContext"); - GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context"); - return FALSE; - } - } - - return TRUE; -} - -gboolean -gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx) -{ - __block GLuint framebuffer; - __block GLuint colorRenderbuffer; - __block GLint width; - __block GLint height; - __block GLuint depthRenderbuffer; - __block GLenum status; - __block CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[ctx->eaglctx->window layer]; - - dispatch_sync(dispatch_get_main_queue(), ^{ - - gst_egl_adaptation_context_make_current (ctx, TRUE); - - if (ctx->eaglctx->framebuffer) { - framebuffer = ctx->eaglctx->framebuffer; - } else { - /* Allocate framebuffer */ - glGenFramebuffers(1, &framebuffer); - } - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - /* Allocate color render buffer */ - glGenRenderbuffers(1, &colorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); - [ctx->eaglctx->eagl_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, colorRenderbuffer); - - /* Get renderbuffer width/height */ - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); - - /* allocate depth render buffer */ - glGenRenderbuffers(1, &depthRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, depthRenderbuffer); - - gst_egl_adaptation_context_make_current (ctx, FALSE); - }); - - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - /* check creation status */ - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if(status != GL_FRAMEBUFFER_COMPLETE) { - NSLog(@"failed to make complete framebuffer object %x", status); - return FALSE; - } - - ctx->eaglctx->framebuffer = framebuffer; - ctx->eaglctx->color_renderbuffer = colorRenderbuffer; - ctx->eaglctx->depth_renderbuffer = colorRenderbuffer; - ctx->surface_width = width; - ctx->surface_height = height; - glBindRenderbuffer(GL_RENDERBUFFER, ctx->eaglctx->color_renderbuffer); - - return TRUE; -} - -gboolean -_gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, gint * num_configs) -{ - CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[ctx->eaglctx->window layer]; - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, - kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, - nil]; - [eaglLayer setOpaque:YES]; - [eaglLayer setDrawableProperties:dict]; - - if (num_configs) - *num_configs = 1; - return TRUE; -} - -void -gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx) -{ - CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[ctx->eaglctx->window layer]; - NSDictionary *dict = [eaglLayer drawableProperties]; - - ctx->buffer_preserved = FALSE; - if ([dict objectForKey: kEAGLDrawablePropertyRetainedBacking] != nil) { - NSNumber *n = [dict objectForKey: kEAGLDrawablePropertyRetainedBacking]; - ctx->buffer_preserved = [n boolValue] != NO; - } else { - GST_DEBUG_OBJECT (ctx->element, "No information about buffer preserving in layer properties"); - } -} - -void -gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx) -{ - /* TODO how can we check this? */ - ctx->pixel_aspect_ratio_n = 1; - ctx->pixel_aspect_ratio_d = 1; -} - -gboolean -gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext * - ctx) -{ - CAEAGLLayer *layer = (CAEAGLLayer *)[ctx->eaglctx->window layer]; - CGSize size = layer.frame.size; - - if (size.width != ctx->surface_width || size.height != ctx->surface_height) { - ctx->surface_width = size.width; - ctx->surface_height = size.height; - GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", - (gint) size.width, (gint) size.height); - if (!gst_egl_adaptation_update_surface (ctx)) { - GST_WARNING_OBJECT (ctx->element, "Failed to update surface " - "to new dimensions"); - } - return TRUE; - } - - return FALSE; -} - -void -gst_egl_adaptation_init_exts (GstEglAdaptationContext * ctx) -{ - const gchar *extensions = (const gchar *) glGetString(GL_EXTENSIONS); - NSString *extensionsString = NULL; - - if (extensions) { - extensionsString= [NSString stringWithCString:extensions encoding: NSASCIIStringEncoding]; - } - - GST_DEBUG_OBJECT (ctx->element, "Available GL extensions: %s\n", - GST_STR_NULL ([extensionsString UTF8String])); -} - -void -gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx) -{ - if (ctx->eaglctx->framebuffer) { - glDeleteFramebuffers (1, &ctx->eaglctx->framebuffer); - ctx->eaglctx->framebuffer = 0; - - glDeleteRenderbuffers(1, &ctx->eaglctx->depth_renderbuffer); - ctx->eaglctx->depth_renderbuffer = 0; - glDeleteRenderbuffers(1, &ctx->eaglctx->color_renderbuffer); - ctx->eaglctx->color_renderbuffer = 0; - - ctx->have_surface = FALSE; - } -} - -static gboolean -gst_egl_adaptation_update_surface (GstEglAdaptationContext * ctx) -{ - glBindFramebuffer(GL_FRAMEBUFFER, ctx->eaglctx->framebuffer); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(1, &ctx->eaglctx->depth_renderbuffer); - - glBindRenderbuffer (GL_RENDERBUFFER, 0); - glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(1, &ctx->eaglctx->color_renderbuffer); - - return gst_egl_adaptation_create_surface (ctx); -} - -void -gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx) -{ - if (ctx->eaglctx->eagl_context) { - [ctx->eaglctx->eagl_context release]; - ctx->eaglctx->eagl_context = NULL; - } -} - -gboolean -gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx) -{ - [ctx->eaglctx->eagl_context presentRenderbuffer:GL_RENDERBUFFER]; - return TRUE; -} - -void -gst_egl_adaptation_set_window (GstEglAdaptationContext * ctx, guintptr window) -{ - ctx->eaglctx->window = (UIView *) window; -} diff --git a/ext/eglgles/gstegladaptation_egl.c b/ext/eglgles/gstegladaptation_egl.c deleted file mode 100644 index de90792191..0000000000 --- a/ext/eglgles/gstegladaptation_egl.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright (C) 2012-2013 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * @author: Sebastian Dröge - * @author: Thiago Santos - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gstegladaptation.h" -#include "video_platform_wrapper.h" -#include - -#include -#include -#include -#include -#include - -#define GST_CAT_DEFAULT egladaption_debug - -/* Some EGL implementations are reporting wrong - * values for the display's EGL_PIXEL_ASPECT_RATIO. - * They are required by the khronos specs to report - * this value as w/h * EGL_DISPLAY_SCALING (Which is - * a constant with value 10000) but at least the - * Galaxy SIII (Android) is reporting just 1 when - * w = h. We use these two to bound returned values to - * sanity. - */ -#define EGL_SANE_DAR_MIN ((EGL_DISPLAY_SCALING)/10) -#define EGL_SANE_DAR_MAX ((EGL_DISPLAY_SCALING)*10) - -#define GST_EGLGLESSINK_EGL_MIN_VERSION 1 - -static const EGLint eglglessink_RGBA8888_attribs[] = { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE -}; - -/* - * GstEglGlesRenderContext: - * @config: Current EGL config - * @eglcontext: Current EGL context - * @egl_minor: EGL version (minor) - * @egl_major: EGL version (major) - * - * This struct holds the sink's EGL/GLES rendering context. - */ -struct _GstEglGlesRenderContext -{ - EGLConfig config; - EGLContext eglcontext; - EGLSurface surface; - EGLint egl_minor, egl_major; -}; - -gboolean -got_egl_error (const char *wtf) -{ - EGLint error; - - if ((error = eglGetError ()) != EGL_SUCCESS) { - GST_CAT_DEBUG (GST_CAT_DEFAULT, "EGL ERROR: %s returned 0x%04x", wtf, - error); - return TRUE; - } - - return FALSE; -} - -/* Prints available EGL/GLES extensions - * If another rendering path is implemented this is the place - * where you want to check for the availability of its supporting - * EGL/GLES extensions. - */ -void -gst_egl_adaptation_init_exts (GstEglAdaptationContext * ctx) -{ -#ifndef GST_DISABLE_GST_DEBUG - const char *eglexts; - unsigned const char *glexts; - - eglexts = eglQueryString (gst_egl_display_get (ctx->display), EGL_EXTENSIONS); - glexts = glGetString (GL_EXTENSIONS); - - GST_DEBUG_OBJECT (ctx->element, "Available EGL extensions: %s\n", - GST_STR_NULL (eglexts)); - GST_DEBUG_OBJECT (ctx->element, "Available GLES extensions: %s\n", - GST_STR_NULL ((const char *) glexts)); -#endif - return; -} - -gboolean -gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx) -{ - GstQuery *query; - GstMessage *msg; - EGLDisplay display; - GST_DEBUG_OBJECT (ctx->element, "Enter EGL initial configuration"); - - if (!platform_wrapper_init ()) { - GST_ERROR_OBJECT (ctx->element, "Couldn't init EGL platform wrapper"); - goto HANDLE_ERROR; - } - - if (!ctx->set_display) { - query = gst_query_new_context (GST_EGL_DISPLAY_CONTEXT_TYPE); - if (gst_pad_peer_query (GST_BASE_SINK_PAD (ctx->element), query)) { - GstContext *context; - - gst_query_parse_context (query, &context); - gst_context_get_egl_display (context, &ctx->set_display); - } - gst_query_unref (query); - } - - if (!ctx->set_display) { - msg = - gst_message_new_need_context (GST_OBJECT_CAST (ctx->element), - GST_EGL_DISPLAY_CONTEXT_TYPE); - gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg); - } - - GST_OBJECT_LOCK (ctx->element); - if (!ctx->set_display) { - GstContext *context; - - GST_OBJECT_UNLOCK (ctx->element); - - display = eglGetDisplay (EGL_DEFAULT_DISPLAY); - if (display == EGL_NO_DISPLAY) { - GST_ERROR_OBJECT (ctx->element, "Could not get EGL display connection"); - goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */ - } - ctx->display = gst_egl_display_new (display, (GDestroyNotify) eglTerminate); - - context = gst_context_new_egl_display (ctx->display, FALSE); - msg = gst_message_new_have_context (GST_OBJECT (ctx->element), context); - gst_element_post_message (GST_ELEMENT_CAST (ctx->element), msg); - } else { - ctx->display = gst_egl_display_ref (ctx->set_display); - } - - if (!eglInitialize (gst_egl_display_get (ctx->display), - &ctx->eglglesctx->egl_major, &ctx->eglglesctx->egl_minor)) { - got_egl_error ("eglInitialize"); - GST_ERROR_OBJECT (ctx->element, "Could not init EGL display connection"); - goto HANDLE_EGL_ERROR; - } - - /* Check against required EGL version - * XXX: Need to review the version requirement in terms of the needed API - */ - if (ctx->eglglesctx->egl_major < GST_EGLGLESSINK_EGL_MIN_VERSION) { - GST_ERROR_OBJECT (ctx->element, "EGL v%d needed, but you only have v%d.%d", - GST_EGLGLESSINK_EGL_MIN_VERSION, ctx->eglglesctx->egl_major, - ctx->eglglesctx->egl_minor); - goto HANDLE_ERROR; - } - - GST_INFO_OBJECT (ctx->element, "System reports supported EGL version v%d.%d", - ctx->eglglesctx->egl_major, ctx->eglglesctx->egl_minor); - - eglBindAPI (EGL_OPENGL_ES_API); - - return TRUE; - - /* Errors */ -HANDLE_EGL_ERROR: - GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", eglGetError ()); -HANDLE_ERROR: - GST_ERROR_OBJECT (ctx->element, "Couldn't setup window/surface from handle"); - return FALSE; -} - -gboolean -gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, - gboolean bind) -{ - g_assert (ctx->display != NULL); - - if (bind && ctx->eglglesctx->surface && ctx->eglglesctx->eglcontext) { - EGLContext *cur_ctx = eglGetCurrentContext (); - - if (cur_ctx == ctx->eglglesctx->eglcontext) { - GST_DEBUG_OBJECT (ctx->element, - "Already attached the context to thread %p", g_thread_self ()); - return TRUE; - } - - GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p", - g_thread_self ()); - if (!eglMakeCurrent (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface, ctx->eglglesctx->surface, - ctx->eglglesctx->eglcontext)) { - got_egl_error ("eglMakeCurrent"); - GST_ERROR_OBJECT (ctx->element, "Couldn't bind context"); - return FALSE; - } - } else { - GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p", - g_thread_self ()); - if (!eglMakeCurrent (gst_egl_display_get (ctx->display), - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { - got_egl_error ("eglMakeCurrent"); - GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context"); - return FALSE; - } - } - - return TRUE; -} - -/* XXX: Lock eglgles context? */ -gboolean -gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext * ctx) -{ - gint width, height; - - /* Save surface dims */ - eglQuerySurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface, EGL_WIDTH, &width); - eglQuerySurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface, EGL_HEIGHT, &height); - - if (width != ctx->surface_width || height != ctx->surface_height) { - ctx->surface_width = width; - ctx->surface_height = height; - GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width, - height); - return TRUE; - } - - return FALSE; -} - -void -gst_egl_adaptation_bind_API (GstEglAdaptationContext * ctx) -{ - eglBindAPI (EGL_OPENGL_ES_API); -} - -gboolean -gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx) -{ - gboolean ret = eglSwapBuffers (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface); - if (ret == EGL_FALSE) { - got_egl_error ("eglSwapBuffers"); - } - return ret; -} - -gboolean -_gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, - gint * num_configs) -{ - EGLint cfg_number; - gboolean ret; - EGLConfig *config = NULL; - - if (!try_only) - config = &ctx->eglglesctx->config; - - ret = eglChooseConfig (gst_egl_display_get (ctx->display), - eglglessink_RGBA8888_attribs, config, 1, &cfg_number) != EGL_FALSE; - - if (!ret) - got_egl_error ("eglChooseConfig"); - else if (num_configs) - *num_configs = cfg_number; - return ret; -} - -gboolean -gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx) -{ - ctx->eglglesctx->surface = - eglCreateWindowSurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->config, ctx->used_window, NULL); - - if (ctx->eglglesctx->surface == EGL_NO_SURFACE) { - got_egl_error ("eglCreateWindowSurface"); - GST_ERROR_OBJECT (ctx->element, "Can't create surface"); - return FALSE; - } - return TRUE; -} - -void -gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx) -{ - EGLint swap_behavior; - - ctx->buffer_preserved = FALSE; - if (eglQuerySurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface, EGL_SWAP_BEHAVIOR, &swap_behavior)) { - GST_DEBUG_OBJECT (ctx->element, "Buffer swap behavior %x", swap_behavior); - ctx->buffer_preserved = swap_behavior == EGL_BUFFER_PRESERVED; - } else { - GST_DEBUG_OBJECT (ctx->element, "Can't query buffer swap behavior"); - } -} - -void -gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx) -{ - EGLint display_par; - - /* fixed value */ - ctx->pixel_aspect_ratio_d = EGL_DISPLAY_SCALING; - - /* Save display's pixel aspect ratio - * - * DAR is reported as w/h * EGL_DISPLAY_SCALING wich is - * a constant with value 10000. This attribute is only - * supported if the EGL version is >= 1.2 - * XXX: Setup this as a property. - * or some other one time check. Right now it's being called once - * per frame. - */ - if (ctx->eglglesctx->egl_major == 1 && ctx->eglglesctx->egl_minor < 2) { - GST_DEBUG_OBJECT (ctx->element, "Can't query PAR. Using default: %dx%d", - EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING); - ctx->pixel_aspect_ratio_n = EGL_DISPLAY_SCALING; - } else { - eglQuerySurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface, EGL_PIXEL_ASPECT_RATIO, &display_par); - /* Fix for outbound DAR reporting on some implementations not - * honoring the 'should return w/h * EGL_DISPLAY_SCALING' spec - * requirement - */ - if (display_par == EGL_UNKNOWN || display_par < EGL_SANE_DAR_MIN || - display_par > EGL_SANE_DAR_MAX) { - GST_DEBUG_OBJECT (ctx->element, "Nonsensical PAR value returned: %d. " - "Bad EGL implementation? " - "Will use default: %d/%d", ctx->pixel_aspect_ratio_n, - EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING); - ctx->pixel_aspect_ratio_n = EGL_DISPLAY_SCALING; - } else { - ctx->pixel_aspect_ratio_n = display_par; - } - } -} - -gboolean -gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx) -{ - EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - - ctx->eglglesctx->eglcontext = - eglCreateContext (gst_egl_display_get (ctx->display), - ctx->eglglesctx->config, EGL_NO_CONTEXT, con_attribs); - - if (ctx->eglglesctx->eglcontext == EGL_NO_CONTEXT) { - GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", - eglGetError ()); - return FALSE; - } - - GST_DEBUG_OBJECT (ctx->element, "EGL Context: %p", - ctx->eglglesctx->eglcontext); - - return TRUE; -} - -EGLContext -gst_egl_adaptation_context_get_egl_context (GstEglAdaptationContext * ctx) -{ - g_return_val_if_fail (ctx != NULL, EGL_NO_CONTEXT); - - return ctx->eglglesctx->eglcontext; -} - -static void -gst_egl_gles_image_data_free (GstEGLGLESImageData * data) -{ - glDeleteTextures (1, &data->texture); - g_slice_free (GstEGLGLESImageData, data); -} - - -GstBuffer * -gst_egl_image_allocator_alloc_eglimage (GstAllocator * allocator, - GstEGLDisplay * display, EGLContext eglcontext, GstVideoFormat format, - gint width, gint height) -{ - GstEGLGLESImageData *data = NULL; - GstBuffer *buffer; - GstVideoInfo info; - gint i; - gint stride[3]; - gsize offset[3]; - GstMemory *mem[3] = { NULL, NULL, NULL }; - guint n_mem; - GstMemoryFlags flags = 0; - - memset (stride, 0, sizeof (stride)); - memset (offset, 0, sizeof (offset)); - - if (!gst_egl_image_memory_is_mappable ()) - flags |= GST_MEMORY_FLAG_NOT_MAPPABLE; - /* See https://bugzilla.gnome.org/show_bug.cgi?id=695203 */ - flags |= GST_MEMORY_FLAG_NO_SHARE; - - gst_video_info_set_format (&info, format, width, height); - - switch (format) { - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR:{ - gsize size; - EGLImageKHR image; - - mem[0] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), &size); - if (mem[0]) { - stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); - n_mem = 1; - GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); - } else { - data = g_slice_new0 (GstEGLGLESImageData); - - stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 3); - size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); - - glGenTextures (1, &data->texture); - if (got_gl_error ("glGenTextures")) - goto mem_error; - - glBindTexture (GL_TEXTURE_2D, data->texture); - if (got_gl_error ("glBindTexture")) - goto mem_error; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* If these are not set the texture image unit will return - * * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * * frames. For a deeper explanation take a look at the OpenGL ES - * * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto mem_error; - - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, - GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - if (got_gl_error ("glTexImage2D")) - goto mem_error; - - image = - eglCreateImageKHR (gst_egl_display_get (display), - eglcontext, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) data->texture, NULL); - if (got_egl_error ("eglCreateImageKHR")) - goto mem_error; - - mem[0] = - gst_egl_image_allocator_wrap (allocator, display, - image, GST_VIDEO_GL_TEXTURE_TYPE_RGB, - flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); - n_mem = 1; - } - break; - } - case GST_VIDEO_FORMAT_RGB16:{ - EGLImageKHR image; - gsize size; - - mem[0] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_RGB, GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), &size); - if (mem[0]) { - stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); - n_mem = 1; - GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); - } else { - data = g_slice_new0 (GstEGLGLESImageData); - - stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 2); - size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); - - glGenTextures (1, &data->texture); - if (got_gl_error ("glGenTextures")) - goto mem_error; - - glBindTexture (GL_TEXTURE_2D, data->texture); - if (got_gl_error ("glBindTexture")) - goto mem_error; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* If these are not set the texture image unit will return - * * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * * frames. For a deeper explanation take a look at the OpenGL ES - * * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto mem_error; - - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, - GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - NULL); - if (got_gl_error ("glTexImage2D")) - goto mem_error; - - image = - eglCreateImageKHR (gst_egl_display_get (display), - eglcontext, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) data->texture, NULL); - if (got_egl_error ("eglCreateImageKHR")) - goto mem_error; - - mem[0] = - gst_egl_image_allocator_wrap (allocator, display, - image, GST_VIDEO_GL_TEXTURE_TYPE_RGB, - flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); - n_mem = 1; - } - break; - } - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21:{ - EGLImageKHR image; - gsize size[2]; - - mem[0] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, - 0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]); - mem[1] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA, - GST_VIDEO_INFO_COMP_WIDTH (&info, 1), - GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]); - - if (mem[0] && mem[1]) { - stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info); - offset[1] = size[0]; - stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info); - n_mem = 2; - GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); - GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); - } else { - if (mem[0]) - gst_memory_unref (mem[0]); - if (mem[1]) - gst_memory_unref (mem[1]); - mem[0] = mem[1] = NULL; - - stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0)); - stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1) * 2); - offset[1] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0); - size[0] = offset[1]; - size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1); - - for (i = 0; i < 2; i++) { - data = g_slice_new0 (GstEGLGLESImageData); - - glGenTextures (1, &data->texture); - if (got_gl_error ("glGenTextures")) - goto mem_error; - - glBindTexture (GL_TEXTURE_2D, data->texture); - if (got_gl_error ("glBindTexture")) - goto mem_error; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* If these are not set the texture image unit will return - * * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * * frames. For a deeper explanation take a look at the OpenGL ES - * * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto mem_error; - - if (i == 0) - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_INFO_COMP_WIDTH (&info, i), - GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, NULL); - else - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, - GST_VIDEO_INFO_COMP_WIDTH (&info, i), - GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE_ALPHA, - GL_UNSIGNED_BYTE, NULL); - - if (got_gl_error ("glTexImage2D")) - goto mem_error; - - image = - eglCreateImageKHR (gst_egl_display_get (display), - eglcontext, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) data->texture, NULL); - if (got_egl_error ("eglCreateImageKHR")) - goto mem_error; - - mem[i] = - gst_egl_image_allocator_wrap (allocator, display, - image, - (i == - 0 ? GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE : - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA), - flags, size[i], data, - (GDestroyNotify) gst_egl_gles_image_data_free); - } - - n_mem = 2; - } - break; - } - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y41B:{ - EGLImageKHR image; - gsize size[3]; - - mem[0] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, - 0), GST_VIDEO_INFO_COMP_HEIGHT (&info, 0), &size[0]); - mem[1] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, - 1), GST_VIDEO_INFO_COMP_HEIGHT (&info, 1), &size[1]); - mem[2] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, GST_VIDEO_INFO_COMP_WIDTH (&info, - 2), GST_VIDEO_INFO_COMP_HEIGHT (&info, 2), &size[2]); - - if (mem[0] && mem[1] && mem[2]) { - stride[0] = size[0] / GST_VIDEO_INFO_HEIGHT (&info); - offset[1] = size[0]; - stride[1] = size[1] / GST_VIDEO_INFO_HEIGHT (&info); - offset[2] = size[1]; - stride[2] = size[2] / GST_VIDEO_INFO_HEIGHT (&info); - n_mem = 3; - GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); - GST_MINI_OBJECT_FLAG_SET (mem[1], GST_MEMORY_FLAG_NO_SHARE); - GST_MINI_OBJECT_FLAG_SET (mem[2], GST_MEMORY_FLAG_NO_SHARE); - } else { - if (mem[0]) - gst_memory_unref (mem[0]); - if (mem[1]) - gst_memory_unref (mem[1]); - if (mem[2]) - gst_memory_unref (mem[2]); - mem[0] = mem[1] = mem[2] = NULL; - - stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 0)); - stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 1)); - stride[2] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (&info, 2)); - size[0] = stride[0] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 0); - size[1] = stride[1] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 1); - size[2] = stride[2] * GST_VIDEO_INFO_COMP_HEIGHT (&info, 2); - offset[0] = 0; - offset[1] = size[0]; - offset[2] = offset[1] + size[1]; - - for (i = 0; i < 3; i++) { - data = g_slice_new0 (GstEGLGLESImageData); - - glGenTextures (1, &data->texture); - if (got_gl_error ("glGenTextures")) - goto mem_error; - - glBindTexture (GL_TEXTURE_2D, data->texture); - if (got_gl_error ("glBindTexture")) - goto mem_error; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* If these are not set the texture image unit will return - * * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * * frames. For a deeper explanation take a look at the OpenGL ES - * * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto mem_error; - - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - GST_VIDEO_INFO_COMP_WIDTH (&info, i), - GST_VIDEO_INFO_COMP_HEIGHT (&info, i), 0, GL_LUMINANCE, - GL_UNSIGNED_BYTE, NULL); - - if (got_gl_error ("glTexImage2D")) - goto mem_error; - - image = - eglCreateImageKHR (gst_egl_display_get (display), - eglcontext, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) data->texture, NULL); - if (got_egl_error ("eglCreateImageKHR")) - goto mem_error; - - mem[i] = - gst_egl_image_allocator_wrap (allocator, display, - image, GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE, - flags, size[i], data, - (GDestroyNotify) gst_egl_gles_image_data_free); - } - - n_mem = 3; - } - break; - } - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_AYUV:{ - gsize size; - EGLImageKHR image; - - mem[0] = - gst_egl_image_allocator_alloc (allocator, display, - GST_VIDEO_GL_TEXTURE_TYPE_RGBA, GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), &size); - if (mem[0]) { - stride[0] = size / GST_VIDEO_INFO_HEIGHT (&info); - n_mem = 1; - GST_MINI_OBJECT_FLAG_SET (mem[0], GST_MEMORY_FLAG_NO_SHARE); - } else { - data = g_slice_new0 (GstEGLGLESImageData); - - stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * 4); - size = stride[0] * GST_VIDEO_INFO_HEIGHT (&info); - - glGenTextures (1, &data->texture); - if (got_gl_error ("glGenTextures")) - goto mem_error; - - glBindTexture (GL_TEXTURE_2D, data->texture); - if (got_gl_error ("glBindTexture")) - goto mem_error; - - /* Set 2D resizing params */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* If these are not set the texture image unit will return - * * (R, G, B, A) = black on glTexImage2D for non-POT width/height - * * frames. For a deeper explanation take a look at the OpenGL ES - * * documentation for glTexParameter */ - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (got_gl_error ("glTexParameteri")) - goto mem_error; - - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, - GST_VIDEO_INFO_WIDTH (&info), - GST_VIDEO_INFO_HEIGHT (&info), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - if (got_gl_error ("glTexImage2D")) - goto mem_error; - - image = - eglCreateImageKHR (gst_egl_display_get (display), - eglcontext, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) data->texture, NULL); - if (got_egl_error ("eglCreateImageKHR")) - goto mem_error; - - mem[0] = - gst_egl_image_allocator_wrap (allocator, display, - image, GST_VIDEO_GL_TEXTURE_TYPE_RGBA, - flags, size, data, (GDestroyNotify) gst_egl_gles_image_data_free); - - n_mem = 1; - } - break; - } - default: - g_assert_not_reached (); - break; - } - - buffer = gst_buffer_new (); - gst_buffer_add_video_meta_full (buffer, 0, format, width, height, - GST_VIDEO_INFO_N_PLANES (&info), offset, stride); - - for (i = 0; i < n_mem; i++) - gst_buffer_append_memory (buffer, mem[i]); - - return buffer; - -mem_error: - { - GST_ERROR_OBJECT (GST_CAT_DEFAULT, "Failed to create EGLImage"); - - if (data) - gst_egl_gles_image_data_free (data); - - if (mem[0]) - gst_memory_unref (mem[0]); - if (mem[1]) - gst_memory_unref (mem[1]); - if (mem[2]) - gst_memory_unref (mem[2]); - - return NULL; - } -} - -void -gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, - gpointer * own_window_data) -{ - platform_destroy_native_window (gst_egl_display_get - (ctx->display), ctx->used_window, own_window_data); - ctx->used_window = 0; -} - -gboolean -gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx, - gint width, gint height, gpointer * own_window_data) -{ - EGLNativeWindowType window = - platform_create_native_window (width, height, own_window_data); - if (window) - gst_egl_adaptation_set_window (ctx, (guintptr) window); - GST_DEBUG_OBJECT (ctx->element, "Using window handle %p", (gpointer) window); - return window != 0; -} - -void -gst_egl_adaptation_set_window (GstEglAdaptationContext * ctx, guintptr window) -{ - ctx->window = (EGLNativeWindowType) window; -} - -void -gst_egl_adaptation_init (GstEglAdaptationContext * ctx) -{ - ctx->eglglesctx = g_new0 (GstEglGlesRenderContext, 1); -} - -void -gst_egl_adaptation_deinit (GstEglAdaptationContext * ctx) -{ - g_free (ctx->eglglesctx); -} - -void -gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx) -{ - if (ctx->eglglesctx->surface) { - eglDestroySurface (gst_egl_display_get (ctx->display), - ctx->eglglesctx->surface); - ctx->eglglesctx->surface = NULL; - ctx->have_surface = FALSE; - } -} - -void -gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx) -{ - if (ctx->eglglesctx->eglcontext) { - eglDestroyContext (gst_egl_display_get (ctx->display), - ctx->eglglesctx->eglcontext); - ctx->eglglesctx->eglcontext = NULL; - } -} diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c deleted file mode 100644 index 64472802d0..0000000000 --- a/ext/eglgles/gsteglglessink.c +++ /dev/null @@ -1,2259 +0,0 @@ -/* - * GStreamer EGL/GLES Sink - * Copyright (C) 2012 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * @author: Sebastian Dröge - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-eglglessink - * - * EglGlesSink renders video frames on a EGL surface it sets up - * from a window it either creates (on X11) or gets a handle to - * through it's xOverlay interface. All the display/surface logic - * in this sink uses EGL to interact with the native window system. - * The rendering logic, in turn, uses OpenGL ES v2. - * - * This sink has been tested to work on X11/Mesa and on Android - * (From Gingerbread on to Jelly Bean) and while it's currently - * using an slow copy-over rendering path it has proven to be fast - * enough on the devices we have tried it on. - * - * - * Supported EGL/OpenGL ES versions - * - * This Sink uses EGLv1 and GLESv2 - * - * - * - * - * Example launch line - * |[ - * gst-launch -v -m videotestsrc ! eglglessink - * ]| - * - * - * - * Example launch line with internal window creation disabled - * - * By setting the create_window property to FALSE you can force the - * sink to wait for a window handle through it's xOverlay interface even - * if internal window creation is supported by the platform. Window creation - * is only supported in X11 right now but it should be trivial to add support - * for different platforms. - * - * |[ - * gst-launch -v -m videotestsrc ! eglglessink create_window=FALSE - * ]| - * - * - * - * Scaling - * - * The sink will try it's best to consider the incoming frame's and display's - * pixel aspect ratio and fill the corresponding surface without altering the - * decoded frame's geometry when scaling. You can disable this logic by setting - * the force_aspect_ratio property to FALSE, in which case the sink will just - * fill the entire surface it has access to regardles of the PAR/DAR relationship. - * - * - * Querying the display aspect ratio is only supported with EGL versions >= 1.2. - * The sink will just assume the DAR to be 1/1 if it can't get access to this - * information. - * - * - * Here is an example launch line with the PAR/DAR aware scaling disabled: - * - * |[ - * gst-launch -v -m videotestsrc ! eglglessink force_aspect_ratio=FALSE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gstegladaptation.h" - -#ifdef USE_EGL_RPI -#include -#endif - -#include "gsteglglessink.h" - -GST_DEBUG_CATEGORY_STATIC (gst_eglglessink_debug); -#define GST_CAT_DEFAULT gst_eglglessink_debug - -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); - -/* Input capabilities. */ -static GstStaticPadTemplate gst_eglglessink_sink_template_factory = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ( -#ifndef HAVE_IOS - GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_EGL_IMAGE, - "{ " "RGBA, BGRA, ARGB, ABGR, " "RGBx, BGRx, xRGB, xBGR, " - "AYUV, Y444, I420, YV12, " "NV12, NV21, Y42B, Y41B, " - "RGB, BGR, RGB16 }") ";" -#endif - GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, - "{ " "RGBA, BGRA, ARGB, ABGR, " "RGBx, BGRx, xRGB, xBGR, " - "AYUV, Y444, I420, YV12, " "NV12, NV21, Y42B, Y41B, " - "RGB, BGR, RGB16 }") ";" - GST_VIDEO_CAPS_MAKE ("{ " - "RGBA, BGRA, ARGB, ABGR, " "RGBx, BGRx, xRGB, xBGR, " - "AYUV, Y444, I420, YV12, " "NV12, NV21, Y42B, Y41B, " - "RGB, BGR, RGB16 }"))); - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_CREATE_WINDOW, - PROP_FORCE_ASPECT_RATIO, -}; - -static void gst_eglglessink_finalize (GObject * object); -static void gst_eglglessink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_eglglessink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static GstStateChangeReturn gst_eglglessink_change_state (GstElement * element, - GstStateChange transition); -static void gst_eglglessink_set_context (GstElement * element, - GstContext * context); -static GstFlowReturn gst_eglglessink_prepare (GstBaseSink * bsink, - GstBuffer * buf); -static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink, - GstBuffer * buf); -static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps); -static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter); -static gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink, - GstQuery * query); -static gboolean gst_eglglessink_query (GstBaseSink * bsink, GstQuery * query); - -/* VideoOverlay interface cruft */ -static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface * - iface); - -/* Actual VideoOverlay interface funcs */ -static void gst_eglglessink_expose (GstVideoOverlay * overlay); -static void gst_eglglessink_set_window_handle (GstVideoOverlay * overlay, - guintptr id); -static void gst_eglglessink_set_render_rectangle (GstVideoOverlay * overlay, - gint x, gint y, gint width, gint height); - -/* Utility */ -static gboolean gst_eglglessink_create_window (GstEglGlesSink * - eglglessink, gint width, gint height); -static gboolean gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink); -static gboolean -gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps); -static GstFlowReturn gst_eglglessink_upload (GstEglGlesSink * sink, - GstBuffer * buf); -static GstFlowReturn gst_eglglessink_render (GstEglGlesSink * sink); -static GstFlowReturn gst_eglglessink_queue_object (GstEglGlesSink * sink, - GstMiniObject * obj); -static inline gboolean egl_init (GstEglGlesSink * eglglessink); - -#ifndef HAVE_IOS -static GstBuffer * -gst_eglglessink_egl_image_buffer_pool_send_blocking (GstBufferPool * bpool, - gpointer data) -{ - GstFlowReturn ret = GST_FLOW_OK; - GstQuery *query = NULL; - GstStructure *s = NULL; - const GValue *v = NULL; - GstBuffer *buffer = NULL; - GstStructure *config = NULL; - GstCaps *caps = NULL; - GstVideoInfo info; - - GstEglGlesSink *eglglessink = GST_EGLGLESSINK (data); - - config = gst_buffer_pool_get_config (bpool); - gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL); - gst_structure_free (config); - - gst_video_info_init (&info); - gst_video_info_from_caps (&info, caps); - - s = gst_structure_new ("eglglessink-allocate-eglimage", - "format", GST_TYPE_VIDEO_FORMAT, GST_VIDEO_INFO_FORMAT (&info), - "width", G_TYPE_INT, GST_VIDEO_INFO_WIDTH (&info), "height", G_TYPE_INT, - GST_VIDEO_INFO_HEIGHT (&info), NULL); - - query = gst_query_new_custom (GST_QUERY_CUSTOM, s); - - ret = - gst_eglglessink_queue_object (eglglessink, GST_MINI_OBJECT_CAST (query)); - - if (ret == GST_FLOW_OK && gst_structure_has_field (s, "buffer")) { - v = gst_structure_get_value (s, "buffer"); - buffer = GST_BUFFER_CAST (g_value_get_pointer (v)); - } - - gst_query_unref (query); - - return buffer; -} - -static void -gst_eglglessink_egl_image_buffer_pool_on_destroy (gpointer data) -{ - GstEglGlesSink *eglglessink = GST_EGLGLESSINK (data); - gst_object_unref (eglglessink); -} -#endif - -#define parent_class gst_eglglessink_parent_class -G_DEFINE_TYPE_WITH_CODE (GstEglGlesSink, gst_eglglessink, GST_TYPE_VIDEO_SINK, - G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, - gst_eglglessink_videooverlay_init)); - -static inline gboolean -egl_init (GstEglGlesSink * eglglessink) -{ - GstCaps *caps; - - if (!gst_egl_adaptation_init_display (eglglessink->egl_context)) { - GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL display"); - goto HANDLE_ERROR; - } - - caps = - gst_egl_adaptation_fill_supported_fbuffer_configs - (eglglessink->egl_context); - if (!caps) { - GST_ERROR_OBJECT (eglglessink, "Display support NONE of our configs"); - goto HANDLE_ERROR; - } else { - GST_OBJECT_LOCK (eglglessink); - gst_caps_replace (&eglglessink->sinkcaps, caps); - GST_OBJECT_UNLOCK (eglglessink); - gst_caps_unref (caps); - } - - eglglessink->egl_started = TRUE; - - return TRUE; - -HANDLE_ERROR: - GST_ERROR_OBJECT (eglglessink, "Failed to perform EGL init"); - return FALSE; -} - -static gpointer -render_thread_func (GstEglGlesSink * eglglessink) -{ - GstMessage *message; - GValue val = { 0 }; - GstDataQueueItem *item = NULL; - GstFlowReturn last_flow = GST_FLOW_OK; - - g_value_init (&val, GST_TYPE_G_THREAD); - g_value_set_boxed (&val, g_thread_self ()); - message = gst_message_new_stream_status (GST_OBJECT_CAST (eglglessink), - GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (eglglessink)); - gst_message_set_stream_status_object (message, &val); - GST_DEBUG_OBJECT (eglglessink, "posting ENTER stream status"); - gst_element_post_message (GST_ELEMENT_CAST (eglglessink), message); - g_value_unset (&val); - - gst_egl_adaptation_bind_API (eglglessink->egl_context); - - while (gst_data_queue_pop (eglglessink->queue, &item)) { - GstMiniObject *object = item->object; - - GST_DEBUG_OBJECT (eglglessink, "Handling object %" GST_PTR_FORMAT, object); - - if (GST_IS_CAPS (object)) { - GstCaps *caps = GST_CAPS_CAST (object); - - if (caps != eglglessink->configured_caps) { - if (!gst_eglglessink_configure_caps (eglglessink, caps)) { - last_flow = GST_FLOW_NOT_NEGOTIATED; - } - } -#ifndef HAVE_IOS - } else if (GST_IS_QUERY (object)) { - GstQuery *query = GST_QUERY_CAST (object); - GstStructure *s = (GstStructure *) gst_query_get_structure (query); - - if (gst_structure_has_name (s, "eglglessink-allocate-eglimage")) { - GstBuffer *buffer; - GstVideoFormat format; - gint width, height; - GValue v = { 0, }; - GstAllocator *allocator = gst_egl_image_allocator_obtain (); - - if (!gst_structure_get_enum (s, "format", GST_TYPE_VIDEO_FORMAT, - (gint *) & format) - || !gst_structure_get_int (s, "width", &width) - || !gst_structure_get_int (s, "height", &height)) { - g_assert_not_reached (); - } - - buffer = - gst_egl_image_allocator_alloc_eglimage - (allocator, eglglessink->egl_context->display, - gst_egl_adaptation_context_get_egl_context - (eglglessink->egl_context), format, width, height); - gst_object_unref (allocator); - g_value_init (&v, G_TYPE_POINTER); - g_value_set_pointer (&v, buffer); - gst_structure_set_value (s, "buffer", &v); - g_value_unset (&v); - } else { - g_assert_not_reached (); - } - last_flow = GST_FLOW_OK; -#endif - } else if (GST_IS_BUFFER (object)) { - GstBuffer *buf = GST_BUFFER_CAST (item->object); - - if (eglglessink->configured_caps) { - last_flow = gst_eglglessink_upload (eglglessink, buf); - } else { - last_flow = GST_FLOW_OK; - GST_DEBUG_OBJECT (eglglessink, - "No caps configured yet, not drawing anything"); - } - } else if (!object) { - if (eglglessink->configured_caps) { - last_flow = gst_eglglessink_render (eglglessink); - } else { - last_flow = GST_FLOW_OK; - GST_DEBUG_OBJECT (eglglessink, - "No caps configured yet, not drawing anything"); - } - } else { - g_assert_not_reached (); - } - - item->destroy (item); - g_mutex_lock (&eglglessink->render_lock); - eglglessink->last_flow = last_flow; - eglglessink->dequeued_object = object; - g_cond_broadcast (&eglglessink->render_cond); - g_mutex_unlock (&eglglessink->render_lock); - - if (last_flow != GST_FLOW_OK) - break; - GST_DEBUG_OBJECT (eglglessink, "Successfully handled object"); - } - - if (last_flow == GST_FLOW_OK) { - g_mutex_lock (&eglglessink->render_lock); - eglglessink->last_flow = GST_FLOW_FLUSHING; - eglglessink->dequeued_object = NULL; - g_cond_broadcast (&eglglessink->render_cond); - g_mutex_unlock (&eglglessink->render_lock); - } - - GST_DEBUG_OBJECT (eglglessink, "Shutting down thread"); - - /* EGL/GLES cleanup */ - gst_egl_adaptation_cleanup (eglglessink->egl_context); - - if (eglglessink->configured_caps) { - gst_caps_unref (eglglessink->configured_caps); - eglglessink->configured_caps = NULL; - } - - g_value_init (&val, GST_TYPE_G_THREAD); - g_value_set_boxed (&val, g_thread_self ()); - message = gst_message_new_stream_status (GST_OBJECT_CAST (eglglessink), - GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (eglglessink)); - gst_message_set_stream_status_object (message, &val); - GST_DEBUG_OBJECT (eglglessink, "posting LEAVE stream status"); - gst_element_post_message (GST_ELEMENT_CAST (eglglessink), message); - g_value_unset (&val); - - return NULL; -} - -static gboolean -gst_eglglessink_start (GstEglGlesSink * eglglessink) -{ - GError *error = NULL; - - GST_DEBUG_OBJECT (eglglessink, "Starting"); - - if (!eglglessink->egl_started) { - GST_ERROR_OBJECT (eglglessink, "EGL uninitialized. Bailing out"); - goto HANDLE_ERROR; - } - - /* Ask for a window to render to */ - if (!eglglessink->have_window) - gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (eglglessink)); - - if (!eglglessink->have_window && !eglglessink->create_window) { - GST_ERROR_OBJECT (eglglessink, "Window handle unavailable and we " - "were instructed not to create an internal one. Bailing out."); - goto HANDLE_ERROR; - } - - eglglessink->last_flow = GST_FLOW_OK; - eglglessink->display_region.w = 0; - eglglessink->display_region.h = 0; - - gst_data_queue_set_flushing (eglglessink->queue, FALSE); - -#if !GLIB_CHECK_VERSION (2, 31, 0) - eglglessink->thread = - g_thread_create ((GThreadFunc) render_thread_func, eglglessink, TRUE, - &error); -#else - eglglessink->thread = g_thread_try_new ("eglglessink-render", - (GThreadFunc) render_thread_func, eglglessink, &error); -#endif - - if (!eglglessink->thread || error != NULL) - goto HANDLE_ERROR; - - GST_DEBUG_OBJECT (eglglessink, "Started"); - - return TRUE; - -HANDLE_ERROR: - GST_ERROR_OBJECT (eglglessink, "Couldn't start"); - g_clear_error (&error); - return FALSE; -} - -static gboolean -gst_eglglessink_stop (GstEglGlesSink * eglglessink) -{ - GST_DEBUG_OBJECT (eglglessink, "Stopping"); - - gst_data_queue_set_flushing (eglglessink->queue, TRUE); - g_mutex_lock (&eglglessink->render_lock); - g_cond_broadcast (&eglglessink->render_cond); - g_mutex_unlock (&eglglessink->render_lock); - - if (eglglessink->thread) { - g_thread_join (eglglessink->thread); - eglglessink->thread = NULL; - } - eglglessink->last_flow = GST_FLOW_FLUSHING; - -#ifndef HAVE_IOS - if (eglglessink->pool) - gst_egl_image_buffer_pool_replace_last_buffer (GST_EGL_IMAGE_BUFFER_POOL - (eglglessink->pool), NULL); -#endif - - if (eglglessink->using_own_window) { - gst_egl_adaptation_destroy_native_window (eglglessink->egl_context, - &eglglessink->own_window_data); - eglglessink->have_window = FALSE; - } - eglglessink->egl_context->used_window = 0; - if (eglglessink->current_caps) { - gst_caps_unref (eglglessink->current_caps); - eglglessink->current_caps = NULL; - } - - GST_DEBUG_OBJECT (eglglessink, "Stopped"); - - return TRUE; -} - -static void -gst_eglglessink_videooverlay_init (GstVideoOverlayInterface * iface) -{ - iface->set_window_handle = gst_eglglessink_set_window_handle; - iface->expose = gst_eglglessink_expose; - iface->set_render_rectangle = gst_eglglessink_set_render_rectangle; -} - -static gboolean -gst_eglglessink_create_window (GstEglGlesSink * eglglessink, gint width, - gint height) -{ - gboolean window_created = FALSE; - - if (!eglglessink->create_window) { - GST_ERROR_OBJECT (eglglessink, "This sink can't create a window by itself"); - return FALSE; - } else - GST_INFO_OBJECT (eglglessink, "Attempting internal window creation"); - - window_created = - gst_egl_adaptation_create_native_window (eglglessink->egl_context, width, - height, &eglglessink->own_window_data); - if (!window_created) { - GST_ERROR_OBJECT (eglglessink, "Could not create window"); - } - return window_created; -} - -static void -gst_eglglessink_expose (GstVideoOverlay * overlay) -{ - GstEglGlesSink *eglglessink; - GstFlowReturn ret; - - eglglessink = GST_EGLGLESSINK (overlay); - GST_DEBUG_OBJECT (eglglessink, "Expose catched, redisplay"); - - /* Render from last seen buffer */ - ret = gst_eglglessink_queue_object (eglglessink, NULL); - if (ret == GST_FLOW_ERROR) - GST_ERROR_OBJECT (eglglessink, "Redisplay failed"); -} - -static gboolean -gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink) -{ - gdouble render_width, render_height; - gdouble texture_width, texture_height; - gdouble x1, x2, y1, y2; - gdouble tx1, tx2, ty1, ty2; - - GST_INFO_OBJECT (eglglessink, "VBO setup. have_vbo:%d", - eglglessink->egl_context->have_vbo); - - if (eglglessink->egl_context->have_vbo) { - glDeleteBuffers (1, &eglglessink->egl_context->position_buffer); - glDeleteBuffers (1, &eglglessink->egl_context->index_buffer); - eglglessink->egl_context->have_vbo = FALSE; - } - - render_width = eglglessink->render_region.w; - render_height = eglglessink->render_region.h; - - texture_width = eglglessink->configured_info.width; - texture_height = eglglessink->configured_info.height; - - GST_DEBUG_OBJECT (eglglessink, "Performing VBO setup"); - - x1 = (eglglessink->display_region.x / render_width) * 2.0 - 1; - y1 = (eglglessink->display_region.y / render_height) * 2.0 - 1; - x2 = ((eglglessink->display_region.x + - eglglessink->display_region.w) / render_width) * 2.0 - 1; - y2 = ((eglglessink->display_region.y + - eglglessink->display_region.h) / render_height) * 2.0 - 1; - - tx1 = (eglglessink->crop.x / texture_width); - tx2 = ((eglglessink->crop.x + eglglessink->crop.w) / texture_width); - ty1 = (eglglessink->crop.y / texture_height); - ty2 = ((eglglessink->crop.y + eglglessink->crop.h) / texture_height); - - /* X-normal, Y-normal orientation */ - eglglessink->egl_context->position_array[0].x = x2; - eglglessink->egl_context->position_array[0].y = y2; - eglglessink->egl_context->position_array[0].z = 0; - eglglessink->egl_context->position_array[0].a = tx2; - eglglessink->egl_context->position_array[0].b = ty1; - - eglglessink->egl_context->position_array[1].x = x2; - eglglessink->egl_context->position_array[1].y = y1; - eglglessink->egl_context->position_array[1].z = 0; - eglglessink->egl_context->position_array[1].a = tx2; - eglglessink->egl_context->position_array[1].b = ty2; - - eglglessink->egl_context->position_array[2].x = x1; - eglglessink->egl_context->position_array[2].y = y2; - eglglessink->egl_context->position_array[2].z = 0; - eglglessink->egl_context->position_array[2].a = tx1; - eglglessink->egl_context->position_array[2].b = ty1; - - eglglessink->egl_context->position_array[3].x = x1; - eglglessink->egl_context->position_array[3].y = y1; - eglglessink->egl_context->position_array[3].z = 0; - eglglessink->egl_context->position_array[3].a = tx1; - eglglessink->egl_context->position_array[3].b = ty2; - - /* X-normal, Y-flip orientation */ - eglglessink->egl_context->position_array[4 + 0].x = x2; - eglglessink->egl_context->position_array[4 + 0].y = y2; - eglglessink->egl_context->position_array[4 + 0].z = 0; - eglglessink->egl_context->position_array[4 + 0].a = tx2; - eglglessink->egl_context->position_array[4 + 0].b = ty2; - - eglglessink->egl_context->position_array[4 + 1].x = x2; - eglglessink->egl_context->position_array[4 + 1].y = y1; - eglglessink->egl_context->position_array[4 + 1].z = 0; - eglglessink->egl_context->position_array[4 + 1].a = tx2; - eglglessink->egl_context->position_array[4 + 1].b = ty1; - - eglglessink->egl_context->position_array[4 + 2].x = x1; - eglglessink->egl_context->position_array[4 + 2].y = y2; - eglglessink->egl_context->position_array[4 + 2].z = 0; - eglglessink->egl_context->position_array[4 + 2].a = tx1; - eglglessink->egl_context->position_array[4 + 2].b = ty2; - - eglglessink->egl_context->position_array[4 + 3].x = x1; - eglglessink->egl_context->position_array[4 + 3].y = y1; - eglglessink->egl_context->position_array[4 + 3].z = 0; - eglglessink->egl_context->position_array[4 + 3].a = tx1; - eglglessink->egl_context->position_array[4 + 3].b = ty1; - - - if (eglglessink->display_region.x == 0) { - /* Borders top/bottom */ - - eglglessink->egl_context->position_array[8 + 0].x = 1; - eglglessink->egl_context->position_array[8 + 0].y = 1; - eglglessink->egl_context->position_array[8 + 0].z = 0; - - eglglessink->egl_context->position_array[8 + 1].x = x2; - eglglessink->egl_context->position_array[8 + 1].y = y2; - eglglessink->egl_context->position_array[8 + 1].z = 0; - - eglglessink->egl_context->position_array[8 + 2].x = -1; - eglglessink->egl_context->position_array[8 + 2].y = 1; - eglglessink->egl_context->position_array[8 + 2].z = 0; - - eglglessink->egl_context->position_array[8 + 3].x = x1; - eglglessink->egl_context->position_array[8 + 3].y = y2; - eglglessink->egl_context->position_array[8 + 3].z = 0; - - eglglessink->egl_context->position_array[12 + 0].x = 1; - eglglessink->egl_context->position_array[12 + 0].y = y1; - eglglessink->egl_context->position_array[12 + 0].z = 0; - - eglglessink->egl_context->position_array[12 + 1].x = 1; - eglglessink->egl_context->position_array[12 + 1].y = -1; - eglglessink->egl_context->position_array[12 + 1].z = 0; - - eglglessink->egl_context->position_array[12 + 2].x = x1; - eglglessink->egl_context->position_array[12 + 2].y = y1; - eglglessink->egl_context->position_array[12 + 2].z = 0; - - eglglessink->egl_context->position_array[12 + 3].x = -1; - eglglessink->egl_context->position_array[12 + 3].y = -1; - eglglessink->egl_context->position_array[12 + 3].z = 0; - } else { - /* Borders left/right */ - - eglglessink->egl_context->position_array[8 + 0].x = x1; - eglglessink->egl_context->position_array[8 + 0].y = 1; - eglglessink->egl_context->position_array[8 + 0].z = 0; - - eglglessink->egl_context->position_array[8 + 1].x = x1; - eglglessink->egl_context->position_array[8 + 1].y = -1; - eglglessink->egl_context->position_array[8 + 1].z = 0; - - eglglessink->egl_context->position_array[8 + 2].x = -1; - eglglessink->egl_context->position_array[8 + 2].y = 1; - eglglessink->egl_context->position_array[8 + 2].z = 0; - - eglglessink->egl_context->position_array[8 + 3].x = -1; - eglglessink->egl_context->position_array[8 + 3].y = -1; - eglglessink->egl_context->position_array[8 + 3].z = 0; - - eglglessink->egl_context->position_array[12 + 0].x = 1; - eglglessink->egl_context->position_array[12 + 0].y = 1; - eglglessink->egl_context->position_array[12 + 0].z = 0; - - eglglessink->egl_context->position_array[12 + 1].x = 1; - eglglessink->egl_context->position_array[12 + 1].y = -1; - eglglessink->egl_context->position_array[12 + 1].z = 0; - - eglglessink->egl_context->position_array[12 + 2].x = x2; - eglglessink->egl_context->position_array[12 + 2].y = y2; - eglglessink->egl_context->position_array[12 + 2].z = 0; - - eglglessink->egl_context->position_array[12 + 3].x = x2; - eglglessink->egl_context->position_array[12 + 3].y = -1; - eglglessink->egl_context->position_array[12 + 3].z = 0; - } - - eglglessink->egl_context->index_array[0] = 0; - eglglessink->egl_context->index_array[1] = 1; - eglglessink->egl_context->index_array[2] = 2; - eglglessink->egl_context->index_array[3] = 3; - - glGenBuffers (1, &eglglessink->egl_context->position_buffer); - glGenBuffers (1, &eglglessink->egl_context->index_buffer); - if (got_gl_error ("glGenBuffers")) - goto HANDLE_ERROR_LOCKED; - - glBindBuffer (GL_ARRAY_BUFFER, eglglessink->egl_context->position_buffer); - if (got_gl_error ("glBindBuffer position_buffer")) - goto HANDLE_ERROR_LOCKED; - - glBufferData (GL_ARRAY_BUFFER, - sizeof (eglglessink->egl_context->position_array), - eglglessink->egl_context->position_array, GL_STATIC_DRAW); - if (got_gl_error ("glBufferData position_buffer")) - goto HANDLE_ERROR_LOCKED; - - glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, - eglglessink->egl_context->index_buffer); - if (got_gl_error ("glBindBuffer index_buffer")) - goto HANDLE_ERROR_LOCKED; - - glBufferData (GL_ELEMENT_ARRAY_BUFFER, - sizeof (eglglessink->egl_context->index_array), - eglglessink->egl_context->index_array, GL_STATIC_DRAW); - if (got_gl_error ("glBufferData index_buffer")) - goto HANDLE_ERROR_LOCKED; - - eglglessink->egl_context->have_vbo = TRUE; - - GST_DEBUG_OBJECT (eglglessink, "VBO setup done"); - - return TRUE; - -HANDLE_ERROR_LOCKED: - GST_ERROR_OBJECT (eglglessink, "Unable to perform VBO setup"); - return FALSE; -} - -static void -gst_eglglessink_set_window_handle (GstVideoOverlay * overlay, guintptr id) -{ - GstEglGlesSink *eglglessink = GST_EGLGLESSINK (overlay); - - g_return_if_fail (GST_IS_EGLGLESSINK (eglglessink)); - GST_DEBUG_OBJECT (eglglessink, "We got a window handle: %p", (gpointer) id); - - /* OK, we have a new window */ - GST_OBJECT_LOCK (eglglessink); - gst_egl_adaptation_set_window (eglglessink->egl_context, id); - eglglessink->have_window = ((gpointer) id != NULL); - GST_OBJECT_UNLOCK (eglglessink); - - return; -} - -static void -gst_eglglessink_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y, - gint width, gint height) -{ - GstEglGlesSink *eglglessink = GST_EGLGLESSINK (overlay); - - g_return_if_fail (GST_IS_EGLGLESSINK (eglglessink)); - - GST_OBJECT_LOCK (eglglessink); - eglglessink->render_region.x = x; - eglglessink->render_region.y = y; - eglglessink->render_region.w = width; - eglglessink->render_region.h = height; - eglglessink->render_region_changed = TRUE; - eglglessink->render_region_user = (width != -1 && height != -1); - GST_OBJECT_UNLOCK (eglglessink); - - return; -} - -static void -queue_item_destroy (GstDataQueueItem * item) -{ - if (item->object && !GST_IS_QUERY (item->object)) - gst_mini_object_unref (item->object); - g_slice_free (GstDataQueueItem, item); -} - -static GstFlowReturn -gst_eglglessink_queue_object (GstEglGlesSink * eglglessink, GstMiniObject * obj) -{ - GstDataQueueItem *item; - GstFlowReturn last_flow; - - g_mutex_lock (&eglglessink->render_lock); - last_flow = eglglessink->last_flow; - g_mutex_unlock (&eglglessink->render_lock); - - if (last_flow != GST_FLOW_OK) - return last_flow; - - item = g_slice_new0 (GstDataQueueItem); - - if (obj == NULL) - item->object = NULL; - else if (GST_IS_QUERY (obj)) - item->object = obj; - else - item->object = gst_mini_object_ref (obj); - item->size = 0; - item->duration = GST_CLOCK_TIME_NONE; - item->visible = TRUE; - item->destroy = (GDestroyNotify) queue_item_destroy; - - GST_DEBUG_OBJECT (eglglessink, "Queueing object %" GST_PTR_FORMAT, obj); - - g_mutex_lock (&eglglessink->render_lock); - if (!gst_data_queue_push (eglglessink->queue, item)) { - item->destroy (item); - g_mutex_unlock (&eglglessink->render_lock); - GST_DEBUG_OBJECT (eglglessink, "Flushing"); - return GST_FLOW_FLUSHING; - } - - GST_DEBUG_OBJECT (eglglessink, "Waiting for object to be handled"); - do { - g_cond_wait (&eglglessink->render_cond, &eglglessink->render_lock); - } while (eglglessink->dequeued_object != obj - && eglglessink->last_flow != GST_FLOW_FLUSHING); - GST_DEBUG_OBJECT (eglglessink, "Object handled: %s", - gst_flow_get_name (eglglessink->last_flow)); - last_flow = eglglessink->last_flow; - g_mutex_unlock (&eglglessink->render_lock); - - return (obj ? last_flow : GST_FLOW_OK); -} - -static gboolean -gst_eglglessink_crop_changed (GstEglGlesSink * eglglessink, - GstVideoCropMeta * crop) -{ - if (crop) { - return (crop->x != eglglessink->crop.x || - crop->y != eglglessink->crop.y || - crop->width != eglglessink->crop.w || - crop->height != eglglessink->crop.h); - } - - return (eglglessink->crop.x != 0 || eglglessink->crop.y != 0 || - eglglessink->crop.w != eglglessink->configured_info.width || - eglglessink->crop.h != eglglessink->configured_info.height); -} - -static gboolean -gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf) -{ - GstVideoFrame vframe; -#ifndef GST_DISABLE_GST_DEBUG - gint w; -#endif - gint h; - - memset (&vframe, 0, sizeof (vframe)); - - if (!gst_video_frame_map (&vframe, &eglglessink->configured_info, buf, - GST_MAP_READ)) { - GST_ERROR_OBJECT (eglglessink, "Couldn't map frame"); - goto HANDLE_ERROR; - } -#ifndef GST_DISABLE_GST_DEBUG - w = GST_VIDEO_FRAME_WIDTH (&vframe); -#endif - h = GST_VIDEO_FRAME_HEIGHT (&vframe); - - GST_DEBUG_OBJECT (eglglessink, - "Got buffer %p: %dx%d size %" G_GSIZE_FORMAT, buf, w, h, - gst_buffer_get_size (buf)); - - switch (eglglessink->configured_info.finfo->format) { - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGB:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (c_w * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (c_w * 3 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (stride_width * 3) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (stride_width * 3 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB, - GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - break; - } - case GST_VIDEO_FORMAT_RGB16:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (c_w * 2 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width * 4) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (stride_width * 2 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - break; - } - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w * 4) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (c_w * 4 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width * 4) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (stride_width * 4 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - break; - } - case GST_VIDEO_FORMAT_AYUV:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w * 4) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (c_w * 4 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width * 4) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (stride_width * 4 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - break; - } - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y41B:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (c_w == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (stride_width == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - stride_width, - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0), - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_COMP_DATA (&vframe, 0)); - - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1); - stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1); - - glActiveTexture (GL_TEXTURE1); - - if (GST_ROUND_UP_8 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (c_w == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (stride_width == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[1]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - stride_width, - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1), - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_COMP_DATA (&vframe, 1)); - - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 2); - stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 2); - - glActiveTexture (GL_TEXTURE2); - - if (GST_ROUND_UP_8 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (c_w == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (stride_width == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[2] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[2]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - stride_width, - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 2), - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_COMP_DATA (&vframe, 2)); - break; - } - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21:{ - gint stride; - gint stride_width; - gint c_w; - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0); - stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0); - - glActiveTexture (GL_TEXTURE0); - - if (GST_ROUND_UP_8 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (c_w) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (c_w == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - stride_width = stride; - - if (GST_ROUND_UP_8 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (GST_ROUND_UP_2 (stride_width) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else if (stride_width == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, - stride_width, - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0), - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0)); - - - stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1); - stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1); - - glActiveTexture (GL_TEXTURE1); - - if (GST_ROUND_UP_8 (c_w * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (c_w * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (c_w * 2 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else { - stride_width = stride / 2; - - if (GST_ROUND_UP_8 (stride_width * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 8); - } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - } else if (stride_width * 2 == stride) { - glPixelStorei (GL_UNPACK_ALIGNMENT, 2); - } else { - GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride); - goto HANDLE_ERROR; - } - } - if (got_gl_error ("glPixelStorei")) - goto HANDLE_ERROR; - - eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[1]); - glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, - stride_width, - GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1), - 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1)); - break; - } - default: - g_assert_not_reached (); - break; - } - - if (got_gl_error ("glTexImage2D")) - goto HANDLE_ERROR; - - gst_video_frame_unmap (&vframe); - - return TRUE; - -HANDLE_ERROR: - { - if (vframe.buffer) - gst_video_frame_unmap (&vframe); - return FALSE; - } -} - -/* Rendering and display */ -static GstFlowReturn -gst_eglglessink_upload (GstEglGlesSink * eglglessink, GstBuffer * buf) -{ - GstVideoCropMeta *crop = NULL; - - if (!buf) { - GST_DEBUG_OBJECT (eglglessink, "Rendering previous buffer again"); - } else if (buf) { -#ifndef HAVE_IOS - GstMemory *mem; -#endif - GstVideoGLTextureUploadMeta *upload_meta; - - crop = gst_buffer_get_video_crop_meta (buf); - - upload_meta = gst_buffer_get_video_gl_texture_upload_meta (buf); - - if (gst_eglglessink_crop_changed (eglglessink, crop)) { - if (crop) { - eglglessink->crop.x = crop->x; - eglglessink->crop.y = crop->y; - eglglessink->crop.w = crop->width; - eglglessink->crop.h = crop->height; - } else { - eglglessink->crop.x = 0; - eglglessink->crop.y = 0; - eglglessink->crop.w = eglglessink->configured_info.width; - eglglessink->crop.h = eglglessink->configured_info.height; - } - eglglessink->crop_changed = TRUE; - } - - if (upload_meta) { - gint i; - - if (upload_meta->n_textures != eglglessink->egl_context->n_textures) - goto HANDLE_ERROR; - - for (i = 0; i < eglglessink->egl_context->n_textures; i++) { - if (i == 0) - glActiveTexture (GL_TEXTURE0); - else if (i == 1) - glActiveTexture (GL_TEXTURE1); - else if (i == 2) - glActiveTexture (GL_TEXTURE2); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[i]); - } - - if (!gst_video_gl_texture_upload_meta_upload (upload_meta, - eglglessink->egl_context->texture)) - goto HANDLE_ERROR; - - eglglessink->orientation = upload_meta->texture_orientation; - eglglessink->stride[0] = 1; - eglglessink->stride[1] = 1; - eglglessink->stride[2] = 1; -#ifndef HAVE_IOS - } else if (gst_buffer_n_memory (buf) >= 1 && - (mem = gst_buffer_peek_memory (buf, 0)) - && gst_is_egl_image_memory (mem)) { - guint n, i; - - n = gst_buffer_n_memory (buf); - - for (i = 0; i < n; i++) { - mem = gst_buffer_peek_memory (buf, i); - - g_assert (gst_is_egl_image_memory (mem)); - - if (i == 0) - glActiveTexture (GL_TEXTURE0); - else if (i == 1) - glActiveTexture (GL_TEXTURE1); - else if (i == 2) - glActiveTexture (GL_TEXTURE2); - - glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[i]); - glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, - gst_egl_image_memory_get_image (mem)); - if (got_gl_error ("glEGLImageTargetTexture2DOES")) - goto HANDLE_ERROR; - eglglessink->orientation = gst_egl_image_memory_get_orientation (mem); - if (eglglessink->orientation != - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL - && eglglessink->orientation != - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP) { - GST_ERROR_OBJECT (eglglessink, "Unsupported EGLImage orientation"); - return GST_FLOW_ERROR; - } - } - if (eglglessink->pool) - gst_egl_image_buffer_pool_replace_last_buffer (GST_EGL_IMAGE_BUFFER_POOL - (eglglessink->pool), buf); - eglglessink->stride[0] = 1; - eglglessink->stride[1] = 1; - eglglessink->stride[2] = 1; -#endif - } else { - eglglessink->orientation = - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL; - if (!gst_eglglessink_fill_texture (eglglessink, buf)) - goto HANDLE_ERROR; - } - } - - return GST_FLOW_OK; - -HANDLE_ERROR: - { - GST_ERROR_OBJECT (eglglessink, "Failed to upload texture"); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_eglglessink_render (GstEglGlesSink * eglglessink) -{ - guint dar_n, dar_d; - gint i; - - /* If no one has set a display rectangle on us initialize - * a sane default. According to the docs on the xOverlay - * interface we are supposed to fill the overlay 100%. We - * do this trying to take PAR/DAR into account unless the - * calling party explicitly ask us not to by setting - * force_aspect_ratio to FALSE. - */ - if (gst_egl_adaptation_update_surface_dimensions (eglglessink->egl_context) || - eglglessink->render_region_changed || - !eglglessink->display_region.w || !eglglessink->display_region.h || - eglglessink->crop_changed) { - GST_OBJECT_LOCK (eglglessink); - - if (!eglglessink->render_region_user) { - eglglessink->render_region.x = 0; - eglglessink->render_region.y = 0; - eglglessink->render_region.w = eglglessink->egl_context->surface_width; - eglglessink->render_region.h = eglglessink->egl_context->surface_height; - } - eglglessink->render_region_changed = FALSE; - eglglessink->crop_changed = FALSE; - - if (!eglglessink->force_aspect_ratio) { - eglglessink->display_region.x = 0; - eglglessink->display_region.y = 0; - eglglessink->display_region.w = eglglessink->render_region.w; - eglglessink->display_region.h = eglglessink->render_region.h; - } else { - GstVideoRectangle frame; - - frame.x = 0; - frame.y = 0; - - if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, - eglglessink->crop.w, eglglessink->crop.h, - eglglessink->configured_info.par_n, - eglglessink->configured_info.par_d, - eglglessink->egl_context->pixel_aspect_ratio_n, - eglglessink->egl_context->pixel_aspect_ratio_d)) { - GST_WARNING_OBJECT (eglglessink, "Could not compute resulting DAR"); - frame.w = eglglessink->crop.w; - frame.h = eglglessink->crop.h; - } else { - /* Find suitable matching new size acording to dar & par - * rationale for prefering leaving the height untouched - * comes from interlacing considerations. - * XXX: Move this to gstutils? - */ - if (eglglessink->crop.h % dar_d == 0) { - frame.w = - gst_util_uint64_scale_int (eglglessink->crop.h, dar_n, dar_d); - frame.h = eglglessink->crop.h; - } else if (eglglessink->crop.w % dar_n == 0) { - frame.h = - gst_util_uint64_scale_int (eglglessink->crop.w, dar_d, dar_n); - frame.w = eglglessink->crop.w; - } else { - /* Neither width nor height can be precisely scaled. - * Prefer to leave height untouched. See comment above. - */ - frame.w = - gst_util_uint64_scale_int (eglglessink->crop.h, dar_n, dar_d); - frame.h = eglglessink->crop.h; - } - } - - gst_video_sink_center_rect (frame, eglglessink->render_region, - &eglglessink->display_region, TRUE); - } - - glViewport (eglglessink->render_region.x, - eglglessink->egl_context->surface_height - - eglglessink->render_region.y - - eglglessink->render_region.h, - eglglessink->render_region.w, eglglessink->render_region.h); - - /* Clear the surface once if its content is preserved */ - if (eglglessink->egl_context->buffer_preserved) { - glClearColor (0.0, 0.0, 0.0, 1.0); - glClear (GL_COLOR_BUFFER_BIT); - } - - if (!gst_eglglessink_setup_vbo (eglglessink)) { - GST_OBJECT_UNLOCK (eglglessink); - GST_ERROR_OBJECT (eglglessink, "VBO setup failed"); - goto HANDLE_ERROR; - } - GST_OBJECT_UNLOCK (eglglessink); - } - - if (!eglglessink->egl_context->buffer_preserved) { - /* Draw black borders */ - GST_DEBUG_OBJECT (eglglessink, "Drawing black border 1"); - glUseProgram (eglglessink->egl_context->glslprogram[1]); - - glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3, - GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (8 * sizeof (coord5))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - - glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); - if (got_gl_error ("glDrawElements")) - goto HANDLE_ERROR; - - GST_DEBUG_OBJECT (eglglessink, "Drawing black border 2"); - - glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3, - GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (12 * sizeof (coord5))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - - glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); - if (got_gl_error ("glDrawElements")) - goto HANDLE_ERROR; - } - - /* Draw video frame */ - GST_DEBUG_OBJECT (eglglessink, "Drawing video frame"); - - glUseProgram (eglglessink->egl_context->glslprogram[0]); - - glUniform2f (eglglessink->egl_context->tex_scale_loc[0][0], - eglglessink->stride[0], 1); - glUniform2f (eglglessink->egl_context->tex_scale_loc[0][1], - eglglessink->stride[1], 1); - glUniform2f (eglglessink->egl_context->tex_scale_loc[0][2], - eglglessink->stride[2], 1); - - for (i = 0; i < eglglessink->egl_context->n_textures; i++) { - glUniform1i (eglglessink->egl_context->tex_loc[0][i], i); - if (got_gl_error ("glUniform1i")) - goto HANDLE_ERROR; - } - - if (eglglessink->orientation == - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL) { - glVertexAttribPointer (eglglessink->egl_context->position_loc[0], 3, - GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (0 * sizeof (coord5))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - - glVertexAttribPointer (eglglessink->egl_context->texpos_loc[0], 2, - GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (3 * sizeof (gfloat))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - } else if (eglglessink->orientation == - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_FLIP) { - glVertexAttribPointer (eglglessink->egl_context->position_loc[0], 3, - GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (4 * sizeof (coord5))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - - glVertexAttribPointer (eglglessink->egl_context->texpos_loc[0], 2, - GL_FLOAT, GL_FALSE, sizeof (coord5), - (gpointer) (4 * sizeof (coord5) + 3 * sizeof (gfloat))); - if (got_gl_error ("glVertexAttribPointer")) - goto HANDLE_ERROR; - } else { - g_assert_not_reached (); - } - - glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); - if (got_gl_error ("glDrawElements")) - goto HANDLE_ERROR; - - if (!gst_egl_adaptation_context_swap_buffers (eglglessink->egl_context)) { - goto HANDLE_ERROR; - } - - - GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame"); - return GST_FLOW_OK; - -HANDLE_ERROR: - GST_ERROR_OBJECT (eglglessink, "Rendering disabled for this frame"); - - return GST_FLOW_ERROR; -} - -static GstFlowReturn -gst_eglglessink_prepare (GstBaseSink * bsink, GstBuffer * buf) -{ - GstEglGlesSink *eglglessink; - - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - - eglglessink = GST_EGLGLESSINK (bsink); - GST_DEBUG_OBJECT (eglglessink, "Got buffer: %p", buf); - - return gst_eglglessink_queue_object (eglglessink, GST_MINI_OBJECT_CAST (buf)); -} - -static GstFlowReturn -gst_eglglessink_show_frame (GstVideoSink * vsink, GstBuffer * buf) -{ - GstEglGlesSink *eglglessink; - - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - - eglglessink = GST_EGLGLESSINK (vsink); - GST_DEBUG_OBJECT (eglglessink, "Got buffer: %p", buf); - - return gst_eglglessink_queue_object (eglglessink, NULL); -} - -static GstCaps * -gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter) -{ - GstEglGlesSink *eglglessink; - GstCaps *ret = NULL; - - eglglessink = GST_EGLGLESSINK (bsink); - - GST_OBJECT_LOCK (eglglessink); - if (eglglessink->sinkcaps) { - ret = gst_caps_ref (eglglessink->sinkcaps); - } else { - ret = - gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD - (bsink))); - } - GST_OBJECT_UNLOCK (eglglessink); - - if (filter) { - GstCaps *tmp = - gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST); - - gst_caps_unref (ret); - ret = tmp; - } - - return ret; -} - -static gboolean -gst_eglglessink_query (GstBaseSink * bsink, GstQuery * query) -{ - GstEglGlesSink *eglglessink; - - eglglessink = GST_EGLGLESSINK (bsink); - - switch (GST_QUERY_TYPE (query)) { -#ifndef HAVE_IOS - case GST_QUERY_CONTEXT:{ - const gchar *context_type; - - if (gst_query_parse_context_type (query, &context_type) && - strcmp (context_type, GST_EGL_DISPLAY_CONTEXT_TYPE) == 0 && - eglglessink->egl_context->display) { - GstContext *context; - - context = - gst_context_new_egl_display (eglglessink->egl_context->display, - FALSE); - gst_query_set_context (query, context); - gst_context_unref (context); - - return TRUE; - } else { - return GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->query (bsink, - query); - } - break; - } - case GST_QUERY_DRAIN: - { - GST_OBJECT_LOCK (eglglessink); - /* no need to do a copy here as the textures which are being rendered are - * in eglglessink->egl_context->texture[i] and they are not part of a pool. - * See comment in gst_egl_image_buffer_pool_acquire_buffer to know what is - * this last_buffer ref is about */ - if (eglglessink->pool) - gst_egl_image_buffer_pool_replace_last_buffer (GST_EGL_IMAGE_BUFFER_POOL - (eglglessink->pool), NULL); - GST_OBJECT_UNLOCK (eglglessink); - - return TRUE; - } -#endif - default: - return GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->query (bsink, - query); - break; - } -} - -static void -gst_eglglessink_set_context (GstElement * element, GstContext * context) -{ -#ifndef HAVE_IOS - GstEglGlesSink *eglglessink; - GstEGLDisplay *display = NULL; - - eglglessink = GST_EGLGLESSINK (element); - - if (gst_context_get_egl_display (context, &display)) { - GST_OBJECT_LOCK (eglglessink); - if (eglglessink->egl_context->set_display) - gst_egl_display_unref (eglglessink->egl_context->set_display); - eglglessink->egl_context->set_display = display; - GST_OBJECT_UNLOCK (eglglessink); - } -#endif -} - -static gboolean -gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ -#ifndef HAVE_IOS - GstEglGlesSink *eglglessink; - GstBufferPool *pool; - GstStructure *config; - GstCaps *caps; - GstVideoInfo info; - gboolean need_pool; - guint size; - GstAllocator *allocator; - GstAllocationParams params; - - eglglessink = GST_EGLGLESSINK (bsink); - - gst_allocation_params_init (¶ms); - - gst_query_parse_allocation (query, &caps, &need_pool); - if (!caps) { - GST_ERROR_OBJECT (eglglessink, "allocation query without caps"); - return FALSE; - } - - if (!gst_video_info_from_caps (&info, caps)) { - GST_ERROR_OBJECT (eglglessink, "allocation query with invalid caps"); - return FALSE; - } - - GST_OBJECT_LOCK (eglglessink); - pool = eglglessink->pool ? gst_object_ref (eglglessink->pool) : NULL; - GST_OBJECT_UNLOCK (eglglessink); - - if (pool) { - GstCaps *pcaps; - - /* we had a pool, check caps */ - GST_DEBUG_OBJECT (eglglessink, "check existing pool caps"); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL); - - if (!gst_caps_is_equal (caps, pcaps)) { - GST_DEBUG_OBJECT (eglglessink, "pool has different caps"); - /* different caps, we can't use this pool */ - gst_object_unref (pool); - pool = NULL; - } - gst_structure_free (config); - } - - if (pool == NULL && need_pool) { - GstVideoInfo info; - - if (!gst_video_info_from_caps (&info, caps)) { - GST_ERROR_OBJECT (eglglessink, "allocation query has invalid caps %" - GST_PTR_FORMAT, caps); - return FALSE; - } - - GST_DEBUG_OBJECT (eglglessink, "create new pool"); - pool = - gst_egl_image_buffer_pool_new - (gst_eglglessink_egl_image_buffer_pool_send_blocking, - gst_object_ref (eglglessink), - gst_eglglessink_egl_image_buffer_pool_on_destroy); - - /* the normal size of a frame */ - size = info.size; - - config = gst_buffer_pool_get_config (pool); - /* we need at least 2 buffer because we hold on to the last one */ - gst_buffer_pool_config_set_params (config, caps, size, 2, 0); - gst_buffer_pool_config_set_allocator (config, NULL, ¶ms); - if (!gst_buffer_pool_set_config (pool, config)) { - gst_object_unref (pool); - GST_ERROR_OBJECT (eglglessink, "failed to set pool configuration"); - return FALSE; - } - } - - if (pool) { - /* we need at least 2 buffer because we hold on to the last one */ - gst_query_add_allocation_pool (query, pool, size, 2, 0); - gst_object_unref (pool); - } - - /* First the default allocator */ - if (!gst_egl_image_memory_is_mappable ()) { - allocator = gst_allocator_find (NULL); - gst_query_add_allocation_param (query, allocator, ¶ms); - gst_object_unref (allocator); - } - - allocator = gst_egl_image_allocator_obtain (); - if (!gst_egl_image_memory_is_mappable ()) - params.flags |= GST_MEMORY_FLAG_NOT_MAPPABLE; - gst_query_add_allocation_param (query, allocator, ¶ms); - gst_object_unref (allocator); - - gst_query_add_allocation_meta (query, - GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL); -#endif - - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); - gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); - - return TRUE; -} - -static gboolean -gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps) -{ - gboolean ret = TRUE; - GstVideoInfo info; - - gst_video_info_init (&info); - if (!(ret = gst_video_info_from_caps (&info, caps))) { - GST_ERROR_OBJECT (eglglessink, "Couldn't parse caps"); - goto HANDLE_ERROR; - } - - eglglessink->configured_info = info; - GST_VIDEO_SINK_WIDTH (eglglessink) = info.width; - GST_VIDEO_SINK_HEIGHT (eglglessink) = info.height; - - if (eglglessink->configured_caps) { - GST_DEBUG_OBJECT (eglglessink, "Caps were already set"); - if (gst_caps_can_intersect (caps, eglglessink->configured_caps)) { - GST_DEBUG_OBJECT (eglglessink, "Caps are compatible anyway"); - goto SUCCEED; - } - - GST_DEBUG_OBJECT (eglglessink, "Caps are not compatible, reconfiguring"); - - /* EGL/GLES cleanup */ - gst_egl_adaptation_cleanup (eglglessink->egl_context); - - gst_caps_unref (eglglessink->configured_caps); - eglglessink->configured_caps = NULL; - } - - if (!gst_egl_adaptation_choose_config (eglglessink->egl_context)) { - GST_ERROR_OBJECT (eglglessink, "Couldn't choose EGL config"); - goto HANDLE_ERROR; - } - - gst_caps_replace (&eglglessink->configured_caps, caps); - - /* By now the application should have set a window - * if it meant to do so - */ - GST_OBJECT_LOCK (eglglessink); - if (!eglglessink->have_window) { - - GST_INFO_OBJECT (eglglessink, - "No window. Will attempt internal window creation"); - if (!gst_eglglessink_create_window (eglglessink, info.width, info.height)) { - GST_ERROR_OBJECT (eglglessink, "Internal window creation failed!"); - GST_OBJECT_UNLOCK (eglglessink); - goto HANDLE_ERROR; - } - eglglessink->using_own_window = TRUE; - eglglessink->have_window = TRUE; - } - GST_DEBUG_OBJECT (eglglessink, "Using window handle %p", - (gpointer) eglglessink->egl_context->window); - eglglessink->egl_context->used_window = eglglessink->egl_context->window; - GST_OBJECT_UNLOCK (eglglessink); - gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (eglglessink), - (guintptr) eglglessink->egl_context->used_window); - - if (!eglglessink->egl_context->have_surface) { - if (!gst_egl_adaptation_init_surface (eglglessink->egl_context, - eglglessink->configured_info.finfo->format)) { - GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL surface from window"); - goto HANDLE_ERROR; - } - } - - gst_egl_adaptation_init_exts (eglglessink->egl_context); - -SUCCEED: - GST_INFO_OBJECT (eglglessink, "Configured caps successfully"); - return TRUE; - -HANDLE_ERROR: - GST_ERROR_OBJECT (eglglessink, "Configuring caps failed"); - return FALSE; -} - -static gboolean -gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps) -{ - GstEglGlesSink *eglglessink; - GstVideoInfo info; -#ifndef HAVE_IOS - GstBufferPool *newpool, *oldpool; - GstStructure *config; - GstAllocationParams params = { 0, }; -#endif - - eglglessink = GST_EGLGLESSINK (bsink); - - GST_DEBUG_OBJECT (eglglessink, - "Current caps %" GST_PTR_FORMAT ", setting caps %" - GST_PTR_FORMAT, eglglessink->current_caps, caps); - - if (gst_eglglessink_queue_object (eglglessink, - GST_MINI_OBJECT_CAST (caps)) != GST_FLOW_OK) { - GST_ERROR_OBJECT (eglglessink, "Failed to configure caps"); - return FALSE; - } - - if (!gst_video_info_from_caps (&info, caps)) { - GST_ERROR_OBJECT (eglglessink, "Invalid caps %" GST_PTR_FORMAT, caps); - return FALSE; - } -#ifndef HAVE_IOS - newpool = - gst_egl_image_buffer_pool_new - (gst_eglglessink_egl_image_buffer_pool_send_blocking, - gst_object_ref (eglglessink), - gst_eglglessink_egl_image_buffer_pool_on_destroy); - config = gst_buffer_pool_get_config (newpool); - /* we need at least 2 buffer because we hold on to the last one */ - gst_buffer_pool_config_set_params (config, caps, info.size, 2, 0); - gst_buffer_pool_config_set_allocator (config, NULL, ¶ms); - if (!gst_buffer_pool_set_config (newpool, config)) { - gst_object_unref (newpool); - GST_ERROR_OBJECT (eglglessink, "Failed to set buffer pool configuration"); - return FALSE; - } - - GST_OBJECT_LOCK (eglglessink); - oldpool = eglglessink->pool; - eglglessink->pool = newpool; - GST_OBJECT_UNLOCK (eglglessink); - - if (oldpool) - gst_object_unref (oldpool); -#endif - - gst_caps_replace (&eglglessink->current_caps, caps); - - return TRUE; -} - -static gboolean -gst_eglglessink_open (GstEglGlesSink * eglglessink) -{ - if (!egl_init (eglglessink)) { - return FALSE; - } - - return TRUE; -} - -static gboolean -gst_eglglessink_close (GstEglGlesSink * eglglessink) -{ -#ifndef HAVE_IOS - if (eglglessink->egl_context->display) { - gst_egl_display_unref (eglglessink->egl_context->display); - eglglessink->egl_context->display = NULL; - } - - GST_OBJECT_LOCK (eglglessink); - if (eglglessink->pool) - gst_object_unref (eglglessink->pool); - eglglessink->pool = NULL; - GST_OBJECT_UNLOCK (eglglessink); -#endif - - gst_caps_unref (eglglessink->sinkcaps); - eglglessink->sinkcaps = NULL; - eglglessink->egl_started = FALSE; - - return TRUE; -} - -static GstStateChangeReturn -gst_eglglessink_change_state (GstElement * element, GstStateChange transition) -{ - GstEglGlesSink *eglglessink; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - eglglessink = GST_EGLGLESSINK (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_eglglessink_open (eglglessink)) { - ret = GST_STATE_CHANGE_FAILURE; - goto done; - } - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - if (!gst_eglglessink_start (eglglessink)) { - ret = GST_STATE_CHANGE_FAILURE; - goto done; - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - if (!gst_eglglessink_close (eglglessink)) { - ret = GST_STATE_CHANGE_FAILURE; - goto done; - } - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (!gst_eglglessink_stop (eglglessink)) { - ret = GST_STATE_CHANGE_FAILURE; - goto done; - } - break; - default: - break; - } - -done: - return ret; -} - -static void -gst_eglglessink_finalize (GObject * object) -{ - GstEglGlesSink *eglglessink; - - g_return_if_fail (GST_IS_EGLGLESSINK (object)); - - eglglessink = GST_EGLGLESSINK (object); - - gst_egl_adaptation_context_free (eglglessink->egl_context); - - if (eglglessink->queue) - g_object_unref (eglglessink->queue); - eglglessink->queue = NULL; - - g_cond_clear (&eglglessink->render_cond); - g_mutex_clear (&eglglessink->render_lock); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_eglglessink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstEglGlesSink *eglglessink; - - g_return_if_fail (GST_IS_EGLGLESSINK (object)); - - eglglessink = GST_EGLGLESSINK (object); - - switch (prop_id) { - case PROP_CREATE_WINDOW: - eglglessink->create_window = g_value_get_boolean (value); - break; - case PROP_FORCE_ASPECT_RATIO: - eglglessink->force_aspect_ratio = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_eglglessink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstEglGlesSink *eglglessink; - - g_return_if_fail (GST_IS_EGLGLESSINK (object)); - - eglglessink = GST_EGLGLESSINK (object); - - switch (prop_id) { - case PROP_CREATE_WINDOW: - g_value_set_boolean (value, eglglessink->create_window); - break; - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, eglglessink->force_aspect_ratio); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* initialize the eglglessink's class */ -static void -gst_eglglessink_class_init (GstEglGlesSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstVideoSinkClass *gstvideosink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstvideosink_class = (GstVideoSinkClass *) klass; - - gobject_class->set_property = gst_eglglessink_set_property; - gobject_class->get_property = gst_eglglessink_get_property; - gobject_class->finalize = gst_eglglessink_finalize; - - gstelement_class->change_state = gst_eglglessink_change_state; - gstelement_class->set_context = gst_eglglessink_set_context; - - gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps); - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps); - gstbasesink_class->propose_allocation = - GST_DEBUG_FUNCPTR (gst_eglglessink_propose_allocation); - gstbasesink_class->prepare = GST_DEBUG_FUNCPTR (gst_eglglessink_prepare); - gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_eglglessink_query); - - gstvideosink_class->show_frame = - GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame); - - g_object_class_install_property (gobject_class, PROP_CREATE_WINDOW, - g_param_spec_boolean ("create-window", "Create Window", - "If set to true, the sink will attempt to create it's own window to " - "render to if none is provided. This is currently only supported " - "when the sink is used under X11", - TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Respect aspect ratio when scaling", - "If set to true, the sink will attempt to preserve the incoming " - "frame's geometry while scaling, taking both the storage's and " - "display's pixel aspect ratio into account", - TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_static_metadata (gstelement_class, - "EGL/GLES vout Sink", - "Sink/Video", - "An EGL/GLES Video Output Sink Implementing the VideoOverlay interface", - "Reynaldo H. Verdejo Pinochet , " - "Sebastian Dröge "); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_eglglessink_sink_template_factory)); -} - -static gboolean -queue_check_full_func (GstDataQueue * queue, guint visible, guint bytes, - guint64 time, gpointer checkdata) -{ - return visible != 0; -} - -static void -gst_eglglessink_init (GstEglGlesSink * eglglessink) -{ - eglglessink->egl_context = - gst_egl_adaptation_context_new (GST_ELEMENT_CAST (eglglessink)); - - /* Init defaults */ - - /** Flags */ - eglglessink->have_window = FALSE; - eglglessink->egl_context->have_surface = FALSE; - eglglessink->egl_context->have_vbo = FALSE; - eglglessink->egl_context->have_texture = FALSE; - eglglessink->egl_started = FALSE; - eglglessink->using_own_window = FALSE; - - /** Props */ - eglglessink->create_window = TRUE; - eglglessink->force_aspect_ratio = TRUE; - - g_mutex_init (&eglglessink->render_lock); - g_cond_init (&eglglessink->render_cond); - eglglessink->queue = - gst_data_queue_new (queue_check_full_func, NULL, NULL, NULL); - eglglessink->last_flow = GST_FLOW_FLUSHING; - - eglglessink->render_region.x = 0; - eglglessink->render_region.y = 0; - eglglessink->render_region.w = -1; - eglglessink->render_region.h = -1; - eglglessink->render_region_changed = TRUE; - eglglessink->render_region_user = FALSE; -} - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and other features - */ -static gboolean -eglglessink_plugin_init (GstPlugin * plugin) -{ - /* debug category for fltering log messages */ - GST_DEBUG_CATEGORY_INIT (gst_eglglessink_debug, "eglglessink", - 0, "Simple EGL/GLES Sink"); - - gst_egl_adaption_init (); - -#ifdef USE_EGL_RPI - GST_DEBUG ("Initialize BCM host"); - bcm_host_init (); -#endif - - return gst_element_register (plugin, "eglglessink", GST_RANK_SECONDARY, - GST_TYPE_EGLGLESSINK); -} - -/* gstreamer looks for this structure to register eglglessinks */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - eglglessink, - "EGL/GLES sink", - eglglessink_plugin_init, - VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/eglgles/gsteglglessink.h b/ext/eglgles/gsteglglessink.h deleted file mode 100644 index d3f6bd7e97..0000000000 --- a/ext/eglgles/gsteglglessink.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * GStreamer EGL/GLES Sink - * Copyright (C) 2012 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * @author: Sebastian Dröge - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_EGLGLESSINK_H__ -#define __GST_EGLGLESSINK_H__ - -#include -#include -#include -#include - -#include "gstegladaptation.h" - -G_BEGIN_DECLS -#define GST_TYPE_EGLGLESSINK \ - (gst_eglglessink_get_type()) -#define GST_EGLGLESSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EGLGLESSINK,GstEglGlesSink)) -#define GST_EGLGLESSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EGLGLESSINK,GstEglGlesSinkClass)) -#define GST_IS_EGLGLESSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EGLGLESSINK)) -#define GST_IS_EGLGLESSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EGLGLESSINK)) - -typedef struct _GstEglGlesSink GstEglGlesSink; -typedef struct _GstEglGlesSinkClass GstEglGlesSinkClass; - -/* - * GstEglGlesSink: - * @format: Caps' video format field - * @display_region: Surface region to use as rendering canvas - * @sinkcaps: Full set of suported caps - * @current_caps: Current caps - * @rendering_path: Rendering path (Slow/Fast) - * @eglglesctx: Pointer to the associated EGL/GLESv2 rendering context - * @flow_lock: Simple concurrent access ward to the sink's runtime state - * @have_window: Set if the sink has access to a window to hold it's canvas - * @using_own_window: Set if the sink created its own window - * @egl_started: Set if the whole EGL setup has been performed - * @create_window: Property value holder to allow/forbid internal window creation - * @force_rendering_slow: Property value holder to force slow rendering path - * @force_aspect_ratio: Property value holder to consider PAR/DAR when scaling - * - * The #GstEglGlesSink data structure. - */ -struct _GstEglGlesSink -{ - GstVideoSink videosink; /* Element hook */ - - /* Region of the surface that should be rendered */ - GstVideoRectangle render_region; - gboolean render_region_changed; - gboolean render_region_user; - - /* Region of render_region that should be filled - * with the video frames */ - GstVideoRectangle display_region; - - GstVideoRectangle crop; - gboolean crop_changed; - GstCaps *sinkcaps; - GstCaps *current_caps, *configured_caps; - GstVideoInfo configured_info; - gfloat stride[3]; - GstVideoGLTextureOrientation orientation; -#ifndef HAVE_IOS - GstBufferPool *pool; -#endif - - GstEglAdaptationContext *egl_context; - - /* Runtime flags */ - gboolean have_window; - gboolean using_own_window; - gboolean egl_started; - - gpointer own_window_data; - - GThread *thread; - gboolean thread_running; - GstDataQueue *queue; - GCond render_cond; - GMutex render_lock; - GstFlowReturn last_flow; - GstMiniObject *dequeued_object; - - GstBuffer *last_buffer; - - /* Properties */ - gboolean create_window; - gboolean force_aspect_ratio; -}; - -struct _GstEglGlesSinkClass -{ - GstVideoSinkClass parent_class; -}; - -GType gst_eglglessink_get_type (void); - -G_END_DECLS -#endif /* __GST_EGLGLESSINK_H__ */ diff --git a/ext/eglgles/video_platform_wrapper.c b/ext/eglgles/video_platform_wrapper.c deleted file mode 100644 index 0482a8fd7e..0000000000 --- a/ext/eglgles/video_platform_wrapper.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * GStreamer Android Video Platform Wrapper - * Copyright (C) 2012 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#ifndef __VCCOREVER__ -#define __VCCOREVER__ 0x04000000 -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC optimize ("gnu89-inline") -#endif - -#define EGL_EGLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES -#include -#include -#include -#include - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#pragma GCC reset_options -#pragma GCC diagnostic pop -#endif - -#include - -#include -#include "video_platform_wrapper.h" - -GST_DEBUG_CATEGORY_STATIC (eglgles_platform_wrapper); -#define GST_CAT_DEFAULT eglgles_platform_wrapper - -/* XXX: Likely to be removed */ -gboolean -platform_wrapper_init (void) -{ - GST_DEBUG_CATEGORY_INIT (eglgles_platform_wrapper, - "eglglessink-platform", 0, - "Platform dependent native-window utility routines for EglGles"); - return TRUE; -} - -#ifdef USE_EGL_X11 -#include - -typedef struct -{ - Display *display; -} X11WindowData; - -EGLNativeWindowType -platform_create_native_window (gint width, gint height, gpointer * window_data) -{ - Display *d; - Window w; - int s; - X11WindowData *data; - - d = XOpenDisplay (NULL); - if (d == NULL) { - GST_ERROR ("Can't open X11 display"); - return (EGLNativeWindowType) 0; - } - - s = DefaultScreen (d); - w = XCreateSimpleWindow (d, RootWindow (d, s), 10, 10, width, height, 1, - BlackPixel (d, s), WhitePixel (d, s)); - XStoreName (d, w, "eglglessink"); - XMapWindow (d, w); - XFlush (d); - - *window_data = data = g_slice_new0 (X11WindowData); - data->display = d; - - return (EGLNativeWindowType) w; -} - -gboolean -platform_destroy_native_window (EGLNativeDisplayType display, - EGLNativeWindowType window, gpointer * window_data) -{ - X11WindowData *data = *window_data; - - /* XXX: Should proly catch BadWindow */ - XDestroyWindow (data->display, (Window) window); - XSync (data->display, FALSE); - XCloseDisplay (data->display); - - g_slice_free (X11WindowData, data); - *window_data = NULL; - return TRUE; -} -#endif - -#ifdef USE_EGL_MALI_FB -#include - -EGLNativeWindowType -platform_create_native_window (gint width, gint height, gpointer * window_data) -{ - fbdev_window *w = g_slice_new0 (fbdev_window); - - w->width = width; - w->height = height; - - return (EGLNativeWindowType) w; -} - -gboolean -platform_destroy_native_window (EGLNativeDisplayType display, - EGLNativeWindowType window, gpointer * window_data) -{ - g_slice_free (fbdev_window, ((fbdev_window *) window)); - - return TRUE; -} - -/* FIXME: Move to gst-libs/gst/egl */ -#if 0 -#include -#include -#include -#include -static gpointer -eglimage_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags) -{ - GstEGLImageMemory *mem; - gint i; - - g_return_val_if_fail (strcmp (gmem->allocator->mem_type, - GST_EGL_IMAGE_MEMORY_NAME) == 0, FALSE); - - mem = GST_EGL_IMAGE_MEMORY (gmem); - - g_mutex_lock (&mem->lock); - for (i = 0; i < mem->n_textures; i++) { - if (mem->memory_refcount[i]) { - /* Only multiple READ maps are allowed */ - if ((mem->memory_flags[i] & GST_MAP_WRITE)) { - g_mutex_unlock (&mem->lock); - return NULL; - } - } - } - - if (!mem->mapped_memory_refcount) { - EGLint attribs[] = { - MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y, - MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_READ_ONLY, - EGL_NONE - }; - GstVideoInfo info; - mali_egl_image *mali_egl_image; - guint8 *plane_memory, *p; - gint stride, h; - gint j; - - gst_video_info_set_format (&info, mem->format, mem->width, mem->height); - - mem->mapped_memory = g_malloc (mem->parent.size); - - for (i = 0; i < mem->n_textures; i++) { - mali_egl_image = mali_egl_image_lock_ptr (mem->image[i]); - if (!mali_egl_image) { - g_free (mem->mapped_memory); - GST_ERROR ("Failed to lock Mali EGL image: 0x%04x", - mali_egl_image_get_error ()); - g_mutex_unlock (&mem->lock); - return NULL; - } - plane_memory = mali_egl_image_map_buffer (mali_egl_image, attribs); - if (!plane_memory) { - mali_egl_image_unlock_ptr (mem->image[i]); - g_free (mem->mapped_memory); - GST_ERROR ("Failed to lock Mali map image: 0x%04x", - mali_egl_image_get_error ()); - g_mutex_unlock (&mem->lock); - return NULL; - } - - p = ((guint8 *) mem->mapped_memory) + mem->offset[i]; - stride = mem->stride[i]; - h = GST_VIDEO_INFO_COMP_HEIGHT (&info, i); - for (j = 0; j < h; j++) { - memcpy (p, plane_memory, stride); - p += mem->stride[i]; - plane_memory += mem->stride[i]; - } - - mali_egl_image_unmap_buffer (mem->image[i], attribs); - mali_egl_image_unlock_ptr (mem->image[i]); - } - } else { - /* Only multiple READ maps are allowed */ - if ((mem->mapped_memory_flags & GST_MAP_WRITE)) { - g_mutex_unlock (&mem->lock); - return NULL; - } - } - mem->mapped_memory_refcount++; - - g_mutex_unlock (&mem->lock); - - return mem->mapped_memory; -} - -static void -eglimage_unmap (GstMemory * gmem) -{ - GstEGLImageMemory *mem; - gint i; - - g_return_if_fail (strcmp (gmem->allocator->mem_type, - GST_EGL_IMAGE_MEMORY_NAME) == 0); - - mem = GST_EGL_IMAGE_MEMORY (gmem); - g_return_if_fail (mem->mapped_memory); - - g_mutex_lock (&mem->lock); - - mem->mapped_memory_refcount--; - if (mem->mapped_memory_refcount > 0) { - g_mutex_unlock (&mem->lock); - return; - } - - /* Write back */ - if ((mem->mapped_memory_flags & GST_MAP_WRITE)) { - EGLint attribs[] = { - MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y, - MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_WRITE_ONLY, - EGL_NONE - }; - GstVideoInfo info; - mali_egl_image *mali_egl_image; - guint8 *plane_memory, *p; - gint stride, h; - gint j; - - gst_video_info_set_format (&info, mem->format, mem->width, mem->height); - - for (i = 0; i < mem->n_textures; i++) { - mali_egl_image = mali_egl_image_lock_ptr (mem->image[i]); - if (!mali_egl_image) { - g_free (mem->mapped_memory); - GST_ERROR ("Failed to lock Mali EGL image: 0x%04x", - mali_egl_image_get_error ()); - g_mutex_unlock (&mem->lock); - return; - } - plane_memory = mali_egl_image_map_buffer (mali_egl_image, attribs); - if (!plane_memory) { - mali_egl_image_unlock_ptr (mem->image[i]); - g_free (mem->mapped_memory); - GST_ERROR ("Failed to lock Mali map image: 0x%04x", - mali_egl_image_get_error ()); - g_mutex_unlock (&mem->lock); - return; - } - - p = ((guint8 *) mem->mapped_memory) + mem->offset[i]; - stride = mem->stride[i]; - h = GST_VIDEO_INFO_COMP_HEIGHT (&info, i); - for (j = 0; j < h; j++) { - memcpy (plane_memory, p, stride); - p += mem->stride[i]; - plane_memory += mem->stride[i]; - } - - mali_egl_image_unmap_buffer (mem->image[i], attribs); - mali_egl_image_unlock_ptr (mem->image[i]); - } - } - g_free (mem->mapped_memory); - - g_mutex_unlock (&mem->lock); -} - -static gboolean -eglimage_video_map (GstVideoMeta * meta, guint plane, - GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags) -{ - GstMemory *gmem; - GstEGLImageMemory *mem; - GstVideoInfo vinfo; - - if (gst_buffer_n_memory (meta->buffer) != 1) - return default_map_video (meta, plane, info, data, stride, flags); - - gmem = gst_buffer_peek_memory (meta->buffer, 0); - if (strcmp (gmem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_NAME) != 0) - return default_map_video (meta, plane, info, data, stride, flags); - - mem = GST_EGL_IMAGE_MEMORY ((gmem->parent ? gmem->parent : gmem)); - - g_mutex_lock (&mem->lock); - if (mem->format == GST_VIDEO_FORMAT_YV12) { - if (plane == 1) - plane = 2; - else if (plane == 2) - plane = 1; - } - - if (mem->mapped_memory_refcount) { - /* Only multiple READ maps are allowed */ - if ((mem->mapped_memory_flags & GST_MAP_WRITE)) { - g_mutex_unlock (&mem->lock); - return FALSE; - } - } - - if (!mem->memory_refcount[plane]) { - EGLint attribs[] = { - MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y, - MALI_EGL_IMAGE_ACCESS_MODE, MALI_EGL_IMAGE_ACCESS_READ_WRITE, - EGL_NONE - }; - - if ((flags & GST_MAP_READ) && (flags & GST_MAP_WRITE)) - attribs[3] = MALI_EGL_IMAGE_ACCESS_READ_WRITE; - else if ((flags & GST_MAP_READ)) - attribs[3] = MALI_EGL_IMAGE_ACCESS_READ_ONLY; - else if ((flags & GST_MAP_WRITE)) - attribs[3] = MALI_EGL_IMAGE_ACCESS_WRITE_ONLY; - - mem->memory_platform_data[plane] = - mali_egl_image_lock_ptr (mem->image[plane]); - if (!mem->memory_platform_data[plane]) { - GST_ERROR ("Failed to lock Mali EGL image: 0x%04x", - mali_egl_image_get_error ()); - goto map_error; - } - - mem->memory[plane] = - mali_egl_image_map_buffer (mem->memory_platform_data[plane], attribs); - if (!mem->memory[plane]) - goto map_error; - - mem->memory_flags[plane] = flags; - } else { - /* Only multiple READ maps are allowed */ - if ((mem->memory_flags[plane] & GST_MAP_WRITE)) { - g_mutex_unlock (&mem->lock); - return FALSE; - } - } - - mem->memory_refcount[plane]++; - gst_video_info_set_format (&vinfo, mem->format, mem->width, mem->height); - - *data = mem->memory[plane]; - *stride = mem->stride[plane]; - - g_mutex_unlock (&mem->lock); - return TRUE; - -map_error: - { - EGLint attribs[] = { - MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y, - EGL_NONE - }; - GST_ERROR ("Failed to map Mali EGL image: 0x%04x", - mali_egl_image_get_error ()); - - if (mem->memory_platform_data[plane]) { - mali_egl_image_unmap_buffer (mem->image[plane], attribs); - mali_egl_image_unlock_ptr (mem->image[plane]); - } - mem->memory[plane] = NULL; - mem->memory_platform_data[plane] = NULL; - - g_mutex_unlock (&mem->lock); - - return FALSE; - } -} - -static gboolean -eglimage_video_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info) -{ - GstMemory *gmem; - GstEGLImageMemory *mem; - EGLint attribs[] = { - MALI_EGL_IMAGE_PLANE, MALI_EGL_IMAGE_PLANE_Y, - EGL_NONE - }; - - if (gst_buffer_n_memory (meta->buffer) != 1) - return default_unmap_video (meta, plane, info); - - gmem = gst_buffer_peek_memory (meta->buffer, 0); - if (strcmp (gmem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_NAME) != 0) - return default_unmap_video (meta, plane, info); - - mem = GST_EGL_IMAGE_MEMORY ((gmem->parent ? gmem->parent : gmem)); - - g_mutex_lock (&mem->lock); - if (mem->format == GST_VIDEO_FORMAT_YV12) { - if (plane == 1) - plane = 2; - else if (plane == 2) - plane = 1; - } - - if (!mem->memory_refcount[plane]) { - g_mutex_unlock (&mem->lock); - g_return_val_if_reached (FALSE); - } - - mem->memory_refcount[plane]--; - if (mem->memory_refcount[plane] > 0) { - g_mutex_unlock (&mem->lock); - return TRUE; - } - - /* Unmaps automatically */ - if (mem->memory_platform_data[plane]) { - mali_egl_image_unmap_buffer (mem->image[plane], attribs); - mali_egl_image_unlock_ptr (mem->image[plane]); - } - mem->memory[plane] = NULL; - mem->memory_platform_data[plane] = NULL; - - g_mutex_unlock (&mem->lock); - - return TRUE; -} - -gboolean -platform_can_map_eglimage (GstMemoryMapFunction * map, - GstMemoryUnmapFunction * unmap, PlatformMapVideo * video_map, - PlatformUnmapVideo * video_unmap) -{ - *map = eglimage_map; - *unmap = eglimage_unmap; - *video_map = eglimage_video_map; - *video_unmap = eglimage_video_unmap; - return TRUE; -} - -gboolean -platform_has_custom_eglimage_alloc (void) -{ - return TRUE; -} - -gboolean -platform_alloc_eglimage (EGLDisplay display, EGLContext context, GLint format, - GLint type, gint width, gint height, GLuint tex_id, EGLImageKHR * image, - gpointer * image_platform_data) -{ - fbdev_pixmap pixmap; - - pixmap.flags = FBDEV_PIXMAP_SUPPORTS_UMP; - pixmap.width = width; - pixmap.height = height; - - switch (format) { - case GL_LUMINANCE: - g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE); - pixmap.red_size = 0; - pixmap.green_size = 0; - pixmap.blue_size = 0; - pixmap.alpha_size = 0; - pixmap.luminance_size = 8; - break; - case GL_LUMINANCE_ALPHA: - g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE); - pixmap.red_size = 0; - pixmap.green_size = 0; - pixmap.blue_size = 0; - pixmap.alpha_size = 8; - pixmap.luminance_size = 8; - break; - case GL_RGB: - if (type == GL_UNSIGNED_BYTE) { - pixmap.red_size = 8; - pixmap.green_size = 8; - pixmap.blue_size = 8; - pixmap.alpha_size = 0; - pixmap.luminance_size = 0; - } else if (type == GL_UNSIGNED_SHORT_5_6_5) { - pixmap.red_size = 5; - pixmap.green_size = 6; - pixmap.blue_size = 5; - pixmap.alpha_size = 0; - pixmap.luminance_size = 0; - } else { - g_return_val_if_reached (FALSE); - } - break; - case GL_RGBA: - g_return_val_if_fail (type == GL_UNSIGNED_BYTE, FALSE); - pixmap.red_size = 8; - pixmap.green_size = 8; - pixmap.blue_size = 8; - pixmap.alpha_size = 8; - pixmap.luminance_size = 0; - break; - default: - g_assert_not_reached (); - return FALSE; - } - - pixmap.buffer_size = - pixmap.red_size + pixmap.green_size + pixmap.blue_size + - pixmap.alpha_size + pixmap.luminance_size; - pixmap.bytes_per_pixel = pixmap.buffer_size / 8; - pixmap.format = 0; - - if (ump_open () != UMP_OK) { - GST_ERROR ("Failed to open UMP"); - return FALSE; - } - - pixmap.data = - ump_ref_drv_allocate (GST_ROUND_UP_4 (pixmap.width) * pixmap.height * - pixmap.bytes_per_pixel, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR); - if (pixmap.data == UMP_INVALID_MEMORY_HANDLE) { - GST_ERROR ("Failed to allocate pixmap data via UMP"); - ump_close (); - return FALSE; - } - - *image_platform_data = g_slice_dup (fbdev_pixmap, &pixmap); - *image = - eglCreateImageKHR (display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer) * image_platform_data, NULL); - if (!image) { - GST_ERROR ("Failed to create EGLImage for pixmap"); - ump_reference_release ((ump_handle) pixmap.data); - ump_close (); - g_slice_free (fbdev_pixmap, *image_platform_data); - return FALSE; - } - - return TRUE; -} - -void -platform_free_eglimage (EGLDisplay display, EGLContext context, GLuint tex_id, - EGLImageKHR * image, gpointer * image_platform_data) -{ - fbdev_pixmap *pixmap = *image_platform_data; - - eglDestroyImageKHR (display, *image); - ump_reference_release ((ump_handle) pixmap->data); - ump_close (); - g_slice_free (fbdev_pixmap, *image_platform_data); -} -#endif -#endif - -#ifdef USE_EGL_RPI -#include -#include - -typedef struct -{ - EGL_DISPMANX_WINDOW_T w; - DISPMANX_DISPLAY_HANDLE_T d; -} RPIWindowData; - -EGLNativeWindowType -platform_create_native_window (gint width, gint height, gpointer * window_data) -{ - DISPMANX_ELEMENT_HANDLE_T dispman_element; - DISPMANX_DISPLAY_HANDLE_T dispman_display; - DISPMANX_UPDATE_HANDLE_T dispman_update; - RPIWindowData *data; - VC_RECT_T dst_rect; - VC_RECT_T src_rect; - GstVideoRectangle src, dst, res; - - uint32_t dp_height; - uint32_t dp_width; - - int ret; - - ret = graphics_get_display_size (0, &dp_width, &dp_height); - if (ret < 0) { - GST_ERROR ("Can't open display"); - return (EGLNativeWindowType) 0; - } - GST_DEBUG ("Got display size: %dx%d\n", dp_width, dp_height); - GST_DEBUG ("Source size: %dx%d\n", width, height); - - /* Center width*height frame inside dp_width*dp_height */ - src.w = width; - src.h = height; - src.x = src.y = 0; - dst.w = dp_width; - dst.h = dp_height; - dst.x = dst.y = 0; - gst_video_sink_center_rect (src, dst, &res, TRUE); - - dst_rect.x = res.x; - dst_rect.y = res.y; - dst_rect.width = res.w; - dst_rect.height = res.h; - - src_rect.x = 0; - src_rect.y = 0; - src_rect.width = width << 16; - src_rect.height = height << 16; - - dispman_display = vc_dispmanx_display_open (0); - dispman_update = vc_dispmanx_update_start (0); - dispman_element = vc_dispmanx_element_add (dispman_update, - dispman_display, 0, &dst_rect, 0, &src_rect, - DISPMANX_PROTECTION_NONE, 0, 0, 0); - - *window_data = data = g_slice_new0 (RPIWindowData); - data->d = dispman_display; - data->w.element = dispman_element; - data->w.width = width; - data->w.height = height; - vc_dispmanx_update_submit_sync (dispman_update); - - return (EGLNativeWindowType) data; -} - -gboolean -platform_destroy_native_window (EGLNativeDisplayType display, - EGLNativeWindowType window, gpointer * window_data) -{ - DISPMANX_DISPLAY_HANDLE_T dispman_display; - DISPMANX_UPDATE_HANDLE_T dispman_update; - RPIWindowData *data = *window_data; - - dispman_display = data->d; - dispman_update = vc_dispmanx_update_start (0); - vc_dispmanx_element_remove (dispman_update, data->w.element); - vc_dispmanx_update_submit_sync (dispman_update); - vc_dispmanx_display_close (dispman_display); - - g_slice_free (RPIWindowData, data); - *window_data = NULL; - return TRUE; -} -#endif - -#if !defined(USE_EGL_X11) && !defined(USE_EGL_MALI_FB) && !defined(USE_EGL_RPI) -/* Dummy functions for creating a native Window */ -EGLNativeWindowType -platform_create_native_window (gint width, gint height, gpointer * window_data) -{ - GST_ERROR ("Can't create native window"); - return (EGLNativeWindowType) 0; -} - -gboolean -platform_destroy_native_window (EGLNativeDisplayType display, - EGLNativeWindowType window, gpointer * window_data) -{ - GST_ERROR ("Can't destroy native window"); - return TRUE; -} -#endif diff --git a/ext/eglgles/video_platform_wrapper.h b/ext/eglgles/video_platform_wrapper.h deleted file mode 100644 index 0ca8924c81..0000000000 --- a/ext/eglgles/video_platform_wrapper.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * GStreamer Android Video Platform Wrapper - * Copyright (C) 2012 Collabora Ltd. - * @author: Reynaldo H. Verdejo Pinochet - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * General idea is to have all platform dependent code here for easy - * tweaking and isolation from the main routines - */ - -#ifndef __GST_VIDEO_PLATFORM_WRAPPER__ -#define __GST_VIDEO_PLATFORM_WRAPPER__ - -#include -#include - -gboolean platform_wrapper_init (void); -EGLNativeWindowType platform_create_native_window (gint width, gint height, gpointer * window_data); -gboolean platform_destroy_native_window (EGLNativeDisplayType display, - EGLNativeWindowType w, gpointer * window_data); - -#endif diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index a357100301..012346997f 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -1,6 +1,3 @@ -if HAVE_EGL -EGL_DIR = egl -endif if USE_OPENGL GL_DIR = gl @@ -10,8 +7,8 @@ GL_DIR = gl endif SUBDIRS = interfaces basecamerabinsrc codecparsers \ - insertbin uridownloader mpegts $(EGL_DIR) $(GL_DIR) + insertbin uridownloader mpegts $(GL_DIR) noinst_HEADERS = gst-i18n-plugin.h gettext.h glib-compat-private.h -DIST_SUBDIRS = interfaces egl gl basecamerabinsrc codecparsers \ +DIST_SUBDIRS = interfaces gl basecamerabinsrc codecparsers \ insertbin uridownloader mpegts diff --git a/gst-libs/gst/egl/Makefile.am b/gst-libs/gst/egl/Makefile.am deleted file mode 100644 index 2270d26d5c..0000000000 --- a/gst-libs/gst/egl/Makefile.am +++ /dev/null @@ -1,95 +0,0 @@ -lib_LTLIBRARIES = libgstegl-@GST_API_VERSION@.la - -libgstegl_@GST_API_VERSION@_la_SOURCES = egl.c - -libgstegl_@GST_API_VERSION@includedir = \ - $(includedir)/gstreamer-@GST_API_VERSION@/gst/egl - -libgstegl_@GST_API_VERSION@include_HEADERS = egl.h - -libgstegl_@GST_API_VERSION@_la_CFLAGS = \ - $(GST_PLUGINS_BAD_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_CFLAGS) \ - $(EGL_CFLAGS) - -libgstegl_@GST_API_VERSION@_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) \ - -lgstvideo-@GST_API_VERSION@ \ - $(GST_LIBS) \ - $(EGL_LIBS) - -libgstegl_@GST_API_VERSION@_la_LDFLAGS = \ - $(GST_LIB_LDFLAGS) \ - $(GST_ALL_LDFLAGS) \ - $(GST_LT_LDFLAGS) - - -if HAVE_INTROSPECTION -BUILT_GIRSOURCES = GstEGL-@GST_API_VERSION@.gir - -gir_headers=$(patsubst %,$(srcdir)/%, $(libgstegl_@GST_API_VERSION@include_HEADERS)) -gir_headers+=$(patsubst %,$(builddir)/%, $(built_headers)) -gir_sources=$(patsubst %,$(srcdir)/%, $(libgstegl_@GST_API_VERSION@_la_SOURCES)) -gir_sources+=$(patsubst %,$(builddir)/%, $(built_sources)) - -GstEGL-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstegl-@GST_API_VERSION@.la - $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ - GST_PLUGIN_SYSTEM_PATH_1_0="" GST_PLUGIN_PATH_1_0="" GST_REGISTRY_UPDATE=no \ - $(INTROSPECTION_SCANNER) -v --namespace GstEGL \ - --nsversion=@GST_API_VERSION@ \ - --strip-prefix=Gst \ - --warn-all \ - --c-include "gst/egl/egl.h" \ - -I$(top_srcdir)/gst-libs \ - -I$(top_builddir)/gst-libs \ - --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ - --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-video-@GST_API_VERSION@` \ - --library=libgstegl-@GST_API_VERSION@.la \ - --include=Gst-@GST_API_VERSION@ \ - --libtool="$(top_builddir)/libtool" \ - --pkg gstreamer-@GST_API_VERSION@ \ - --pkg gstreamer-video-@GST_API_VERSION@ \ - --pkg-export gstreamer-egl-@GST_API_VERSION@ \ - --add-init-section="gst_init(NULL,NULL);" \ - -DGST_USE_UNSTABLE_API \ - --output $@ \ - $(gir_headers) \ - $(gir_sources) - -# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to -# install anything - we need to install inside our prefix. -girdir = $(datadir)/gir-1.0 -gir_DATA = $(BUILT_GIRSOURCES) - -typelibsdir = $(libdir)/girepository-1.0/ - -typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) - -%.typelib: %.gir $(INTROSPECTION_COMPILER) - $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ - $(INTROSPECTION_COMPILER) \ - --includedir=$(srcdir) \ - --includedir=$(builddir) \ - --includedir=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_API_VERSION@` \ - --includedir=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \ - $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) - -CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) -endif - -Android.mk: $(BUILT_SOURCES) Makefile.am - androgenizer -:PROJECT libgstegl -:STATIC libgstegl-@GST_API_VERSION@ \ - -:TAGS eng debug \ - -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ - -:SOURCES $(libgstegl_@GST_API_VERSION@_la_SOURCES) \ - $(built_sources) \ - -:CFLAGS $(DEFS) $(libgstegl_@GST_API_VERSION@_la_CFLAGS) \ - -:LDFLAGS $(libgstegl_@GST_API_VERSION@_la_LDFLAGS) \ - $(libgstegl@GST_API_VERSION@_la_LIBADD) \ - -ldl \ - -:HEADER_TARGET gstreamer-@GST_API_VERSION@/gst/egl \ - -:HEADERS $(libgsteglinclude_HEADERS) \ - $(built_headers) \ - -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ - > $@ diff --git a/gst-libs/gst/egl/egl.c b/gst-libs/gst/egl/egl.c deleted file mode 100644 index 26268a3002..0000000000 --- a/gst-libs/gst/egl/egl.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * GStreamer EGL Library - * Copyright (C) 2012 Collabora Ltd. - * @author: Sebastian Dröge - * * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#ifndef __VCCOREVER__ -#define __VCCOREVER__ 0x04000000 -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wredundant-decls" -#pragma GCC optimize ("gnu89-inline") -#endif - -#define EGL_EGLEXT_PROTOTYPES - -#include -#include - -#if defined (USE_EGL_RPI) && defined(__GNUC__) -#pragma GCC reset_options -#pragma GCC diagnostic pop -#endif - -typedef struct -{ - GstMemory parent; - - GstEGLDisplay *display; - EGLImageKHR image; - GstVideoGLTextureType type; - GstVideoGLTextureOrientation orientation; - - gpointer user_data; - GDestroyNotify user_data_destroy; -} GstEGLImageMemory; - -#define GST_EGL_IMAGE_MEMORY(mem) ((GstEGLImageMemory*)(mem)) - -gboolean -gst_egl_image_memory_is_mappable (void) -{ - return FALSE; -} - -gboolean -gst_is_egl_image_memory (GstMemory * mem) -{ - g_return_val_if_fail (mem != NULL, FALSE); - g_return_val_if_fail (mem->allocator != NULL, FALSE); - - return g_strcmp0 (mem->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0; -} - -EGLImageKHR -gst_egl_image_memory_get_image (GstMemory * mem) -{ - g_return_val_if_fail (gst_is_egl_image_memory (mem), EGL_NO_IMAGE_KHR); - - if (mem->parent) - mem = mem->parent; - - return GST_EGL_IMAGE_MEMORY (mem)->image; -} - -GstEGLDisplay * -gst_egl_image_memory_get_display (GstMemory * mem) -{ - g_return_val_if_fail (gst_is_egl_image_memory (mem), NULL); - - if (mem->parent) - mem = mem->parent; - - return gst_egl_display_ref (GST_EGL_IMAGE_MEMORY (mem)->display); -} - -GstVideoGLTextureType -gst_egl_image_memory_get_type (GstMemory * mem) -{ - g_return_val_if_fail (gst_is_egl_image_memory (mem), -1); - - if (mem->parent) - mem = mem->parent; - - return GST_EGL_IMAGE_MEMORY (mem)->type; -} - -GstVideoGLTextureOrientation -gst_egl_image_memory_get_orientation (GstMemory * mem) -{ - g_return_val_if_fail (gst_is_egl_image_memory (mem), - GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL); - - if (mem->parent) - mem = mem->parent; - - return GST_EGL_IMAGE_MEMORY (mem)->orientation; -} - -void -gst_egl_image_memory_set_orientation (GstMemory * mem, - GstVideoGLTextureOrientation orientation) -{ - g_return_if_fail (gst_is_egl_image_memory (mem)); - - if (mem->parent) - mem = mem->parent; - - GST_EGL_IMAGE_MEMORY (mem)->orientation = orientation; -} - -static GstMemory * -gst_egl_image_allocator_alloc_vfunc (GstAllocator * allocator, gsize size, - GstAllocationParams * params) -{ - g_warning - ("Use gst_egl_image_allocator_alloc() to allocate from this allocator"); - - return NULL; -} - -static void -gst_egl_image_allocator_free_vfunc (GstAllocator * allocator, GstMemory * mem) -{ - GstEGLImageMemory *emem = (GstEGLImageMemory *) mem; - EGLDisplay display; - - g_return_if_fail (gst_is_egl_image_memory (mem)); - - /* Shared memory should not destroy all the data */ - if (!mem->parent) { - display = gst_egl_display_get (emem->display); - eglDestroyImageKHR (display, emem->image); - - if (emem->user_data_destroy) - emem->user_data_destroy (emem->user_data); - - gst_egl_display_unref (emem->display); - } - - g_slice_free (GstEGLImageMemory, emem); -} - -static gpointer -gst_egl_image_mem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) -{ - return NULL; -} - -static void -gst_egl_image_mem_unmap (GstMemory * mem) -{ -} - -static GstMemory * -gst_egl_image_mem_share (GstMemory * mem, gssize offset, gssize size) -{ - GstMemory *sub; - GstMemory *parent; - - if (offset != 0) - return NULL; - - if (size != -1 && size != mem->size) - return NULL; - - /* find the real parent */ - if ((parent = mem->parent) == NULL) - parent = (GstMemory *) mem; - - if (size == -1) - size = mem->size - offset; - - sub = (GstMemory *) g_slice_new (GstEGLImageMemory); - - /* the shared memory is always readonly */ - gst_memory_init (GST_MEMORY_CAST (sub), GST_MINI_OBJECT_FLAGS (parent) | - GST_MINI_OBJECT_FLAG_LOCK_READONLY, mem->allocator, parent, - mem->maxsize, mem->align, mem->offset + offset, size); - - return sub; -} - -static GstMemory * -gst_egl_image_mem_copy (GstMemory * mem, gssize offset, gssize size) -{ - return NULL; -} - -static gboolean -gst_egl_image_mem_is_span (GstMemory * mem1, GstMemory * mem2, gsize * offset) -{ - return FALSE; -} - -typedef GstAllocator GstEGLImageAllocator; -typedef GstAllocatorClass GstEGLImageAllocatorClass; - -GType gst_egl_image_allocator_get_type (void); -G_DEFINE_TYPE (GstEGLImageAllocator, gst_egl_image_allocator, - GST_TYPE_ALLOCATOR); - -#define GST_TYPE_EGL_IMAGE_ALLOCATOR (gst_egl_image_mem_allocator_get_type()) -#define GST_IS_EGL_IMAGE_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EGL_IMAGE_ALLOCATOR)) - -static void -gst_egl_image_allocator_class_init (GstEGLImageAllocatorClass * klass) -{ - GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass; - - allocator_class->alloc = gst_egl_image_allocator_alloc_vfunc; - allocator_class->free = gst_egl_image_allocator_free_vfunc; -} - -static void -gst_egl_image_allocator_init (GstEGLImageAllocator * allocator) -{ - GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); - - alloc->mem_type = GST_EGL_IMAGE_MEMORY_TYPE; - alloc->mem_map = gst_egl_image_mem_map; - alloc->mem_unmap = gst_egl_image_mem_unmap; - alloc->mem_share = gst_egl_image_mem_share; - alloc->mem_copy = gst_egl_image_mem_copy; - alloc->mem_is_span = gst_egl_image_mem_is_span; - - GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); -} - -static gpointer -gst_egl_image_allocator_init_instance (gpointer data) -{ - return g_object_new (gst_egl_image_allocator_get_type (), NULL); -} - -GstAllocator * -gst_egl_image_allocator_obtain (void) -{ - static GOnce once = G_ONCE_INIT; - - g_once (&once, gst_egl_image_allocator_init_instance, NULL); - - g_return_val_if_fail (once.retval != NULL, NULL); - - return GST_ALLOCATOR (g_object_ref (once.retval)); -} - -GstMemory * -gst_egl_image_allocator_alloc (GstAllocator * allocator, - GstEGLDisplay * display, GstVideoGLTextureType type, gint width, - gint height, gsize * size) -{ - return NULL; -} - -GstMemory * -gst_egl_image_allocator_wrap (GstAllocator * allocator, - GstEGLDisplay * display, EGLImageKHR image, GstVideoGLTextureType type, - GstMemoryFlags flags, gsize size, gpointer user_data, - GDestroyNotify user_data_destroy) -{ - GstEGLImageMemory *mem; - - g_return_val_if_fail (display != NULL, NULL); - g_return_val_if_fail (image != EGL_NO_IMAGE_KHR, NULL); - - if (!allocator) { - allocator = gst_egl_image_allocator_obtain (); - } - - mem = g_slice_new (GstEGLImageMemory); - gst_memory_init (GST_MEMORY_CAST (mem), flags, - allocator, NULL, size, 0, 0, size); - - mem->display = gst_egl_display_ref (display); - mem->image = image; - mem->type = type; - mem->orientation = GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL; - - mem->user_data = user_data; - mem->user_data_destroy = user_data_destroy; - - return GST_MEMORY_CAST (mem); -} - -GstContext * -gst_context_new_egl_display (GstEGLDisplay * display, gboolean persistent) -{ - GstContext *context; - GstStructure *s; - - context = gst_context_new (GST_EGL_DISPLAY_CONTEXT_TYPE, persistent); - s = gst_context_writable_structure (context); - gst_structure_set (s, "display", GST_TYPE_EGL_DISPLAY, display, NULL); - - return context; -} - -gboolean -gst_context_get_egl_display (GstContext * context, GstEGLDisplay ** display) -{ - const GstStructure *s; - - g_return_val_if_fail (GST_IS_CONTEXT (context), FALSE); - g_return_val_if_fail (strcmp (gst_context_get_context_type (context), - GST_EGL_DISPLAY_CONTEXT_TYPE) == 0, FALSE); - - s = gst_context_get_structure (context); - return gst_structure_get (s, "display", GST_TYPE_EGL_DISPLAY, display, NULL); -} - -struct _GstEGLDisplay -{ - EGLDisplay display; - volatile gint refcount; - GDestroyNotify destroy_notify; -}; - -GstEGLDisplay * -gst_egl_display_new (EGLDisplay display, GDestroyNotify destroy_notify) -{ - GstEGLDisplay *gdisplay; - - gdisplay = g_slice_new (GstEGLDisplay); - gdisplay->display = display; - gdisplay->refcount = 1; - gdisplay->destroy_notify = destroy_notify; - - return gdisplay; -} - -GstEGLDisplay * -gst_egl_display_ref (GstEGLDisplay * display) -{ - g_return_val_if_fail (display != NULL, NULL); - - g_atomic_int_inc (&display->refcount); - - return display; -} - -void -gst_egl_display_unref (GstEGLDisplay * display) -{ - g_return_if_fail (display != NULL); - - if (g_atomic_int_dec_and_test (&display->refcount)) { - if (display->destroy_notify) - display->destroy_notify (display->display); - g_slice_free (GstEGLDisplay, display); - } -} - -EGLDisplay -gst_egl_display_get (GstEGLDisplay * display) -{ - g_return_val_if_fail (display != NULL, EGL_NO_DISPLAY); - - return display->display; -} - -G_DEFINE_BOXED_TYPE (GstEGLDisplay, gst_egl_display, - (GBoxedCopyFunc) gst_egl_display_ref, - (GBoxedFreeFunc) gst_egl_display_unref); - - -struct _GstEGLImageBufferPoolPrivate -{ - GstAllocator *allocator; - GstAllocationParams params; - GstVideoInfo info; - gboolean add_metavideo; - gboolean want_eglimage; - GstBuffer *last_buffer; - GstEGLImageBufferPoolSendBlockingAllocate send_blocking_allocate_func; - gpointer send_blocking_allocate_data; - GDestroyNotify send_blocking_allocate_destroy; -}; - -G_DEFINE_TYPE (GstEGLImageBufferPool, gst_egl_image_buffer_pool, - GST_TYPE_VIDEO_BUFFER_POOL); - -GstBufferPool * -gst_egl_image_buffer_pool_new (GstEGLImageBufferPoolSendBlockingAllocate - blocking_allocate_func, gpointer blocking_allocate_data, - GDestroyNotify destroy_func) -{ - GstEGLImageBufferPool *pool = - g_object_new (GST_TYPE_EGL_IMAGE_BUFFER_POOL, NULL); - GstEGLImageBufferPoolPrivate *priv = - G_TYPE_INSTANCE_GET_PRIVATE (pool, GST_TYPE_EGL_IMAGE_BUFFER_POOL, - GstEGLImageBufferPoolPrivate); - - pool->priv = priv; - - priv->allocator = NULL; - priv->last_buffer = NULL; - priv->send_blocking_allocate_func = blocking_allocate_func; - priv->send_blocking_allocate_data = blocking_allocate_data; - priv->send_blocking_allocate_destroy = destroy_func; - - return (GstBufferPool *) pool; -} - -void -gst_egl_image_buffer_pool_replace_last_buffer (GstEGLImageBufferPool * pool, - GstBuffer * buffer) -{ - g_return_if_fail (pool != NULL); - - gst_buffer_replace (&pool->priv->last_buffer, buffer); -} - -static const gchar ** -gst_egl_image_buffer_pool_get_options (GstBufferPool * bpool) -{ - static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL - }; - - return options; -} - -static gboolean -gst_egl_image_buffer_pool_set_config (GstBufferPool * bpool, - GstStructure * config) -{ - GstEGLImageBufferPool *pool = GST_EGL_IMAGE_BUFFER_POOL (bpool); - GstEGLImageBufferPoolPrivate *priv = pool->priv; - GstCaps *caps; - GstVideoInfo info; - - if (priv->allocator) - gst_object_unref (priv->allocator); - priv->allocator = NULL; - - if (!GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->set_config (bpool, config)) - return FALSE; - - if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL) - || !caps) - return FALSE; - - if (!gst_video_info_from_caps (&info, caps)) - return FALSE; - - if (!gst_buffer_pool_config_get_allocator (config, &priv->allocator, - &priv->params)) - return FALSE; - if (priv->allocator) - gst_object_ref (priv->allocator); - - priv->add_metavideo = - gst_buffer_pool_config_has_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_META); - - priv->want_eglimage = (priv->allocator - && g_strcmp0 (priv->allocator->mem_type, GST_EGL_IMAGE_MEMORY_TYPE) == 0); - - priv->info = info; - - return TRUE; -} - -static GstFlowReturn -gst_egl_image_buffer_pool_alloc_buffer (GstBufferPool * bpool, - GstBuffer ** buffer, GstBufferPoolAcquireParams * params) -{ - GstEGLImageBufferPool *pool = GST_EGL_IMAGE_BUFFER_POOL (bpool); - GstEGLImageBufferPoolPrivate *priv = pool->priv; - - *buffer = NULL; - - if (!priv->add_metavideo || !priv->want_eglimage) - return - GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->alloc_buffer (bpool, - buffer, params); - - if (!priv->allocator) - return GST_FLOW_NOT_NEGOTIATED; - - switch (priv->info.finfo->format) { - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y41B:{ - - if (priv->send_blocking_allocate_func) - *buffer = priv->send_blocking_allocate_func (bpool, - priv->send_blocking_allocate_data); - - if (!*buffer) { - GST_WARNING ("Fallback memory allocation"); - return - GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->alloc_buffer (bpool, - buffer, params); - } - - return GST_FLOW_OK; - break; - } - default: - return - GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->alloc_buffer (bpool, - buffer, params); - break; - } - - return GST_FLOW_ERROR; -} - -static GstFlowReturn -gst_egl_image_buffer_pool_acquire_buffer (GstBufferPool * bpool, - GstBuffer ** buffer, GstBufferPoolAcquireParams * params) -{ - GstFlowReturn ret; - GstEGLImageBufferPool *pool; - - ret = - GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->acquire_buffer (bpool, - buffer, params); - if (ret != GST_FLOW_OK || !*buffer) - return ret; - - pool = GST_EGL_IMAGE_BUFFER_POOL (bpool); - - /* XXX: Don't return the memory we just rendered, glEGLImageTargetTexture2DOES() - * keeps the EGLImage unmappable until the next one is uploaded - */ - if (*buffer && *buffer == pool->priv->last_buffer) { - GstBuffer *oldbuf = *buffer; - - ret = - GST_BUFFER_POOL_CLASS - (gst_egl_image_buffer_pool_parent_class)->acquire_buffer (bpool, - buffer, params); - gst_object_replace ((GstObject **) & oldbuf->pool, (GstObject *) pool); - gst_buffer_unref (oldbuf); - } - - return ret; -} - -static void -gst_egl_image_buffer_pool_finalize (GObject * object) -{ - GstEGLImageBufferPool *pool = GST_EGL_IMAGE_BUFFER_POOL (object); - GstEGLImageBufferPoolPrivate *priv = pool->priv; - - if (priv->allocator) - gst_object_unref (priv->allocator); - priv->allocator = NULL; - - gst_egl_image_buffer_pool_replace_last_buffer (pool, NULL); - - if (priv->send_blocking_allocate_destroy) - priv->send_blocking_allocate_destroy (priv->send_blocking_allocate_data); - priv->send_blocking_allocate_destroy = NULL; - priv->send_blocking_allocate_data = NULL; - - G_OBJECT_CLASS (gst_egl_image_buffer_pool_parent_class)->finalize (object); -} - -static void -gst_egl_image_buffer_pool_class_init (GstEGLImageBufferPoolClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass; - - g_type_class_add_private (klass, sizeof (GstEGLImageBufferPoolPrivate)); - - gobject_class->finalize = gst_egl_image_buffer_pool_finalize; - gstbufferpool_class->get_options = gst_egl_image_buffer_pool_get_options; - gstbufferpool_class->set_config = gst_egl_image_buffer_pool_set_config; - gstbufferpool_class->alloc_buffer = gst_egl_image_buffer_pool_alloc_buffer; - gstbufferpool_class->acquire_buffer = - gst_egl_image_buffer_pool_acquire_buffer; -} - -static void -gst_egl_image_buffer_pool_init (GstEGLImageBufferPool * pool) -{ -} diff --git a/gst-libs/gst/egl/egl.h b/gst-libs/gst/egl/egl.h deleted file mode 100644 index c0d53cbe04..0000000000 --- a/gst-libs/gst/egl/egl.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * GStreamer EGL Library - * Copyright (C) 2012 Collabora Ltd. - * @author: Sebastian Dröge - * * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_EGL_H__ -#define __GST_EGL_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define GST_EGL_IMAGE_MEMORY_TYPE "EGLImage" - -#define GST_CAPS_FEATURE_MEMORY_EGL_IMAGE "memory:EGLImage" - -typedef struct _GstEGLDisplay GstEGLDisplay; - -/* EGLImage GstMemory handling */ -gboolean gst_egl_image_memory_is_mappable (void); -gboolean gst_is_egl_image_memory (GstMemory * mem); -EGLImageKHR gst_egl_image_memory_get_image (GstMemory * mem); -GstEGLDisplay *gst_egl_image_memory_get_display (GstMemory * mem); -GstVideoGLTextureType gst_egl_image_memory_get_type (GstMemory * mem); -GstVideoGLTextureOrientation gst_egl_image_memory_get_orientation (GstMemory * mem); -void gst_egl_image_memory_set_orientation (GstMemory * mem, - GstVideoGLTextureOrientation orientation); - -/* Generic EGLImage allocator that doesn't support mapping, copying or anything */ -GstAllocator *gst_egl_image_allocator_obtain (void); -GstMemory *gst_egl_image_allocator_alloc (GstAllocator * allocator, - GstEGLDisplay * display, GstVideoGLTextureType type, gint width, gint height, - gsize * size); -GstMemory *gst_egl_image_allocator_wrap (GstAllocator * allocator, - GstEGLDisplay * display, EGLImageKHR image, GstVideoGLTextureType type, - GstMemoryFlags flags, gsize size, gpointer user_data, - GDestroyNotify user_data_destroy); - -#define GST_EGL_DISPLAY_CONTEXT_TYPE "gst.egl.EGLDisplay" -GstContext * gst_context_new_egl_display (GstEGLDisplay * display, gboolean persistent); -gboolean gst_context_get_egl_display (GstContext * context, - GstEGLDisplay ** display); - -/* EGLDisplay wrapper with refcount, connection is closed after last ref is gone */ -#define GST_TYPE_EGL_DISPLAY (gst_egl_display_get_type()) -GType gst_egl_display_get_type (void); - -GstEGLDisplay *gst_egl_display_new (EGLDisplay display, GDestroyNotify destroy_notify); -GstEGLDisplay *gst_egl_display_ref (GstEGLDisplay * display); -void gst_egl_display_unref (GstEGLDisplay * display); -EGLDisplay gst_egl_display_get (GstEGLDisplay * display); - -/* EGLImage buffer pool */ - -#define GST_TYPE_EGL_IMAGE_BUFFER_POOL (gst_egl_image_buffer_pool_get_type()) -#define GST_EGL_IMAGE_BUFFER_POOL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_EGL_IMAGE_BUFFER_POOL, GstEGLImageBufferPool)) -#define GST_EGL_IMAGE_BUFFER_POOL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_EGL_IMAGE_BUFFER_POOL, GstEGLImageBufferPoolClass)) -#define GST_EGL_IS_IMAGE_BUFFER_POOL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_EGL_IMAGE_BUFFER_POOL)) -#define GST_EGL_IS_IMAGE_BUFFER_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_EGL_IMAGE_BUFFER_POOL)) -#define GST_EGL_IMAGE_BUFFER_POO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_EGL_IMAGE_BUFFER_POOL, GstEGLImageBufferPoolClass)) - -typedef struct _GstEGLImageBufferPool GstEGLImageBufferPool; -typedef struct _GstEGLImageBufferPoolClass GstEGLImageBufferPoolClass; -typedef struct _GstEGLImageBufferPoolPrivate GstEGLImageBufferPoolPrivate; - -struct _GstEGLImageBufferPool { - GstVideoBufferPool parent; - - GstEGLImageBufferPoolPrivate *priv; - - gpointer _reserved[GST_PADDING]; -}; - -struct _GstEGLImageBufferPoolClass { - GstVideoBufferPoolClass parent_class; - - gpointer _reserved[GST_PADDING]; -}; - -GType gst_egl_image_buffer_pool_get_type (void); - -typedef GstBuffer *(*GstEGLImageBufferPoolSendBlockingAllocate) (GstBufferPool * - pool, gpointer data); - -GstBufferPool *gst_egl_image_buffer_pool_new ( - GstEGLImageBufferPoolSendBlockingAllocate blocking_allocate_func, - gpointer blocking_allocate_data, GDestroyNotify destroy_func); -void gst_egl_image_buffer_pool_replace_last_buffer (GstEGLImageBufferPool * pool, GstBuffer * buffer); - -G_END_DECLS -#endif /* __GST_EGL_H__ */ diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 0015069e4e..3e53a6ee59 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am @@ -12,11 +12,6 @@ pcverfiles_uninstalled = \ gstreamer-insertbin-@GST_API_VERSION@-uninstalled.pc \ gstreamer-mpegts-@GST_API_VERSION@-uninstalled.pc -if HAVE_EGL -pcverfiles += gstreamer-egl-@GST_API_VERSION@.pc -pcverfiles_uninstalled += gstreamer-egl-@GST_API_VERSION@-uninstalled.pc -endif - if HAVE_GST_GL pcverfiles += gstreamer-gl-@GST_API_VERSION@.pc pcverfiles_uninstalled += gstreamer-gl-@GST_API_VERSION@-uninstalled.pc @@ -43,7 +38,6 @@ pcinfiles = \ gstreamer-codecparsers.pc.in gstreamer-codecparsers-uninstalled.pc.in \ gstreamer-gl.pc.in gstreamer-gl-uninstalled.pc.in \ gstreamer-insertbin.pc.in gstreamer-insertbin-uninstalled.pc.in \ - gstreamer-egl.pc.in gstreamer-egl-uninstalled.pc.in \ gstreamer-mpegts.pc.in gstreamer-mpegts-uninstalled.pc.in DISTCLEANFILES = $(pcinfiles:.in=) diff --git a/win32/common/config.h b/win32/common/config.h index fda2f55469..6365037a7a 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -205,9 +205,6 @@ /* Define to enable DVB Source (used by dvb). */ #undef HAVE_DVB -/* Define to enable eglgles sink (used by eglgles). */ -#undef HAVE_EGLGLES - /* Define to enable building of experimental plug-ins. */ #undef HAVE_EXPERIMENTAL