diff options
author | Tim-Philipp Müller <tim@centricular.com> | 2017-12-11 14:20:59 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2017-12-19 12:02:31 +0000 |
commit | ee589cd337ffaf2c4096cdaaae44c502d7ef0cd0 (patch) | |
tree | eee80e448ce75bd3be8e240fc1a8e0cb9cffbf24 | |
parent | 769a21d0bb310906b880c07da0e1e2376e11c187 (diff) |
gl: most of opengl plugin has moved to -base, keep mixer bits in -bad for now
Since they rely on GstVideoAggregator.
Fix detection of things again, and Meson
74 files changed, 42 insertions, 19162 deletions
diff --git a/configure.ac b/configure.ac index 0f3e02f7d..a1707ac03 100644 --- a/configure.ac +++ b/configure.ac @@ -1899,6 +1899,8 @@ AG_GST_CHECK_FEATURE(GL, [gl elements], gl, [ dnl HAVE_GL="yes" dnlfi ]) +dnl FIXME +AM_CONDITIONAL(USE_OPENGL, false) dnl *** gtk+ *** HAVE_GTK3_GL="no" @@ -2705,6 +2707,7 @@ ext/faad/Makefile ext/fdkaac/Makefile ext/flite/Makefile ext/fluidsynth/Makefile +ext/gl/Makefile ext/gsm/Makefile ext/hls/Makefile ext/iqa/Makefile diff --git a/ext/gl/Makefile.am b/ext/gl/Makefile.am index adeadbf60..1931af7c5 100644 --- a/ext/gl/Makefile.am +++ b/ext/gl/Makefile.am @@ -1,164 +1,52 @@ -plugin_LTLIBRARIES = libgstopengl.la +plugin_LTLIBRARIES = libgstopenglmixers.la -libgstopengl_la_SOURCES = \ +# These have to stay in -bad until we can move GstVideoAggregator to -base +libgstopenglmixers_la_SOURCES = \ gstopengl.c \ gstglbasemixer.c \ - gstgluploadelement.c \ - gstgldownloadelement.c \ - gstglcolorconvertelement.c \ - gstglfilterbin.c \ - gstglmixerbin.c \ - gstglsinkbin.c \ - gstglsrcbin.c \ - gstglimagesink.c \ - gstglfiltercube.c \ - gstgleffects.c \ - effects/gstgleffectscurves.c \ - effects/gstgleffectssources.c \ - effects/gstgleffectidentity.c \ - effects/gstgleffectmirror.c \ - effects/gstgleffectsqueeze.c \ - effects/gstgleffectstretch.c \ - effects/gstgleffectfisheye.c \ - effects/gstgleffecttwirl.c \ - effects/gstgleffectbulge.c \ - effects/gstgleffecttunnel.c \ - effects/gstgleffectsquare.c \ - effects/gstgleffectlumatocurve.c \ - effects/gstgleffectrgbtocurve.c \ - effects/gstgleffectsin.c \ - effects/gstgleffectxray.c \ - effects/gstgleffectglow.c \ - effects/gstgleffectblur.c \ - effects/gstgleffectsobel.c \ - effects/gstgleffectlaplacian.c \ - gstglcolorscale.c \ - gstglcolorbalance.c \ + gstglmosaic.c \ gstglmixer.c \ - gstglvideomixer.c \ - gstglfiltershader.c \ - gstglfilterapp.c \ - gstglviewconvert.c \ - gstglstereosplit.c \ - gstgldeinterlace.c \ + gstglmixerbin.c \ gstglstereomix.c \ - gltestsrc.c \ - gstgltestsrc.c \ - gstglutils.c + gstglutils.c \ + gstglvideomixer.c noinst_HEADERS = \ gstglbasemixer.h \ - gstgluploadelement.h \ - gstgldownloadelement.h \ - gstglcolorconvertelement.h \ - gstglfilterbin.h \ - gstglmixerbin.h \ - gstglsinkbin.h \ - gstglsrcbin.h \ - gstglimagesink.h \ - gstglfiltercube.h \ - gstgleffects.h \ - effects/gstgleffectssources.h \ - gstglcolorscale.h \ - gstglcolorbalance.h \ + gstglmosaic.h \ gstglmixer.h \ - gstglvideomixer.h \ - gstglfiltershader.h \ - gstglfilterapp.h \ - gstglstereosplit.h \ + gstglmixerbin.h \ gstglstereomix.h \ - gstgldeinterlace.h \ - gstglviewconvert.h \ - gltestsrc.h \ - gstgltestsrc.h \ - gstglutils.h + gstglutils.h \ + gstglvideomixer.h # full opengl required if USE_OPENGL -libgstopengl_la_SOURCES += \ - gstglfilterglass.c \ - gstglmosaic.c - -noinst_HEADERS += \ - gstglfilterglass.h \ - gstglmosaic.h \ - effects/gstgleffectscurves.h \ - effects/gstgleffectlumatocurve.h - -if HAVE_PNG -libgstopengl_la_SOURCES += \ - gstgldifferencematte.c - -noinst_HEADERS += \ - gstgldifferencematte.h -endif +libgstopenglmixers_la_SOURCES += gstglmosaic.c +noinst_HEADERS += gstglmosaic.h endif -if HAVE_GRAPHENE -libgstopengl_la_SOURCES += \ - gstgltransformation.c \ - gstglvideoflip.c - -noinst_HEADERS += \ - gstgltransformation.h \ - gstglvideoflip.h -endif - -if HAVE_JPEG -if HAVE_PNG -libgstopengl_la_SOURCES += \ - gstgloverlay.c - -noinst_HEADERS += \ - gstgloverlay.h -endif -endif - -if HAVE_WINDOW_COCOA -libgstopengl_la_SOURCES += \ - caopengllayersink.m - -noinst_HEADERS += \ - caopengllayersink.h -endif - -libgstopengl_la_OBJCFLAGS = \ - -I$(top_srcdir)/gst-libs \ - -I$(top_builddir)/gst-libs \ - -fobjc-arc \ - $(GST_OBJCFLAGS) \ - $(GST_BASE_CFLAGS) \ - $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_CONTROLLER_CFLAGS) \ - $(GL_OBJCFLAGS) +# FIXME: can we remove GL flags here? # check order of CFLAGS and LIBS, shouldn't the order be the other way around # (like in AM_CFLAGS)? -libgstopengl_la_CFLAGS = \ - -I$(top_srcdir)/gst-libs \ - -I$(top_builddir)/gst-libs \ - $(GST_CFLAGS) \ - $(GST_BASE_CFLAGS) \ +libgstopenglmixers_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ $(GST_CONTROLLER_CFLAGS) \ - $(GL_CFLAGS) \ - $(LIBPNG_CFLAGS) \ - $(GRAPHENE_CFLAGS) + $(GST_CFLAGS) \ + $(GL_CFLAGS) -libgstopengl_la_LIBADD = \ - $(top_builddir)/gst-libs/gst/gl/libgstgl-$(GST_API_VERSION).la \ - $(top_builddir)/gst-libs/gst/video/libgstbadvideo-$(GST_API_VERSION).la \ +libgstopenglmixers_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/video/libgstbadvideo-@GST_API_VERSION@.la \ + $(GST_PLUGINS_BASE_LIBS) \ + -lgstgl-@GST_API_VERSION@ $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \ - -lgstpbutils-$(GST_API_VERSION) \ $(GST_CONTROLLER_LIBS) \ + $(GST_LIBS) \ $(GL_LIBS) \ - $(LIBPNG_LIBS) \ - $(JPEG_LIBS) \ - $(LIBM) \ - $(GRAPHENE_LIBS) - -libgstopengl_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstopengl_la_LIBTOOLFLAGS = --tag=CC - + $(LIBM) +libgstopenglmixers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstopenglmixers_la_LIBTOOLFLAGS = --tag=CC diff --git a/ext/gl/caopengllayersink.h b/ext/gl/caopengllayersink.h deleted file mode 100644 index c2710033d..000000000 --- a/ext/gl/caopengllayersink.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 __CA_OPENGL_LAYER_SINK_H__ -#define __CA_OPENGL_LAYER_SINK_H__ - -#include <gst/gst.h> -#include <gst/video/gstvideosink.h> -#include <gst/video/video.h> - -#include <gst/gl/gl.h> -#include <gst/gl/gstglfuncs.h> -#include <gst/gl/cocoa/gstglcaopengllayer.h> - -G_BEGIN_DECLS - -#define GST_TYPE_CA_OPENGL_LAYER_SINK \ - (gst_ca_opengl_layer_sink_get_type()) -#define GST_CA_OPENGL_LAYER_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CA_OPENGL_LAYER_SINK,GstCAOpenGLLayerSink)) -#define GST_CA_OPENGL_LAYER_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CA_OPENGL_LAYER_SINK,GstCAOpenGLLayerSinkClass)) -#define GST_IS_CA_OPENGL_LAYER_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CA_OPENGL_LAYER_SINK)) -#define GST_IS_CA_OPENGL_LAYER_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CA_OPENGL_LAYER_SINK)) - -typedef struct _GstCAOpenGLLayerSink GstCAOpenGLLayerSink; -typedef struct _GstCAOpenGLLayerSinkClass GstCAOpenGLLayerSinkClass; - -struct _GstCAOpenGLLayerSink -{ - GstVideoSink video_sink; - - /* caps */ - GstVideoInfo info; - GstCaps *gl_caps; - - /* gl state */ - GstGLDisplay *display; - GstGLContext *other_context; - GstGLContext *context; - - guint next_tex; - GstBuffer *next_buffer; - GstBuffer *next_sync; - - gpointer layer; - - gboolean keep_aspect_ratio; - - /* avoid replacing the stored_buffer while drawing */ - GMutex drawing_lock; - GstBuffer *stored_buffer; - GstBuffer *stored_sync; - GLuint redisplay_texture; - - gboolean caps_change; - guint window_width; - guint window_height; - - /* gl state */ - GstGLShader *redisplay_shader; - GLuint vao; - GLuint vertex_buffer; - GLuint vbo_indices; - GLint attr_position; - GLint attr_texture; -}; - -struct _GstCAOpenGLLayerSinkClass -{ - GstVideoSinkClass video_sink_class; -}; - -GType gst_ca_opengl_layer_sink_get_type(void); -GType gst_ca_opengl_layer_sink_bin_get_type (void); - -G_END_DECLS - -#endif /* __CA_OPENGL_LAYER_SINK__ */ diff --git a/ext/gl/caopengllayersink.m b/ext/gl/caopengllayersink.m deleted file mode 100644 index 1cb72e5b9..000000000 --- a/ext/gl/caopengllayersink.m +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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-caopengllayersink - * - * caopengllayersink renders incoming video frames to CAOpenGLLayer that - * can be retrieved through the layer property and placed in the Core - * Animation render tree. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "caopengllayersink.h" -#include "gstglsinkbin.h" -#include <QuartzCore/QuartzCore.h> - -GST_DEBUG_CATEGORY (gst_debug_ca_sink); -#define GST_CAT_DEFAULT gst_debug_ca_sink - -typedef GstGLSinkBin GstCAOpenGLLayerSinkBin; -typedef GstGLSinkBinClass GstCAOpenGLLayerSinkBinClass; - -G_DEFINE_TYPE (GstCAOpenGLLayerSinkBin, gst_ca_opengl_layer_sink_bin, - GST_TYPE_GL_SINK_BIN); - -enum -{ - PROP_BIN_0, - PROP_BIN_QOS, - PROP_BIN_FORCE_ASPECT_RATIO, - PROP_BIN_LAST_SAMPLE, - PROP_BIN_LAYER, -}; - -static void -_on_notify_layer (GObject * object, GParamSpec *pspec, gpointer user_data) -{ - GstCAOpenGLLayerSinkBin *self = user_data; - - g_object_notify (G_OBJECT (self), "layer"); -} - -static void -gst_ca_opengl_layer_sink_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec) -{ - g_object_set_property (G_OBJECT (GST_GL_SINK_BIN (object)->sink), - param_spec->name, value); -} - -static void -gst_ca_opengl_layer_sink_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec) -{ - g_object_get_property (G_OBJECT (GST_GL_SINK_BIN (object)->sink), - param_spec->name, value); -} - -static void -gst_ca_opengl_layer_sink_bin_init (GstCAOpenGLLayerSinkBin * self) -{ - gpointer *sink = g_object_new (GST_TYPE_CA_OPENGL_LAYER_SINK, NULL); - - g_signal_connect (sink, "notify::layer", G_CALLBACK (_on_notify_layer), self); - - gst_gl_sink_bin_finish_init_with_element (GST_GL_SINK_BIN (self), - GST_ELEMENT (sink)); -} - -static void -gst_ca_opengl_layer_sink_bin_class_init (GstCAOpenGLLayerSinkBinClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->get_property = gst_ca_opengl_layer_sink_bin_get_property; - gobject_class->set_property = gst_ca_opengl_layer_sink_bin_set_property; - - g_object_class_install_property (gobject_class, PROP_BIN_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_BIN_LAST_SAMPLE, - g_param_spec_boxed ("last-sample", "Last Sample", - "The last sample received in the sink", GST_TYPE_SAMPLE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_BIN_LAYER, - g_param_spec_pointer ("layer", "CAOpenGLLayer", - "OpenGL Core Animation layer", - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_BIN_QOS, - g_param_spec_boolean ("qos", "Quality of Service", - "Generate Quality-of-Service events upstream", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -#define GST_CA_OPENGL_LAYER_SINK_GET_LOCK(glsink) \ - (GST_CA_OPENGL_LAYER_SINK(glsink)->drawing_lock) -#define GST_CA_OPENGL_LAYER_SINK_LOCK(glsink) \ - (g_mutex_lock(&GST_CA_OPENGL_LAYER_SINK_GET_LOCK (glsink))) -#define GST_CA_OPENGL_LAYER_SINK_UNLOCK(glsink) \ - (g_mutex_unlock(&GST_CA_OPENGL_LAYER_SINK_GET_LOCK (glsink))) - -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - -#define SUPPORTED_GL_APIS GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3 - -static void gst_ca_opengl_layer_sink_thread_init_redisplay (GstCAOpenGLLayerSink * ca_sink); -static void gst_ca_opengl_layer_sink_cleanup_glthread (GstCAOpenGLLayerSink * ca_sink); -static void gst_ca_opengl_layer_sink_on_resize (GstCAOpenGLLayerSink * ca_sink, - gint width, gint height); -static void gst_ca_opengl_layer_sink_on_draw (GstCAOpenGLLayerSink * ca_sink); - -static void gst_ca_opengl_layer_sink_finalize (GObject * object); -static void gst_ca_opengl_layer_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec); -static void gst_ca_opengl_layer_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec); - -static gboolean gst_ca_opengl_layer_sink_stop (GstBaseSink * bsink); - -static gboolean gst_ca_opengl_layer_sink_query (GstBaseSink * bsink, GstQuery * query); -static void gst_ca_opengl_layer_sink_set_context (GstElement * element, - GstContext * context); - -static GstStateChangeReturn gst_ca_opengl_layer_sink_change_state (GstElement * - element, GstStateChange transition); - -static void gst_ca_opengl_layer_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, - GstClockTime * start, GstClockTime * end); -static gboolean gst_ca_opengl_layer_sink_set_caps (GstBaseSink * bsink, GstCaps * caps); -static GstFlowReturn gst_ca_opengl_layer_sink_prepare (GstBaseSink * bsink, - GstBuffer * buf); -static GstFlowReturn gst_ca_opengl_layer_sink_show_frame (GstVideoSink * bsink, - GstBuffer * buf); -static gboolean gst_ca_opengl_layer_sink_propose_allocation (GstBaseSink * bsink, - GstQuery * query); - -static GstStaticPadTemplate gst_ca_opengl_layer_sink_template = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " - "format = (string) RGBA, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE "," - "texture-target = (string) 2D") - ); - -enum -{ - PROP_0, - PROP_FORCE_ASPECT_RATIO, - PROP_CONTEXT, - PROP_LAYER, -}; - -#define gst_ca_opengl_layer_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstCAOpenGLLayerSink, gst_ca_opengl_layer_sink, - GST_TYPE_VIDEO_SINK, GST_DEBUG_CATEGORY_INIT (gst_debug_ca_sink, - "caopengllayersink", 0, "CAOpenGLLayer Video Sink")); - -static void -gst_ca_opengl_layer_sink_class_init (GstCAOpenGLLayerSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstVideoSinkClass *gstvideosink_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstvideosink_class = (GstVideoSinkClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->set_property = gst_ca_opengl_layer_sink_set_property; - gobject_class->get_property = gst_ca_opengl_layer_sink_get_property; - - g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CONTEXT, - g_param_spec_object ("context", - "OpenGL context", - "Get OpenGL context", - GST_TYPE_GL_CONTEXT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_LAYER, - g_param_spec_pointer ("layer", "CAOpenGLLayer", - "OpenGL Core Animation layer", - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, "CAOpenGLLayer video sink", - "Sink/Video", "A video sink based on CAOpenGLLayer", - "Matthew Waters <matthew@centricular.com>"); - - gst_element_class_add_static_pad_template (element_class, &gst_ca_opengl_layer_sink_template); - - gobject_class->finalize = gst_ca_opengl_layer_sink_finalize; - - gstelement_class->change_state = gst_ca_opengl_layer_sink_change_state; - gstelement_class->set_context = gst_ca_opengl_layer_sink_set_context; - gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_ca_opengl_layer_sink_query); - gstbasesink_class->set_caps = gst_ca_opengl_layer_sink_set_caps; - gstbasesink_class->get_times = gst_ca_opengl_layer_sink_get_times; - gstbasesink_class->prepare = gst_ca_opengl_layer_sink_prepare; - gstbasesink_class->propose_allocation = gst_ca_opengl_layer_sink_propose_allocation; - gstbasesink_class->stop = gst_ca_opengl_layer_sink_stop; - - gstvideosink_class->show_frame = - GST_DEBUG_FUNCPTR (gst_ca_opengl_layer_sink_show_frame); -} - -static void -gst_ca_opengl_layer_sink_init (GstCAOpenGLLayerSink * ca_sink) -{ - ca_sink->display = NULL; - ca_sink->keep_aspect_ratio = TRUE; - ca_sink->stored_buffer = NULL; - ca_sink->redisplay_texture = 0; - - g_mutex_init (&ca_sink->drawing_lock); -} - -static void -gst_ca_opengl_layer_sink_finalize (GObject * object) -{ - GstCAOpenGLLayerSink *ca_sink; - - g_return_if_fail (GST_IS_CA_OPENGL_LAYER_SINK (object)); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (object); - - g_mutex_clear (&ca_sink->drawing_lock); - - if (ca_sink->layer) { - CFRelease(ca_sink->layer); - ca_sink->layer = NULL; - } - - GST_DEBUG ("finalized"); - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_ca_opengl_layer_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstCAOpenGLLayerSink *ca_sink; - - g_return_if_fail (GST_IS_CA_OPENGL_LAYER_SINK (object)); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - { - ca_sink->keep_aspect_ratio = g_value_get_boolean (value); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_ca_opengl_layer_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstCAOpenGLLayerSink *ca_sink; - - g_return_if_fail (GST_IS_CA_OPENGL_LAYER_SINK (object)); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, ca_sink->keep_aspect_ratio); - break; - case PROP_CONTEXT: - g_value_set_object (value, ca_sink->context); - break; - case PROP_LAYER: - g_value_set_pointer (value, ca_sink->layer); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -_create_layer (gpointer data) -{ - GstCAOpenGLLayerSink *ca_sink = data; - id layer; - - if (!ca_sink->layer) { - layer = [[NSClassFromString(@"GstGLCAOpenGLLayer") alloc] - initWithGstGLContext:ca_sink->context]; - - ca_sink->layer = (__bridge_retained gpointer)layer; - [layer setDrawCallback:(GstGLWindowCB)gst_ca_opengl_layer_sink_on_draw - data:ca_sink notify:NULL]; - [layer setResizeCallback:(GstGLWindowResizeCB)gst_ca_opengl_layer_sink_on_resize - data:ca_sink notify:NULL]; - g_object_notify (G_OBJECT (ca_sink), "layer"); - } -} - -static void -_invoke_on_main (GstGLWindowCB func, gpointer data) -{ - if ([NSThread isMainThread]) { - func (data); - } else { - dispatch_sync (dispatch_get_main_queue (), ^{ - func (data); - }); - } -} - -static gboolean -_ensure_gl_setup (GstCAOpenGLLayerSink * ca_sink) -{ - GError *error = NULL; - - if (!gst_gl_ensure_element_data (ca_sink, &ca_sink->display, - &ca_sink->other_context)) - return FALSE; - - gst_gl_display_filter_gl_api (ca_sink->display, SUPPORTED_GL_APIS); - - if (!ca_sink->context) { - if (!gst_gl_display_create_context (ca_sink->display, - ca_sink->other_context, &ca_sink->context, &error)) { - goto context_error; - } - } - - if (!ca_sink->layer) - _invoke_on_main ((GstGLWindowCB) _create_layer, ca_sink); - - return TRUE; - -context_error: - { - GST_ELEMENT_ERROR (ca_sink, RESOURCE, NOT_FOUND, ("%s", error->message), - (NULL)); - gst_object_unref (ca_sink->context); - ca_sink->context = NULL; - return FALSE; - } -} - -static gboolean -gst_ca_opengl_layer_sink_query (GstBaseSink * bsink, GstQuery * query) -{ - GstCAOpenGLLayerSink *ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) ca_sink, query, - ca_sink->display, ca_sink->context, ca_sink->other_context)) - return TRUE; - break; - } - case GST_QUERY_DRAIN: - { - GstBuffer *buf = NULL; - - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - ca_sink->redisplay_texture = 0; - buf = ca_sink->stored_buffer; - ca_sink->stored_buffer = NULL; - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - - if (buf) - gst_buffer_unref (buf); - - gst_buffer_replace (&ca_sink->next_buffer, NULL); - gst_buffer_replace (&ca_sink->next_sync, NULL); - - break; - } - default: - break; - } - - return GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); -} - -static gboolean -gst_ca_opengl_layer_sink_stop (GstBaseSink * bsink) -{ - GstCAOpenGLLayerSink *ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - - if (ca_sink->gl_caps) { - gst_caps_unref (ca_sink->gl_caps); - ca_sink->gl_caps = NULL; - } - - return TRUE; -} - -static void -gst_ca_opengl_layer_sink_set_context (GstElement * element, GstContext * context) -{ - GstCAOpenGLLayerSink *ca_sink = GST_CA_OPENGL_LAYER_SINK (element); - - gst_gl_handle_set_context (element, context, &ca_sink->display, - &ca_sink->other_context); - - if (ca_sink->display) - gst_gl_display_filter_gl_api (ca_sink->display, SUPPORTED_GL_APIS); - - GST_ELEMENT_CLASS (parent_class)->set_context (element, context); -} - -static GstStateChangeReturn -gst_ca_opengl_layer_sink_change_state (GstElement * element, GstStateChange transition) -{ - GstCAOpenGLLayerSink *ca_sink; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - GST_DEBUG ("changing state: %s => %s", - gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), - gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - _ensure_gl_setup (ca_sink); - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - 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_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - /* mark the redisplay_texture as unavailable (=0) - * to avoid drawing - */ - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - ca_sink->redisplay_texture = 0; - - gst_buffer_replace (&ca_sink->stored_sync, NULL); - - if (ca_sink->stored_buffer) { - gst_buffer_unref (ca_sink->stored_buffer); - ca_sink->stored_buffer = NULL; - } - gst_buffer_replace (&ca_sink->next_buffer, NULL); - gst_buffer_replace (&ca_sink->next_sync, NULL); - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - - GST_VIDEO_SINK_WIDTH (ca_sink) = 1; - GST_VIDEO_SINK_HEIGHT (ca_sink) = 1; - if (ca_sink->context) { - gst_object_unref (ca_sink->context); - ca_sink->context = NULL; - } - - if (ca_sink->display) { - gst_object_unref (ca_sink->display); - ca_sink->display = NULL; - } - break; - } - case GST_STATE_CHANGE_READY_TO_NULL: - if (ca_sink->layer) { - CFRelease(ca_sink->layer); - ca_sink->layer = NULL; - } - break; - default: - break; - } - - return ret; -} - -static void -gst_ca_opengl_layer_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, - GstClockTime * start, GstClockTime * end) -{ - GstCAOpenGLLayerSink *ca_sink; - - ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - *start = GST_BUFFER_TIMESTAMP (buf); - if (GST_BUFFER_DURATION_IS_VALID (buf)) - *end = *start + GST_BUFFER_DURATION (buf); - else { - if (GST_VIDEO_INFO_FPS_N (&ca_sink->info) > 0) { - *end = *start + - gst_util_uint64_scale_int (GST_SECOND, - GST_VIDEO_INFO_FPS_D (&ca_sink->info), - GST_VIDEO_INFO_FPS_N (&ca_sink->info)); - } - } - } -} - -static gboolean -gst_ca_opengl_layer_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) -{ - GstCAOpenGLLayerSink *ca_sink; - gint width; - gint height; - gboolean ok; - gint par_n, par_d; - gint display_par_n, display_par_d; - guint display_ratio_num, display_ratio_den; - GstVideoInfo vinfo; - - GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - - ok = gst_video_info_from_caps (&vinfo, caps); - if (!ok) - return FALSE; - - width = GST_VIDEO_INFO_WIDTH (&vinfo); - height = GST_VIDEO_INFO_HEIGHT (&vinfo); - - par_n = GST_VIDEO_INFO_PAR_N (&vinfo); - par_d = GST_VIDEO_INFO_PAR_D (&vinfo); - - if (!par_n) - par_n = 1; - - display_par_n = 1; - display_par_d = 1; - - ok = gst_video_calculate_display_ratio (&display_ratio_num, - &display_ratio_den, width, height, par_n, par_d, display_par_n, - display_par_d); - - if (!ok) - return FALSE; - - GST_TRACE ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, - display_par_d); - - if (height % display_ratio_den == 0) { - GST_DEBUG ("keeping video height"); - GST_VIDEO_SINK_WIDTH (ca_sink) = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - GST_VIDEO_SINK_HEIGHT (ca_sink) = height; - } else if (width % display_ratio_num == 0) { - GST_DEBUG ("keeping video width"); - GST_VIDEO_SINK_WIDTH (ca_sink) = width; - GST_VIDEO_SINK_HEIGHT (ca_sink) = (guint) - gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); - } else { - GST_DEBUG ("approximating while keeping video height"); - GST_VIDEO_SINK_WIDTH (ca_sink) = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - GST_VIDEO_SINK_HEIGHT (ca_sink) = height; - } - GST_DEBUG ("scaling to %dx%d", GST_VIDEO_SINK_WIDTH (ca_sink), - GST_VIDEO_SINK_HEIGHT (ca_sink)); - - ca_sink->info = vinfo; - if (!_ensure_gl_setup (ca_sink)) - return FALSE; - - ca_sink->caps_change = TRUE; - - return TRUE; -} - -static GstFlowReturn -gst_ca_opengl_layer_sink_prepare (GstBaseSink * bsink, GstBuffer * buf) -{ - GstCAOpenGLLayerSink *ca_sink; - GstBuffer *next_sync, *old_sync, *old_buffer; - GstVideoFrame gl_frame; - GstGLSyncMeta *sync_meta; - - ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - - GST_TRACE ("preparing buffer:%p", buf); - - if (GST_VIDEO_SINK_WIDTH (ca_sink) < 1 || - GST_VIDEO_SINK_HEIGHT (ca_sink) < 1) { - return GST_FLOW_NOT_NEGOTIATED; - } - - if (!_ensure_gl_setup (ca_sink)) - return GST_FLOW_NOT_NEGOTIATED; - - if (!gst_video_frame_map (&gl_frame, &ca_sink->info, buf, - GST_MAP_READ | GST_MAP_GL)) { - goto upload_failed; - } - - ca_sink->next_tex = *(guint *) gl_frame.data[0]; - - next_sync = gst_buffer_new (); - sync_meta = gst_buffer_add_gl_sync_meta (ca_sink->context, next_sync); - gst_gl_sync_meta_set_sync_point (sync_meta, ca_sink->context); - - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - ca_sink->next_tex = *(guint *) gl_frame.data[0]; - - old_buffer = ca_sink->next_buffer; - ca_sink->next_buffer = gst_buffer_ref (buf); - - old_sync = ca_sink->next_sync; - ca_sink->next_sync = next_sync; - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - - if (old_buffer) - gst_buffer_unref (old_buffer); - if (old_sync) - gst_buffer_unref (old_sync); - - gst_video_frame_unmap (&gl_frame); - - return GST_FLOW_OK; - -upload_failed: - { - GST_ELEMENT_ERROR (ca_sink, RESOURCE, NOT_FOUND, - ("%s", "Failed to upload buffer"), (NULL)); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_ca_opengl_layer_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) -{ - GstCAOpenGLLayerSink *ca_sink; - GstBuffer *stored_buffer, *old_sync; - - GST_TRACE ("rendering buffer:%p", buf); - - ca_sink = GST_CA_OPENGL_LAYER_SINK (vsink); - - GST_TRACE ("redisplay texture:%u of size:%ux%u, window size:%ux%u", - ca_sink->next_tex, GST_VIDEO_INFO_WIDTH (&ca_sink->info), - GST_VIDEO_INFO_HEIGHT (&ca_sink->info), - GST_VIDEO_SINK_WIDTH (ca_sink), - GST_VIDEO_SINK_HEIGHT (ca_sink)); - - /* Avoid to release the texture while drawing */ - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - ca_sink->redisplay_texture = ca_sink->next_tex; - - stored_buffer = ca_sink->stored_buffer; - ca_sink->stored_buffer = gst_buffer_ref (ca_sink->next_buffer); - - old_sync = ca_sink->stored_sync; - ca_sink->stored_sync = gst_buffer_ref (ca_sink->next_sync); - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - - /* The layer will automatically call the draw callback to draw the new - * content */ - [CATransaction begin]; - [(__bridge GstGLCAOpenGLLayer *)(ca_sink->layer) setNeedsDisplay]; - [CATransaction commit]; - - GST_TRACE ("post redisplay"); - - if (stored_buffer) - gst_buffer_unref (stored_buffer); - if (old_sync) - gst_buffer_unref (old_sync); - - return GST_FLOW_OK; -} - -static gboolean -gst_ca_opengl_layer_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstCAOpenGLLayerSink *ca_sink = GST_CA_OPENGL_LAYER_SINK (bsink); - GstBufferPool *pool = NULL; - GstStructure *config; - GstCaps *caps; - GstVideoInfo info; - guint size; - gboolean need_pool; - - if (!_ensure_gl_setup (ca_sink)) - return FALSE; - - gst_query_parse_allocation (query, &caps, &need_pool); - - if (caps == NULL) - goto no_caps; - - if (!gst_video_info_from_caps (&info, caps)) - goto invalid_caps; - - /* the normal size of a frame */ - size = info.size; - - if (need_pool) { - GST_DEBUG_OBJECT (ca_sink, "create new pool"); - - pool = gst_gl_buffer_pool_new (ca_sink->context); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - - if (!gst_buffer_pool_set_config (pool, config)) - goto config_failed; - } - - /* we need at least 2 buffer because we hold on to the last one */ - gst_query_add_allocation_pool (query, pool, size, 2, 0); - if (pool) - gst_object_unref (pool); - - if (ca_sink->context->gl_vtable->FenceSync) - gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); - - return TRUE; - - /* ERRORS */ -no_caps: - { - GST_DEBUG_OBJECT (bsink, "no caps specified"); - return FALSE; - } -invalid_caps: - { - GST_DEBUG_OBJECT (bsink, "invalid caps specified"); - return FALSE; - } -config_failed: - { - GST_DEBUG_OBJECT (bsink, "failed setting config"); - return FALSE; - } -} - -/* *INDENT-OFF* */ -static const GLfloat vertices[] = { - 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 1.0f -}; - -static const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; -/* *INDENT-ON* */ - -static void -_bind_buffer (GstCAOpenGLLayerSink * ca_sink) -{ - const GstGLFuncs *gl = ca_sink->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, ca_sink->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, ca_sink->vertex_buffer); - - /* Load the vertex position */ - gl->VertexAttribPointer (ca_sink->attr_position, 3, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) 0); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (ca_sink->attr_texture, 2, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - - gl->EnableVertexAttribArray (ca_sink->attr_position); - gl->EnableVertexAttribArray (ca_sink->attr_texture); -} - -static void -_unbind_buffer (GstCAOpenGLLayerSink * ca_sink) -{ - const GstGLFuncs *gl = ca_sink->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (ca_sink->attr_position); - gl->DisableVertexAttribArray (ca_sink->attr_texture); -} - -/* Called in the gl thread */ -static void -gst_ca_opengl_layer_sink_thread_init_redisplay (GstCAOpenGLLayerSink * ca_sink) -{ - const GstGLFuncs *gl = ca_sink->context->gl_vtable; - GError *error = NULL; - - if (!(ca_sink->redisplay_shader = gst_gl_shader_new_default (ca_sink->context, &error))) { - GST_ERROR_OBJECT (ca_sink, "Failed to link shader: %s", error->message); - gst_ca_opengl_layer_sink_cleanup_glthread (ca_sink); - return; - } - - ca_sink->attr_position = - gst_gl_shader_get_attribute_location (ca_sink->redisplay_shader, - "a_position"); - ca_sink->attr_texture = - gst_gl_shader_get_attribute_location (ca_sink->redisplay_shader, - "a_texcoord"); - - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &ca_sink->vao); - gl->BindVertexArray (ca_sink->vao); - } - - if (!ca_sink->vertex_buffer) { - gl->GenBuffers (1, &ca_sink->vertex_buffer); - gl->BindBuffer (GL_ARRAY_BUFFER, ca_sink->vertex_buffer); - gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); - } - - if (!ca_sink->vbo_indices) { - gl->GenBuffers (1, &ca_sink->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, ca_sink->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, - GL_STATIC_DRAW); - } - - if (gl->GenVertexArrays) { - _bind_buffer (ca_sink); - gl->BindVertexArray (0); - } - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); -} - -static void -gst_ca_opengl_layer_sink_cleanup_glthread (GstCAOpenGLLayerSink * ca_sink) -{ - const GstGLFuncs *gl = ca_sink->context->gl_vtable; - - if (ca_sink->redisplay_shader) { - gst_object_unref (ca_sink->redisplay_shader); - ca_sink->redisplay_shader = NULL; - } - - if (ca_sink->vao) { - gl->DeleteVertexArrays (1, &ca_sink->vao); - ca_sink->vao = 0; - } - - if (ca_sink->vbo_indices) { - gl->DeleteBuffers (1, &ca_sink->vbo_indices); - ca_sink->vbo_indices = 0; - } - - if (ca_sink->vertex_buffer) { - gl->DeleteBuffers (1, &ca_sink->vertex_buffer); - ca_sink->vertex_buffer = 0; - } -} - -static void -gst_ca_opengl_layer_sink_on_resize (GstCAOpenGLLayerSink * ca_sink, gint width, gint height) -{ - /* Here ca_sink members (ex:ca_sink->info) have a life time of set_caps. - * It means that they cannot not change between two set_caps - */ - const GstGLFuncs *gl = ca_sink->context->gl_vtable; - - GST_TRACE ("GL Window resized to %ux%u", width, height); - - width = MAX (1, width); - height = MAX (1, height); - - ca_sink->window_width = width; - ca_sink->window_height = height; - - /* default reshape */ - if (ca_sink->keep_aspect_ratio) { - GstVideoRectangle src, dst, result; - - src.x = 0; - src.y = 0; - src.w = GST_VIDEO_SINK_WIDTH (ca_sink); - src.h = GST_VIDEO_SINK_HEIGHT (ca_sink); - - dst.x = 0; - dst.y = 0; - dst.w = width; - dst.h = height; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - gl->Viewport (result.x, result.y, result.w, result.h); - } else { - gl->Viewport (0, 0, width, height); - } -} - -static void -gst_ca_opengl_layer_sink_on_draw (GstCAOpenGLLayerSink * ca_sink) -{ - /* Here ca_sink members (ex:ca_sink->info) have a life time of set_caps. - * It means that they cannot not change between two set_caps as well as - * for the redisplay_texture size. - * Whereas redisplay_texture id changes every sink_render - */ - - const GstGLFuncs *gl = NULL; - GstGLSyncMeta *sync_meta; - - g_return_if_fail (GST_IS_CA_OPENGL_LAYER_SINK (ca_sink)); - - gl = ca_sink->context->gl_vtable; - - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - - if (G_UNLIKELY (!ca_sink->redisplay_shader)) { - gst_ca_opengl_layer_sink_thread_init_redisplay (ca_sink); - } - - /* check if texture is ready for being drawn */ - if (!ca_sink->redisplay_texture) { - gl->ClearColor (0.0f, 0.0f, 0.0f, 1.0f); - gl->Clear (GL_COLOR_BUFFER_BIT); - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - return; - } - - /* opengl scene */ - GST_TRACE ("redrawing texture:%u", ca_sink->redisplay_texture); - - if (ca_sink->caps_change) { - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); - gst_ca_opengl_layer_sink_on_resize (ca_sink, ca_sink->window_width, - ca_sink->window_height); - GST_CA_OPENGL_LAYER_SINK_LOCK (ca_sink); - ca_sink->caps_change = FALSE; - } - - sync_meta = gst_buffer_get_gl_sync_meta (ca_sink->stored_sync); - if (sync_meta) - gst_gl_sync_meta_wait (sync_meta, gst_gl_context_get_current ()); - - gl->BindTexture (GL_TEXTURE_2D, 0); - - gl->ClearColor (0.0, 0.0, 0.0, 0.0); - gl->Clear (GL_COLOR_BUFFER_BIT); - - gst_gl_shader_use (ca_sink->redisplay_shader); - - if (gl->GenVertexArrays) - gl->BindVertexArray (ca_sink->vao); - _bind_buffer (ca_sink); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, ca_sink->redisplay_texture); - gst_gl_shader_set_uniform_1i (ca_sink->redisplay_shader, "tex", 0); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (ca_sink); - - /* end default opengl scene */ - GST_CA_OPENGL_LAYER_SINK_UNLOCK (ca_sink); -} diff --git a/ext/gl/effects/gstgleffectblur.c b/ext/gl/effects/gstgleffectblur.c deleted file mode 100644 index 074519ad4..000000000 --- a/ext/gl/effects/gstgleffectblur.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -static float * -gst_gl_effects_blur_kernel (void) -{ - /* gaussian kernel (well, actually vector), size 9, standard - * deviation 3.0 */ - /* FIXME: make this a runtime property */ - static gfloat *kernel = NULL; - if (G_UNLIKELY (NULL == kernel)) { - /* 3x3 matrix */ - kernel = g_malloc (sizeof (gfloat) * 9); - fill_gaussian_kernel (kernel, 7, 3.f); - } - return kernel; -} - -void -gst_gl_effects_blur (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "hconv0", - hconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "gauss_width", - GST_VIDEO_INFO_WIDTH (&filter->in_info)); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, - gst_gl_effects_blur_kernel ()); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->midtexture[0], shader); - - shader = gst_gl_effects_get_fragment_shader (effects, "vconv0", - vconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "gauss_height", - GST_VIDEO_INFO_HEIGHT (&filter->in_info)); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, - gst_gl_effects_blur_kernel ()); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[0], - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectbulge.c b/ext/gl/effects/gstgleffectbulge.c deleted file mode 100644 index d2a9a14cb..000000000 --- a/ext/gl/effects/gstgleffectbulge.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_bulge (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "bulge", - bulge_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectfisheye.c b/ext/gl/effects/gstgleffectfisheye.c deleted file mode 100644 index fe3ebdcde..000000000 --- a/ext/gl/effects/gstgleffectfisheye.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_fisheye (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "fisheye", - fisheye_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectglow.c b/ext/gl/effects/gstgleffectglow.c deleted file mode 100644 index 6309ce774..000000000 --- a/ext/gl/effects/gstgleffectglow.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -static gboolean kernel_ready = FALSE; -static float gauss_kernel[7]; - -void -gst_gl_effects_glow (GstGLEffects * effects) -{ - const GstGLFuncs *gl = GST_GL_BASE_FILTER (effects)->context->gl_vtable; - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - if (!kernel_ready) { - fill_gaussian_kernel (gauss_kernel, 7, 10.0); - kernel_ready = TRUE; - } - - /* threshold */ - shader = gst_gl_effects_get_fragment_shader (effects, "luma_threshold", - luma_threshold_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->midtexture[0], shader); - - /* blur */ - shader = gst_gl_effects_get_fragment_shader (effects, "hconv7", - hconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "gauss_width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[0], - effects->midtexture[1], shader); - - shader = gst_gl_effects_get_fragment_shader (effects, "vconv7", - vconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 7, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "gauss_height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[1], - effects->midtexture[2], shader); - - /* add blurred luma to intexture */ - shader = gst_gl_effects_get_fragment_shader (effects, "sum", - sum_fragment_source_gles2); - gst_gl_shader_use (shader); - - gl->ActiveTexture (GL_TEXTURE2); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (effects->intexture)); - - gst_gl_shader_set_uniform_1f (shader, "alpha", 1.0f); - gst_gl_shader_set_uniform_1i (shader, "base", 2); - - gl->ActiveTexture (GL_TEXTURE1); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (effects->midtexture[2])); - - gst_gl_shader_set_uniform_1f (shader, "beta", (gfloat) 1 / 3.5f); - gst_gl_shader_set_uniform_1i (shader, "blend", 1); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[2], - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectidentity.c b/ext/gl/effects/gstgleffectidentity.c deleted file mode 100644 index b81c32df2..000000000 --- a/ext/gl/effects/gstgleffectidentity.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_identity (GstGLEffects * effects) -{ - GstGLContext *context = GST_GL_BASE_FILTER (effects)->context; - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = g_hash_table_lookup (effects->shaderstable, "identity0"); - if (!shader) { - GError *error = NULL; - - if (!(shader = gst_gl_shader_new_default (context, &error))) { - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("Failed to initialize identity shader: %s", error->message), (NULL)); - return; - } - - g_hash_table_insert (effects->shaderstable, (gchar *) "identity0", shader); - } - gst_gl_shader_use (shader); - - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectlaplacian.c b/ext/gl/effects/gstgleffectlaplacian.c deleted file mode 100644 index 4652b0fe5..000000000 --- a/ext/gl/effects/gstgleffectlaplacian.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com> - * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -static gfloat kernel[9] = { - 0.0, -1.0, 0.0, - -1.0, 4.0, -1.0, - 0.0, -1.0, 0.0 -}; - -void -gst_gl_effects_laplacian (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "conv0", - conv9_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->in_info)); - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->in_info)); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, kernel); - gst_gl_shader_set_uniform_1i (shader, "invert", effects->invert); - - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectlumatocurve.c b/ext/gl/effects/gstgleffectlumatocurve.c deleted file mode 100644 index a9c2a5b31..000000000 --- a/ext/gl/effects/gstgleffectlumatocurve.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" -#include "gstgleffectlumatocurve.h" - -void -gst_gl_effects_luma_to_curve (GstGLEffects * effects, - const GstGLEffectsCurve * curve, gint curve_index, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLContext *context = GST_GL_BASE_FILTER (effects)->context; - GstGLFilter *filter = GST_GL_FILTER (effects); - const GstGLFuncs *gl = context->gl_vtable; - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "luma_to_curve", - luma_to_curve_fragment_source_gles2); - - if (!shader) - return; - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - } -#endif - - if (effects->curve[curve_index] == 0) { - /* this parameters are needed to have a right, predictable, mapping */ - gl->GenTextures (1, &effects->curve[curve_index]); - - gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB, - curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); - } - - gst_gl_shader_use (shader); - gl->ActiveTexture (GL_TEXTURE2); - gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); - - gst_gl_shader_set_uniform_1i (shader, "curve", 2); - - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, shader); -} - -void -gst_gl_effects_heat (GstGLEffects * effects) -{ - gst_gl_effects_luma_to_curve (effects, &heat_curve, - GST_GL_EFFECTS_CURVE_HEAT, effects->intexture, effects->outtexture); -} - -void -gst_gl_effects_sepia (GstGLEffects * effects) -{ - gst_gl_effects_luma_to_curve (effects, &sepia_curve, - GST_GL_EFFECTS_CURVE_SEPIA, effects->intexture, effects->outtexture); -} - -void -gst_gl_effects_luma_xpro (GstGLEffects * effects) -{ - gst_gl_effects_luma_to_curve (effects, &luma_xpro_curve, - GST_GL_EFFECTS_CURVE_LUMA_XPRO, effects->intexture, effects->outtexture); -} diff --git a/ext/gl/effects/gstgleffectlumatocurve.h b/ext/gl/effects/gstgleffectlumatocurve.h deleted file mode 100644 index f90577f38..000000000 --- a/ext/gl/effects/gstgleffectlumatocurve.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_LUMA_TO_CURVE_H__ -#define __GST_GL_LUMA_TO_CURVE_H__ - -#include "gstgleffectscurves.h" - -G_BEGIN_DECLS - -void gst_gl_effects_luma_to_curve (GstGLEffects *effects, - const GstGLEffectsCurve *curve, - gint curve_index, - GstGLMemory *in_tex, - GstGLMemory *out_tex); -G_END_DECLS - -#endif /* __GST_GL_LUMA_TO_CURVE_H__ */ diff --git a/ext/gl/effects/gstgleffectmirror.c b/ext/gl/effects/gstgleffectmirror.c deleted file mode 100644 index a25d8745d..000000000 --- a/ext/gl/effects/gstgleffectmirror.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_mirror (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "mirror", - mirror_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectrgbtocurve.c b/ext/gl/effects/gstgleffectrgbtocurve.c deleted file mode 100644 index 5bead68e4..000000000 --- a/ext/gl/effects/gstgleffectrgbtocurve.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" -#include "gstgleffectscurves.h" - -static void -gst_gl_effects_rgb_to_curve (GstGLEffects * effects, - const GstGLEffectsCurve * curve, gint curve_index, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLContext *context = GST_GL_BASE_FILTER (effects)->context; - GstGLFilter *filter = GST_GL_FILTER (effects); - const GstGLFuncs *gl = context->gl_vtable; - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "rgb_to_curve", - rgb_to_curve_fragment_source_gles2); - - if (!shader) - return; - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - } -#endif - - if (effects->curve[curve_index] == 0) { - /* this parameters are needed to have a right, predictable, mapping */ - gl->GenTextures (1, &effects->curve[curve_index]); - - gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGB, - curve->width, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, curve->pixel_data); - } - - gst_gl_shader_use (shader); - gl->ActiveTexture (GL_TEXTURE2); - gl->BindTexture (GL_TEXTURE_2D, effects->curve[curve_index]); - - gst_gl_shader_set_uniform_1i (shader, "curve", 2); - - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, shader); -} - -void -gst_gl_effects_xpro (GstGLEffects * effects) -{ - gst_gl_effects_rgb_to_curve (effects, &xpro_curve, GST_GL_EFFECTS_CURVE_XPRO, - effects->intexture, effects->outtexture); -} diff --git a/ext/gl/effects/gstgleffectscurves.c b/ext/gl/effects/gstgleffectscurves.c deleted file mode 100644 index d16361bea..000000000 --- a/ext/gl/effects/gstgleffectscurves.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "gstgleffectscurves.h" - -/* CURVE for the heat signature effect */ -const GstGLEffectsCurve xpro_curve = { - 256, 1, 3, - "\0\0\37\0\0\37\0\1\40\0\2!\0\2\"\0\3\"\1\4%\1\4%\1\5%\1\5'\1\7'\1\7(\1\7" - "(\1\10*\1\11+\1\11,\1\12,\1\13/\1\14/\1\14" "1\2\15" "1\2\15" "1\2\16" - "4\2\17" "" "4\3\17" "5\3\22" "7\3\22" "7\3\23" "8\3\24" - "9\3\25;\3\26;\3\27<\3\27=\4\31" - "=\4\33?\4\34@\5\34B\5\35C\5\36D\5\40D\5\40G\5!G\6\"H\6$H\7&J\7&K\7*M\7*M" - "\10+N\10-P\11-P\11/R\11" "3R\11" "3T\12" "4U\12" "5U\13" "7W\14" "8Y\14" - "9Y\14" - "<Y\16=[\16@^\16@^\17C^\17D`\20F`\20Jb\22Jb\22Kc\23Me\24Nf\25Qg\26Rg\27Ti" - "\27Wj\30Xl\31Yl\33\\m\34^p\35`p\40bp\40fq!fr$gt$lt%lu'mv(px*qy-ty/uz/x|0" - "y}3|}4}~5\177\2018\203\2019\203\201;\204\202=\207\203?\210\204@\214\204C" - "\214\206D\216\207G\217\210H\223\211K\223\211M\225\212P\226\214Q\231\215T" - "\232\215U\234\216X\235\217Y\240\220\\\241\220^\243\221`\244\223b\246\224" - "e\250\224f\252\225i\253\226l\255\227m\256\231p\261\231q\262\232t\264\233" - "v\265\234x\267\234z\270\235|\271\236~\274\240\201\275\240\202\277\241\204" - "\300\242\207\302\243\210\303\243\212\305\244\214\306\245\216\307\246\220" - "\311\250\221\313\250\224\315\251\226\316\252\227\317\253\232\321\253\234" - "\322\254\235\323\255\240\325\256\242\326\256\242\330\256\245\331\261\250" - "\331\262\251\332\262\253\334\263\255\335\264\256\336\265\261\340\266\263" - "\341\266\264\342\267\266\343\270\270\344\271\271\344\271\271\346\273\276" - "\347\274\277\350\275\277\351\275\302\352\276\304\353\277\306\353\300\307" - "\355\300\311\356\301\314\356\302\315\357\303\317\360\304\320\360\304\322" - "\361\305\323\362\306\325\362\307\327\363\307\330\363\310\330\364\311\333" - "\364\313\334\365\313\336\365\314\340\365\314\342\366\316\342\366\316\346" - "\367\317\347\367\320\351\367\320\353\370\322\354\370\322\356\370\323\356" - "\370\324\360\371\325\360\371\325\363\371\326\363\371\327\363\372\330\365" - "\372\330\366\372\331\366\372\331\370\372\332\371\373\332\371\373\333\372" - "\373\334\373\373\335\373\373\336\374\373\336\374\374\337\374\374\340\375" - "\374\341\375\374\341\376\374\342\376\374\343\376\374\344\376\374\344\377" - "\374\345\377\374\346\377\375\346\377\375\346\377\375\347\377\375\350\377" - "\375\351\377\375\352\377\375\352\377\375\352\377\375\353\377\375\353\377" - "\376\354\377\376\354\377\376\356\377\376\356\377\376\356\377\376\357\377" - "\376\360\377\376\360\377\376\360\377\376\360\377\376\362\377\376\362\377" - "\376\363\377\376\363\377\376\363\377\376\363\377\376\364\377\376\364\377" - "\376\365\377\377\365\377\377\366\377\377\366\377\377\366\377\377\367\377" - "\377\367\377\377\367\377\377\370", -}; - -const GstGLEffectsCurve luma_xpro_curve = { - 256, 1, 3, - "\0\0\1\0\1\1\0\1\2\0\1\2\0\1\2\0\1\2\0\1\3\0\2\3\0\2\4\0\2\4\0\2\5\0\2\6" - "\0\3\6\0\3\6\0\3\7\0\3\10\0\4\10\0\4\11\0\4\12\0\4\12\1\4\13\1\5\14\1\5\15" - "\1\5\15\1\5\16\1\5\17\1\6\17\1\6\20\1\7\21\1\7\23\2\10\23\2\10\24\2\10\24" - "\2\11\26\2\11\27\2\11\30\3\11\31\3\12\31\3\13\32\3\13\33\4\13\34\4\14\35" - "\4\14\36\4\15\37\5\15\40\5\15\"\6\16#\6\17#\6\20$\7\20%\7\20%\10\21&\10\22" - "'\10\22)\11\24*\11\24*\12\24+\12\26.\13\26.\14\27.\14\30/\15\31" - "1\15\31" "" "2\16\32" "3\16\33" "3\20\33" "5\20\35" "6\20\36" "7\22\37" - "7\23\"9\23#9\24$" ":\25$<\27&<\27'=\31'?\31)?\32*@\35+B\35-C\36.C\37" - "1E\"2F#3H$5H&6I'7I)7K" - "+:M-<N-<N1@N1BQ2BQ6CQ6EU7HU<IU=IV@NX@NXBQZCS[FU[HU]IV_MZ_N[_Q]`S_bU`dXbe" - "Zbe]gg]ig`ji`jjdljenlgpljqnpwppwpqxqszqw|sx}u|\201u}\203w\177\204x\177\206" - "x\204\210x\204\212z\212\213|\212\217}\217\221}\221\222}\222\224\177\226\224" - "\201\226\226\203\230\233\203\235\235\204\236\235\204\236\236\210\244\242" - "\210\244\242\210\245\244\212\251\245\213\252\251\213\254\252\215\257\254" - "\215\261\256\217\261\257\221\266\261\221\267\261\222\273\264\224\273\267" - "\224\274\267\224\276\273\230\301\273\230\302\274\231\304\276\231\307\302" - "\233\312\302\235\312\304\235\314\306\236\316\307\240\320\311\240\321\314" - "\242\324\315\242\325\316\244\327\320\245\332\321\245\333\321\245\334\323" - "\251\335\325\251\335\330\252\341\332\254\341\332\256\344\334\256\346\334" - "\256\347\337\257\347\340\261\350\340\263\351\342\263\352\344\264\354\345" - "\266\355\346\266\356\347\267\357\350\271\360\351\273\361\352\273\362\352" - "\274\362\355\276\364\356\277\364\357\277\365\360\277\365\360\302\366\361" - "\302\367\361\304\370\363\304\370\363\307\370\364\307\371\364\311\371\366" - "\312\372\367\312\372\367\314\372\367\316\373\370\316\373\370\320\373\371" - "\320\374\371\321\374\372\323\374\372\324\375\372\325\375\372\325\375\373" - "\327\375\373\330\375\374\332\375\374\333\375\375\334\376\375\334\376\375" - "\335\376\375\337\376\375\337\376\375\340\376\376\342\376\376\344\376\376" - "\344\376\376\345\376\376\346\376\376\347\376\376\350\377\376\351\377\377" - "\353\377\377\354\377\377\356\377\377\357\377\377\361\377\377\361\377\377" - "\361\377\377\364\377\377\365\377\377\366\377\377\367\377\377\367\377\377" - "\371\377\377\371\377\377\372\377\377\373\377\377\373\377\377\374\377\377" - "\375\377\377\375\377\377\375\377\377\376", -}; - -/* CURVE for the heat signature effect */ -const GstGLEffectsCurve heat_curve = { - 256, 1, 3, - "\0\0\0\0\0\0\0\1\0\0\1\0\0\1\1\0\2\1\0\2\1\1\2\1\1\2\2\1\2\2\1\3\2\1\3\3" - "\1\3\3\1\4\3\1\4\4\1\5\4\1\5\5\2\5\6\2\6\6\2\6\7\2\6\7\2\7\7\2\7\11\2\10" - "\11\2\10\12\3\11\13\3\11\13\3\11\14\3\12\15\3\12\17\3\13\17\3\14\20\3\14" - "\22\4\15\23\4\16\24\4\16\26\4\16\27\4\17\31\4\20\34\4\21\34\5\21\40\5\22" - "\40\5\22$\5\23$\5\25&\6\25(\6\26-\6\26-\6\27" "0\6\31" "2\7\31" - "5\7\32;\7\34" - ";\7\34?\10\35C\10\36G\10\37L\10\40V\11!V\11\"[\11$a\11&l\12&l\12'r\12(~\13" - "*~\13,\204\14,\213\14.\221\14/\227\14" "1\236\15" "2\244\15" "4\252\15" - "5\260" "\16" "7\267\16" - "8\275\17:\302\17;\310\17=\323\20?\323\21@\330\21D\335\21D" - "\342\22E\346\22I\353\23I\356\23K\362\24M\365\24N\370\25P\372\26R\374\26T" - "\376\26V\377\27X\377\27Z\377\30\\\376\31`\376\31`\375\32b\373\32d\371\33" - "f\366\34j\363\34j\360\35l\354\36n\350\36r\344\37r\337\40t\333\40w\326!y\321" - "\"|\314#~\307$\201\301$\204\267%\207\267&\212\261'\214\254(\217\247(\222" - "\241)\226\234*\231\227+\234\222,\237\216-\242\211.\245\205/\251\2010\254" - "}1\257z2\262w3\266t4\271p5\274m6\277j7\302f8\305c9\310`:\314\\;\317Y<\321" - "V>\324S?\327P@\332LA\335IB\337FC\342CE\344@F\347=G\351;I\3538I\3558M\357" - "3P\3610S\363.V\365+Y\366)\\\370'`\371%d\372#g\373\"l\374\40p\374\37t\374" - "\35t\375\34}\376\33\202\376\32\202\375\31\213\375\30\220\375\27\225\375\27" - "\232\373\26\237\372\25\244\371\24\251\370\23\256\367\23\262\367\22\267\364" - "\21\274\362\20\300\361\20\305\357\17\311\355\16\311\353\16\322\351\15\326" - "\346\15\332\346\14\336\344\14\341\337\13\341\335\13\350\332\12\353\330\11" - "\356\330\11\360\322\10\362\320\10\364\320\10\364\312\7\366\307\7\366\304" - "\7\367\302\6\367\277\6\370\274\5\367\271\5\367\271\5\367\263\4\365\260\4" - "\364\255\4\363\253\3\362\250\3\361\245\3\360\242\3\357\240\3\357\235\2\355" - "\232\2\355\227\2\354\225\2\353\221\1\353\216\1\353\216\1\353\213\1\353\204" - "\1\353\201\1\354}\1\354y\0\354v\0\355r\0\355n\0\355j\0\356f\0\356b\0\357" - "_\0\357[\0\357W\0\357S\0\360O\0\360O\0\361K\0\361C\0\362@\0\363<\0\3638\0" - "\3648\0\3641\0\365.\0\366+\0\366'\0\367'\0\370!\0\370\36\0\370\33\0\371\30" - "\0\371\26\0\373\26\0\373\23\0\374\15\0\374\13\0\375\10\0\375\5\0\376\3\0", -}; - -const GstGLEffectsCurve sepia_curve = { - 256, 1, 3, - "\0\0\0\0\0\0\0\0\0\0\1\0\1\1\0\1\1\0\1\1\1\2\1\1\2\2\1\3\2\1\3\2\1\3\2\1" - "\4\3\2\4\3\2\4\3\2\6\4\2\6\4\2\6\4\2\7\5\2\7\5\3\11\6\3\11\6\3\12\7\3\13" - "\10\3\15\10\4\16\11\4\17\11\4\21\12\4\22\13\4\22\13\5\23\14\5\24\15\5\26" - "\16\6\31\20\6\31\21\6\32\22\7\34\22\7\35\23\7\40\24\10\40\26\10!\26\11#\30" - "\11&\31\12&\32\12'\34\13)\34\13*\37\13,\37\13-\40\14.\"\15" "0\"\15" - "2#\17" "" "3&\17" "4&\17" "5'\20" "8(\21" - "9)\21:*\23<,\23=-\23A.\24A0\25B0\25C2\26D3" - "\30H4\30H7\31K7\32K8\32L9\33M:\34P<\34Q=\35S>\37T?\37UA\40VB!XC!ZD#\\F#^" - "G#^J$`J&bK'bM'eM(fO)gP)iQ*kS,mT-mU-nV.oX/rY0sZ2u]2v]3w^3x`4za5{c7|c8~e8\177" - "f9\200i:\203i<\204j<\206k=\207m>\210n?\211o?\213qA\214rC\215sC\217uD\220" - "vD\221wF\223xG\224zH\225{J\227|K\230~K\231\177L\232\200M\234\202O\235\203" - "P\236\204Q\240\206Q\241\207S\242\210T\243\211U\245\213V\246\214X\247\215" - "Y\250\217Y\252\220Z\253\221\\\254\223]\254\224^\255\225`\257\227a\260\230" - "b\261\231c\262\232e\264\234e\265\235f\266\236g\267\240i\267\241i\272\242" - "k\273\243m\274\245n\274\246o\276\247q\277\250r\300\252s\301\253u\302\254" - "v\304\255w\305\257x\306\257z\306\261{\307\262|\310\264~\310\265\177\313\266" - "\200\314\267\202\315\267\203\316\272\204\317\273\206\317\274\207\320\276" - "\210\322\277\211\323\277\213\324\301\214\325\302\215\326\304\217\326\305" - "\220\327\306\221\327\307\223\331\310\224\333\311\225\334\311\227\334\313" - "\227\335\315\231\335\316\231\337\317\234\340\320\235\341\320\235\341\323" - "\240\342\324\241\343\324\242\343\326\243\345\327\245\345\330\245\346\331" - "\250\346\333\252\347\334\253\351\335\254\351\335\255\351\337\257\352\340" - "\260\353\341\260\354\342\262\355\343\264\355\344\265\355\345\266\356\346" - "\266\356\347\272\357\350\273\360\351\274\360\351\276\361\352\277\361\353" - "\300\362\353\301\362\354\302\362\355\304\362\356\305\364\357\305\364\357" - "\310\364\360\311\365\361\313\365\361\314\366\362\315\366\362\316\366\363" - "\316\367\364\320\367\364\320\367\365\324\367\365\324\370\366\326\370\366" - "\327\371\366\330\371\367\331\371\367\333\371\370\333\372\370\336\372\370" - "\336\372\371\340\373\371\341\373\372\342\373\372\343\374\372\344\374\373" - "\344\374\373\347\374\374\350\375\374\351\375\374\351\375\374\352\375\375" - "\352\376\375\353\376\376\355\376\376\356\376\376\357\377\377\357", -}; - -const GstGLEffectsCurve xray_curve = { - 256, 1, 3, - "\377\377\377\377\377\377\376\376\376\375\375\376\374\375\375\373\374\375" - "\372\374\374\371\374\374\370\373\373\366\373\372\366\372\372\365\372\371" - "\363\371\371\363\371\370\362\370\370\360\370\367\360\367\366\357\367\365" - "\356\366\365\355\366\364\353\365\363\353\365\363\352\364\362\351\363\362" - "\347\363\361\346\362\361\345\362\361\344\362\360\343\361\357\343\361\356" - "\342\360\356\341\360\356\340\357\355\336\356\354\336\356\354\335\355\353" - "\334\355\353\333\355\352\331\354\351\331\353\351\330\353\350\327\353\350" - "\325\352\347\325\351\347\324\350\346\323\350\345\322\347\344\321\347\344" - "\320\347\344\317\346\343\316\346\342\315\345\341\314\344\341\313\344\340" - "\312\344\340\311\343\337\310\342\337\307\342\335\306\341\335\305\341\335" - "\303\340\334\303\337\333\302\337\333\301\337\332\300\336\331\276\335\331" - "\276\334\330\274\334\330\274\334\327\273\333\327\272\333\326\271\332\325" - "\270\332\325\267\331\324\266\330\323\265\330\323\264\327\322\263\327\321" - "\262\326\320\261\325\320\257\325\317\257\324\317\256\324\316\254\323\315" - "\254\322\315\253\322\314\252\321\313\251\321\313\250\320\312\246\317\311" - "\245\317\311\245\316\310\244\316\307\243\315\307\242\314\306\241\314\305" - "\240\312\305\237\312\304\236\312\303\235\311\303\234\311\302\233\307\301" - "\232\307\300\231\307\300\230\306\277\227\305\276\226\305\276\225\304\275" - "\224\303\274\223\303\273\222\302\273\221\301\272\220\301\271\217\300\270" - "\216\277\270\215\277\267\214\276\266\213\275\265\212\275\265\211\274\264" - "\210\273\263\207\273\262\206\272\262\205\271\261\204\270\260\203\270\257" - "\202\267\257\201\266\256\200\266\255\177\265\254~\264\253}\263\253|\263\252" - "{\262\251z\261\250y\260\247x\260\247w\257\246v\256\245u\255\244t\255\243" - "s\254\243r\253\242q\252\241p\252\240o\251\237n\250\236m\247\235l\246\235" - "l\246\235j\245\233i\244\232h\243\231g\242\230f\242\227e\241\226d\240\226" - "c\237\225b\236\224a\235\223`\234\222_\234\221_\233\220]\232\217\\\231\216" - "\\\230\215Z\227\214Y\226\214X\226\213W\225\212V\224\211U\223\210T\222\207" - "S\221\206R\221\205Q\217\204P\216\203O\215\202N\215\201M\214\200M\213\177" - "K\212~J\211}I\211|H\210|G\206zG\205zE\204xD\203vC\203vB\201tA\200s@\200q" - "@~p>}o>|o<{l<yk;xi9wh8wg8te6sd5qd4pa3n_2m]1k\\0j\\0hY.fW-dU,cT+aR*_P)_O(" - "]M'YK'XI%VI$TF$RD\"OB!M@\40K?\37I=\37G=\35E9\34C9\34A5\33>5\31<2\31<0\27" - ":.\27" "5,\26" "3*\24" - "1*\23.&\22.&\22*\"\21'\40\17%\36\16\"\34\15\"\32\14" - "\36\32\13\33\26\13\31\24\11\26\22\11\24\20\7\24\16\6\21\16\5\14\14\4\12\10" - "\3\7\6\3\5\4\1\2\2", -}; diff --git a/ext/gl/effects/gstgleffectscurves.h b/ext/gl/effects/gstgleffectscurves.h deleted file mode 100644 index 9b566a50e..000000000 --- a/ext/gl/effects/gstgleffectscurves.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_EFFECTS_TEXTURES_H__ -#define __GST_GL_EFFECTS_TEXTURES_H__ - -#include <glib.h> - -struct _GstGLEffectsCurve { - guint width; - guint height; - guint bytes_per_pixel; /* 3:RGB */ - guint8 pixel_data[256 * 1 * 3 + 1]; -}; - -typedef struct _GstGLEffectsCurve GstGLEffectsCurve; - -/* CURVE for the heat signature effect */ -extern const GstGLEffectsCurve xpro_curve; - -extern const GstGLEffectsCurve luma_xpro_curve; - -/* CURVE for the heat signature effect */ -extern const GstGLEffectsCurve heat_curve; - -extern const GstGLEffectsCurve sepia_curve; - -extern const GstGLEffectsCurve xray_curve; - -#endif diff --git a/ext/gl/effects/gstgleffectsin.c b/ext/gl/effects/gstgleffectsin.c deleted file mode 100644 index 24b66132e..000000000 --- a/ext/gl/effects/gstgleffectsin.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_sin (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "sin", - sin_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectsobel.c b/ext/gl/effects/gstgleffectsobel.c deleted file mode 100644 index 4fbe60f15..000000000 --- a/ext/gl/effects/gstgleffectsobel.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008-2010 Filippo Argiolas <filippo.argiolas@gmail.com> - * Copyright (C) 2015 Michał Dębski <debski.mi.zd@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_sobel (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "desat0", - desaturate_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->midtexture[0], shader); - - shader = gst_gl_effects_get_fragment_shader (effects, "hconv0", - sep_sobel_hconv3_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[0], - effects->midtexture[1], shader); - - shader = gst_gl_effects_get_fragment_shader (effects, "vconv0", - sep_sobel_vconv3_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[1], - effects->midtexture[0], shader); - - shader = gst_gl_effects_get_fragment_shader (effects, "len0", - sep_sobel_length_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1i (shader, "invert", effects->invert); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[0], - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectsquare.c b/ext/gl/effects/gstgleffectsquare.c deleted file mode 100644 index 911d30fdf..000000000 --- a/ext/gl/effects/gstgleffectsquare.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_square (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "square", - square_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectsqueeze.c b/ext/gl/effects/gstgleffectsqueeze.c deleted file mode 100644 index 1999978d6..000000000 --- a/ext/gl/effects/gstgleffectsqueeze.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_squeeze (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "squeeze", - squeeze_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectssources.c b/ext/gl/effects/gstgleffectssources.c deleted file mode 100644 index b83e1d7cc..000000000 --- a/ext/gl/effects/gstgleffectssources.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gl/gstglconfig.h> - -#include "../gstgleffects.h" -#include "gstgleffectssources.h" -#include <math.h> - -/* A common file for sources is needed since shader sources can be - * generic and reused by several effects */ - -/* FIXME */ -/* Move sooner or later into single .frag .vert files and either bake - * them into a c file at compile time or load them at run time */ - - -/* fill a normalized and zero centered gaussian vector for separable - * gaussian convolution */ - -void -fill_gaussian_kernel (float *kernel, int size, float sigma) -{ - int i; - float sum; - int l; - - /* need an odd sized vector to center it at zero */ - g_return_if_fail ((size % 2) != 0); - - sum = 0.0; - l = (size - 1) / 2; - - for (i = 0; i < size; i++) { - kernel[i] = expf (-0.5 * pow ((i - l) / sigma, 2.0)); - sum += kernel[i]; - } - - for (i = 0; i < size; i++) { - kernel[i] /= sum; - } -} - -/* *INDENT-OFF* */ - -/* Mirror effect */ -const gchar *mirror_fragment_source_opengl = - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = gl_TexCoord[0].xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " normcoord.x *= sign (normcoord.x);" - " texturecoord = normcoord + 0.5;" - " vec4 color = texture2D (tex, texturecoord);" - " gl_FragColor = color * gl_Color;" - "}"; - -const gchar *mirror_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " float normcoord = texturecoord.x - 0.5;" - " normcoord *= sign (normcoord);" - " texturecoord.x = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *squeeze_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord = texturecoord - 0.5;" - /* Add a very small value to length otherwise it could be 0 */ - " float r = length (normcoord)+0.01;" - " r = pow(r, 0.40)*1.3;" - " normcoord = normcoord / r;" - " texturecoord = (normcoord + 0.5);" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *stretch_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " float r = length (normcoord);" - " normcoord *= 2.0 - smoothstep(0.0, 0.35, r);" - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *tunnel_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - /* little trick with normalized coords to obtain a circle with - * rect textures */ - " normcoord = (texturecoord - 0.5);" - " float r = length(normcoord);" - " if (r > 0.0)" - " normcoord *= clamp (r, 0.0, 0.275) / r;" - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *fisheye_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " float r = length (normcoord);" - " normcoord *= r * 1.41421;" /* sqrt (2) */ - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *twirl_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " float r = length (normcoord);" - /* calculate rotation angle: maximum (about pi/2) at the origin and - * gradually decrease it up to 0.6 of each quadrant */ - " float phi = (1.0 - smoothstep (0.0, 0.3, r)) * 1.6;" - /* precalculate sin phi and cos phi, save some alu */ - " float s = sin(phi);" - " float c = cos(phi);" - /* rotate */ - " normcoord *= mat2(c, s, -s, c);" - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *bulge_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " float r = length (normcoord);" - " normcoord *= smoothstep (-0.05, 0.25, r);" - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *square_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec2 normcoord;" - " normcoord = texturecoord - 0.5;" - " float r = length (normcoord);" - " normcoord *= 1.0 + smoothstep(0.125, 0.25, abs(normcoord));" - " normcoord /= 2.0; /* zoom amount */" - " texturecoord = normcoord + 0.5;" - " gl_FragColor = texture2D (tex, texturecoord);" - "}"; - -const gchar *luma_threshold_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec4 color = texture2D(tex, texturecoord);" - " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" /* BT.709 (from orange book) */ - " gl_FragColor = vec4 (vec3 (smoothstep (0.30, 0.50, luma)), color.a);" - "}"; - -const gchar *sep_sobel_length_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform bool invert;" - "void main () {" - " vec4 g = texture2D (tex, v_texcoord.xy);" - /* restore black background with grey edges */ - " g -= vec4(0.5, 0.5, 0.0, 0.0);" - " float len = length (g);" - /* little trick to avoid IF operator */ - /* TODO: test if a standalone inverting pass is worth */ - " gl_FragColor = abs(vec4(vec3(float(invert) - len), 1.0));" - "}"; - -const gchar *desaturate_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec4 color = texture2D (tex, v_texcoord.xy);" - " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" - " gl_FragColor = vec4(vec3(luma), color.a);" - "}"; - -const gchar *sep_sobel_hconv3_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform float width;" - "void main () {" - " float w = 1.0 / width;" - " vec2 texturecoord[3];" - " texturecoord[1] = v_texcoord.xy;" - " texturecoord[0] = texturecoord[1] - vec2(w, 0.0);" - " texturecoord[2] = texturecoord[1] + vec2(w, 0.0);" - " float grad_kern[3];" - " grad_kern[0] = 1.0;" - " grad_kern[1] = 0.0;" - " grad_kern[2] = -1.0;" - " float blur_kern[3];" - " blur_kern[0] = 0.25;" - " blur_kern[1] = 0.5;" - " blur_kern[2] = 0.25;" - " int i;" - " vec4 sum = vec4 (0.0);" - " for (i = 0; i < 3; i++) { " - " vec4 neighbor = texture2D(tex, texturecoord[i]); " - " sum.r = neighbor.r * blur_kern[i] + sum.r;" - " sum.g = neighbor.g * grad_kern[i] + sum.g;" - " }" - " gl_FragColor = sum + vec4(0.0, 0.5, 0.0, 0.0);" - "}"; - -const gchar *sep_sobel_vconv3_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform float height;" - "void main () {" - " float h = 1.0 / height;" - " vec2 texturecoord[3];" - " texturecoord[1] = v_texcoord.xy;" - " texturecoord[0] = texturecoord[1] - vec2(0.0, h);" - " texturecoord[2] = texturecoord[1] + vec2(0.0, h);" - " float grad_kern[3];" - " grad_kern[0] = 1.0;" - " grad_kern[1] = 0.0;" - " grad_kern[2] = -1.0;" - " float blur_kern[3];" - " blur_kern[0] = 0.25;" - " blur_kern[1] = 0.5;" - " blur_kern[2] = 0.25;" - " int i;" - " vec4 sum = vec4 (0.0);" - " for (i = 0; i < 3; i++) { " - " vec4 neighbor = texture2D(tex, texturecoord[i]); " - " sum.r = neighbor.r * grad_kern[i] + sum.r;" - " sum.g = neighbor.g * blur_kern[i] + sum.g;" - " }" - " gl_FragColor = sum + vec4(0.5, 0.0, 0.0, 0.0);" - "}"; - -const gchar *hconv7_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform float kernel[7];" - "uniform float gauss_width;" - "void main () {" - " float w = 1.0 / gauss_width;" - " vec2 texturecoord[7];" - " texturecoord[3] = v_texcoord.xy;" - " texturecoord[2] = texturecoord[3] - vec2(w, 0.0);" - " texturecoord[1] = texturecoord[2] - vec2(w, 0.0);" - " texturecoord[0] = texturecoord[1] - vec2(w, 0.0);" - " texturecoord[4] = texturecoord[3] + vec2(w, 0.0);" - " texturecoord[5] = texturecoord[4] + vec2(w, 0.0);" - " texturecoord[6] = texturecoord[5] + vec2(w, 0.0);" - " int i;" - " vec4 sum = vec4 (0.0);" - " for (i = 0; i < 7; i++) { " - " vec4 neighbor = texture2D(tex, texturecoord[i]); " - " sum += neighbor * kernel[i];" - " }" - " gl_FragColor = sum;" - "}"; - -/* vertical convolution 7x7 */ -const gchar *vconv7_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform float kernel[7];" - "uniform float gauss_height;" - "void main () {" - " float h = 1.0 / gauss_height;" - " vec2 texturecoord[7];" - " texturecoord[3] = v_texcoord.xy;" - " texturecoord[2] = texturecoord[3] - vec2(0.0, h);" - " texturecoord[1] = texturecoord[2] - vec2(0.0, h);" - " texturecoord[0] = texturecoord[1] - vec2(0.0, h);" - " texturecoord[4] = texturecoord[3] + vec2(0.0, h);" - " texturecoord[5] = texturecoord[4] + vec2(0.0, h);" - " texturecoord[6] = texturecoord[5] + vec2(0.0, h);" - " int i;" - " vec4 sum = vec4 (0.0);" - " for (i = 0; i < 7; i++) { " - " vec4 neighbor = texture2D(tex, texturecoord[i]);" - " sum += neighbor * kernel[i];" - " }" - " gl_FragColor = sum;" - "}"; - -/* TODO: support several blend modes */ -const gchar *sum_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D base;" - "uniform sampler2D blend;" - "uniform float alpha;" - "uniform float beta;" - "void main () {" - " vec4 basecolor = texture2D (base, v_texcoord.xy);" - " vec4 blendcolor = texture2D (blend, v_texcoord.xy);" - " gl_FragColor = alpha * basecolor + beta * blendcolor;" - "}"; - -const gchar *multiply_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D base;" - "uniform sampler2D blend;" - "uniform float alpha;" - "void main () {" - " vec4 basecolor = texture2D (base, v_texcoord.xy);" - " vec4 blendcolor = texture2D (blend, v_texcoord.xy);" - " gl_FragColor = (1.0 - alpha) * basecolor + alpha * basecolor * blendcolor;" - "}"; - -/* lut operations, map luma to tex1d, see orange book (chapter 19) */ -const gchar *luma_to_curve_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform sampler2D curve;" - "void main () {" - " vec2 texturecoord = v_texcoord.xy;" - " vec4 color = texture2D (tex, texturecoord);" - " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" - " color = texture2D (curve, vec2(luma, 0.0));" - " gl_FragColor = color;" - "}"; - -/* lut operations, map rgb to tex1d, see orange book (chapter 19) */ -const gchar *rgb_to_curve_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform sampler2D curve;" - "void main () {" - " vec4 color = texture2D (tex, v_texcoord.xy);" - " vec4 outcolor;" - " outcolor.r = texture2D (curve, vec2(color.r, 0.0)).r;" - " outcolor.g = texture2D (curve, vec2(color.g, 0.0)).g;" - " outcolor.b = texture2D (curve, vec2(color.b, 0.0)).b;" - " outcolor.a = color.a;" - " gl_FragColor = outcolor;" - "}"; - -const gchar *sin_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "void main () {" - " vec4 color = texture2D (tex, vec2(v_texcoord.xy));" - " float luma = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));" -/* calculate hue with the Preucil formula */ - " float cosh = color.r - 0.5*(color.g + color.b);" -/* sqrt(3)/2 = 0.866 */ - " float sinh = 0.866*(color.g - color.b);" -/* hue = atan2 h */ - " float sch = (1.0-sinh)*cosh;" -/* ok this is a little trick I came up because I didn't find any - * detailed proof of the Preucil formula. The issue is that tan(h) is - * pi-periodic so the smoothstep thing gives both reds (h = 0) and - * cyans (h = 180). I don't want to use atan since it requires - * branching and doesn't work on i915. So take only the right half of - * the circle where cosine is positive */ -/* take a slightly purple color trying to get rid of human skin reds */ -/* tanh = +-1.0 for h = +-45, where yellow=60, magenta=-60 */ - " float a = smoothstep (0.3, 1.0, sch);" - " float b = smoothstep (-0.4, -0.1, sinh);" - " float mix = a * b;" - " gl_FragColor = color * mix + luma * (1.0 - mix);" - "}"; - -const gchar *interpolate_fragment_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D base;" - "uniform sampler2D blend;" - "void main () {" - "vec4 basecolor = texture2D (base, v_texcoord);" - "vec4 blendcolor = texture2D (blend, v_texcoord);" - "vec4 white = vec4(1.0);" - "gl_FragColor = blendcolor + (1.0 - blendcolor.a) * basecolor;" - "}"; - -const gchar *texture_interp_fragment_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D base;" - "uniform sampler2D blend;" - "uniform sampler2D alpha;" - "void main () {" - " vec4 basecolor = texture2D (base, v_texcoord);" - " vec4 blendcolor = texture2D (blend, v_texcoord);" - " vec4 alphacolor = texture2D (alpha, v_texcoord);" - " gl_FragColor = (alphacolor * blendcolor) + (1.0 - alphacolor) * basecolor;" - "}"; - -const gchar *difference_fragment_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D saved;" - "uniform sampler2D current;" - "void main () {" - "vec4 savedcolor = texture2D (saved, v_texcoord);" - "vec4 currentcolor = texture2D (current, v_texcoord);" - "gl_FragColor = vec4 (step (0.12, length (savedcolor - currentcolor)));" - "}"; - -/* This filter is meant as a demo of gst-plugins-gl + glsl - capabilities. So I'm keeping this shader readable enough. If and - when this shader will be used in production be careful to hard code - kernel into the shader and remove unneeded zero multiplications in - the convolution */ -const gchar *conv9_fragment_source_gles2 = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord;" - "uniform sampler2D tex;" - "uniform float kernel[9];" - "uniform float width, height;" - "uniform bool invert;" - "void main () {" - " float w = 1.0 / width;" - " float h = 1.0 / height;" - " vec2 texturecoord[9];" - " texturecoord[4] = v_texcoord.xy;" /* 0 0 */ - " texturecoord[5] = texturecoord[4] + vec2(w, 0.0);" /* 1 0 */ - " texturecoord[2] = texturecoord[5] - vec2(0.0, h);" /* 1 -1 */ - " texturecoord[1] = texturecoord[2] - vec2(w, 0.0);" /* 0 -1 */ - " texturecoord[0] = texturecoord[1] - vec2(w, 0.0);" /* -1 -1 */ - " texturecoord[3] = texturecoord[0] + vec2(0.0, h);" /* -1 0 */ - " texturecoord[6] = texturecoord[3] + vec2(0.0, h);" /* -1 1 */ - " texturecoord[7] = texturecoord[6] + vec2(w, 0.0);" /* 0 1 */ - " texturecoord[8] = texturecoord[7] + vec2(w, 0.0);" /* 1 1 */ - " int i;" - " vec3 sum = vec3 (0.0);" - " for (i = 0; i < 9; i++) { " - " vec4 neighbor = texture2D (tex, texturecoord[i]);" - " sum += neighbor.xyz * kernel[i];" - " }" - " gl_FragColor = vec4 (abs(sum - vec3(float(invert))), 1.0);" - "}"; - -/* *INDENT-ON* */ diff --git a/ext/gl/effects/gstgleffectssources.h b/ext/gl/effects/gstgleffectssources.h deleted file mode 100644 index fcd5c934b..000000000 --- a/ext/gl/effects/gstgleffectssources.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_EFFECTS_SOURCES_H__ -#define __GST_GL_EFFECTS_SOURCES_H__ - -extern const gchar *mirror_fragment_source_gles2; -extern const gchar *squeeze_fragment_source_gles2; -extern const gchar *stretch_fragment_source_gles2; -extern const gchar *fisheye_fragment_source_gles2; -extern const gchar *twirl_fragment_source_gles2; -extern const gchar *bulge_fragment_source_gles2; -extern const gchar *tunnel_fragment_source_gles2; -extern const gchar *square_fragment_source_gles2; -extern const gchar *luma_threshold_fragment_source_gles2; -extern const gchar *hconv7_fragment_source_gles2; -extern const gchar *vconv7_fragment_source_gles2; -extern const gchar *sum_fragment_source_gles2; -extern const gchar *luma_to_curve_fragment_source_gles2; -extern const gchar *rgb_to_curve_fragment_source_gles2; -extern const gchar *sin_fragment_source_gles2; -extern const gchar *desaturate_fragment_source_gles2; -extern const gchar *sep_sobel_hconv3_fragment_source_gles2; -extern const gchar *sep_sobel_vconv3_fragment_source_gles2; -extern const gchar *sep_sobel_length_fragment_source_gles2; -extern const gchar *multiply_fragment_source_gles2; -extern const gchar *conv9_fragment_source_gles2; - -extern const gchar *interpolate_fragment_source; -extern const gchar *texture_interp_fragment_source; -extern const gchar *difference_fragment_source; - -void fill_gaussian_kernel (float *kernel, int size, float sigma); - -#endif /* __GST_GL_EFFECTS_SOURCES_H__ */ diff --git a/ext/gl/effects/gstgleffectstretch.c b/ext/gl/effects/gstgleffectstretch.c deleted file mode 100644 index bbc0c4c71..000000000 --- a/ext/gl/effects/gstgleffectstretch.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_stretch (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "stretch", - stretch_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffecttunnel.c b/ext/gl/effects/gstgleffecttunnel.c deleted file mode 100644 index 4990b832d..000000000 --- a/ext/gl/effects/gstgleffecttunnel.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_tunnel (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "tunnel", - tunnel_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffecttwirl.c b/ext/gl/effects/gstgleffecttwirl.c deleted file mode 100644 index 57a9b534d..000000000 --- a/ext/gl/effects/gstgleffecttwirl.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" - -void -gst_gl_effects_twirl (GstGLEffects * effects) -{ - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - shader = gst_gl_effects_get_fragment_shader (effects, "twirl", - twirl_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->outtexture, shader); -} diff --git a/ext/gl/effects/gstgleffectxray.c b/ext/gl/effects/gstgleffectxray.c deleted file mode 100644 index a7c9b36a1..000000000 --- a/ext/gl/effects/gstgleffectxray.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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 - -#include "../gstgleffects.h" -#include "gstgleffectscurves.h" -#include "gstgleffectlumatocurve.h" - -static gboolean kernel_ready = FALSE; -static float gauss_kernel[7]; - -void -gst_gl_effects_xray (GstGLEffects * effects) -{ - const GstGLFuncs *gl = GST_GL_BASE_FILTER (effects)->context->gl_vtable; - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLShader *shader; - - if (!kernel_ready) { - fill_gaussian_kernel (gauss_kernel, 7, 1.5); - kernel_ready = TRUE; - } - - /* map luma to xray curve */ - gst_gl_effects_luma_to_curve (effects, &xray_curve, GST_GL_EFFECTS_CURVE_XRAY, - effects->intexture, effects->midtexture[0]); - - /* horizontal blur */ - shader = gst_gl_effects_get_fragment_shader (effects, "hconv7", - hconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "gauss_width", - GST_VIDEO_INFO_WIDTH (&filter->in_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[0], - effects->midtexture[1], shader); - - /* vertical blur */ - shader = gst_gl_effects_get_fragment_shader (effects, "vconv7", - vconv7_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel); - gst_gl_shader_set_uniform_1f (shader, "gauss_height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[1], - effects->midtexture[2], shader); - - /* detect edges with Sobel */ - /* the old version used edges from the blurred texture, this uses - * the ones from original texture, still not sure what I like - * more. This one gives better edges obviously but behaves badly - * with noise */ - /* desaturate */ - shader = gst_gl_effects_get_fragment_shader (effects, "desaturate", - desaturate_fragment_source_gles2); - gst_gl_filter_render_to_target_with_shader (filter, effects->intexture, - effects->midtexture[3], shader); - - /* horizonal convolution */ - shader = gst_gl_effects_get_fragment_shader (effects, "sobel_hconv3", - sep_sobel_hconv3_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[3], - effects->midtexture[4], shader); - - /* vertical convolution */ - shader = gst_gl_effects_get_fragment_shader (effects, "sobel_vconv3", - sep_sobel_vconv3_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[4], - effects->midtexture[3], shader); - - /* gradient length */ - shader = gst_gl_effects_get_fragment_shader (effects, "sobel_length", - sep_sobel_length_fragment_source_gles2); - gst_gl_shader_use (shader); - gst_gl_shader_set_uniform_1i (shader, "invert", TRUE); - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[3], - effects->midtexture[4], shader); - - /* multiply edges with the blurred image */ - shader = gst_gl_effects_get_fragment_shader (effects, "multiply", - multiply_fragment_source_gles2); - gst_gl_shader_use (shader); - - gl->ActiveTexture (GL_TEXTURE2); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (effects->midtexture[2])); - - gst_gl_shader_set_uniform_1i (shader, "base", 2); - - gl->ActiveTexture (GL_TEXTURE1); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (effects->midtexture[4])); - - gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.5f); - gst_gl_shader_set_uniform_1i (shader, "blend", 1); - - gst_gl_filter_render_to_target_with_shader (filter, effects->midtexture[4], - effects->outtexture, shader); -} diff --git a/ext/gl/gltestsrc.c b/ext/gl/gltestsrc.c deleted file mode 100644 index f6faea3b6..000000000 --- a/ext/gl/gltestsrc.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * Copyright (C) <2016> Matthew Waters <matthew@centricular.com> - * - * 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 - -#include <gst/gl/gstglfuncs.h> - -#include "gltestsrc.h" - -#define MAX_ATTRIBUTES 4 - -struct vts_color_struct -{ - gfloat R, G, B; -}; - -struct XYZWRGB -{ - gfloat X, Y, Z, W, R, G, B; -}; - -enum -{ - COLOR_WHITE = 0, - COLOR_YELLOW, - COLOR_CYAN, - COLOR_GREEN, - COLOR_MAGENTA, - COLOR_RED, - COLOR_BLUE, - COLOR_BLACK, - COLOR_NEG_I, - COLOR_POS_Q, - COLOR_SUPER_BLACK, - COLOR_DARK_GREY -}; - -static const struct vts_color_struct vts_colors[] = { - /* 100% white */ - {1.0f, 1.0f, 1.0f}, - /* yellow */ - {1.0f, 1.0f, 0.0f}, - /* cyan */ - {0.0f, 1.0f, 1.0f}, - /* green */ - {0.0f, 1.0f, 0.0f}, - /* magenta */ - {1.0f, 0.0f, 1.0f}, - /* red */ - {1.0f, 0.0f, 0.0f}, - /* blue */ - {0.0f, 0.0f, 1.0f}, - /* black */ - {0.0f, 0.0f, 0.0f}, - /* -I */ - {0.0, 0.0f, 0.5f}, - /* +Q */ - {0.0f, 0.5, 1.0f}, - /* superblack */ - {0.0f, 0.0f, 0.0f}, - /* 7.421875% grey */ - {19. / 256.0f, 19. / 256.0f, 19. / 256.0}, -}; - -/* *INDENT-OFF* */ -static const GLfloat positions[] = { - -1.0, 1.0, 0.0, 1.0, - 1.0, 1.0, 0.0, 1.0, - 1.0, -1.0, 0.0, 1.0, - -1.0, -1.0, 0.0, 1.0, -}; - -static const GLushort indices_quad[] = { 0, 1, 2, 0, 2, 3 }; -/* *INDENT-ON* */ - -struct attribute -{ - const gchar *name; - gint location; - guint n_elements; - GLenum element_type; - guint offset; /* in bytes */ - guint stride; /* in bytes */ -}; - -struct SrcShader -{ - struct BaseSrcImpl base; - - GstGLShader *shader; - - guint vao; - guint vbo; - guint vbo_indices; - - guint n_attributes; - struct attribute attributes[MAX_ATTRIBUTES]; - - gconstpointer vertices; - gsize vertices_size; - const gushort *indices; - guint index_offset; - guint n_indices; -}; - -static void -_bind_buffer (struct SrcShader *src) -{ - GstGLContext *context = src->base.context; - const GstGLFuncs *gl = context->gl_vtable; - gint i; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, src->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, src->vbo); - - /* Load the vertex position */ - for (i = 0; i < src->n_attributes; i++) { - struct attribute *attr = &src->attributes[i]; - - if (attr->location == -1) - attr->location = - gst_gl_shader_get_attribute_location (src->shader, attr->name); - - gl->VertexAttribPointer (attr->location, attr->n_elements, - attr->element_type, GL_FALSE, attr->stride, - (void *) (gintptr) attr->offset); - - gl->EnableVertexAttribArray (attr->location); - } -} - -static void -_unbind_buffer (struct SrcShader *src) -{ - GstGLContext *context = src->base.context; - const GstGLFuncs *gl = context->gl_vtable; - gint i; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - for (i = 0; i < src->n_attributes; i++) { - struct attribute *attr = &src->attributes[i]; - - gl->DisableVertexAttribArray (attr->location); - } -} - -static gboolean -_src_shader_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info) -{ - struct SrcShader *src = impl; - const GstGLFuncs *gl = context->gl_vtable; - - src->base.context = context; - - if (!src->vbo) { - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &src->vao); - gl->BindVertexArray (src->vao); - } - - gl->GenBuffers (1, &src->vbo); - gl->BindBuffer (GL_ARRAY_BUFFER, src->vbo); - gl->BufferData (GL_ARRAY_BUFFER, src->vertices_size, - src->vertices, GL_STATIC_DRAW); - - gl->GenBuffers (1, &src->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, src->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, src->n_indices * sizeof (gushort), - src->indices, GL_STATIC_DRAW); - - if (gl->GenVertexArrays) { - _bind_buffer (src); - gl->BindVertexArray (0); - } - - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - } - - return TRUE; -} - -static gboolean -_src_shader_fill_bound_fbo (gpointer impl) -{ - struct SrcShader *src = impl; - const GstGLFuncs *gl; - - g_return_val_if_fail (src->base.context, FALSE); - g_return_val_if_fail (src->shader, FALSE); - gl = src->base.context->gl_vtable; - - gst_gl_shader_use (src->shader); - - if (gl->GenVertexArrays) - gl->BindVertexArray (src->vao); - _bind_buffer (src); - - gl->DrawElements (GL_TRIANGLES, src->n_indices, GL_UNSIGNED_SHORT, - (gpointer) (gintptr) src->index_offset); - - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (src); - - gst_gl_context_clear_shader (src->base.context); - - return TRUE; -} - -static void -_src_shader_deinit (gpointer impl) -{ - struct SrcShader *src = impl; - const GstGLFuncs *gl = src->base.context->gl_vtable; - - if (src->shader) - gst_object_unref (src->shader); - src->shader = NULL; - - if (src->vao) - gl->DeleteVertexArrays (1, &src->vao); - src->vao = 0; - - if (src->vbo) - gl->DeleteBuffers (1, &src->vbo); - src->vbo = 0; - - if (src->vbo_indices) - gl->DeleteBuffers (1, &src->vbo_indices); - src->vbo_indices = 0; -} - -/* *INDENT-OFF* */ -static const gchar *smpte_vertex_src = - "attribute vec4 position;\n" - "attribute vec4 a_color;\n" - "varying vec4 color;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - " color = a_color;\n" - "}"; - -static const gchar *smpte_fragment_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec4 color;\n" - "void main()\n" - "{\n" - " gl_FragColor = color;\n" - "}"; - -static const gchar *snow_vertex_src = - "attribute vec4 position;\n" - "varying vec2 out_uv;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - " out_uv = position.xy;\n" - "}"; - -static const gchar *snow_fragment_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform float time;\n" - "varying vec2 out_uv;\n" - "\n" - "float rand(vec2 co){\n" - " return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);\n" - "}\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(rand(time * out_uv));\n" - "}"; -/* *INDENT-ON* */ - -#define N_QUADS 21 -struct SrcSMPTE -{ - struct SrcShader base; - - GstGLShader *snow_shader; - GstGLShader *color_shader; - gint attr_snow_position; -}; - -static gpointer -_src_smpte_new (GstGLTestSrc * test) -{ - struct SrcSMPTE *src = g_new0 (struct SrcSMPTE, 1); - - src->base.base.src = test; - - return src; -} - -static gboolean -_src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info) -{ - struct SrcSMPTE *src = impl; - struct XYZWRGB *coord; - gushort *plane_indices; - GError *error = NULL; - int color_idx = 0; - int i; - - src->base.base.context = context; - - coord = g_new0 (struct XYZWRGB, N_QUADS * 4); - plane_indices = g_new0 (gushort, N_QUADS * 6); - - /* top row */ - for (i = 0; i < 7; i++) { - coord[color_idx * 4 + 0].X = -1.0f + i * (2.0f / 7.0f); - coord[color_idx * 4 + 0].Y = 1.0f / 3.0f; - coord[color_idx * 4 + 1].X = -1.0f + (i + 1) * (2.0f / 7.0f); - coord[color_idx * 4 + 1].Y = 1.0f / 3.0f; - coord[color_idx * 4 + 2].X = -1.0f + (i + 1) * (2.0f / 7.0f); - coord[color_idx * 4 + 2].Y = -1.0f; - coord[color_idx * 4 + 3].X = -1.0f + i * (2.0f / 7.0f); - coord[color_idx * 4 + 3].Y = -1.0f; - color_idx++; - } - - /* middle row */ - for (i = 0; i < 7; i++) { - coord[color_idx * 4 + 0].X = -1.0f + i * (2.0f / 7.0f); - coord[color_idx * 4 + 0].Y = 0.5f; - coord[color_idx * 4 + 1].X = -1.0f + (i + 1) * (2.0f / 7.0f); - coord[color_idx * 4 + 1].Y = 0.5f; - coord[color_idx * 4 + 2].X = -1.0f + (i + 1) * (2.0f / 7.0f); - coord[color_idx * 4 + 2].Y = 1.0f / 3.0f; - coord[color_idx * 4 + 3].X = -1.0f + i * (2.0f / 7.0f); - coord[color_idx * 4 + 3].Y = 1.0f / 3.0f; - color_idx++; - } - - /* bottom row, left three */ - for (i = 0; i < 3; i++) { - coord[color_idx * 4 + 0].X = -1.0f + i / 3.0f; - coord[color_idx * 4 + 0].Y = 1.0f; - coord[color_idx * 4 + 1].X = -1.0f + (i + 1) / 3.0f; - coord[color_idx * 4 + 1].Y = 1.0f; - coord[color_idx * 4 + 2].X = -1.0f + (i + 1) / 3.0f; - coord[color_idx * 4 + 2].Y = 0.5f; - coord[color_idx * 4 + 3].X = -1.0f + i / 3.0f; - coord[color_idx * 4 + 3].Y = 0.5f; - color_idx++; - } - - /* bottom row, middle three (the blacks) */ - for (i = 0; i < 3; i++) { - coord[color_idx * 4 + 0].X = i / 6.0f; - coord[color_idx * 4 + 0].Y = 1.0f; - coord[color_idx * 4 + 1].X = (i + 1) / 6.0f; - coord[color_idx * 4 + 1].Y = 1.0f; - coord[color_idx * 4 + 2].X = (i + 1) / 6.0f; - coord[color_idx * 4 + 2].Y = 0.5f; - coord[color_idx * 4 + 3].X = i / 6.0f; - coord[color_idx * 4 + 3].Y = 0.5f; - color_idx++; - } - - g_assert (color_idx < N_QUADS); - - for (i = 0; i < N_QUADS - 1; i++) { - int j, k; - if (i < 7) { - k = i; - } else if ((i - 7) & 1) { - k = COLOR_BLACK; - } else { - k = 13 - i; - } - - if (i == 14) { - k = COLOR_NEG_I; - } else if (i == 15) { - k = COLOR_WHITE; - } else if (i == 16) { - k = COLOR_POS_Q; - } else if (i == 17) { - k = COLOR_SUPER_BLACK; - } else if (i == 18) { - k = COLOR_BLACK; - } else if (i == 19) { - k = COLOR_DARK_GREY; - } - - for (j = 0; j < 4; j++) { - coord[i * 4 + j].Z = 0.0f; - coord[i * 4 + j].W = 1.0f; - coord[i * 4 + j].R = vts_colors[k].R; - coord[i * 4 + j].G = vts_colors[k].G; - coord[i * 4 + j].B = vts_colors[k].B; - } - - for (j = 0; j < 6; j++) - plane_indices[i * 6 + j] = i * 4 + indices_quad[j]; - } - - /* snow */ - coord[color_idx * 4 + 0].X = 0.5f; - coord[color_idx * 4 + 0].Y = 1.0f; - coord[color_idx * 4 + 0].Z = 0.0f; - coord[color_idx * 4 + 0].W = 1.0f; - coord[color_idx * 4 + 1].X = 1.0f; - coord[color_idx * 4 + 1].Y = 1.0f; - coord[color_idx * 4 + 1].Z = 0.0f; - coord[color_idx * 4 + 1].W = 1.0f; - coord[color_idx * 4 + 2].X = 1.0f; - coord[color_idx * 4 + 2].Y = 0.5f; - coord[color_idx * 4 + 2].Z = 0.0f; - coord[color_idx * 4 + 2].W = 1.0f; - coord[color_idx * 4 + 3].X = 0.5f; - coord[color_idx * 4 + 3].Y = 0.5f; - coord[color_idx * 4 + 3].Z = 0.0f; - coord[color_idx * 4 + 3].W = 1.0f; - for (i = 0; i < 6; i++) - plane_indices[color_idx * 6 + i] = color_idx * 4 + indices_quad[i]; - color_idx++; - - if (src->color_shader) - gst_object_unref (src->color_shader); - src->color_shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - smpte_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - smpte_fragment_src), NULL); - if (!src->color_shader) { - GST_ERROR_OBJECT (src->base.base.src, "%s", error->message); - return FALSE; - } - - if (src->snow_shader) - gst_object_unref (src->snow_shader); - src->snow_shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - snow_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - snow_fragment_src), NULL); - if (!src->snow_shader) { - GST_ERROR_OBJECT (src->base.base.src, "%s", error->message); - return FALSE; - } - - src->attr_snow_position = -1; - - src->base.n_attributes = 2; - - src->base.attributes[0].name = "position"; - src->base.attributes[0].location = -1; - src->base.attributes[0].n_elements = 4; - src->base.attributes[0].element_type = GL_FLOAT; - src->base.attributes[0].offset = 0; - src->base.attributes[0].stride = sizeof (struct XYZWRGB); - - src->base.attributes[1].name = "a_color"; - src->base.attributes[1].location = -1; - src->base.attributes[1].n_elements = 3; - src->base.attributes[1].element_type = GL_FLOAT; - src->base.attributes[1].offset = 4 * sizeof (gfloat); - src->base.attributes[1].stride = sizeof (struct XYZWRGB); - - if (src->base.shader) - gst_object_unref (src->base.shader); - src->base.shader = gst_object_ref (src->color_shader); - src->base.vertices = (gfloat *) coord; - src->base.vertices_size = sizeof (struct XYZWRGB) * N_QUADS * 4; - src->base.indices = plane_indices; - src->base.n_indices = N_QUADS * 6; - - return _src_shader_init (impl, context, v_info); -} - -static gboolean -_src_smpte_fill_bound_fbo (gpointer impl) -{ - struct SrcSMPTE *src = impl; - gint attr_color_position = -1; - - src->base.n_attributes = 2; - if (src->base.shader) - gst_object_unref (src->base.shader); - src->base.shader = gst_object_ref (src->color_shader); - src->base.n_indices = (N_QUADS - 1) * 6; - src->base.index_offset = 0; - if (!_src_shader_fill_bound_fbo (impl)) - return FALSE; - attr_color_position = src->base.attributes[0].location; - - src->base.attributes[0].location = src->attr_snow_position; - src->base.n_attributes = 1; - if (src->base.shader) - gst_object_unref (src->base.shader); - src->base.shader = gst_object_ref (src->snow_shader); - src->base.n_indices = 6; - src->base.index_offset = (N_QUADS - 1) * 6 * sizeof (gushort); - gst_gl_shader_use (src->snow_shader); - gst_gl_shader_set_uniform_1f (src->snow_shader, "time", - (gfloat) src->base.base.src->running_time / GST_SECOND); - if (!_src_shader_fill_bound_fbo (impl)) - return FALSE; - src->attr_snow_position = src->base.attributes[0].location; - src->base.attributes[0].location = attr_color_position; - - return TRUE; -} - -static void -_src_smpte_free (gpointer impl) -{ - struct SrcSMPTE *src = impl; - - if (!impl) - return; - - _src_shader_deinit (impl); - - g_free ((gpointer) src->base.vertices); - g_free ((gpointer) src->base.indices); - - if (src->snow_shader) - gst_object_unref (src->snow_shader); - if (src->color_shader) - gst_object_unref (src->color_shader); - - g_free (impl); -} - -static const struct SrcFuncs src_smpte = { - GST_GL_TEST_SRC_SMPTE, - _src_smpte_new, - _src_smpte_init, - _src_smpte_fill_bound_fbo, - _src_smpte_free, -}; - -#undef N_QUADS - -struct SrcUniColor -{ - struct BaseSrcImpl base; - - struct vts_color_struct color; -}; - -static gpointer -_src_uni_color_new (GstGLTestSrc * test) -{ - struct SrcUniColor *src = g_new0 (struct SrcUniColor, 1); - - src->base.src = test; - - return src; -} - -static gboolean -_src_uni_color_init (gpointer impl, GstGLContext * context, - GstVideoInfo * v_info) -{ - struct SrcUniColor *src = impl; - - src->base.context = context; - src->base.v_info = *v_info; - - return TRUE; -} - -static gboolean -_src_uni_color_fill_bound_fbo (gpointer impl) -{ - struct SrcUniColor *src = impl; - const GstGLFuncs *gl = src->base.context->gl_vtable; - - gl->ClearColor (src->color.R, src->color.G, src->color.B, 1.0f); - gl->Clear (GL_COLOR_BUFFER_BIT); - - return TRUE; -} - -static void -_src_uni_color_free (gpointer impl) -{ - g_free (impl); -} - -#define SRC_UNICOLOR(name, cap_name) \ -static gpointer \ -G_PASTE(G_PASTE(_src_unicolor_,name),_new) (GstGLTestSrc * test) \ -{ \ - struct SrcUniColor *src = _src_uni_color_new (test); \ - src->color = vts_colors[G_PASTE(COLOR_,cap_name)]; \ - return src; \ -} \ -static const struct SrcFuncs G_PASTE (src_,name) = { \ - G_PASTE(GST_GL_TEST_SRC_,cap_name), \ - G_PASTE(G_PASTE(_src_unicolor_,name),_new), \ - _src_uni_color_init, \ - _src_uni_color_fill_bound_fbo, \ - _src_uni_color_free, \ -} - -SRC_UNICOLOR (white, WHITE); -SRC_UNICOLOR (black, BLACK); -SRC_UNICOLOR (red, RED); -SRC_UNICOLOR (green, GREEN); -SRC_UNICOLOR (blue, BLUE); - -static gpointer -_src_blink_new (GstGLTestSrc * test) -{ - struct SrcUniColor *src = _src_uni_color_new (test); - - src->color = vts_colors[COLOR_WHITE]; - - return src; -} - -static gboolean -_src_blink_fill_bound_fbo (gpointer impl) -{ - struct SrcUniColor *src = impl; - - if (src->color.R > 0.5) { - src->color = vts_colors[COLOR_BLACK]; - } else { - src->color = vts_colors[COLOR_WHITE]; - } - - return _src_uni_color_fill_bound_fbo (impl); -} - -static const struct SrcFuncs src_blink = { - GST_GL_TEST_SRC_BLINK, - _src_blink_new, - _src_uni_color_init, - _src_blink_fill_bound_fbo, - _src_uni_color_free, -}; - -/* *INDENT-OFF* */ -static const gchar *checkers_vertex_src = "attribute vec4 position;\n" - "varying vec2 uv;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - /* RPi gives incorrect results for positive uv (plus it makes us start on - * the right pixel color i.e. red) */ - " uv = position.xy - 1.0;\n" - "}"; - -static const gchar *checkers_fragment_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform float checker_width;\n" - "uniform float width;\n" - "uniform float height;\n" - "varying vec2 uv;\n" - "void main()\n" - "{\n" - " vec2 xy_mod = floor (0.5 * uv * vec2(width, height) / (checker_width));\n" - " float result = mod (xy_mod.x + xy_mod.y, 2.0);\n" - " gl_FragColor.r = step (result, 0.5);\n" - " gl_FragColor.g = 1.0 - gl_FragColor.r;\n" - " gl_FragColor.ba = vec2(0.0, 1.0);\n" - "}"; -/* *INDENT-ON* */ - -struct SrcCheckers -{ - struct SrcShader base; - - guint checker_width; -}; - -static gboolean -_src_checkers_init (gpointer impl, GstGLContext * context, - GstVideoInfo * v_info) -{ - struct SrcCheckers *src = impl; - GError *error = NULL; - - src->base.base.context = context; - - if (src->base.shader) - gst_object_unref (src->base.shader); - src->base.shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - checkers_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - checkers_fragment_src), NULL); - if (!src->base.shader) { - GST_ERROR_OBJECT (src->base.base.src, "%s", error->message); - return FALSE; - } - - src->base.n_attributes = 1; - - src->base.attributes[0].name = "position"; - src->base.attributes[0].location = -1; - src->base.attributes[0].n_elements = 4; - src->base.attributes[0].element_type = GL_FLOAT; - src->base.attributes[0].offset = 0; - src->base.attributes[0].stride = 4 * sizeof (gfloat); - - src->base.vertices = positions; - src->base.vertices_size = sizeof (positions); - src->base.indices = indices_quad; - src->base.n_indices = 6; - - gst_gl_shader_use (src->base.shader); - gst_gl_shader_set_uniform_1f (src->base.shader, "checker_width", - src->checker_width); - gst_gl_shader_set_uniform_1f (src->base.shader, "width", - (gfloat) GST_VIDEO_INFO_WIDTH (v_info)); - gst_gl_shader_set_uniform_1f (src->base.shader, "height", - (gfloat) GST_VIDEO_INFO_HEIGHT (v_info)); - gst_gl_context_clear_shader (src->base.base.context); - - return _src_shader_init (impl, context, v_info); -} - -static void -_src_checkers_free (gpointer impl) -{ - struct SrcCheckers *src = impl; - - if (!src) - return; - - _src_shader_deinit (impl); - - g_free (impl); -} - -static gpointer -_src_checkers_new (GstGLTestSrc * test) -{ - struct SrcCheckers *src = g_new0 (struct SrcCheckers, 1); - - src->base.base.src = test; - - return src; -} - -#define SRC_CHECKERS(spacing) \ -static gpointer \ -G_PASTE(G_PASTE(_src_checkers,spacing),_new) (GstGLTestSrc * test) \ -{ \ - struct SrcCheckers *src = _src_checkers_new (test); \ - src->checker_width = spacing; \ - return src; \ -} \ -static const struct SrcFuncs G_PASTE(src_checkers,spacing) = { \ - G_PASTE(GST_GL_TEST_SRC_CHECKERS,spacing), \ - G_PASTE(G_PASTE(_src_checkers,spacing),_new), \ - _src_checkers_init, \ - _src_shader_fill_bound_fbo, \ - _src_checkers_free, \ -} - -SRC_CHECKERS (1); -SRC_CHECKERS (2); -SRC_CHECKERS (4); -SRC_CHECKERS (8); - -static gboolean -_src_snow_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info) -{ - struct SrcShader *src = impl; - GError *error = NULL; - - src->base.context = context; - - if (src->shader) - gst_object_unref (src->shader); - src->shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - snow_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - snow_fragment_src), NULL); - if (!src->shader) { - GST_ERROR_OBJECT (src->base.src, "%s", error->message); - return FALSE; - } - - src->n_attributes = 1; - - src->attributes[0].name = "position"; - src->attributes[0].location = -1; - src->attributes[0].n_elements = 4; - src->attributes[0].element_type = GL_FLOAT; - src->attributes[0].offset = 0; - src->attributes[0].stride = 4 * sizeof (gfloat); - - src->vertices = positions; - src->vertices_size = sizeof (positions); - src->indices = indices_quad; - src->n_indices = 6; - - return _src_shader_init (impl, context, v_info); -} - -static gboolean -_src_snow_fill_bound_fbo (gpointer impl) -{ - struct SrcShader *src = impl; - - g_return_val_if_fail (src->base.context, FALSE); - g_return_val_if_fail (src->shader, FALSE); - - gst_gl_shader_use (src->shader); - gst_gl_shader_set_uniform_1f (src->shader, "time", - (gfloat) src->base.src->running_time / GST_SECOND); - - return _src_shader_fill_bound_fbo (impl); -} - -static void -_src_snow_free (gpointer impl) -{ - struct SrcShader *src = impl; - - if (!src) - return; - - _src_shader_deinit (impl); - - g_free (impl); -} - -static gpointer -_src_snow_new (GstGLTestSrc * test) -{ - struct SrcShader *src = g_new0 (struct SrcShader, 1); - - src->base.src = test; - - return src; -} - -static const struct SrcFuncs src_snow = { - GST_GL_TEST_SRC_SNOW, - _src_snow_new, - _src_snow_init, - _src_snow_fill_bound_fbo, - _src_snow_free, -}; - -/* *INDENT-OFF* */ -static const gchar *mandelbrot_vertex_src = "attribute vec4 position;\n" - "uniform float aspect_ratio;\n" - "varying vec2 fractal_position;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - " fractal_position = vec2(position.y * 0.5 - 0.3, aspect_ratio * position.x * 0.5);\n" - " fractal_position *= 2.5;\n" - "}"; - -static const gchar *mandelbrot_fragment_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform float time;\n" - "varying vec2 fractal_position;\n" - "const vec4 K = vec4(1.0, 0.66, 0.33, 3.0);\n" - "vec4 hsv_to_rgb(float hue, float saturation, float value) {\n" - " vec4 p = abs(fract(vec4(hue) + K) * 6.0 - K.wwww);\n" - " return value * mix(K.xxxx, clamp(p - K.xxxx, 0.0, 1.0), saturation);\n" - "}\n" - "vec4 i_to_rgb(int i) {\n" - " float hue = float(i) / 100.0 + sin(time);\n" - " return hsv_to_rgb(hue, 0.5, 0.8);\n" - "}\n" - "vec2 pow_2_complex(vec2 c) {\n" - " return vec2(c.x*c.x - c.y*c.y, 2.0 * c.x * c.y);\n" - "}\n" - "vec2 mandelbrot(vec2 c, vec2 c0) {\n" - " return pow_2_complex(c) + c0;\n" - "}\n" - "vec4 iterate_pixel(vec2 position) {\n" - " vec2 c = vec2(0);\n" - " for (int i=0; i < 20; i++) {\n" - " if (c.x*c.x + c.y*c.y > 2.0*2.0)\n" - " return i_to_rgb(i);\n" - " c = mandelbrot(c, position);\n" - " }\n" - " return vec4(0, 0, 0, 1);\n" - "}\n" - "void main() {\n" - " gl_FragColor = iterate_pixel(fractal_position);\n" - "}"; -/* *INDENT-ON* */ - -static gboolean -_src_mandelbrot_init (gpointer impl, GstGLContext * context, - GstVideoInfo * v_info) -{ - struct SrcShader *src = impl; - GError *error = NULL; - - src->base.context = context; - - if (src->shader) - gst_object_unref (src->shader); - src->shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - mandelbrot_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - mandelbrot_fragment_src), NULL); - if (!src->shader) { - GST_ERROR_OBJECT (src->base.src, "%s", error->message); - return FALSE; - } - - src->n_attributes = 1; - - src->attributes[0].name = "position"; - src->attributes[0].location = -1; - src->attributes[0].n_elements = 4; - src->attributes[0].element_type = GL_FLOAT; - src->attributes[0].offset = 0; - src->attributes[0].stride = 4 * sizeof (gfloat); - - src->vertices = positions; - src->vertices_size = sizeof (positions); - src->indices = indices_quad; - src->n_indices = 6; - - gst_gl_shader_use (src->shader); - gst_gl_shader_set_uniform_1f (src->shader, "aspect_ratio", - (gfloat) GST_VIDEO_INFO_WIDTH (v_info) / - (gfloat) GST_VIDEO_INFO_HEIGHT (v_info)); - gst_gl_context_clear_shader (src->base.context); - - return _src_shader_init (impl, context, v_info); -} - -static gboolean -_src_mandelbrot_fill_bound_fbo (gpointer impl) -{ - struct SrcShader *src = impl; - - g_return_val_if_fail (src->base.context, FALSE); - g_return_val_if_fail (src->shader, FALSE); - - gst_gl_shader_use (src->shader); - gst_gl_shader_set_uniform_1f (src->shader, "time", - (gfloat) src->base.src->running_time / GST_SECOND); - - return _src_shader_fill_bound_fbo (impl); -} - -static void -_src_mandelbrot_free (gpointer impl) -{ - struct SrcShader *src = impl; - - if (!src) - return; - - _src_shader_deinit (impl); - - g_free (impl); -} - -static gpointer -_src_mandelbrot_new (GstGLTestSrc * test) -{ - struct SrcShader *src = g_new0 (struct SrcShader, 1); - - src->base.src = test; - - return src; -} - -static const struct SrcFuncs src_mandelbrot = { - GST_GL_TEST_SRC_MANDELBROT, - _src_mandelbrot_new, - _src_mandelbrot_init, - _src_mandelbrot_fill_bound_fbo, - _src_mandelbrot_free, -}; - -/* *INDENT-OFF* */ -static const gchar *circular_vertex_src = - "attribute vec4 position;\n" - "varying vec2 uv;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - " uv = position.xy;\n" - "}"; - -static const gchar *circular_fragment_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform float aspect_ratio;\n" - "varying vec2 uv;\n" - "#define PI 3.14159265\n" - "void main() {\n" - " float dist = 0.5 * sqrt(uv.x * uv.x + uv.y / aspect_ratio * uv.y / aspect_ratio);\n" - " float seg = floor(dist * 16.0);\n" - " if (seg <= 0.0 || seg >= 8.0) {\n" - " gl_FragColor = vec4(vec3(0.0), 1.0);\n" - " } else {\n" - " float d = floor (256.0 * dist * 200.0 * pow (2.0, - (seg - 1.0) / 4.0) + 0.5) / 128.0;\n" - " gl_FragColor = vec4 (vec3(sin (d * PI) * 0.5 + 0.5), 1.0);\n" - " }\n" - "}"; -/* *INDENT-ON* */ - -static gboolean -_src_circular_init (gpointer impl, GstGLContext * context, - GstVideoInfo * v_info) -{ - struct SrcShader *src = impl; - GError *error = NULL; - - src->base.context = context; - - if (src->shader) - gst_object_unref (src->shader); - src->shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - circular_vertex_src), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - circular_fragment_src), NULL); - if (!src->shader) { - GST_ERROR_OBJECT (src->base.src, "%s", error->message); - return FALSE; - } - - src->n_attributes = 1; - - src->attributes[0].name = "position"; - src->attributes[0].location = -1; - src->attributes[0].n_elements = 4; - src->attributes[0].element_type = GL_FLOAT; - src->attributes[0].offset = 0; - src->attributes[0].stride = 4 * sizeof (gfloat); - - src->vertices = positions; - src->vertices_size = sizeof (positions); - src->indices = indices_quad; - src->n_indices = 6; - - gst_gl_shader_use (src->shader); - gst_gl_shader_set_uniform_1f (src->shader, "aspect_ratio", - (gfloat) GST_VIDEO_INFO_WIDTH (v_info) / - (gfloat) GST_VIDEO_INFO_HEIGHT (v_info)); - gst_gl_context_clear_shader (src->base.context); - - return _src_shader_init (impl, context, v_info); -} - -static void -_src_circular_free (gpointer impl) -{ - struct SrcShader *src = impl; - - if (!src) - return; - - _src_shader_deinit (impl); - - g_free (impl); -} - -static gpointer -_src_circular_new (GstGLTestSrc * test) -{ - struct SrcShader *src = g_new0 (struct SrcShader, 1); - - src->base.src = test; - - return src; -} - -static const struct SrcFuncs src_circular = { - GST_GL_TEST_SRC_CIRCULAR, - _src_circular_new, - _src_circular_init, - _src_mandelbrot_fill_bound_fbo, - _src_circular_free, -}; - -static const struct SrcFuncs *src_impls[] = { - &src_smpte, - &src_snow, - &src_black, - &src_white, - &src_red, - &src_green, - &src_blue, - &src_checkers1, - &src_checkers2, - &src_checkers4, - &src_checkers8, - &src_circular, - &src_blink, - &src_mandelbrot, -}; - -const struct SrcFuncs * -gst_gl_test_src_get_src_funcs_for_pattern (GstGLTestSrcPattern pattern) -{ - gint i; - - for (i = 0; i < G_N_ELEMENTS (src_impls); i++) { - if (src_impls[i]->pattern == pattern) - return src_impls[i]; - } - - return NULL; -} diff --git a/ext/gl/gltestsrc.h b/ext/gl/gltestsrc.h deleted file mode 100644 index dbcab0cab..000000000 --- a/ext/gl/gltestsrc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* GStreamer - * Copyright (C) <2003> David A. Schleef <ds@schleef.org> - * - * 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 __GL_TEST_SRC_H__ -#define __GL_TEST_SRC_H__ - -#include <glib.h> - -typedef struct _GstGLTestSrc GstGLTestSrc; - -/** - * GstGLTestSrcPattern: - * @GST_GL_TEST_SRC_SMPTE: A standard SMPTE test pattern - * @GST_GL_TEST_SRC_SNOW: Random noise - * @GST_GL_TEST_SRC_BLACK: A black image - * @GST_GL_TEST_SRC_WHITE: A white image - * @GST_GL_TEST_SRC_RED: A red image - * @GST_GL_TEST_SRC_GREEN: A green image - * @GST_GL_TEST_SRC_BLUE: A blue image - * @GST_GL_TEST_SRC_CHECKERS1: Checkers pattern (1px) - * @GST_GL_TEST_SRC_CHECKERS2: Checkers pattern (2px) - * @GST_GL_TEST_SRC_CHECKERS4: Checkers pattern (4px) - * @GST_GL_TEST_SRC_CHECKERS8: Checkers pattern (8px) - * @GST_GL_TEST_SRC_CIRCULAR: Circular pattern - * @GST_GL_TEST_SRC_BLINK: Alternate between black and white - * - * The test pattern to produce. - */ -typedef enum { - GST_GL_TEST_SRC_SMPTE, - GST_GL_TEST_SRC_SNOW, - GST_GL_TEST_SRC_BLACK, - GST_GL_TEST_SRC_WHITE, - GST_GL_TEST_SRC_RED, - GST_GL_TEST_SRC_GREEN, - GST_GL_TEST_SRC_BLUE, - GST_GL_TEST_SRC_CHECKERS1, - GST_GL_TEST_SRC_CHECKERS2, - GST_GL_TEST_SRC_CHECKERS4, - GST_GL_TEST_SRC_CHECKERS8, - GST_GL_TEST_SRC_CIRCULAR, - GST_GL_TEST_SRC_BLINK, - GST_GL_TEST_SRC_MANDELBROT -} GstGLTestSrcPattern; - -#include "gstgltestsrc.h" - -struct BaseSrcImpl { - GstGLTestSrc *src; - GstGLContext *context; - GstVideoInfo v_info; -}; - -struct SrcFuncs -{ - GstGLTestSrcPattern pattern; - gpointer (*new) (GstGLTestSrc * src); - gboolean (*init) (gpointer impl, GstGLContext * context, GstVideoInfo * v_info); - gboolean (*fill_bound_fbo) (gpointer impl); - void (*free) (gpointer impl); -}; - -const struct SrcFuncs * gst_gl_test_src_get_src_funcs_for_pattern (GstGLTestSrcPattern pattern); - -#endif diff --git a/ext/gl/gstglcolorbalance.c b/ext/gl/gstglcolorbalance.c deleted file mode 100644 index 81630469d..000000000 --- a/ext/gl/gstglcolorbalance.c +++ /dev/null @@ -1,551 +0,0 @@ -/* GStreamer - * Copyright (C) <2016> Matthew Waters <matthew@centricular.com> - * - * 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. - */ -/* - * This file was modified from videobalance and converted to OpenGL - */ - -/** - * SECTION:element-glcolorbalance - * @title: glcolorbalance - * - * Adjusts brightness, contrast, hue, saturation on a video stream. - * - * ## Example launch line - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! glcolorbalance saturation=0.0 ! glcolorconvert ! gldownload ! ximagesink - * ]| This pipeline converts the image to black and white by setting the - * saturation to 0.0. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <string.h> -#include <gst/gl/gstglfuncs.h> -#include <gst/math-compat.h> -#include <gst/video/colorbalance.h> - -#include "gstglcolorbalance.h" - -GST_DEBUG_CATEGORY_STATIC (glcolorbalance_debug); -#define GST_CAT_DEFAULT glcolorbalance_debug - -/* GstGLColorBalance properties */ -#define DEFAULT_PROP_CONTRAST 1.0 -#define DEFAULT_PROP_BRIGHTNESS 0.0 -#define DEFAULT_PROP_HUE 0.0 -#define DEFAULT_PROP_SATURATION 1.0 - -/* *INDENT-OFF* */ -static const gchar *color_balance_frag = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform float brightness;\n" - "uniform float contrast;\n" - "uniform float saturation;\n" - "uniform float hue;\n" - "varying vec2 v_texcoord;\n" - "uniform sampler2D tex;\n" - "#define from_yuv_bt601_offset vec3(-0.0625, -0.5, -0.5)\n" - "#define from_yuv_bt601_rcoeff vec3(1.164, 0.000, 1.596)\n" - "#define from_yuv_bt601_gcoeff vec3(1.164,-0.391,-0.813)\n" - "#define from_yuv_bt601_bcoeff vec3(1.164, 2.018, 0.000)\n" - "#define from_rgb_bt601_offset vec3(0.0625, 0.5, 0.5)\n" - "#define from_rgb_bt601_ycoeff vec3(0.256816, 0.504154, 0.0979137)\n" - "#define from_rgb_bt601_ucoeff vec3(-0.148246, -0.29102, 0.439266)\n" - "#define from_rgb_bt601_vcoeff vec3(0.439271, -0.367833, -0.071438)\n" - "#define PI 3.14159265\n" - "\n" - "vec3 yuv_to_rgb (vec3 val) {\n" - " vec3 rgb;\n" - " val += from_yuv_bt601_offset;\n" - " rgb.r = dot(val, from_yuv_bt601_rcoeff);\n" - " rgb.g = dot(val, from_yuv_bt601_gcoeff);\n" - " rgb.b = dot(val, from_yuv_bt601_bcoeff);\n" - " return rgb;\n" - "}\n" - "vec3 rgb_to_yuv (vec3 val) {\n" - " vec3 yuv;\n" - " yuv.r = dot(val.rgb, from_rgb_bt601_ycoeff);\n" - " yuv.g = dot(val.rgb, from_rgb_bt601_ucoeff);\n" - " yuv.b = dot(val.rgb, from_rgb_bt601_vcoeff);\n" - " yuv += from_rgb_bt601_offset;\n" - " return yuv;\n" - "}\n" - /* 224 = 256 - (256 - 240) - 16*/ - "float luma_to_narrow (float luma) {\n" - " return (luma + 16.0 / 256.0) * 219.0 / 256.0;" - "}\n" - "float luma_to_full (float luma) {\n" - " return (luma * 256.0 / 219.0) - 16.0 / 256.0;" - "}\n" - "void main () {\n" - " vec3 yuv;\n" - /* operations translated from videobalanceand tested with glvideomixer - * with one pad's paremeters blend-equation-rgb={subtract,reverse-subtract}, - * blend-function-src-rgb=src-color and blend-function-dst-rgb=dst-color */ - " float hue_cos = cos (PI * hue);\n" - " float hue_sin = sin (PI * hue);\n" - " vec4 rgba = texture2D (tex, v_texcoord);\n" - " yuv = rgb_to_yuv (rgba.rgb);\n" - " yuv.x = clamp (luma_to_narrow (luma_to_full(yuv.x) * contrast) + brightness, 0.0, 1.0);\n" - " vec2 uv = yuv.yz;\n" - " yuv.y = clamp (0.5 + (((uv.x - 0.5) * hue_cos + (uv.y - 0.5) * hue_sin) * saturation), 0.0, 1.0);\n" - " yuv.z = clamp (0.5 + (((0.5 - uv.x) * hue_sin + (uv.y - 0.5) * hue_cos) * saturation), 0.0, 1.0);\n" - " rgba.rgb = yuv_to_rgb (yuv);\n" - " gl_FragColor = rgba;\n" - "}\n"; -/* *INDENT-ON* */ - -enum -{ - PROP_0, - PROP_CONTRAST, - PROP_BRIGHTNESS, - PROP_HUE, - PROP_SATURATION -}; - -static void gst_gl_color_balance_colorbalance_init (GstColorBalanceInterface * - iface); - -static void gst_gl_color_balance_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_color_balance_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -#define gst_gl_color_balance_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLColorBalance, gst_gl_color_balance, - GST_TYPE_GL_FILTER, - G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE, - gst_gl_color_balance_colorbalance_init)); - -static gboolean -gst_gl_color_balance_is_passthrough (GstGLColorBalance * glcolorbalance) -{ - return glcolorbalance->contrast == 1.0 && - glcolorbalance->brightness == 0.0 && - glcolorbalance->hue == 0.0 && glcolorbalance->saturation == 1.0; -} - -static void -gst_gl_color_balance_update_properties (GstGLColorBalance * glcolorbalance) -{ - gboolean current_passthrough, passthrough; - GstBaseTransform *base = GST_BASE_TRANSFORM (glcolorbalance); - - GST_OBJECT_LOCK (glcolorbalance); - passthrough = gst_gl_color_balance_is_passthrough (glcolorbalance); - GST_OBJECT_UNLOCK (glcolorbalance); - current_passthrough = gst_base_transform_is_passthrough (base); - - gst_base_transform_set_passthrough (base, passthrough); - if (current_passthrough != passthrough) - gst_base_transform_reconfigure_src (base); -} - -static gboolean -_create_shader (GstGLColorBalance * balance) -{ - GstGLBaseFilter *base_filter = GST_GL_BASE_FILTER (balance); - GstGLFilter *filter = GST_GL_FILTER (balance); - GError *error = NULL; - - if (balance->shader) - gst_object_unref (balance->shader); - - if (!(balance->shader = - gst_gl_shader_new_link_with_stages (base_filter->context, &error, - gst_glsl_stage_new_default_vertex (base_filter->context), - gst_glsl_stage_new_with_string (base_filter->context, - GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - color_balance_frag), NULL))) { - GST_ELEMENT_ERROR (balance, RESOURCE, NOT_FOUND, ("%s", - "Failed to initialize colorbalance shader"), ("%s", - error ? error->message : "Unknown error")); - return FALSE; - } - - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (balance->shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (balance->shader, "a_texcoord"); - - return TRUE; -} - -static gboolean -gst_gl_color_balance_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (base_filter); - - if (!_create_shader (balance)) - return FALSE; - - return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter); -} - -static void -gst_gl_color_balance_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (base_filter); - - if (balance->shader) - gst_object_unref (balance->shader); - balance->shader = NULL; - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static void -gst_gl_color_balance_before_transform (GstBaseTransform * base, GstBuffer * buf) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (base); - GstClockTime timestamp, stream_time; - - timestamp = GST_BUFFER_TIMESTAMP (buf); - stream_time = - gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp); - - GST_DEBUG_OBJECT (balance, "sync to %" GST_TIME_FORMAT, - GST_TIME_ARGS (timestamp)); - - if (GST_CLOCK_TIME_IS_VALID (stream_time)) - gst_object_sync_values (GST_OBJECT (balance), stream_time); -} - -static gboolean -gst_gl_color_balance_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (filter); - - if (!balance->shader) - _create_shader (balance); - - gst_gl_shader_use (balance->shader); - GST_OBJECT_LOCK (balance); - gst_gl_shader_set_uniform_1f (balance->shader, "brightness", - balance->brightness); - gst_gl_shader_set_uniform_1f (balance->shader, "contrast", balance->contrast); - gst_gl_shader_set_uniform_1f (balance->shader, "saturation", - balance->saturation); - gst_gl_shader_set_uniform_1f (balance->shader, "hue", balance->hue); - GST_OBJECT_UNLOCK (balance); - - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, - balance->shader); - - return TRUE; -} - -static void -gst_gl_color_balance_finalize (GObject * object) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (object); - GList *channels = NULL; - - channels = balance->channels; - while (channels) { - GstColorBalanceChannel *channel = channels->data; - - g_object_unref (channel); - channels->data = NULL; - channels = g_list_next (channels); - } - - if (balance->channels) - g_list_free (balance->channels); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_gl_color_balance_class_init (GstGLColorBalanceClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; - GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass; - GstGLBaseFilterClass *base_filter_class = (GstGLBaseFilterClass *) klass; - GstGLFilterClass *filter_class = (GstGLFilterClass *) klass; - - GST_DEBUG_CATEGORY_INIT (glcolorbalance_debug, "glcolorbalance", 0, - "glcolorbalance"); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->finalize = gst_gl_color_balance_finalize; - gobject_class->set_property = gst_gl_color_balance_set_property; - gobject_class->get_property = gst_gl_color_balance_get_property; - - g_object_class_install_property (gobject_class, PROP_CONTRAST, - g_param_spec_double ("contrast", "Contrast", "contrast", - 0.0, 2.0, DEFAULT_PROP_CONTRAST, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BRIGHTNESS, - g_param_spec_double ("brightness", "Brightness", "brightness", -1.0, 1.0, - DEFAULT_PROP_BRIGHTNESS, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_HUE, - g_param_spec_double ("hue", "Hue", "hue", -1.0, 1.0, DEFAULT_PROP_HUE, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_SATURATION, - g_param_spec_double ("saturation", "Saturation", "saturation", 0.0, 2.0, - DEFAULT_PROP_SATURATION, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_static_metadata (gstelement_class, "Video balance", - "Filter/Effect/Video", - "Adjusts brightness, contrast, hue, saturation on a video stream", - "Matthew Waters <matthew@centricular.com>"); - - trans_class->before_transform = - GST_DEBUG_FUNCPTR (gst_gl_color_balance_before_transform); - trans_class->transform_ip_on_passthrough = FALSE; - - base_filter_class->gl_start = - GST_DEBUG_FUNCPTR (gst_gl_color_balance_gl_start); - base_filter_class->gl_stop = GST_DEBUG_FUNCPTR (gst_gl_color_balance_gl_stop); - - filter_class->filter_texture = - GST_DEBUG_FUNCPTR (gst_gl_color_balance_filter_texture); -} - -static void -gst_gl_color_balance_init (GstGLColorBalance * glcolorbalance) -{ - const gchar *channels[4] = { "HUE", "SATURATION", - "BRIGHTNESS", "CONTRAST" - }; - gint i; - - /* Initialize propertiews */ - glcolorbalance->contrast = DEFAULT_PROP_CONTRAST; - glcolorbalance->brightness = DEFAULT_PROP_BRIGHTNESS; - glcolorbalance->hue = DEFAULT_PROP_HUE; - glcolorbalance->saturation = DEFAULT_PROP_SATURATION; - - gst_gl_color_balance_update_properties (glcolorbalance); - - /* Generate the channels list */ - for (i = 0; i < G_N_ELEMENTS (channels); i++) { - GstColorBalanceChannel *channel; - - channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); - channel->label = g_strdup (channels[i]); - channel->min_value = -1000; - channel->max_value = 1000; - - glcolorbalance->channels = - g_list_append (glcolorbalance->channels, channel); - } -} - -static const GList * -gst_gl_color_balance_colorbalance_list_channels (GstColorBalance * balance) -{ - GstGLColorBalance *glcolorbalance = GST_GL_COLOR_BALANCE (balance); - - g_return_val_if_fail (glcolorbalance != NULL, NULL); - g_return_val_if_fail (GST_IS_GL_COLOR_BALANCE (glcolorbalance), NULL); - - return glcolorbalance->channels; -} - -static void -gst_gl_color_balance_colorbalance_set_value (GstColorBalance * balance, - GstColorBalanceChannel * channel, gint value) -{ - GstGLColorBalance *vb = GST_GL_COLOR_BALANCE (balance); - gdouble new_val; - gboolean changed = FALSE; - - g_return_if_fail (vb != NULL); - g_return_if_fail (GST_IS_GL_COLOR_BALANCE (vb)); - g_return_if_fail (channel->label != NULL); - - GST_OBJECT_LOCK (vb); - if (!g_ascii_strcasecmp (channel->label, "HUE")) { - new_val = (value + 1000.0) * 2.0 / 2000.0 - 1.0; - changed = new_val != vb->hue; - vb->hue = new_val; - } else if (!g_ascii_strcasecmp (channel->label, "SATURATION")) { - new_val = (value + 1000.0) * 2.0 / 2000.0; - changed = new_val != vb->saturation; - vb->saturation = new_val; - } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) { - new_val = (value + 1000.0) * 2.0 / 2000.0 - 1.0; - changed = new_val != vb->brightness; - vb->brightness = new_val; - } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) { - new_val = (value + 1000.0) * 2.0 / 2000.0; - changed = new_val != vb->contrast; - vb->contrast = new_val; - } - GST_OBJECT_UNLOCK (vb); - - if (changed) - gst_gl_color_balance_update_properties (vb); - - if (changed) { - gst_color_balance_value_changed (balance, channel, - gst_color_balance_get_value (balance, channel)); - } -} - -static gint -gst_gl_color_balance_colorbalance_get_value (GstColorBalance * balance, - GstColorBalanceChannel * channel) -{ - GstGLColorBalance *vb = GST_GL_COLOR_BALANCE (balance); - gint value = 0; - - g_return_val_if_fail (vb != NULL, 0); - g_return_val_if_fail (GST_IS_GL_COLOR_BALANCE (vb), 0); - g_return_val_if_fail (channel->label != NULL, 0); - - if (!g_ascii_strcasecmp (channel->label, "HUE")) { - value = (vb->hue + 1) * 2000.0 / 2.0 - 1000.0; - } else if (!g_ascii_strcasecmp (channel->label, "SATURATION")) { - value = vb->saturation * 2000.0 / 2.0 - 1000.0; - } else if (!g_ascii_strcasecmp (channel->label, "BRIGHTNESS")) { - value = (vb->brightness + 1) * 2000.0 / 2.0 - 1000.0; - } else if (!g_ascii_strcasecmp (channel->label, "CONTRAST")) { - value = vb->contrast * 2000.0 / 2.0 - 1000.0; - } - - return value; -} - -static GstColorBalanceType -gst_gl_color_balance_colorbalance_get_balance_type (GstColorBalance * balance) -{ - return GST_COLOR_BALANCE_HARDWARE; -} - -static void -gst_gl_color_balance_colorbalance_init (GstColorBalanceInterface * iface) -{ - iface->list_channels = gst_gl_color_balance_colorbalance_list_channels; - iface->set_value = gst_gl_color_balance_colorbalance_set_value; - iface->get_value = gst_gl_color_balance_colorbalance_get_value; - iface->get_balance_type = gst_gl_color_balance_colorbalance_get_balance_type; -} - -static GstColorBalanceChannel * -gst_gl_color_balance_find_channel (GstGLColorBalance * balance, - const gchar * label) -{ - GList *l; - - for (l = balance->channels; l; l = l->next) { - GstColorBalanceChannel *channel = l->data; - - if (g_ascii_strcasecmp (channel->label, label) == 0) - return channel; - } - return NULL; -} - -static void -gst_gl_color_balance_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (object); - gdouble d; - const gchar *label = NULL; - - GST_OBJECT_LOCK (balance); - switch (prop_id) { - case PROP_CONTRAST: - d = g_value_get_double (value); - GST_DEBUG_OBJECT (balance, "Changing contrast from %lf to %lf", - balance->contrast, d); - if (d != balance->contrast) - label = "CONTRAST"; - balance->contrast = d; - break; - case PROP_BRIGHTNESS: - d = g_value_get_double (value); - GST_DEBUG_OBJECT (balance, "Changing brightness from %lf to %lf", - balance->brightness, d); - if (d != balance->brightness) - label = "BRIGHTNESS"; - balance->brightness = d; - break; - case PROP_HUE: - d = g_value_get_double (value); - GST_DEBUG_OBJECT (balance, "Changing hue from %lf to %lf", balance->hue, - d); - if (d != balance->hue) - label = "HUE"; - balance->hue = d; - break; - case PROP_SATURATION: - d = g_value_get_double (value); - GST_DEBUG_OBJECT (balance, "Changing saturation from %lf to %lf", - balance->saturation, d); - if (d != balance->saturation) - label = "SATURATION"; - balance->saturation = d; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - GST_OBJECT_UNLOCK (balance); - gst_gl_color_balance_update_properties (balance); - - if (label) { - GstColorBalanceChannel *channel = - gst_gl_color_balance_find_channel (balance, label); - gst_color_balance_value_changed (GST_COLOR_BALANCE (balance), channel, - gst_color_balance_get_value (GST_COLOR_BALANCE (balance), channel)); - } -} - -static void -gst_gl_color_balance_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLColorBalance *balance = GST_GL_COLOR_BALANCE (object); - - switch (prop_id) { - case PROP_CONTRAST: - g_value_set_double (value, balance->contrast); - break; - case PROP_BRIGHTNESS: - g_value_set_double (value, balance->brightness); - break; - case PROP_HUE: - g_value_set_double (value, balance->hue); - break; - case PROP_SATURATION: - g_value_set_double (value, balance->saturation); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/ext/gl/gstglcolorbalance.h b/ext/gl/gstglcolorbalance.h deleted file mode 100644 index cf0bcd7b8..000000000 --- a/ext/gl/gstglcolorbalance.h +++ /dev/null @@ -1,73 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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_GL_COLOR_BALANCE_H__ -#define __GST_GL_COLOR_BALANCE_H__ - -#include <gst/gst.h> -#include <gst/video/video.h> -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_COLOR_BALANCE \ - (gst_gl_color_balance_get_type()) -#define GST_GL_COLOR_BALANCE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_COLOR_BALANCE,GstGLColorBalance)) -#define GST_GL_COLOR_BALANCE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_COLOR_BALANCE,GstGLColorBalanceClass)) -#define GST_IS_GL_COLOR_BALANCE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_COLOR_BALANCE)) -#define GST_IS_GL_COLOR_BALANCE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_COLOR_BALANCE)) - -typedef struct _GstGLColorBalance GstGLColorBalance; -typedef struct _GstGLColorBalanceClass GstGLColorBalanceClass; - -/** - * GstGLColorBalance: - * - * Opaque data structure. - */ -struct _GstGLColorBalance { - GstGLFilter videofilter; - - /* < private > */ - GstGLShader *shader; - - /* channels for interface */ - GList *channels; - - /* properties */ - gdouble contrast; - gdouble brightness; - gdouble hue; - gdouble saturation; -}; - -struct _GstGLColorBalanceClass { - GstGLFilterClass parent_class; -}; - -GType gst_gl_color_balance_get_type(void); - -G_END_DECLS - -#endif /* __GST_GL_COLOR_BALANCE_H__ */ diff --git a/ext/gl/gstglcolorconvertelement.c b/ext/gl/gstglcolorconvertelement.c deleted file mode 100644 index 642b4942d..000000000 --- a/ext/gl/gstglcolorconvertelement.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012-2014 Matthew Waters <ystree00@gmail.com> - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 - -#include <gst/gl/gl.h> -#include "gstglcolorconvertelement.h" - -GST_DEBUG_CATEGORY_STATIC (gst_gl_color_convert_element_debug); -#define GST_CAT_DEFAULT gst_gl_color_convert_element_debug - -G_DEFINE_TYPE_WITH_CODE (GstGLColorConvertElement, gst_gl_color_convert_element, - GST_TYPE_GL_BASE_FILTER, - GST_DEBUG_CATEGORY_INIT (gst_gl_color_convert_element_debug, - "glconvertelement", 0, "convert"); - ); - -static gboolean gst_gl_color_convert_element_set_caps (GstBaseTransform * bt, - GstCaps * in_caps, GstCaps * out_caps); -static GstCaps *gst_gl_color_convert_element_transform_caps (GstBaseTransform * - bt, GstPadDirection direction, GstCaps * caps, GstCaps * filter); -static gboolean gst_gl_color_convert_element_get_unit_size (GstBaseTransform * - trans, GstCaps * caps, gsize * size); -static gboolean -gst_gl_color_convert_element_filter_meta (GstBaseTransform * trans, - GstQuery * query, GType api, const GstStructure * params); -static gboolean gst_gl_color_convert_element_decide_allocation (GstBaseTransform - * trans, GstQuery * query); -static GstFlowReturn -gst_gl_color_convert_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * inbuf, GstBuffer ** outbuf); -static GstFlowReturn gst_gl_color_convert_element_transform (GstBaseTransform * - bt, GstBuffer * inbuf, GstBuffer * outbuf); -static GstCaps *gst_gl_color_convert_element_fixate_caps (GstBaseTransform * - bt, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); - -static GstStaticPadTemplate gst_gl_color_convert_element_src_pad_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_COLOR_CONVERT_VIDEO_CAPS)); - -static GstStaticPadTemplate gst_gl_color_convert_element_sink_pad_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_COLOR_CONVERT_VIDEO_CAPS)); - -static gboolean -gst_gl_color_convert_element_stop (GstBaseTransform * bt) -{ - GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt); - - if (convert->convert) { - gst_object_unref (convert->convert); - convert->convert = NULL; - } - - gst_caps_replace (&convert->in_caps, NULL); - gst_caps_replace (&convert->out_caps, NULL); - - return - GST_BASE_TRANSFORM_CLASS (gst_gl_color_convert_element_parent_class)->stop - (bt); -} - -static void -gst_gl_color_convert_element_class_init (GstGLColorConvertElementClass * klass) -{ - GstBaseTransformClass *bt_class = GST_BASE_TRANSFORM_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - bt_class->transform_caps = gst_gl_color_convert_element_transform_caps; - bt_class->set_caps = gst_gl_color_convert_element_set_caps; - bt_class->get_unit_size = gst_gl_color_convert_element_get_unit_size; - bt_class->filter_meta = gst_gl_color_convert_element_filter_meta; - bt_class->decide_allocation = gst_gl_color_convert_element_decide_allocation; - bt_class->prepare_output_buffer = - gst_gl_color_convert_element_prepare_output_buffer; - bt_class->transform = gst_gl_color_convert_element_transform; - bt_class->stop = gst_gl_color_convert_element_stop; - bt_class->fixate_caps = gst_gl_color_convert_element_fixate_caps; - - bt_class->passthrough_on_same_caps = TRUE; - - gst_element_class_add_static_pad_template (element_class, - &gst_gl_color_convert_element_src_pad_template); - gst_element_class_add_static_pad_template (element_class, - &gst_gl_color_convert_element_sink_pad_template); - - gst_element_class_set_metadata (element_class, - "OpenGL color converter", "Filter/Converter/Video", - "Converts between color spaces using OpenGL shaders", - "Matthew Waters <matthew@centricular.com>"); -} - -static void -gst_gl_color_convert_element_init (GstGLColorConvertElement * convert) -{ - gst_base_transform_set_prefer_passthrough (GST_BASE_TRANSFORM (convert), - TRUE); -} - -static gboolean -gst_gl_color_convert_element_set_caps (GstBaseTransform * bt, - GstCaps * in_caps, GstCaps * out_caps) -{ - GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt); - - gst_caps_replace (&convert->in_caps, in_caps); - gst_caps_replace (&convert->out_caps, out_caps); - - if (convert->convert) - gst_gl_color_convert_set_caps (convert->convert, in_caps, out_caps); - - return TRUE; -} - -static GstCaps * -gst_gl_color_convert_element_transform_caps (GstBaseTransform * bt, - GstPadDirection direction, GstCaps * caps, GstCaps * filter) -{ - GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; - - return gst_gl_color_convert_transform_caps (context, direction, caps, filter); -} - -static gboolean -gst_gl_color_convert_element_get_unit_size (GstBaseTransform * trans, - GstCaps * caps, gsize * size) -{ - gboolean ret = FALSE; - GstVideoInfo info; - - ret = gst_video_info_from_caps (&info, caps); - if (ret) - *size = GST_VIDEO_INFO_SIZE (&info); - - return TRUE; -} - -static gboolean -gst_gl_color_convert_element_filter_meta (GstBaseTransform * trans, - GstQuery * query, GType api, const GstStructure * params) -{ - /* propose all metadata upstream */ - return TRUE; -} - -static gboolean -gst_gl_color_convert_element_decide_allocation (GstBaseTransform * trans, - GstQuery * query) -{ - GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (trans); - GstGLContext *context; - - /* get gl context */ - if (!GST_BASE_TRANSFORM_CLASS - (gst_gl_color_convert_element_parent_class)->decide_allocation (trans, - query)) - return FALSE; - - context = GST_GL_BASE_FILTER (trans)->context; - - if (!convert->convert) - convert->convert = gst_gl_color_convert_new (context); - - if (!gst_gl_color_convert_set_caps (convert->convert, convert->in_caps, - convert->out_caps)) - return FALSE; - - if (!gst_gl_color_convert_decide_allocation (convert->convert, query)) - return FALSE; - - return TRUE; -} - -static GstFlowReturn -gst_gl_color_convert_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * inbuf, GstBuffer ** outbuf) -{ - GstGLColorConvertElement *convert = GST_GL_COLOR_CONVERT_ELEMENT (bt); - GstBaseTransformClass *bclass; - - bclass = GST_BASE_TRANSFORM_GET_CLASS (bt); - - if (gst_base_transform_is_passthrough (bt)) { - *outbuf = inbuf; - return GST_FLOW_OK; - } - - if (!convert->convert) - return GST_FLOW_NOT_NEGOTIATED; - - *outbuf = gst_gl_color_convert_perform (convert->convert, inbuf); - if (!*outbuf) { - GST_ELEMENT_ERROR (bt, RESOURCE, NOT_FOUND, - ("%s", "Failed to convert video buffer"), (NULL)); - return GST_FLOW_ERROR; - } - - /* basetransform doesn't unref if they're the same */ - if (inbuf == *outbuf) - gst_buffer_unref (*outbuf); - else - bclass->copy_metadata (bt, inbuf, *outbuf); - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_gl_color_convert_element_transform (GstBaseTransform * bt, - GstBuffer * inbuf, GstBuffer * outbuf) -{ - return GST_FLOW_OK; -} - -static GstCaps * -gst_gl_color_convert_element_fixate_caps (GstBaseTransform * - bt, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) -{ - GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; - - return gst_gl_color_convert_fixate_caps (context, direction, caps, othercaps); -} diff --git a/ext/gl/gstglcolorconvertelement.h b/ext/gl/gstglcolorconvertelement.h deleted file mode 100644 index 2a0dd1dca..000000000 --- a/ext/gl/gstglcolorconvertelement.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters <ystree00@gmail.com> - * - * 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_GL_COLOR_CONVERT_ELEMENT_H__ -#define __GST_GL_COLOR_CONVERT_ELEMENT_H__ - -#include <gst/video/video.h> -#include <gst/gstmemory.h> - -#include <gst/gl/gstgl_fwd.h> - -G_BEGIN_DECLS - -GType gst_gl_color_convert_element_get_type (void); -#define GST_TYPE_GL_COLOR_CONVERT_ELEMENT (gst_gl_color_convert_element_get_type()) -#define GST_GL_COLOR_CONVERT_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_COLOR_CONVERT_ELEMENT,GstGLColorConvertElement)) -#define GST_GL_COLOR_CONVERT_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLColorConvertElementClass)) -#define GST_IS_GL_COLOR_CONVERT_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_COLOR_CONVERT_ELEMENT)) -#define GST_IS_GL_COLOR_CONVERT_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_COLOR_CONVERT_ELEMENT)) -#define GST_GL_COLOR_CONVERT_ELEMENT_CAST(obj) ((GstGLColorConvertElement*)(obj)) - -typedef struct _GstGLColorConvertElement GstGLColorConvertElement; -typedef struct _GstGLColorConvertElementClass GstGLColorConvertElementClass; -typedef struct _GstGLColorConvertElementPrivate GstGLColorConvertElementPrivate; - -struct _GstGLColorConvertElement -{ - GstGLBaseFilter parent; - - GstGLColorConvert *convert; - GstCaps *in_caps; - GstCaps *out_caps; -}; - -struct _GstGLColorConvertElementClass -{ - GstGLBaseFilterClass object_class; -}; - -G_END_DECLS - -#endif /* __GST_GL_COLOR_CONVERT_ELEMENT_H__ */ diff --git a/ext/gl/gstglcolorscale.c b/ext/gl/gstglcolorscale.c deleted file mode 100644 index 88b71ef70..000000000 --- a/ext/gl/gstglcolorscale.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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-glcolorscale - * @title: glcolorscale - * - * video frame scaling and colorspace conversion. - * - * ## Scaling and Color space conversion - * - * Equivalent to glupload ! gldownload. - * - * ## Examples - * |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw ! glcolorscale ! ximagesink - * ]| A pipeline to test colorspace conversion. - * FBO is required. - |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw, width=640, height=480, format=AYUV ! glcolorscale ! \ - * video/x-raw, width=320, height=240, format=YV12 ! videoconvert ! autovideosink - * ]| A pipeline to test hardware scaling and colorspace conversion. - * FBO and GLSL are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstglcolorscale.h" - -#define GST_CAT_DEFAULT gst_gl_colorscale_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -/* Properties */ -enum -{ - PROP_0 -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_colorscale_debug, "glcolorscale", 0, "glcolorscale element"); -#define gst_gl_colorscale_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLColorscale, gst_gl_colorscale, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_colorscale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_colorscale_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_colorscale_gl_start (GstGLBaseFilter * base_filter); -static void gst_gl_colorscale_gl_stop (GstGLBaseFilter * base_filter); - -static gboolean gst_gl_colorscale_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static void -gst_gl_colorscale_class_init (GstGLColorscaleClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - GstBaseTransformClass *basetransform_class; - GstGLBaseFilterClass *base_filter_class; - GstGLFilterClass *filter_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - basetransform_class = GST_BASE_TRANSFORM_CLASS (klass); - base_filter_class = GST_GL_BASE_FILTER_CLASS (klass); - filter_class = GST_GL_FILTER_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_colorscale_set_property; - gobject_class->get_property = gst_gl_colorscale_get_property; - - gst_element_class_set_metadata (element_class, "OpenGL color scale", - "Filter/Effect/Video", "Colorspace converter and video scaler", - "Julien Isorce <julien.isorce@gmail.com>\n" - "Matthew Waters <matthew@centricular.com>"); - - basetransform_class->passthrough_on_same_caps = TRUE; - - base_filter_class->gl_start = GST_DEBUG_FUNCPTR (gst_gl_colorscale_gl_start); - base_filter_class->gl_stop = GST_DEBUG_FUNCPTR (gst_gl_colorscale_gl_stop); - base_filter_class->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2; - - filter_class->filter_texture = gst_gl_colorscale_filter_texture; -} - -static void -gst_gl_colorscale_init (GstGLColorscale * colorscale) -{ -} - -static void -gst_gl_colorscale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_colorscale_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_colorscale_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLColorscale *colorscale = GST_GL_COLORSCALE (base_filter); - GstGLFilter *filter = GST_GL_FILTER (base_filter); - GstGLShader *shader; - GError *error = NULL; - - if (!(shader = gst_gl_shader_new_default (base_filter->context, &error))) { - GST_ERROR_OBJECT (colorscale, "Failed to initialize shader: %s", - error->message); - gst_object_unref (shader); - return FALSE; - } - - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (shader, "a_texcoord"); - - colorscale->shader = shader; - - return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter); -} - -static void -gst_gl_colorscale_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLColorscale *colorscale = GST_GL_COLORSCALE (base_filter); - - if (colorscale->shader) { - gst_object_unref (colorscale->shader); - colorscale->shader = NULL; - } - - return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static gboolean -gst_gl_colorscale_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLColorscale *colorscale = GST_GL_COLORSCALE (filter); - - if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context)) - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, - colorscale->shader); - - return TRUE; -} diff --git a/ext/gl/gstglcolorscale.h b/ext/gl/gstglcolorscale.h deleted file mode 100644 index 933599651..000000000 --- a/ext/gl/gstglcolorscale.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GLCOLORSCALE_H_ -#define _GST_GLCOLORSCALE_H_ - -#include <gst/gst.h> -#include <gst/video/video.h> - -#include <gst/gl/gstglfilter.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_COLORSCALE (gst_gl_colorscale_get_type()) -#define GST_GL_COLORSCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_COLORSCALE,GstGLColorscale)) -#define GST_IS_GL_COLORSCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_COLORSCALE)) -#define GST_GL_COLORSCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_COLORSCALE,GstGLColorscaleClass)) -#define GST_IS_GL_COLORSCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_COLORSCALE)) -#define GST_GL_COLORSCALE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_COLORSCALE,GstGLColorscaleClass)) - -typedef struct _GstGLColorscale GstGLColorscale; -typedef struct _GstGLColorscaleClass GstGLColorscaleClass; - - -struct _GstGLColorscale -{ - GstGLFilter filter; - - GstGLShader *shader; -}; - -struct _GstGLColorscaleClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_colorscale_get_type (void); - -G_END_DECLS - -#endif /* _GST_GLCOLORSCALE_H_ */ diff --git a/ext/gl/gstgldeinterlace.c b/ext/gl/gstgldeinterlace.c deleted file mode 100644 index 3b26715dc..000000000 --- a/ext/gl/gstgldeinterlace.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Julien Isorce <julien.isorce@mail.com> - * - * 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-deinterlace - * @title: deinterlace - * - * Deinterlacing using based on fragment shaders. - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! gldeinterlace ! glimagesink - * ]| - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gl/gstglfuncs.h> - -#include "gstgldeinterlace.h" - -#define GST_CAT_DEFAULT gst_gl_deinterlace_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_0, - PROP_METHOD -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_deinterlace_debug, "gldeinterlace", 0, "gldeinterlace element"); -#define gst_gl_deinterlace_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLDeinterlace, gst_gl_deinterlace, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_deinterlace_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_gl_deinterlace_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_deinterlace_start (GstBaseTransform * trans); -static gboolean gst_gl_deinterlace_reset (GstBaseTransform * trans); -static gboolean gst_gl_deinterlace_init_fbo (GstGLFilter * filter); -static gboolean gst_gl_deinterlace_filter (GstGLFilter * filter, - GstBuffer * inbuf, GstBuffer * outbuf); -static gboolean gst_gl_deinterlace_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); -static gboolean gst_gl_deinterlace_vfir_callback (GstGLFilter * filter, - GstGLMemory * in_tex, gpointer stuff); -static gboolean gst_gl_deinterlace_greedyh_callback (GstGLFilter * filter, - GstGLMemory * in_tex, gpointer stuff); - -/* *INDENT-OFF* */ -static const gchar *greedyh_fragment_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform sampler2D tex;\n" - "uniform sampler2D tex_prev;\n" - "uniform float max_comb;\n" - "uniform float motion_threshold;\n" - "uniform float motion_sense;\n" - "uniform float width;\n" - "uniform float height;\n" - "varying vec2 v_texcoord;\n" - - "void main () {\n" - " if (int(mod(v_texcoord.y * height, 2.0)) == 0) {\n" - " gl_FragColor = vec4(texture2D(tex_prev, v_texcoord).rgb, 1.0);\n" - " } else {\n" - " vec2 texcoord_L1_a1, texcoord_L3_a1, texcoord_L1, texcoord_L3, texcoord_L1_1, texcoord_L3_1;\n" - " vec3 L1_a1, L3_a1, L1, L3, L1_1, L3_1;\n" - - " texcoord_L1 = vec2(v_texcoord.x, v_texcoord.y - 1.0 / height);\n" - " texcoord_L3 = vec2(v_texcoord.x, v_texcoord.y + 1.0 / height);\n" - " L1 = texture2D(tex_prev, texcoord_L1).rgb;\n" - " L3 = texture2D(tex_prev, texcoord_L3).rgb;\n" - " if (v_texcoord.x == 1.0 && v_texcoord.y == 1.0) {\n" - " L1_1 = L1;\n" - " L3_1 = L3;\n" - " } else {\n" - " texcoord_L1_1 = vec2(v_texcoord.x + 1.0 / width, v_texcoord.y - 1.0 / height);\n" - " texcoord_L3_1 = vec2(v_texcoord.x + 1.0 / width, v_texcoord.y + 1.0 / height);\n" - " L1_1 = texture2D(tex_prev, texcoord_L1_1).rgb;\n" - " L3_1 = texture2D(tex_prev, texcoord_L3_1).rgb;\n" - " }\n" - - " if (int(ceil(v_texcoord.x + v_texcoord.y)) == 0) {\n" - " L1_a1 = L1;\n" - " L3_a1 = L3;\n" - " } else {\n" - " texcoord_L1_a1 = vec2(v_texcoord.x - 1.0 / width, v_texcoord.y - 1.0 / height);\n" - " texcoord_L3_a1 = vec2(v_texcoord.x - 1.0 / width, v_texcoord.y + 1.0 / height);\n" - " L1_a1 = texture2D(tex_prev, texcoord_L1_a1).rgb;\n" - " L3_a1 = texture2D(tex_prev, texcoord_L3_a1).rgb;\n" - " }\n" - //STEP 1 - " vec3 avg_a1 = (L1_a1 + L3_a1) / 2.0;\n" - " vec3 avg = (L1 + L3) / 2.0;\n" - " vec3 avg_1 = (L1_1 + L3_1) / 2.0;\n" - " vec3 avg_s = (avg_a1 + avg_1) / 2.0;\n" - " vec3 avg_sc = (avg_s + avg) / 2.0;\n" - " vec3 L2 = texture2D(tex, v_texcoord).rgb;\n" - " vec3 LP2 = texture2D(tex_prev, v_texcoord).rgb;\n" - " vec3 best;\n" - " if (abs(L2.r - avg_sc.r) < abs(LP2.r - avg_sc.r)) {\n" - " best.r = L2.r;\n" " } else {\n" - " best.r = LP2.r;\n" - " }\n" - - " if (abs(L2.g - avg_sc.g) < abs(LP2.g - avg_sc.g)) {\n" - " best.g = L2.g;\n" - " } else {\n" - " best.g = LP2.g;\n" - " }\n" - - " if (abs(L2.b - avg_sc.b) < abs(LP2.b - avg_sc.b)) {\n" - " best.b = L2.b;\n" - " } else {\n" - " best.b = LP2.b;\n" - " }\n" - //STEP 2 - " vec3 last;\n" - " last.r = clamp(best.r, max(min(L1.r, L3.r) - max_comb, 0.0), min(max(L1.r, L3.r) + max_comb, 1.0));\n" - " last.g = clamp(best.g, max(min(L1.g, L3.g) - max_comb, 0.0), min(max(L1.g, L3.g) + max_comb, 1.0));\n" - " last.b = clamp(best.b, max(min(L1.b, L3.b) - max_comb, 0.0), min(max(L1.b, L3.b) + max_comb, 1.0));\n" - //STEP 3 - " const vec3 luma = vec3 (0.299011, 0.586987, 0.114001);" - " float mov = min(max(abs(dot(L2 - LP2, luma)) - motion_threshold, 0.0) * motion_sense, 1.0);\n" - " last = last * (1.0 - mov) + avg_sc * mov;\n" - " gl_FragColor = vec4(last, 1.0);\n" - " }\n" - "}\n"; - -const gchar *vfir_fragment_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform sampler2D tex;\n" - "uniform float width;\n" - "uniform float height;\n" - "varying vec2 v_texcoord;\n" - "void main()\n" - "{\n" - " vec2 topcoord, botcoord;\n" - " vec4 cur_color, top_color, bot_color;\n" - " topcoord.x = v_texcoord.x;\n" - " botcoord.x = v_texcoord.x;\n" - " if (v_texcoord.y == 0.0 || v_texcoord.y == 1.0) {\n" - " topcoord.y = v_texcoord.y ;\n" - " botcoord.y = v_texcoord.y ;\n" - " }\n" - " else {\n" - " topcoord.y = v_texcoord.y - 1.0/height;\n" - " botcoord.y = v_texcoord.y + 1.0/height;\n" - " }\n" - " cur_color = texture2D(tex, v_texcoord);\n" - " top_color = texture2D(tex, topcoord);\n" - " bot_color = texture2D(tex, botcoord);\n" - " gl_FragColor = 0.5*cur_color + 0.25*top_color + 0.25*bot_color;\n" - "}"; -/* *INDENT-ON* */ - -/* dont' forget to edit the following when a new method is added */ -typedef enum -{ - GST_GL_DEINTERLACE_VFIR, - GST_GL_DEINTERLACE_GREEDYH -} GstGLDeinterlaceMethod; - -static const GEnumValue * -gst_gl_deinterlace_get_methods (void) -{ - static const GEnumValue method_types[] = { - {GST_GL_DEINTERLACE_VFIR, "Blur Vertical", "vfir"}, - {GST_GL_DEINTERLACE_GREEDYH, "Motion Adaptive: Advanced Detection", - "greedyh"}, - {0, NULL, NULL} - }; - return method_types; -} - -#define GST_TYPE_GL_DEINTERLACE_METHODS (gst_gl_deinterlace_method_get_type ()) -static GType -gst_gl_deinterlace_method_get_type (void) -{ - static GType gl_deinterlace_method_type = 0; - if (!gl_deinterlace_method_type) { - gl_deinterlace_method_type = - g_enum_register_static ("GstGLDeinterlaceMethod", - gst_gl_deinterlace_get_methods ()); - } - return gl_deinterlace_method_type; -} - -static void -gst_gl_deinterlace_set_method (GstGLDeinterlace * deinterlace, - guint method_types) -{ - switch (method_types) { - case GST_GL_DEINTERLACE_VFIR: - deinterlace->deinterlacefunc = gst_gl_deinterlace_vfir_callback; - deinterlace->current_method = method_types; - break; - case GST_GL_DEINTERLACE_GREEDYH: - deinterlace->deinterlacefunc = gst_gl_deinterlace_greedyh_callback; - deinterlace->current_method = method_types; - break; - default: - g_assert_not_reached (); - break; - } -} - -static void -gst_gl_deinterlace_class_init (GstGLDeinterlaceClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_deinterlace_set_property; - gobject_class->get_property = gst_gl_deinterlace_get_property; - - gst_element_class_set_metadata (element_class, - "OpenGL deinterlacing filter", "Deinterlace", - "Deinterlacing based on fragment shaders", - "Julien Isorce <julien.isorce@mail.com>"); - - g_object_class_install_property (gobject_class, - PROP_METHOD, - g_param_spec_enum ("method", - "Deinterlace Method", - "Select which deinterlace method apply to GL video texture", - GST_TYPE_GL_DEINTERLACE_METHODS, - GST_GL_DEINTERLACE_VFIR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_deinterlace_start; - GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_deinterlace_reset; - - GST_GL_FILTER_CLASS (klass)->filter = gst_gl_deinterlace_filter; - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_deinterlace_filter_texture; - GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_deinterlace_init_fbo; - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_deinterlace_init (GstGLDeinterlace * filter) -{ - filter->shaderstable = NULL; - filter->deinterlacefunc = gst_gl_deinterlace_vfir_callback; - filter->current_method = GST_GL_DEINTERLACE_VFIR; - filter->prev_buffer = NULL; - filter->prev_tex = NULL; -} - -static gboolean -gst_gl_deinterlace_start (GstBaseTransform * trans) -{ - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (trans); - - deinterlace_filter->shaderstable = g_hash_table_new (g_str_hash, g_str_equal); - - return GST_BASE_TRANSFORM_CLASS (parent_class)->start (trans); -} - -static void -gst_gl_deinterlace_ghash_func_clean (gpointer key, gpointer value, - gpointer data) -{ - GstGLShader *shader = (GstGLShader *) value; - - gst_object_unref (shader); - - value = NULL; -} - -static gboolean -gst_gl_deinterlace_reset (GstBaseTransform * trans) -{ - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (trans); - - gst_buffer_replace (&deinterlace_filter->prev_buffer, NULL); - - //blocking call, wait the opengl thread has destroyed the shader - if (deinterlace_filter->shaderstable) { - /* release shaders in the gl thread */ - g_hash_table_foreach (deinterlace_filter->shaderstable, - gst_gl_deinterlace_ghash_func_clean, deinterlace_filter); - - /* clean the htable without calling values destructors - * because shaders have been released in the glthread - * through the foreach func */ - g_hash_table_unref (deinterlace_filter->shaderstable); - deinterlace_filter->shaderstable = NULL; - } - - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans); -} - -static void -gst_gl_deinterlace_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLDeinterlace *filter = GST_GL_DEINTERLACE (object); - - switch (prop_id) { - case PROP_METHOD: - gst_gl_deinterlace_set_method (filter, g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_deinterlace_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLDeinterlace *filter = GST_GL_DEINTERLACE (object); - - switch (prop_id) { - case PROP_METHOD: - g_value_set_enum (value, filter->current_method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_deinterlace_init_fbo (GstGLFilter * filter) -{ - return TRUE; -} - -static gboolean -gst_gl_deinterlace_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter); - - //blocking call, use a FBO - gst_gl_filter_render_to_target (filter, in_tex, out_tex, - deinterlace_filter->deinterlacefunc, deinterlace_filter); - - return TRUE; -} - -static gboolean -gst_gl_deinterlace_filter (GstGLFilter * filter, GstBuffer * inbuf, - GstBuffer * outbuf) -{ - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter); - - gst_gl_filter_filter_texture (filter, inbuf, outbuf); - - gst_buffer_replace (&deinterlace_filter->prev_buffer, inbuf); - - return TRUE; -} - -static GstGLShader * -gst_gl_deinterlace_get_fragment_shader (GstGLFilter * filter, - const gchar * shader_name, const gchar * shader_source) -{ - GstGLShader *shader = NULL; - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter); - GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; - - shader = g_hash_table_lookup (deinterlace_filter->shaderstable, shader_name); - - if (!shader) { - GError *error = NULL; - - if (!(shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - shader_source), NULL))) { - GST_ELEMENT_ERROR (deinterlace_filter, RESOURCE, NOT_FOUND, - ("Failed to initialize %s shader", shader_name), (NULL)); - } - - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (shader, "a_texcoord"); - } - - g_hash_table_insert (deinterlace_filter->shaderstable, (gchar *) shader_name, - shader); - - return shader; -} - -static gboolean -gst_gl_deinterlace_vfir_callback (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer user_data) -{ - GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; - const GstGLFuncs *gl = context->gl_vtable; - GstGLShader *shader; - - shader = gst_gl_deinterlace_get_fragment_shader (filter, "vfir", - vfir_fragment_source); - - if (!shader) - return FALSE; - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - } -#endif - - gst_gl_shader_use (shader); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - - gst_gl_filter_draw_fullscreen_quad (filter); - - return TRUE; -} - -static gboolean -gst_gl_deinterlace_greedyh_callback (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer user_data) -{ - GstGLShader *shader; - GstGLDeinterlace *deinterlace_filter = GST_GL_DEINTERLACE (filter); - GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; - GstGLFuncs *gl = context->gl_vtable; - - shader = - gst_gl_deinterlace_get_fragment_shader (filter, "greedhy", - greedyh_fragment_source); - - if (!shader) - return FALSE; - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (context)) { - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - } -#endif - - gst_gl_shader_use (shader); - - if (G_LIKELY (deinterlace_filter->prev_tex != NULL)) { - gl->ActiveTexture (GL_TEXTURE1); - gst_gl_shader_set_uniform_1i (shader, "tex_prev", 1); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (deinterlace_filter->prev_tex)); - } - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "max_comb", 5.0f / 255.0f); - gst_gl_shader_set_uniform_1f (shader, "motion_threshold", 25.0f / 255.0f); - gst_gl_shader_set_uniform_1f (shader, "motion_sense", 30.0f / 255.0f); - - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - - gst_gl_filter_draw_fullscreen_quad (filter); - - /* we keep the previous buffer around so this is safe */ - deinterlace_filter->prev_tex = in_tex; - - return TRUE; -} diff --git a/ext/gl/gstgldeinterlace.h b/ext/gl/gstgldeinterlace.h deleted file mode 100644 index 3d78d6609..000000000 --- a/ext/gl/gstgldeinterlace.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_DEINTERLACE_H_ -#define _GST_GL_DEINTERLACE_H_ - -#include <gst/gl/gstglfilter.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_DEINTERLACE (gst_gl_deinterlace_get_type()) -#define GST_GL_DEINTERLACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DEINTERLACE,GstGLDeinterlace)) -#define GST_IS_GL_DEINTERLACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DEINTERLACE)) -#define GST_GL_DEINTERLACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_DEINTERLACE,GstGLDeinterlaceClass)) -#define GST_IS_GL_DEINTERLACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_DEINTERLACE)) -#define GST_GL_DEINTERLACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_DEINTERLACE,GstGLDeinterlaceClass)) - -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) - -typedef struct _GstGLDeinterlace GstGLDeinterlace; -typedef struct _GstGLDeinterlaceClass GstGLDeinterlaceClass; - -struct _GstGLDeinterlace -{ - GstGLFilter filter; - - GstGLFilterRenderFunc deinterlacefunc; - GHashTable *shaderstable; - GstBuffer *prev_buffer; - GstGLMemory * prev_tex; - - gint current_method; -}; - -struct _GstGLDeinterlaceClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_deinterlace_get_type (void); - -G_END_DECLS - -#endif /* _GST_GLFILTERLAPLACIAN_H_ */ diff --git a/ext/gl/gstgldifferencematte.c b/ext/gl/gstgldifferencematte.c deleted file mode 100644 index e80577054..000000000 --- a/ext/gl/gstgldifferencematte.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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-gldifferencematte. - * @title: gldifferencematte. - * - * Saves a background frame and replace it with a pixbuf. - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! gldifferencemate location=backgroundimagefile ! glimagesink - * ]| - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdlib.h> -#include <png.h> - -#include <gst/gl/gstglfuncs.h> - -#include "gstgldifferencematte.h" -#include "effects/gstgleffectssources.h" - -#if PNG_LIBPNG_VER >= 10400 -#define int_p_NULL NULL -#define png_infopp_NULL NULL -#endif - -#define GST_CAT_DEFAULT gst_gl_differencematte_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_differencematte_debug, "gldifferencematte", 0, "gldifferencematte element"); - -#define gst_gl_differencematte_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLDifferenceMatte, gst_gl_differencematte, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_differencematte_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_gl_differencematte_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_differencematte_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static gboolean gst_gl_differencematte_loader (GstGLFilter * filter); - -enum -{ - PROP_0, - PROP_LOCATION, -}; - - -/* init resources that need a gl context */ -static gboolean -gst_gl_differencematte_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (base_filter); - GstGLFilter *filter = GST_GL_FILTER (base_filter); - GstGLContext *context = base_filter->context; - GstGLBaseMemoryAllocator *tex_alloc; - GstGLAllocationParams *params; - GError *error = NULL; - gint i; - - if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter)) - return FALSE; - - tex_alloc = (GstGLBaseMemoryAllocator *) - gst_gl_memory_allocator_get_default (context); - params = - (GstGLAllocationParams *) gst_gl_video_allocation_params_new (context, - NULL, &filter->out_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - - for (i = 0; i < 4; i++) - differencematte->midtexture[i] = - (GstGLMemory *) gst_gl_base_memory_alloc (tex_alloc, params); - gst_gl_allocation_params_free (params); - gst_object_unref (tex_alloc); - - if (!(differencematte->identity_shader = - gst_gl_shader_new_default (context, &error))) { - GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s", - "Failed to compile identity shader"), ("%s", error->message)); - return FALSE; - } - - if (!(differencematte->shader[0] = - gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - difference_fragment_source), NULL))) { - GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s", - "Failed to compile difference shader"), ("%s", error->message)); - return FALSE; - } - - if (!(differencematte->shader[1] = - gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - hconv7_fragment_source_gles2), NULL))) { - GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s", - "Failed to compile convolution shader"), ("%s", error->message)); - return FALSE; - } - - if (!(differencematte->shader[2] = - gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - vconv7_fragment_source_gles2), NULL))) { - GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s", - "Failed to compile convolution shader"), ("%s", error->message)); - return FALSE; - } - - if (!(differencematte->shader[3] = - gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - texture_interp_fragment_source), NULL))) { - GST_ELEMENT_ERROR (differencematte, RESOURCE, NOT_FOUND, ("%s", - "Failed to compile interpolation shader"), ("%s", error->message)); - return FALSE; - } - - /* FIXME: this should really be per shader */ - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (differencematte->shader[2], - "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (differencematte->shader[2], - "a_texcoord"); - - return TRUE; -} - -/* free resources that need a gl context */ -static void -gst_gl_differencematte_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (base_filter); - gint i; - - if (differencematte->savedbgtexture) { - gst_memory_unref (GST_MEMORY_CAST (differencematte->savedbgtexture)); - differencematte->savedbgtexture = NULL; - } - - if (differencematte->newbgtexture) { - gst_memory_unref (GST_MEMORY_CAST (differencematte->newbgtexture)); - differencematte->newbgtexture = NULL; - } - - for (i = 0; i < 4; i++) { - if (differencematte->identity_shader) { - gst_object_unref (differencematte->identity_shader); - differencematte->identity_shader = NULL; - } - - if (differencematte->shader[i]) { - gst_object_unref (differencematte->shader[i]); - differencematte->shader[i] = NULL; - } - - if (differencematte->midtexture[i]) { - gst_memory_unref (GST_MEMORY_CAST (differencematte->midtexture[i])); - differencematte->midtexture[i] = NULL; - } - } - differencematte->location = NULL; - differencematte->pixbuf = NULL; - differencematte->bg_has_changed = FALSE; - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static void -gst_gl_differencematte_class_init (GstGLDifferenceMatteClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_differencematte_set_property; - gobject_class->get_property = gst_gl_differencematte_get_property; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_differencematte_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_differencematte_gl_stop; - - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_differencematte_filter_texture; - - g_object_class_install_property (gobject_class, - PROP_LOCATION, - g_param_spec_string ("location", - "Background image location", - "Background image location", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, - "Gstreamer OpenGL DifferenceMatte", "Filter/Effect/Video", - "Saves a background frame and replace it with a pixbuf", - "Filippo Argiolas <filippo.argiolas@gmail.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2; -} - -static void -gst_gl_differencematte_init (GstGLDifferenceMatte * differencematte) -{ - differencematte->shader[0] = NULL; - differencematte->shader[1] = NULL; - differencematte->shader[2] = NULL; - differencematte->shader[3] = NULL; - differencematte->location = NULL; - differencematte->pixbuf = NULL; - differencematte->savedbgtexture = 0; - differencematte->newbgtexture = 0; - differencematte->bg_has_changed = FALSE; - - fill_gaussian_kernel (differencematte->kernel, 7, 30.0); -} - -static void -gst_gl_differencematte_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object); - - switch (prop_id) { - case PROP_LOCATION: - g_free (differencematte->location); - differencematte->bg_has_changed = TRUE; - differencematte->location = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_differencematte_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (object); - - switch (prop_id) { - case PROP_LOCATION: - g_value_set_string (value, differencematte->location); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -init_pixbuf_texture (GstGLDifferenceMatte * differencematte) -{ - GstGLContext *context = GST_GL_BASE_FILTER (differencematte)->context; - GstGLFilter *filter = GST_GL_FILTER (differencematte); - GstGLBaseMemoryAllocator *tex_alloc; - GstGLAllocationParams *params; - GstVideoInfo v_info; - - tex_alloc = (GstGLBaseMemoryAllocator *) - gst_gl_memory_allocator_get_default (context); - gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, - differencematte->pbuf_width, differencematte->pbuf_height); - params = - (GstGLAllocationParams *) gst_gl_video_allocation_params_new (context, - NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - - differencematte->newbgtexture = - (GstGLMemory *) gst_gl_base_memory_alloc (tex_alloc, params); - gst_gl_allocation_params_free (params); - - if (differencematte->savedbgtexture == NULL) { - params = - (GstGLAllocationParams *) gst_gl_video_allocation_params_new (context, - NULL, &filter->out_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, - GST_GL_RGBA); - - differencematte->savedbgtexture = - (GstGLMemory *) gst_gl_base_memory_alloc (tex_alloc, params); - gst_gl_allocation_params_free (params); - } - - gst_object_unref (tex_alloc); -} - -static gboolean -gst_gl_differencematte_diff (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gst_gl_shader_use (differencematte->shader[0]); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0); - - gl->ActiveTexture (GL_TEXTURE1); - gl->BindTexture (GL_TEXTURE_2D, - gst_gl_memory_get_texture_id (differencematte->savedbgtexture)); - - gst_gl_shader_set_uniform_1i (differencematte->shader[0], "saved", 1); - - gst_gl_filter_draw_fullscreen_quad (filter); - - return TRUE; -} - -static gboolean -gst_gl_differencematte_hblur (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gst_gl_shader_use (differencematte->shader[1]); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (differencematte->shader[1], "tex", 0); - - gst_gl_shader_set_uniform_1fv (differencematte->shader[1], "kernel", 7, - differencematte->kernel); - gst_gl_shader_set_uniform_1f (differencematte->shader[1], "gauss_width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - - gst_gl_filter_draw_fullscreen_quad (filter); - - return TRUE; -} - -static gboolean -gst_gl_differencematte_vblur (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gst_gl_shader_use (differencematte->shader[2]); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (differencematte->shader[2], "tex", 0); - - gst_gl_shader_set_uniform_1fv (differencematte->shader[2], "kernel", 7, - differencematte->kernel); - gst_gl_shader_set_uniform_1f (differencematte->shader[2], "gauss_height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - - gst_gl_filter_draw_fullscreen_quad (filter); - - return TRUE; -} - -static gboolean -gst_gl_differencematte_interp (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gst_gl_shader_use (differencematte->shader[3]); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_set_uniform_1i (differencematte->shader[3], "blend", 0); - - gl->ActiveTexture (GL_TEXTURE1); - gl->BindTexture (GL_TEXTURE_2D, differencematte->newbgtexture->tex_id); - - gst_gl_shader_set_uniform_1i (differencematte->shader[3], "base", 1); - - gl->ActiveTexture (GL_TEXTURE2); - gl->BindTexture (GL_TEXTURE_2D, differencematte->midtexture[2]->tex_id); - - gst_gl_shader_set_uniform_1i (differencematte->shader[3], "alpha", 2); - - gst_gl_filter_draw_fullscreen_quad (filter); - - return TRUE; -} - -static gboolean -gst_gl_differencematte_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - - differencematte->intexture = in_tex; - - if (differencematte->bg_has_changed && (differencematte->location != NULL)) { - - if (!gst_gl_differencematte_loader (filter)) - differencematte->pixbuf = NULL; - - init_pixbuf_texture (differencematte); - - /* save current frame, needed to calculate difference between - * this frame and next ones */ - gst_gl_filter_render_to_target_with_shader (filter, in_tex, - differencematte->savedbgtexture, differencematte->identity_shader); - - if (differencematte->pixbuf) { - free (differencematte->pixbuf); - differencematte->pixbuf = NULL; - } - - differencematte->bg_has_changed = FALSE; - } - - if (differencematte->savedbgtexture != NULL) { - gst_gl_filter_render_to_target (filter, in_tex, - differencematte->midtexture[0], gst_gl_differencematte_diff, NULL); - gst_gl_filter_render_to_target (filter, differencematte->midtexture[0], - differencematte->midtexture[1], gst_gl_differencematte_hblur, NULL); - gst_gl_filter_render_to_target (filter, differencematte->midtexture[1], - differencematte->midtexture[2], gst_gl_differencematte_vblur, NULL); - gst_gl_filter_render_to_target (filter, in_tex, out_tex, - gst_gl_differencematte_interp, NULL); - } else { - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, - differencematte->identity_shader); - } - - return TRUE; -} - -static void -user_warning_fn (png_structp png_ptr, png_const_charp warning_msg) -{ - g_warning ("%s\n", warning_msg); -} - -#define LOAD_ERROR(msg) { GST_WARNING ("unable to load %s: %s", differencematte->location, msg); return FALSE; } - -static gboolean -gst_gl_differencematte_loader (GstGLFilter * filter) -{ - GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); - - png_structp png_ptr; - png_infop info_ptr; - guint sig_read = 0; - png_uint_32 width = 0; - png_uint_32 height = 0; - gint bit_depth = 0; - gint color_type = 0; - gint interlace_type = 0; - png_FILE_p fp = NULL; - guint y = 0; - guchar **rows = NULL; - gint filler; - - if (!GST_GL_BASE_FILTER (filter)->context) - return TRUE; - - if ((fp = fopen (differencematte->location, "rb")) == NULL) - LOAD_ERROR ("file not found"); - - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (png_ptr == NULL) { - fclose (fp); - LOAD_ERROR ("failed to initialize the png_struct"); - } - - png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); - - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL) { - fclose (fp); - png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); - LOAD_ERROR ("failed to initialize the memory for image information"); - } - - png_init_io (png_ptr, fp); - - png_set_sig_bytes (png_ptr, sig_read); - - png_read_info (png_ptr, info_ptr); - - png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, int_p_NULL, int_p_NULL); - - if (color_type == PNG_COLOR_TYPE_RGB) { - filler = 0xff; - png_set_filler (png_ptr, filler, PNG_FILLER_AFTER); - color_type = PNG_COLOR_TYPE_RGB_ALPHA; - } - - if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { - fclose (fp); - png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); - LOAD_ERROR ("color type is not rgb"); - } - - differencematte->pbuf_width = width; - differencematte->pbuf_height = height; - - differencematte->pixbuf = - (guchar *) malloc (sizeof (guchar) * width * height * 4); - - rows = (guchar **) malloc (sizeof (guchar *) * height); - - for (y = 0; y < height; ++y) - rows[y] = (guchar *) (differencematte->pixbuf + y * width * 4); - - png_read_image (png_ptr, rows); - - free (rows); - - png_read_end (png_ptr, info_ptr); - png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL); - fclose (fp); - - return TRUE; -} diff --git a/ext/gl/gstgldifferencematte.h b/ext/gl/gstgldifferencematte.h deleted file mode 100644 index a4fd27552..000000000 --- a/ext/gl/gstgldifferencematte.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_DIFFERENCEMATTE_H_ -#define _GST_GL_DIFFERENCEMATTE_H_ - -#include <gst/gl/gstglfilter.h> - -#define GST_TYPE_GL_DIFFERENCEMATTE (gst_gl_differencematte_get_type()) -#define GST_GL_DIFFERENCEMATTE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_DIFFERENCEMATTE,GstGLDifferenceMatte)) -#define GST_IS_GL_DIFFERENCEMATTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_DIFFERENCEMATTE)) -#define GST_GL_DIFFERENCEMATTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) , GST_TYPE_GL_DIFFERENCEMATTE,GstGLDifferenceMatteClass)) -#define GST_IS_GL_DIFFERENCEMATTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_DIFFERENCEMATTE)) -#define GST_GL_DIFFERENCEMATTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_DIFFERENCEMATTE,GstGLDifferenceMatteClass)) - -typedef struct _GstGLDifferenceMatte GstGLDifferenceMatte; -typedef struct _GstGLDifferenceMatteClass GstGLDifferenceMatteClass; - -struct _GstGLDifferenceMatte -{ - GstGLFilter filter; - - GstGLShader *identity_shader; - GstGLShader *shader[4]; - - gchar *location; - gboolean bg_has_changed; - - guchar *pixbuf; - gint pbuf_width, pbuf_height; - GstGLMemory *savedbgtexture; - GstGLMemory *newbgtexture; - GstGLMemory *midtexture[4]; - GstGLMemory *intexture; - float kernel[7]; -}; - -struct _GstGLDifferenceMatteClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_differencematte_get_type (void); - -#endif /* _GST_GL_DIFFERENCEMATTE_H_ */ diff --git a/ext/gl/gstgldownloadelement.c b/ext/gl/gstgldownloadelement.c deleted file mode 100644 index c8f101eaa..000000000 --- a/ext/gl/gstgldownloadelement.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters <ystree00@gmail.com> - * - * 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 - -#include <gst/gl/gl.h> -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF -#include <gst/gl/egl/gsteglimage.h> -#include <gst/allocators/gstdmabuf.h> -#endif - -#include "gstgldownloadelement.h" - -GST_DEBUG_CATEGORY_STATIC (gst_gl_download_element_debug); -#define GST_CAT_DEFAULT gst_gl_download_element_debug - -#define gst_gl_download_element_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLDownloadElement, gst_gl_download_element, - GST_TYPE_GL_BASE_FILTER, - GST_DEBUG_CATEGORY_INIT (gst_gl_download_element_debug, "gldownloadelement", - 0, "download element");); - -static gboolean gst_gl_download_element_get_unit_size (GstBaseTransform * trans, - GstCaps * caps, gsize * size); -static GstCaps *gst_gl_download_element_transform_caps (GstBaseTransform * bt, - GstPadDirection direction, GstCaps * caps, GstCaps * filter); -static gboolean gst_gl_download_element_set_caps (GstBaseTransform * bt, - GstCaps * in_caps, GstCaps * out_caps); -static GstFlowReturn -gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * buffer, GstBuffer ** outbuf); -static GstFlowReturn gst_gl_download_element_transform (GstBaseTransform * bt, - GstBuffer * buffer, GstBuffer * outbuf); -static gboolean gst_gl_download_element_decide_allocation (GstBaseTransform * - trans, GstQuery * query); -static void gst_gl_download_element_finalize (GObject * object); - -static GstStaticPadTemplate gst_gl_download_element_src_pad_template = - GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ( -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF - "video/x-raw(" GST_CAPS_FEATURE_MEMORY_DMABUF "); " -#endif - "video/x-raw; video/x-raw(memory:GLMemory)")); - -static GstStaticPadTemplate gst_gl_download_element_sink_pad_template = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(memory:GLMemory); video/x-raw")); - -static void -gst_gl_download_element_class_init (GstGLDownloadElementClass * klass) -{ - GstBaseTransformClass *bt_class = GST_BASE_TRANSFORM_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - bt_class->transform_caps = gst_gl_download_element_transform_caps; - bt_class->set_caps = gst_gl_download_element_set_caps; - bt_class->get_unit_size = gst_gl_download_element_get_unit_size; - bt_class->prepare_output_buffer = - gst_gl_download_element_prepare_output_buffer; - bt_class->transform = gst_gl_download_element_transform; - bt_class->decide_allocation = gst_gl_download_element_decide_allocation; - - bt_class->passthrough_on_same_caps = TRUE; - - gst_element_class_add_static_pad_template (element_class, - &gst_gl_download_element_src_pad_template); - gst_element_class_add_static_pad_template (element_class, - &gst_gl_download_element_sink_pad_template); - - gst_element_class_set_metadata (element_class, - "OpenGL downloader", "Filter/Video", - "Downloads data from OpenGL", "Matthew Waters <matthew@centricular.com>"); - - object_class->finalize = gst_gl_download_element_finalize; -} - -static void -gst_gl_download_element_init (GstGLDownloadElement * download) -{ - gst_base_transform_set_prefer_passthrough (GST_BASE_TRANSFORM (download), - TRUE); -} - -static gboolean -gst_gl_download_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps, - GstCaps * out_caps) -{ - GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt); - GstVideoInfo out_info; - GstCapsFeatures *features = NULL; - - if (!gst_video_info_from_caps (&out_info, out_caps)) - return FALSE; - - features = gst_caps_get_features (out_caps, 0); - - dl->do_pbo_transfers = FALSE; - if (dl->dmabuf_allocator) { - gst_object_unref (GST_OBJECT (dl->dmabuf_allocator)); - dl->dmabuf_allocator = NULL; - } - - if (!features) { - dl->do_pbo_transfers = TRUE; - return TRUE; - } - - if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) { - /* do nothing with the buffer */ -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF - } else if (gst_caps_features_contains (features, - GST_CAPS_FEATURE_MEMORY_DMABUF)) { - dl->dmabuf_allocator = gst_dmabuf_allocator_new (); -#endif - } else if (gst_caps_features_contains (features, - GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) { - dl->do_pbo_transfers = TRUE; - } - - return TRUE; -} - -static GstCaps * -_set_caps_features (const GstCaps * caps, const gchar * feature_name) -{ - GstCaps *tmp = gst_caps_copy (caps); - guint n = gst_caps_get_size (tmp); - guint i = 0; - - for (i = 0; i < n; i++) - gst_caps_set_features (tmp, i, - gst_caps_features_from_string (feature_name)); - - return tmp; -} - -static GstCaps * -gst_gl_download_element_transform_caps (GstBaseTransform * bt, - GstPadDirection direction, GstCaps * caps, GstCaps * filter) -{ - GstCaps *result, *tmp; - - if (direction == GST_PAD_SRC) { - tmp = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_GL_MEMORY); - tmp = gst_caps_merge (gst_caps_ref (caps), tmp); - } else { - GstCaps *newcaps; - tmp = gst_caps_ref (caps); - -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF - newcaps = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_DMABUF); - tmp = gst_caps_merge (tmp, newcaps); -#endif - - newcaps = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); - tmp = gst_caps_merge (tmp, newcaps); - } - - if (filter) { - result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (tmp); - } else { - result = tmp; - } - - GST_DEBUG_OBJECT (bt, "returning caps %" GST_PTR_FORMAT, result); - - return result; -} - -static gboolean -gst_gl_download_element_get_unit_size (GstBaseTransform * trans, GstCaps * caps, - gsize * size) -{ - gboolean ret = FALSE; - GstVideoInfo info; - - ret = gst_video_info_from_caps (&info, caps); - if (ret) - *size = GST_VIDEO_INFO_SIZE (&info); - - return TRUE; -} - -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF - -struct DmabufInfo -{ - GstMemory *dmabuf; - gint stride; - gsize offset; -}; - -static void -_free_dmabuf_info (struct DmabufInfo *info) -{ - gst_memory_unref (info->dmabuf); - g_free (info); -} - -static GQuark -_dmabuf_info_quark (void) -{ - static GQuark quark = 0; - - if (!quark) - quark = g_quark_from_static_string ("GstGLDownloadDmabufInfo"); - return quark; -} - -static struct DmabufInfo * -_get_cached_dmabuf_info (GstGLMemory * mem) -{ - return gst_mini_object_get_qdata (GST_MINI_OBJECT (mem), - _dmabuf_info_quark ()); -} - -static void -_set_cached_dmabuf_info (GstGLMemory * mem, struct DmabufInfo *info) -{ - return gst_mini_object_set_qdata (GST_MINI_OBJECT (mem), - _dmabuf_info_quark (), info, (GDestroyNotify) _free_dmabuf_info); -} - -struct DmabufTransfer -{ - GstGLDownloadElement *download; - GstGLMemory *glmem; - struct DmabufInfo *info; -}; - -static void -_create_cached_dmabuf_info (GstGLContext * context, gpointer data) -{ - struct DmabufTransfer *transfer = (struct DmabufTransfer *) data; - GstEGLImage *image; - - image = gst_egl_image_from_texture (context, transfer->glmem, NULL); - if (image) { - int fd; - gint stride; - gsize offset; - - if (gst_egl_image_export_dmabuf (image, &fd, &stride, &offset)) { - GstGLDownloadElement *download = transfer->download; - struct DmabufInfo *info; - gsize maxsize; - - gst_memory_get_sizes (GST_MEMORY_CAST (transfer->glmem), NULL, &maxsize); - - info = g_new0 (struct DmabufInfo, 1); - info->dmabuf = - gst_dmabuf_allocator_alloc (download->dmabuf_allocator, fd, maxsize); - info->stride = stride; - info->offset = offset; - - transfer->info = info; - } - - gst_egl_image_unref (image); - } -} - -static GstBuffer * -_try_export_dmabuf (GstGLDownloadElement * download, GstBuffer * inbuf) -{ - GstGLMemory *glmem; - GstBuffer *buffer = NULL; - int i; - gsize offset[GST_VIDEO_MAX_PLANES]; - gint stride[GST_VIDEO_MAX_PLANES]; - GstCaps *src_caps; - GstVideoInfo out_info; - gsize total_offset; - - glmem = GST_GL_MEMORY_CAST (gst_buffer_peek_memory (inbuf, 0)); - if (glmem) { - GstGLContext *context = GST_GL_BASE_MEMORY_CAST (glmem)->context; - if (gst_gl_context_get_gl_platform (context) != GST_GL_PLATFORM_EGL) - return NULL; - } - - buffer = gst_buffer_new (); - total_offset = 0; - - for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - struct DmabufInfo *info; - - glmem = GST_GL_MEMORY_CAST (gst_buffer_peek_memory (inbuf, i)); - info = _get_cached_dmabuf_info (glmem); - if (!info) { - GstGLContext *context = GST_GL_BASE_MEMORY_CAST (glmem)->context; - struct DmabufTransfer transfer; - - transfer.download = download; - transfer.glmem = glmem; - transfer.info = NULL; - gst_gl_context_thread_add (context, _create_cached_dmabuf_info, - &transfer); - info = transfer.info; - - if (info) - _set_cached_dmabuf_info (glmem, info); - } - - if (info) { - offset[i] = total_offset + info->offset; - stride[i] = info->stride; - total_offset += gst_memory_get_sizes (info->dmabuf, NULL, NULL); - gst_buffer_insert_memory (buffer, -1, gst_memory_ref (info->dmabuf)); - } else { - gst_buffer_unref (buffer); - buffer = NULL; - goto export_complete; - } - } - - src_caps = gst_pad_get_current_caps (GST_BASE_TRANSFORM (download)->srcpad); - gst_video_info_from_caps (&out_info, src_caps); - - if (download->add_videometa) { - gst_buffer_add_video_meta_full (buffer, GST_VIDEO_FRAME_FLAG_NONE, - out_info.finfo->format, out_info.width, out_info.height, - out_info.finfo->n_planes, offset, stride); - } else { - int i; - gboolean match = TRUE; - for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { - if (offset[i] != out_info.offset[i] || stride[i] != out_info.stride[i]) { - match = FALSE; - break; - } - } - - if (!match) { - gst_buffer_unref (buffer); - buffer = NULL; - } - } - -export_complete: - - return buffer; -} -#endif /* GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF */ - -static GstFlowReturn -gst_gl_download_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * inbuf, GstBuffer ** outbuf) -{ - GstGLDownloadElement *dl = GST_GL_DOWNLOAD_ELEMENT (bt); - gint i, n; - - *outbuf = inbuf; - - if (dl->do_pbo_transfers) { - n = gst_buffer_n_memory (*outbuf); - for (i = 0; i < n; i++) { - GstMemory *mem = gst_buffer_peek_memory (*outbuf, i); - - if (gst_is_gl_memory_pbo (mem)) - gst_gl_memory_pbo_download_transfer ((GstGLMemoryPBO *) mem); - } - } -#if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_DMABUF - else if (dl->dmabuf_allocator) { - GstBuffer *buffer = _try_export_dmabuf (dl, inbuf); - if (buffer) { - if (GST_BASE_TRANSFORM_GET_CLASS (bt)->copy_metadata) - if (!GST_BASE_TRANSFORM_GET_CLASS (bt)->copy_metadata (bt, inbuf, - buffer)) { - GST_ELEMENT_WARNING (GST_ELEMENT (bt), STREAM, NOT_IMPLEMENTED, - ("could not copy metadata"), (NULL)); - } - - *outbuf = buffer; - } else { - GstCaps *src_caps; - GstCapsFeatures *features; - - gst_object_unref (dl->dmabuf_allocator); - dl->dmabuf_allocator = NULL; - - src_caps = gst_pad_get_current_caps (bt->srcpad); - src_caps = gst_caps_make_writable (src_caps); - features = gst_caps_get_features (src_caps, 0); - gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_DMABUF); - - if (!gst_base_transform_update_src_caps (bt, src_caps)) { - GST_ERROR_OBJECT (bt, "DMABuf exportation didn't work and system " - "memory is not supported."); - return GST_FLOW_NOT_NEGOTIATED; - } - } - } -#endif - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_gl_download_element_transform (GstBaseTransform * bt, - GstBuffer * inbuf, GstBuffer * outbuf) -{ - return GST_FLOW_OK; -} - -static gboolean -gst_gl_download_element_decide_allocation (GstBaseTransform * trans, - GstQuery * query) -{ - GstGLDownloadElement *download = GST_GL_DOWNLOAD_ELEMENT_CAST (trans); - - if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { - download->add_videometa = TRUE; - } else { - download->add_videometa = FALSE; - } - - return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans, - query); -} - -static void -gst_gl_download_element_finalize (GObject * object) -{ - GstGLDownloadElement *download = GST_GL_DOWNLOAD_ELEMENT_CAST (object); - - if (download->dmabuf_allocator) { - gst_object_unref (GST_OBJECT (download->dmabuf_allocator)); - download->dmabuf_allocator = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} diff --git a/ext/gl/gstgldownloadelement.h b/ext/gl/gstgldownloadelement.h deleted file mode 100644 index a9fb4e165..000000000 --- a/ext/gl/gstgldownloadelement.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters <ystree00@gmail.com> - * - * 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_GL_DOWNLOAD_ELEMENT_H__ -#define __GST_GL_DOWNLOAD_ELEMENT_H__ - -#include <gst/video/video.h> -#include <gst/gstmemory.h> - -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -GType gst_gl_download_element_get_type (void); -#define GST_TYPE_GL_DOWNLOAD_ELEMENT (gst_gl_download_element_get_type()) -#define GST_GL_DOWNLOAD_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DOWNLOAD_ELEMENT,GstGLDownloadElement)) -#define GST_GL_DOWNLOAD_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLDownloadElementClass)) -#define GST_IS_GL_DOWNLOAD_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DOWNLOAD_ELEMENT)) -#define GST_IS_GL_DOWNLOAD_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_DOWNLOAD_ELEMENT)) -#define GST_GL_DOWNLOAD_ELEMENT_CAST(obj) ((GstGLDownloadElement*)(obj)) - -typedef struct _GstGLDownloadElement GstGLDownloadElement; -typedef struct _GstGLDownloadElementClass GstGLDownloadElementClass; - -struct _GstGLDownloadElement -{ - /* <private> */ - GstGLBaseFilter parent; - - gboolean do_pbo_transfers; - GstAllocator * dmabuf_allocator; - gboolean add_videometa; -}; - -struct _GstGLDownloadElementClass -{ - /* <private> */ - GstGLBaseFilterClass object_class; -}; - -G_END_DECLS - -#endif /* __GST_GL_DOWNLOAD_ELEMENT_H__ */ diff --git a/ext/gl/gstgleffects.c b/ext/gl/gstgleffects.c deleted file mode 100644 index 97a8dfe8a..000000000 --- a/ext/gl/gstgleffects.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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-gleffects. - * @title: gleffects. - * - * GL Shading Language effects. - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! gleffects effect=5 ! glimagesink - * ]| - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstgleffects.h" - -#define GST_CAT_DEFAULT gst_gl_effects_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_0 = 0x0, - PROP_EFFECT = 0x1 << 1, - PROP_HSWAP = 0x1 << 2, - PROP_INVERT = 0x1 << 3 -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_effects_debug, "gleffects", 0, "gleffects element"); - -#define gst_gl_effects_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLEffects, gst_gl_effects, GST_TYPE_GL_FILTER, - DEBUG_INIT); - -static void gst_gl_effects_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_effects_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_effects_init_resources (GstBaseTransform * trans); -static gboolean gst_gl_effects_reset_resources (GstBaseTransform * trans); - -static gboolean gst_gl_effects_on_init_gl_context (GstGLFilter * filter); - -static void gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, - gpointer data); - -static gboolean gst_gl_effects_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); -static gboolean gst_gl_effects_filters_is_property_supported (const - GstGLEffectsFilterDescriptor *, gint property); - -/* dont' forget to edit the following when a new effect is added */ -typedef enum -{ - GST_GL_EFFECT_IDENTITY, - GST_GL_EFFECT_MIRROR, - GST_GL_EFFECT_SQUEEZE, - GST_GL_EFFECT_STRETCH, - GST_GL_EFFECT_TUNNEL, - GST_GL_EFFECT_FISHEYE, - GST_GL_EFFECT_TWIRL, - GST_GL_EFFECT_BULGE, - GST_GL_EFFECT_SQUARE, - GST_GL_EFFECT_HEAT, - GST_GL_EFFECT_SEPIA, - GST_GL_EFFECT_XPRO, - GST_GL_EFFECT_LUMA_XPRO, - GST_GL_EFFECT_XRAY, - GST_GL_EFFECT_SIN, - GST_GL_EFFECT_GLOW, - GST_GL_EFFECT_SOBEL, - GST_GL_EFFECT_BLUR, - GST_GL_EFFECT_LAPLACIAN, - GST_GL_N_EFFECTS -} GstGLEffectsEffect; - -static const GEnumValue * -gst_gl_effects_get_effects (void) -{ - static const GEnumValue effect_types[] = { - {GST_GL_EFFECT_IDENTITY, "Do nothing Effect", "identity"}, - {GST_GL_EFFECT_MIRROR, "Mirror Effect", "mirror"}, - {GST_GL_EFFECT_SQUEEZE, "Squeeze Effect", "squeeze"}, - {GST_GL_EFFECT_STRETCH, "Stretch Effect", "stretch"}, - {GST_GL_EFFECT_TUNNEL, "Light Tunnel Effect", "tunnel"}, - {GST_GL_EFFECT_FISHEYE, "FishEye Effect", "fisheye"}, - {GST_GL_EFFECT_TWIRL, "Twirl Effect", "twirl"}, - {GST_GL_EFFECT_BULGE, "Bulge Effect", "bulge"}, - {GST_GL_EFFECT_SQUARE, "Square Effect", "square"}, - {GST_GL_EFFECT_HEAT, "Heat Signature Effect", "heat"}, - {GST_GL_EFFECT_SEPIA, "Sepia Toning Effect", "sepia"}, - {GST_GL_EFFECT_XPRO, "Cross Processing Effect", "xpro"}, - {GST_GL_EFFECT_LUMA_XPRO, "Luma Cross Processing Effect", "lumaxpro"}, - {GST_GL_EFFECT_XRAY, "Glowing negative effect", "xray"}, - {GST_GL_EFFECT_SIN, "All Grey but Red Effect", "sin"}, - {GST_GL_EFFECT_GLOW, "Glow Lighting Effect", "glow"}, - {GST_GL_EFFECT_SOBEL, "Sobel edge detection Effect", "sobel"}, - {GST_GL_EFFECT_BLUR, "Blur with 9x9 separable convolution Effect", "blur"}, - {GST_GL_EFFECT_LAPLACIAN, "Laplacian Convolution Demo Effect", "laplacian"}, - {0, NULL, NULL} - }; - return effect_types; -} - -#define GST_TYPE_GL_EFFECTS_EFFECT (gst_gl_effects_effect_get_type ()) -static GType -gst_gl_effects_effect_get_type (void) -{ - static GType gl_effects_effect_type = 0; - if (!gl_effects_effect_type) { - gl_effects_effect_type = - g_enum_register_static ("GstGLEffectsEffect", - gst_gl_effects_get_effects ()); - } - return gl_effects_effect_type; -} - -static void -gst_gl_effects_set_effect (GstGLEffects * effects, gint effect_type) -{ - GstGLBaseFilterClass *filter_class = GST_GL_BASE_FILTER_GET_CLASS (effects); - - switch (effect_type) { - case GST_GL_EFFECT_IDENTITY: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_identity; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_MIRROR: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_mirror; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_SQUEEZE: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_squeeze; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_STRETCH: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_stretch; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_TUNNEL: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_tunnel; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_FISHEYE: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_fisheye; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_TWIRL: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_twirl; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_BULGE: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_bulge; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_SQUARE: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_square; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_HEAT: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_heat; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_SEPIA: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sepia; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_XPRO: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xpro; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_LUMA_XPRO: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_luma_xpro; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_SIN: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sin; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_XRAY: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_xray; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_GLOW: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_glow; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_SOBEL: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_sobel; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_BLUR: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_blur; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - case GST_GL_EFFECT_LAPLACIAN: - effects->effect = (GstGLEffectProcessFunc) gst_gl_effects_laplacian; - filter_class->supported_gl_api = - GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; - effects->current_effect = effect_type; - break; - default: - g_assert_not_reached (); - } - - effects->current_effect = effect_type; -} - -/* init resources that need a gl context */ -static gboolean -gst_gl_effects_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLEffects *effects = GST_GL_EFFECTS (base_filter); - GstGLFilter *filter = GST_GL_FILTER (base_filter); - GstGLContext *context = base_filter->context; - GstGLBaseMemoryAllocator *base_alloc; - GstGLAllocationParams *params; - gint i; - - if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter)) - return FALSE; - - base_alloc = (GstGLBaseMemoryAllocator *) - gst_allocator_find (GST_GL_MEMORY_ALLOCATOR_NAME); - params = - (GstGLAllocationParams *) gst_gl_video_allocation_params_new (context, - NULL, &filter->out_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - - for (i = 0; i < NEEDED_TEXTURES; i++) { - if (effects->midtexture[i]) - gst_memory_unref (GST_MEMORY_CAST (effects->midtexture[i])); - - effects->midtexture[i] = - (GstGLMemory *) gst_gl_base_memory_alloc (base_alloc, params); - } - - gst_object_unref (base_alloc); - gst_gl_allocation_params_free (params); - - return TRUE; -} - -/* free resources that need a gl context */ -static void -gst_gl_effects_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLEffects *effects = GST_GL_EFFECTS (base_filter); - const GstGLFuncs *gl = base_filter->context->gl_vtable; - gint i = 0; - - for (i = 0; i < NEEDED_TEXTURES; i++) { - gst_memory_unref (GST_MEMORY_CAST (effects->midtexture[i])); - } - - for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) { - gl->DeleteTextures (1, &effects->curve[i]); - effects->curve[i] = 0; - } - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static void -gst_gl_effects_class_init (GstGLEffectsClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_effects_init_resources; - GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_effects_reset_resources; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_effects_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_effects_gl_stop; - - GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_effects_filter_texture; - GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_effects_on_init_gl_context; - - klass->filter_descriptor = NULL; - - gst_element_class_set_metadata (element_class, - "Gstreamer OpenGL Effects", "Filter/Effect/Video", - "GL Shading Language effects", - "Filippo Argiolas <filippo.argiolas@gmail.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_effects_filter_class_init (GstGLEffectsClass * klass, - const GstGLEffectsFilterDescriptor * filter_descriptor) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - klass->filter_descriptor = filter_descriptor; - - gobject_class->set_property = gst_gl_effects_set_property; - gobject_class->get_property = gst_gl_effects_get_property; - - /* if filterDescriptor is null it's a generic gleffects */ - if (!filter_descriptor) { - g_object_class_install_property (gobject_class, - PROP_EFFECT, - g_param_spec_enum ("effect", - "Effect", - "Select which effect apply to GL video texture", - GST_TYPE_GL_EFFECTS_EFFECT, - GST_GL_EFFECT_IDENTITY, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - } else { - gchar *description = g_strdup_printf ("GL Shading Language effects - %s", - filter_descriptor->filter_longname); - - gst_element_class_set_metadata (element_class, - filter_descriptor->filter_longname, "Filter/Effect/Video", - description, "Filippo Argiolas <filippo.argiolas@gmail.com>"); - - g_free (description); - } - - g_object_class_install_property (gobject_class, - PROP_HSWAP, - g_param_spec_boolean ("hswap", - "Horizontal Swap", - "Switch video texture left to right, useful with webcams", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* FIXME: make it work on every effect */ - if (gst_gl_effects_filters_is_property_supported (filter_descriptor, - PROP_INVERT)) { - g_object_class_install_property (gobject_class, PROP_INVERT, - g_param_spec_boolean ("invert", "Invert the colors for sobel effect", - "Invert colors to get dark edges on bright background when using sobel effect", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - } -} - -static void -set_horizontal_swap (GstGLEffects * effects) -{ -#if GST_GL_HAVE_OPENGL - GstGLContext *context = GST_GL_BASE_FILTER (effects)->context; - const GstGLFuncs *gl = context->gl_vtable; - - if (gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) { - const gfloat mirrormatrix[16] = { - -1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 - }; - - gl->MatrixMode (GL_MODELVIEW); - gl->LoadMatrixf (mirrormatrix); - } -#endif -} - -static void -gst_gl_effects_init (GstGLEffects * effects) -{ - effects->horizontal_swap = FALSE; - effects->invert = FALSE; - effects->effect = gst_gl_effects_identity; -} - -static void -gst_gl_effects_filter_init (GstGLEffects * effects) -{ - gst_gl_effects_set_effect (effects, - GST_GL_EFFECTS_GET_CLASS (effects)->filter_descriptor->effect); -} - -static void -gst_gl_effects_ghash_func_clean (gpointer key, gpointer value, gpointer data) -{ - GstGLShader *shader = (GstGLShader *) value; - - gst_object_unref (shader); - - value = NULL; -} - -static gboolean -gst_gl_effects_reset_resources (GstBaseTransform * trans) -{ - GstGLEffects *effects = GST_GL_EFFECTS (trans); - - /* release shaders in the gl thread */ - g_hash_table_foreach (effects->shaderstable, gst_gl_effects_ghash_func_clean, - effects); - - /* clean the htable without calling values destructors - * because shaders have been released in the glthread - * through the foreach func */ - g_hash_table_unref (effects->shaderstable); - effects->shaderstable = NULL; - - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans); -} - -static void -gst_gl_effects_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLEffects *effects = GST_GL_EFFECTS (object); - - switch (prop_id) { - case PROP_EFFECT: - gst_gl_effects_set_effect (effects, g_value_get_enum (value)); - break; - case PROP_HSWAP: - effects->horizontal_swap = g_value_get_boolean (value); - break; - case PROP_INVERT: - effects->invert = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_effects_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLEffects *effects = GST_GL_EFFECTS (object); - - switch (prop_id) { - case PROP_EFFECT: - g_value_set_enum (value, effects->current_effect); - break; - case PROP_HSWAP: - g_value_set_boolean (value, effects->horizontal_swap); - break; - case PROP_INVERT: - g_value_set_boolean (value, effects->invert); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_effects_init_resources (GstBaseTransform * trans) -{ - GstGLEffects *effects = GST_GL_EFFECTS (trans); - gint i; - - effects->shaderstable = g_hash_table_new (g_str_hash, g_str_equal); - - for (i = 0; i < NEEDED_TEXTURES; i++) { - effects->midtexture[i] = 0; - } - for (i = 0; i < GST_GL_EFFECTS_N_CURVES; i++) { - effects->curve[i] = 0; - } - - return GST_BASE_TRANSFORM_CLASS (parent_class)->start (trans); -} - -static gboolean -gst_gl_effects_on_init_gl_context (GstGLFilter * filter) -{ - return TRUE; -} - -static gboolean -gst_gl_effects_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLEffects *effects = GST_GL_EFFECTS (filter); - - effects->intexture = in_tex; - effects->outtexture = out_tex; - - if (effects->horizontal_swap == TRUE) - set_horizontal_swap (effects); - - effects->effect (effects); - - return TRUE; -} - -GstGLShader * -gst_gl_effects_get_fragment_shader (GstGLEffects * effects, - const gchar * shader_name, const gchar * shader_source_gles2) -{ - GstGLShader *shader = NULL; - GstGLFilter *filter = GST_GL_FILTER (effects); - GstGLContext *context = GST_GL_BASE_FILTER (filter)->context; - - shader = g_hash_table_lookup (effects->shaderstable, shader_name); - - if (!shader) { - GError *error = NULL; - - if (!(shader = gst_gl_shader_new_link_with_stages (context, &error, - gst_glsl_stage_new_default_vertex (context), - gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - shader_source_gles2), NULL))) { - GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND, - ("Failed to initialize %s shader", shader_name), (NULL)); - } - - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (shader, "a_texcoord"); - } - - g_hash_table_insert (effects->shaderstable, (gchar *) shader_name, shader); - - return shader; -} - -static const GstGLEffectsFilterDescriptor * -gst_gl_effects_filters_supported_properties (void) -{ - /* Horizontal swap property is supported by all filters */ - static const GstGLEffectsFilterDescriptor effects[] = { - {GST_GL_EFFECT_SOBEL, PROP_INVERT, NULL}, - {GST_GL_EFFECT_LAPLACIAN, PROP_INVERT, NULL}, - {0, 0, NULL} - }; - return effects; -} - -static inline gboolean -gst_gl_effects_filters_is_property_supported (const GstGLEffectsFilterDescriptor - * descriptor, gint property) -{ - /* generic filter (NULL descriptor) supports all properties */ - return !descriptor || (descriptor->supported_properties & property); -} - -static const GstGLEffectsFilterDescriptor * -gst_gl_effects_filters_descriptors (void) -{ - static GstGLEffectsFilterDescriptor *descriptors = NULL; - if (!descriptors) { - const GEnumValue *e; - const GEnumValue *effect = gst_gl_effects_get_effects (); - const GstGLEffectsFilterDescriptor *defined; - guint n_filters = 0, i; - - for (e = effect; NULL != e->value_nick; ++e, ++n_filters) { - } - - descriptors = g_new0 (GstGLEffectsFilterDescriptor, n_filters + 1); - for (i = 0; i < n_filters; ++i, ++effect) { - descriptors[i].effect = effect->value; - descriptors[i].filter_name = effect->value_nick; - descriptors[i].filter_longname = effect->value_name; - } - - for (defined = gst_gl_effects_filters_supported_properties (); - 0 != defined->supported_properties; ++defined) { - - for (i = 0; i < n_filters; ++i) { - if (descriptors[i].effect == defined->effect) { - descriptors[i].supported_properties = defined->supported_properties; - break; - } - } - if (i >= n_filters) { - GST_WARNING ("Could not match gstgleffects-%s descriptor", - defined->filter_name); - } - } - } - return descriptors; -} - -gboolean -gst_gl_effects_register_filters (GstPlugin * plugin, GstRank rank) -{ - static volatile gsize registered = 0; - - if (g_once_init_enter (®istered)) { - GTypeInfo info = { - sizeof (GstGLEffectsClass), - NULL, - NULL, - (GClassInitFunc) gst_gl_effects_filter_class_init, - NULL, - NULL, - sizeof (GstGLEffects), - 0, - NULL - }; - GType generic_type = - g_type_register_static (GST_TYPE_GL_EFFECTS, "GstGLEffectsGeneric", - &info, 0); - - if (gst_element_register (plugin, "gleffects", rank, generic_type)) { - const GstGLEffectsFilterDescriptor *filters; - for (filters = gst_gl_effects_filters_descriptors (); - NULL != filters->filter_name; ++filters) { - gchar *name = g_strdup_printf ("gleffects_%s", filters->filter_name); - GTypeInfo info = { - sizeof (GstGLEffectsClass), - NULL, - NULL, - (GClassInitFunc) gst_gl_effects_filter_class_init, - NULL, - filters, - sizeof (GstGLEffects), - 0, - (GInstanceInitFunc) gst_gl_effects_filter_init - }; - GType type = - g_type_register_static (GST_TYPE_GL_EFFECTS, name, &info, 0); - if (!gst_element_register (plugin, name, rank, type)) { - GST_WARNING ("Could not register %s", name); - } - g_free (name); - } - } - g_once_init_leave (®istered, generic_type); - } - return registered; -} diff --git a/ext/gl/gstgleffects.h b/ext/gl/gstgleffects.h deleted file mode 100644 index a090e0d57..000000000 --- a/ext/gl/gstgleffects.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_EFFECTS_H__ -#define __GST_GL_EFFECTS_H__ - -#include <gst/gl/gstglfilter.h> -#include <gst/gl/gstglfuncs.h> - -#include "effects/gstgleffectssources.h" - -G_BEGIN_DECLS - -#define GST_TYPE_GL_EFFECTS (gst_gl_effects_get_type()) -#define GST_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_EFFECTS,GstGLEffects)) -#define GST_IS_GL_EFFECTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_EFFECTS)) -#define GST_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass)) -#define GST_IS_GL_EFFECTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_EFFECTS)) -#define GST_GL_EFFECTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_EFFECTS,GstGLEffectsClass)) - -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - -typedef struct _GstGLEffects GstGLEffects; -typedef struct _GstGLEffectsClass GstGLEffectsClass; - -typedef struct { - gint effect; - guint supported_properties; - const gchar *filter_name; - const gchar *filter_longname; -} GstGLEffectsFilterDescriptor; - -typedef void (* GstGLEffectProcessFunc) (GstGLEffects *effects); - -#define NEEDED_TEXTURES 5 - -enum { - GST_GL_EFFECTS_CURVE_HEAT, - GST_GL_EFFECTS_CURVE_SEPIA, - GST_GL_EFFECTS_CURVE_XPRO, - GST_GL_EFFECTS_CURVE_LUMA_XPRO, - GST_GL_EFFECTS_CURVE_XRAY, - GST_GL_EFFECTS_N_CURVES -}; - -struct _GstGLEffects -{ - GstGLFilter filter; - - GstGLEffectProcessFunc effect; - gint current_effect; - - GstGLMemory *intexture; - GstGLMemory *midtexture[NEEDED_TEXTURES]; - GstGLMemory *outtexture; - - GLuint curve[GST_GL_EFFECTS_N_CURVES]; - - GHashTable *shaderstable; - - gboolean horizontal_swap; /* switch left to right */ - gboolean invert; /* colours */ -}; - -struct _GstGLEffectsClass -{ - GstGLFilterClass filter_class; - const GstGLEffectsFilterDescriptor *filter_descriptor; -}; - -GType gst_gl_effects_get_type (void); -gboolean gst_gl_effects_register_filters (GstPlugin *, GstRank); -GstGLShader* gst_gl_effects_get_fragment_shader (GstGLEffects *effects, - const gchar * shader_name, const gchar * shader_source_gles2); - -void gst_gl_effects_identity (GstGLEffects *effects); -void gst_gl_effects_mirror (GstGLEffects *effects); -void gst_gl_effects_squeeze (GstGLEffects *effects); -void gst_gl_effects_stretch (GstGLEffects *effects); -void gst_gl_effects_tunnel (GstGLEffects *effects); -void gst_gl_effects_fisheye (GstGLEffects *effects); -void gst_gl_effects_twirl (GstGLEffects *effects); -void gst_gl_effects_bulge (GstGLEffects *effects); -void gst_gl_effects_square (GstGLEffects *effects); -void gst_gl_effects_heat (GstGLEffects *effects); -void gst_gl_effects_sepia (GstGLEffects *effects); -void gst_gl_effects_xpro (GstGLEffects *effects); -void gst_gl_effects_xray (GstGLEffects *effects); -void gst_gl_effects_luma_xpro (GstGLEffects *effects); -void gst_gl_effects_sin (GstGLEffects *effects); -void gst_gl_effects_glow (GstGLEffects *effects); -void gst_gl_effects_sobel (GstGLEffects *effects); -void gst_gl_effects_blur (GstGLEffects *effects); -void gst_gl_effects_laplacian (GstGLEffects *effects); - -G_END_DECLS - -#endif /*__GST_GL_EFFECTS_H__ */ diff --git a/ext/gl/gstglfilterapp.c b/ext/gl/gstglfilterapp.c deleted file mode 100644 index 8426d0316..000000000 --- a/ext/gl/gstglfilterapp.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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-glfilterapp - * @title: glfilterapp - * - * The resize and redraw callbacks can be set from a client code. - * - * ## CLient callbacks - * - * The graphic scene can be written from a client code through the - * two glfilterapp properties. - * - * ## Examples - * see gst-plugins-gl/tests/examples/generic/recordgraphic - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstglfilterapp.h" - -#define GST_CAT_DEFAULT gst_gl_filter_app_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - SIGNAL_0, - CLIENT_DRAW_SIGNAL, - LAST_SIGNAL -}; - -static guint gst_gl_filter_app_signals[LAST_SIGNAL] = { 0 }; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_filter_app_debug, "glfilterapp", 0, "glfilterapp element"); - -#define gst_gl_filter_app_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLFilterApp, gst_gl_filter_app, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_filter_app_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_filter_app_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_filter_app_set_caps (GstGLFilter * filter, - GstCaps * incaps, GstCaps * outcaps); -static gboolean gst_gl_filter_app_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static gboolean gst_gl_filter_app_gl_start (GstGLBaseFilter * base_filter); -static void gst_gl_filter_app_gl_stop (GstGLBaseFilter * base_filter); - -static void -gst_gl_filter_app_class_init (GstGLFilterAppClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_filter_app_set_property; - gobject_class->get_property = gst_gl_filter_app_get_property; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_filter_app_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_filter_app_gl_stop; - - GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_app_set_caps; - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_filter_app_filter_texture; - - /** - * GstGLFilterApp::client-draw: - * @object: the #GstGLImageSink - * @texture: the #guint id of the texture. - * @width: the #guint width of the texture. - * @height: the #guint height of the texture. - * - * Will be emitted before to draw the texture. The client should - * redraw the surface/contents with the @texture, @width and @height. - * - * Returns: whether the texture was redrawn by the signal. If not, a - * default redraw will occur. - */ - gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL] = - g_signal_new ("client-draw", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - - gst_element_class_set_metadata (element_class, - "OpenGL application filter", "Filter/Effect", - "Use client callbacks to define the scene", - "Julien Isorce <julien.isorce@gmail.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_filter_app_init (GstGLFilterApp * filter) -{ -} - -static void -gst_gl_filter_app_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filter_app_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_filter_app_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLFilter *filter = GST_GL_FILTER (base_filter); - GError *error = NULL; - - if (!(filter->default_shader = - gst_gl_shader_new_default (base_filter->context, &error))) { - GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, ("%s", - "Failed to create the default shader"), ("%s", error->message)); - return FALSE; - } - - return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter); -} - -static void -gst_gl_filter_app_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLFilter *filter = GST_GL_FILTER (base_filter); - - if (filter->default_shader) - gst_object_unref (filter->default_shader); - filter->default_shader = NULL; - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static gboolean -gst_gl_filter_app_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps) -{ - //GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter); - - return TRUE; -} - -struct glcb2 -{ - GstGLFilterApp *app; - GstGLMemory *in_tex; - GstGLMemory *out_tex; -}; - -static gboolean -_emit_draw_signal (gpointer data) -{ - struct glcb2 *cb = data; - gboolean drawn; - - g_signal_emit (cb->app, gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL], 0, - cb->in_tex->tex_id, gst_gl_memory_get_texture_width (cb->out_tex), - gst_gl_memory_get_texture_height (cb->out_tex), &drawn); - - return !drawn; -} - -static gboolean -gst_gl_filter_app_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLFilterApp *app_filter = GST_GL_FILTER_APP (filter); - gboolean default_draw; - struct glcb2 cb; - - cb.app = app_filter; - cb.in_tex = in_tex; - cb.out_tex = out_tex; - - default_draw = - gst_gl_framebuffer_draw_to_texture (filter->fbo, - out_tex, _emit_draw_signal, &cb); - - if (default_draw) { - gst_gl_filter_render_to_target_with_shader (filter, in_tex, out_tex, - filter->default_shader); - } - - return TRUE; -} diff --git a/ext/gl/gstglfilterapp.h b/ext/gl/gstglfilterapp.h deleted file mode 100644 index d7e9a6f2a..000000000 --- a/ext/gl/gstglfilterapp.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_FILTERAPP_H_ -#define _GST_GL_FILTERAPP_H_ - -#include <gst/gl/gstglfilter.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_FILTER_APP (gst_gl_filter_app_get_type()) -#define GST_GL_FILTER_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_APP,GstGLFilterApp)) -#define GST_IS_GL_FILTER_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_APP)) -#define GST_GL_FILTER_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_APP,GstGLFilterAppClass)) -#define GST_IS_GL_FILTER_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_APP)) -#define GST_GL_FILTER_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_APP,GstGLFilterAppClass)) -typedef struct _GstGLFilterApp GstGLFilterApp; -typedef struct _GstGLFilterAppClass GstGLFilterAppClass; - -struct _GstGLFilterApp -{ - GstGLFilter filter; -}; - -struct _GstGLFilterAppClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_filter_app_get_type (void); - -G_END_DECLS - -#endif /* _GST_GLFILTERAPP_H_ */ diff --git a/ext/gl/gstglfilterbin.c b/ext/gl/gstglfilterbin.c deleted file mode 100644 index a3621ec7b..000000000 --- a/ext/gl/gstglfilterbin.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 - -#include "gstglfilterbin.h" - -#define GST_CAT_DEFAULT gst_gl_filter_bin_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -/* Properties */ -enum -{ - PROP_0, - PROP_FILTER, -}; - -enum -{ - SIGNAL_0, - SIGNAL_CREATE_ELEMENT, - LAST_SIGNAL -}; - -static guint gst_gl_filter_bin_signals[LAST_SIGNAL] = { 0 }; - -#define gst_gl_filter_bin_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLFilterBin, gst_gl_filter_bin, - GST_TYPE_BIN, GST_DEBUG_CATEGORY_INIT (gst_gl_filter_bin_debug, - "glfilterbin", 0, "glfilterbin element");); - -static void gst_gl_filter_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_gl_filter_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); - -static GstStateChangeReturn gst_gl_filter_bin_change_state (GstElement * - element, GstStateChange transition); - -static GstStaticPadTemplate _src_pad_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(ANY)")); - -static void -gst_gl_filter_bin_class_init (GstGLFilterBinClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstCaps *upload_caps; - - element_class->change_state = gst_gl_filter_bin_change_state; - - gobject_class->set_property = gst_gl_filter_bin_set_property; - gobject_class->get_property = gst_gl_filter_bin_get_property; - - gst_element_class_add_static_pad_template (element_class, &_src_pad_template); - - upload_caps = gst_gl_upload_get_input_template_caps (); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps)); - gst_caps_unref (upload_caps); - - g_object_class_install_property (gobject_class, PROP_FILTER, - g_param_spec_object ("filter", - "GL filter element", - "The GL filter chain to use", - GST_TYPE_ELEMENT, - GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * GstFilterBin::create-element: - * @object: the #GstGLFilterBin - * - * Will be emitted when we need the processing element/s that this bin will use - * - * Returns: a new #GstElement - */ - gst_gl_filter_bin_signals[SIGNAL_CREATE_ELEMENT] = - g_signal_new ("create-element", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_ELEMENT, 0); - - gst_element_class_set_metadata (element_class, - "GL Filter Bin", "Filter/Video", - "Infrastructure to process GL textures", - "Matthew Waters <matthew@centricular.com>"); -} - -static void -gst_gl_filter_bin_init (GstGLFilterBin * self) -{ - GstPad *pad; - - self->upload = gst_element_factory_make ("glupload", NULL); - self->in_convert = gst_element_factory_make ("glcolorconvert", NULL); - self->out_convert = gst_element_factory_make ("glcolorconvert", NULL); - self->download = gst_element_factory_make ("gldownload", NULL); - - gst_bin_add (GST_BIN (self), self->upload); - gst_bin_add (GST_BIN (self), self->in_convert); - gst_bin_add (GST_BIN (self), self->out_convert); - gst_bin_add (GST_BIN (self), self->download); - - gst_element_link_pads (self->upload, "src", self->in_convert, "sink"); - gst_element_link_pads (self->out_convert, "src", self->download, "sink"); - - pad = gst_element_get_static_pad (self->download, "src"); - if (pad) { - GST_DEBUG_OBJECT (self, "setting target src pad %" GST_PTR_FORMAT, pad); - self->srcpad = gst_ghost_pad_new ("src", pad); - gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); - gst_object_unref (pad); - } - - pad = gst_element_get_static_pad (self->upload, "sink"); - if (pad) { - GST_DEBUG_OBJECT (self, "setting target sink pad %" GST_PTR_FORMAT, pad); - self->sinkpad = gst_ghost_pad_new ("sink", pad); - gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad); - gst_object_unref (pad); - } -} - -static gboolean -_connect_filter_element (GstGLFilterBin * self) -{ - gboolean res = TRUE; - - gst_object_set_name (GST_OBJECT (self->filter), "filter"); - res &= gst_bin_add (GST_BIN (self), self->filter); - - res &= gst_element_link_pads (self->in_convert, "src", self->filter, "sink"); - res &= gst_element_link_pads (self->filter, "src", self->out_convert, "sink"); - - if (!res) - GST_ERROR_OBJECT (self, "Failed to link filter element into the pipeline"); - - return res; -} - -void -gst_gl_filter_bin_finish_init_with_element (GstGLFilterBin * self, - GstElement * element) -{ - g_return_if_fail (GST_IS_ELEMENT (element)); - - self->filter = element; - - if (!_connect_filter_element (self)) { - gst_object_unref (self->filter); - self->filter = NULL; - } -} - -void -gst_gl_filter_bin_finish_init (GstGLFilterBin * self) -{ - GstGLFilterBinClass *klass = GST_GL_FILTER_BIN_GET_CLASS (self); - GstElement *element = NULL; - - if (klass->create_element) - element = klass->create_element (); - - if (element) - gst_gl_filter_bin_finish_init_with_element (self, element); -} - -static void -gst_gl_filter_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLFilterBin *self = GST_GL_FILTER_BIN (object); - - switch (prop_id) { - case PROP_FILTER: - g_value_set_object (value, self->filter); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filter_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLFilterBin *self = GST_GL_FILTER_BIN (object); - - switch (prop_id) { - case PROP_FILTER: - { - GstElement *filter = g_value_get_object (value); - if (self->filter) - gst_bin_remove (GST_BIN (self), self->filter); - self->filter = filter; - if (filter) { - gst_object_ref_sink (filter); - _connect_filter_element (self); - } - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstStateChangeReturn -gst_gl_filter_bin_change_state (GstElement * element, GstStateChange transition) -{ - GstGLFilterBin *self = GST_GL_FILTER_BIN (element); - GstGLFilterBinClass *klass = GST_GL_FILTER_BIN_GET_CLASS (self); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!self->filter) { - if (klass->create_element) - self->filter = klass->create_element (); - - if (!self->filter) - g_signal_emit (element, - gst_gl_filter_bin_signals[SIGNAL_CREATE_ELEMENT], 0, - &self->filter); - - if (!self->filter) { - GST_ERROR_OBJECT (element, "Failed to retrieve element"); - return GST_STATE_CHANGE_FAILURE; - } - if (!_connect_filter_element (self)) - return GST_STATE_CHANGE_FAILURE; - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - default: - break; - } - - return ret; -} diff --git a/ext/gl/gstglfilterbin.h b/ext/gl/gstglfilterbin.h deleted file mode 100644 index 4a77c6c79..000000000 --- a/ext/gl/gstglfilterbin.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2007 David Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_FILTER_BIN_H_ -#define _GST_GL_FILTER_BIN_H_ - -#include <gst/gst.h> -#include <gst/base/gstbasetransform.h> -#include <gst/video/video.h> - -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -GType gst_gl_filter_bin_get_type(void); -#define GST_TYPE_GL_FILTER_BIN (gst_gl_filter_bin_get_type()) -#define GST_GL_FILTER_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_BIN,GstGLFilterBin)) -#define GST_IS_GL_FILTER_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_BIN)) -#define GST_GL_FILTER_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_BIN,GstGLFilterBinClass)) -#define GST_IS_GL_FILTER_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_BIN)) -#define GST_GL_FILTER_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_BIN,GstGLFilterBinClass)) - -typedef struct _GstGLFilterBin GstGLFilterBin; -typedef struct _GstGLFilterBinClass GstGLFilterBinClass; - -/** - * GstGLFilterBin: - * @parent: parent #GstBin - */ -struct _GstGLFilterBin -{ - GstBin parent; - - GstPad *srcpad; - GstPad *sinkpad; - - GstElement *upload; - GstElement *in_convert; - GstElement *filter; - GstElement *out_convert; - GstElement *download; -}; - -/** - * GstGLFilterBinClass: - * @parent_class: parent class - */ -struct _GstGLFilterBinClass -{ - GstBinClass parent_class; - - GstElement * (*create_element) (void); -}; - -void gst_gl_filter_bin_finish_init (GstGLFilterBin * self); -void gst_gl_filter_bin_finish_init_with_element (GstGLFilterBin * self, - GstElement * element); - -G_END_DECLS - -#endif /* _GST_GL_FILTER_BIN_H_ */ diff --git a/ext/gl/gstglfiltercube.c b/ext/gl/gstglfiltercube.c deleted file mode 100644 index 9e04ea081..000000000 --- a/ext/gl/gstglfiltercube.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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-glfiltercube - * @title: glfiltercube - * - * The resize and redraw callbacks can be set from a client code. - * - * ## Examples - * |[ - * gst-launch-1.0 -v videotestsrc ! glfiltercube ! glimagesink - * ]| A pipeline to mpa textures on the 6 cube faces.. - * FBO is required. - * |[ - * gst-launch-1.0 -v videotestsrc ! glfiltercube ! video/x-raw, width=640, height=480 ! glimagesink - * ]| Resize scene after drawing the cube. - * The scene size is greater than the input video size. - |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw, width=640, height=480 ! glfiltercube ! glimagesink - * ]| Resize scene before drawing the cube. - * The scene size is greater than the input video size. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gl/gstglapi.h> -#include "gstglfiltercube.h" -#include "gstglutils.h" - -#define GST_CAT_DEFAULT gst_gl_filter_cube_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_0, - PROP_RED, - PROP_GREEN, - PROP_BLUE, - PROP_FOVY, - PROP_ASPECT, - PROP_ZNEAR, - PROP_ZFAR -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_filter_cube_debug, "glfiltercube", 0, "glfiltercube element"); -#define gst_gl_filter_cube_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLFilterCube, gst_gl_filter_cube, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_filter_cube_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_filter_cube_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter, - GstCaps * incaps, GstCaps * outcaps); -static gboolean gst_gl_filter_cube_gl_start (GstGLBaseFilter * filter); -static void gst_gl_filter_cube_gl_stop (GstGLBaseFilter * filter); -static gboolean _callback (gpointer stuff); -static gboolean gst_gl_filter_cube_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -/* vertex source */ -static const gchar *cube_v_src = - "attribute vec4 a_position; \n" - "attribute vec2 a_texcoord; \n" - "uniform mat4 u_matrix; \n" - "uniform float xrot_degree, yrot_degree, zrot_degree; \n" - "varying vec2 v_texcoord; \n" - "void main() \n" - "{ \n" - " float PI = 3.14159265; \n" - " float xrot = xrot_degree*2.0*PI/360.0; \n" - " float yrot = yrot_degree*2.0*PI/360.0; \n" - " float zrot = zrot_degree*2.0*PI/360.0; \n" - " mat4 matX = mat4 ( \n" - " 1.0, 0.0, 0.0, 0.0, \n" - " 0.0, cos(xrot), sin(xrot), 0.0, \n" - " 0.0, -sin(xrot), cos(xrot), 0.0, \n" - " 0.0, 0.0, 0.0, 1.0 ); \n" - " mat4 matY = mat4 ( \n" - " cos(yrot), 0.0, -sin(yrot), 0.0, \n" - " 0.0, 1.0, 0.0, 0.0, \n" - " sin(yrot), 0.0, cos(yrot), 0.0, \n" - " 0.0, 0.0, 0.0, 1.0 ); \n" - " mat4 matZ = mat4 ( \n" - " cos(zrot), sin(zrot), 0.0, 0.0, \n" - " -sin(zrot), cos(zrot), 0.0, 0.0, \n" - " 0.0, 0.0, 1.0, 0.0, \n" - " 0.0, 0.0, 0.0, 1.0 ); \n" - " gl_Position = u_matrix * matZ * matY * matX * a_position; \n" - " v_texcoord = a_texcoord; \n" - "} \n"; - -/* fragment source */ -static const gchar *cube_f_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "varying vec2 v_texcoord; \n" - "uniform sampler2D s_texture; \n" - "void main() \n" - "{ \n" - " gl_FragColor = texture2D( s_texture, v_texcoord );\n" - "} \n"; - -static void -gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_filter_cube_set_property; - gobject_class->get_property = gst_gl_filter_cube_get_property; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_filter_cube_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_filter_cube_gl_stop; - - GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_cube_set_caps; - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_filter_cube_filter_texture; - - g_object_class_install_property (gobject_class, PROP_RED, - g_param_spec_float ("red", "Red", "Background red color", - 0.0f, 1.0f, 0.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_GREEN, - g_param_spec_float ("green", "Green", "Background green color", - 0.0f, 1.0f, 0.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_BLUE, - g_param_spec_float ("blue", "Blue", "Background blue color", - 0.0f, 1.0f, 0.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_FOVY, - g_param_spec_double ("fovy", "Fovy", "Field of view angle in degrees", - 0.0, 180.0, 45.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ASPECT, - g_param_spec_double ("aspect", "Aspect", - "Field of view in the x direction", 0.0, 100, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ZNEAR, - g_param_spec_double ("znear", "Znear", - "Specifies the distance from the viewer to the near clipping plane", - 0.0, 100.0, 0.1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ZFAR, - g_param_spec_double ("zfar", "Zfar", - "Specifies the distance from the viewer to the far clipping plane", - 0.0, 1000.0, 100.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, "OpenGL cube filter", - "Filter/Effect/Video", "Map input texture on the 6 cube faces", - "Julien Isorce <julien.isorce@gmail.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_filter_cube_init (GstGLFilterCube * filter) -{ - filter->shader = NULL; - filter->fovy = 45; - filter->aspect = 0; - filter->znear = 0.1; - filter->zfar = 100; -} - -static void -gst_gl_filter_cube_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLFilterCube *filter = GST_GL_FILTER_CUBE (object); - - switch (prop_id) { - case PROP_RED: - filter->red = g_value_get_float (value); - break; - case PROP_GREEN: - filter->green = g_value_get_float (value); - break; - case PROP_BLUE: - filter->blue = g_value_get_float (value); - break; - case PROP_FOVY: - filter->fovy = g_value_get_double (value); - break; - case PROP_ASPECT: - filter->aspect = g_value_get_double (value); - break; - case PROP_ZNEAR: - filter->znear = g_value_get_double (value); - break; - case PROP_ZFAR: - filter->zfar = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filter_cube_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLFilterCube *filter = GST_GL_FILTER_CUBE (object); - - switch (prop_id) { - case PROP_RED: - g_value_set_float (value, filter->red); - break; - case PROP_GREEN: - g_value_set_float (value, filter->green); - break; - case PROP_BLUE: - g_value_set_float (value, filter->blue); - break; - case PROP_FOVY: - g_value_set_double (value, filter->fovy); - break; - case PROP_ASPECT: - g_value_set_double (value, filter->aspect); - break; - case PROP_ZNEAR: - g_value_set_double (value, filter->znear); - break; - case PROP_ZFAR: - g_value_set_double (value, filter->zfar); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_filter_cube_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps) -{ - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); - - if (cube_filter->aspect == 0) - cube_filter->aspect = (gdouble) GST_VIDEO_INFO_WIDTH (&filter->out_info) / - (gdouble) GST_VIDEO_INFO_HEIGHT (&filter->out_info); - - return TRUE; -} - -static void -gst_gl_filter_cube_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (base_filter); - const GstGLFuncs *gl = base_filter->context->gl_vtable; - - if (cube_filter->vao) { - gl->DeleteVertexArrays (1, &cube_filter->vao); - cube_filter->vao = 0; - } - - if (cube_filter->vertex_buffer) { - gl->DeleteBuffers (1, &cube_filter->vertex_buffer); - cube_filter->vertex_buffer = 0; - } - - if (cube_filter->vbo_indices) { - gl->DeleteBuffers (1, &cube_filter->vbo_indices); - cube_filter->vbo_indices = 0; - } - - if (cube_filter->shader) { - gst_object_unref (cube_filter->shader); - cube_filter->shader = NULL; - } - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static gboolean -gst_gl_filter_cube_gl_start (GstGLBaseFilter * filter) -{ - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); - - /* blocking call, wait the opengl thread has compiled the shader */ - return gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, - cube_v_src, cube_f_src, &cube_filter->shader); -} - -static gboolean -gst_gl_filter_cube_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); - - cube_filter->in_tex = in_tex; - - return gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex, _callback, - cube_filter); -} - -/* *INDENT-OFF* */ -static const GLfloat vertices[] = { - /*| Vertex | TexCoord |*/ - /* front face */ - 1.0, 1.0, -1.0, 1.0, 0.0, - 1.0, -1.0, -1.0, 1.0, 1.0, - -1.0, -1.0, -1.0, 0.0, 1.0, - -1.0, 1.0, -1.0, 0.0, 0.0, - /* back face */ - 1.0, 1.0, 1.0, 1.0, 0.0, - -1.0, 1.0, 1.0, 0.0, 0.0, - -1.0, -1.0, 1.0, 0.0, 1.0, - 1.0, -1.0, 1.0, 1.0, 1.0, - /* right face */ - 1.0, 1.0, 1.0, 1.0, 0.0, - 1.0, -1.0, 1.0, 0.0, 0.0, - 1.0, -1.0, -1.0, 0.0, 1.0, - 1.0, 1.0, -1.0, 1.0, 1.0, - /* left face */ - -1.0, 1.0, 1.0, 1.0, 0.0, - -1.0, 1.0, -1.0, 1.0, 1.0, - -1.0, -1.0, -1.0, 0.0, 1.0, - -1.0, -1.0, 1.0, 0.0, 0.0, - /* top face */ - 1.0, -1.0, 1.0, 1.0, 0.0, - -1.0, -1.0, 1.0, 0.0, 0.0, - -1.0, -1.0, -1.0, 0.0, 1.0, - 1.0, -1.0, -1.0, 1.0, 1.0, - /* bottom face */ - 1.0, 1.0, 1.0, 1.0, 0.0, - 1.0, 1.0, -1.0, 1.0, 1.0, - -1.0, 1.0, -1.0, 0.0, 1.0, - -1.0, 1.0, 1.0, 0.0, 0.0 -}; - -static const GLushort indices[] = { - 0, 1, 2, - 0, 2, 3, - 4, 5, 6, - 4, 6, 7, - 8, 9, 10, - 8, 10, 11, - 12, 13, 14, - 12, 14, 15, - 16, 17, 18, - 16, 18, 19, - 20, 21, 22, - 20, 22, 23 -}; -/* *INDENT-ON* */ - -static void -_bind_buffer (GstGLFilterCube * cube_filter) -{ - const GstGLFuncs *gl = GST_GL_BASE_FILTER (cube_filter)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, cube_filter->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, cube_filter->vertex_buffer); - - cube_filter->attr_position = - gst_gl_shader_get_attribute_location (cube_filter->shader, "a_position"); - - cube_filter->attr_texture = - gst_gl_shader_get_attribute_location (cube_filter->shader, "a_texcoord"); - - /* Load the vertex position */ - gl->VertexAttribPointer (cube_filter->attr_position, 3, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) 0); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (cube_filter->attr_texture, 2, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - - gl->EnableVertexAttribArray (cube_filter->attr_position); - gl->EnableVertexAttribArray (cube_filter->attr_texture); -} - -static void -_unbind_buffer (GstGLFilterCube * cube_filter) -{ - const GstGLFuncs *gl = GST_GL_BASE_FILTER (cube_filter)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (cube_filter->attr_position); - gl->DisableVertexAttribArray (cube_filter->attr_texture); -} - -static gboolean -_callback (gpointer stuff) -{ - GstGLFilter *filter = GST_GL_FILTER (stuff); - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - static GLfloat xrot = 0; - static GLfloat yrot = 0; - static GLfloat zrot = 0; - - const GLfloat matrix[] = { - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - - gl->Enable (GL_DEPTH_TEST); - - gl->ClearColor (cube_filter->red, cube_filter->green, cube_filter->blue, 0.0); - gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - gst_gl_shader_use (cube_filter->shader); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, cube_filter->in_tex->tex_id); - gst_gl_shader_set_uniform_1i (cube_filter->shader, "s_texture", 0); - gst_gl_shader_set_uniform_1f (cube_filter->shader, "xrot_degree", xrot); - gst_gl_shader_set_uniform_1f (cube_filter->shader, "yrot_degree", yrot); - gst_gl_shader_set_uniform_1f (cube_filter->shader, "zrot_degree", zrot); - gst_gl_shader_set_uniform_matrix_4fv (cube_filter->shader, "u_matrix", 1, - GL_FALSE, matrix); - - if (!cube_filter->vertex_buffer) { - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &cube_filter->vao); - gl->BindVertexArray (cube_filter->vao); - } - - gl->GenBuffers (1, &cube_filter->vertex_buffer); - gl->BindBuffer (GL_ARRAY_BUFFER, cube_filter->vertex_buffer); - gl->BufferData (GL_ARRAY_BUFFER, 6 * 4 * 5 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); - - gl->GenBuffers (1, &cube_filter->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, cube_filter->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, - GL_STATIC_DRAW); - - if (gl->GenVertexArrays) { - _bind_buffer (cube_filter); - gl->BindVertexArray (0); - } - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - } - - if (gl->GenVertexArrays) - gl->BindVertexArray (cube_filter->vao); - _bind_buffer (cube_filter); - - gl->DrawElements (GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0); - - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (cube_filter); - - gl->Disable (GL_DEPTH_TEST); - - xrot += 0.3f; - yrot += 0.2f; - zrot += 0.4f; - - return TRUE; -} diff --git a/ext/gl/gstglfiltercube.h b/ext/gl/gstglfiltercube.h deleted file mode 100644 index 2dcd6c5d5..000000000 --- a/ext/gl/gstglfiltercube.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_FILTERCUBE_H_ -#define _GST_GL_FILTERCUBE_H_ - -#include <gst/gl/gstglfilter.h> -#include <gst/gl/gstglfuncs.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_FILTER_CUBE (gst_gl_filter_cube_get_type()) -#define GST_GL_FILTER_CUBE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_CUBE,GstGLFilterCube)) -#define GST_IS_GL_FILTER_CUBE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_CUBE)) -#define GST_GL_FILTER_CUBE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_CUBE,GstGLFilterCubeClass)) -#define GST_IS_GL_FILTER_CUBE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_CUBE)) -#define GST_GL_FILTER_CUBE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_CUBE,GstGLFilterCubeClass)) - -typedef struct _GstGLFilterCube GstGLFilterCube; -typedef struct _GstGLFilterCubeClass GstGLFilterCubeClass; - -struct _GstGLFilterCube -{ - GstGLFilter filter; - - GstGLShader *shader; - GstGLMemory *in_tex; - - /* background color */ - gfloat red; - gfloat green; - gfloat blue; - - /* perspective */ - gdouble fovy; - gdouble aspect; - gdouble znear; - gdouble zfar; - - GLuint vao; - GLuint vbo_indices; - GLuint vertex_buffer; - GLint attr_position; - GLint attr_texture; -}; - -struct _GstGLFilterCubeClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_filter_cube_get_type (void); - -G_END_DECLS - -#endif /* _GST_GLFILTERCUBE_H_ */ diff --git a/ext/gl/gstglfilterglass.c b/ext/gl/gstglfilterglass.c deleted file mode 100644 index 31f63b542..000000000 --- a/ext/gl/gstglfilterglass.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * Inspired from http://www.mdk.org.pl/2007/11/17/gl-colorspace-conversions - * - * 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-glfilterglass - * @title: glfilterglass - * - * Map textures on moving glass. - * - * ## Examples - * |[ - * gst-launch-1.0 -v videotestsrc ! glfilterglass ! glimagesink - * ]| A pipeline inspired from http://www.mdk.org.pl/2007/11/17/gl-colorspace-conversions - * FBO is required. - * |[ - * gst-launch-1.0 -v videotestsrc ! glfilterglass ! video/x-raw, width=640, height=480 ! glimagesink - * ]| The scene is greater than the input size. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <math.h> -#include <gst/gl/gstglfuncs.h> - -#include "gstglfilterglass.h" - -#include "gstglutils.h" - -#define GST_CAT_DEFAULT gst_gl_filter_glass_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_0 -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_filter_glass_debug, "glfilterglass", 0, "glfilterglass element"); -#define gst_gl_filter_glass_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLFilterGlass, gst_gl_filter_glass, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_filter_glass_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_filter_glass_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_filter_glass_reset (GstBaseTransform * trans); - -static gboolean gst_gl_filter_glass_init_shader (GstGLFilter * filter); -static gboolean gst_gl_filter_glass_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static void gst_gl_filter_glass_draw_background_gradient (); -static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, - gint width, gint height, guint texture, gfloat center_x, gfloat center_y, - gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation); - -static gboolean gst_gl_filter_glass_callback (gpointer stuff); - -/* *INDENT-OFF* */ -static const gchar *glass_fragment_source = - "uniform sampler2D tex;\n" - "varying float alpha;\n" - "void main () {\n" - " float p = 0.0525;\n" - " float L1 = p*1.0;\n" - " float L2 = 1.0 - L1;\n" - " float L3 = 1.0 - L1;\n" - " float w = 1.0;\n" - " float r = L1;\n" - " if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y < L1)\n" - " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n" - " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y < L1)\n" - " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L1) * (gl_TexCoord[0].y - L1) );\n" - " else if (gl_TexCoord[0].x > L2 && gl_TexCoord[0].y > L3)\n" - " r = sqrt( (gl_TexCoord[0].x - L2) * (gl_TexCoord[0].x - L2) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n" - " else if (gl_TexCoord[0].x < L1 && gl_TexCoord[0].y > L3)\n" - " r = sqrt( (gl_TexCoord[0].x - L1) * (gl_TexCoord[0].x - L1) + (gl_TexCoord[0].y - L3) * (gl_TexCoord[0].y - L3) );\n" - " if (r > L1)\n" - " w = 0.0;\n" - " vec4 color = texture2D (tex, gl_TexCoord[0].st);\n" - " gl_FragColor = vec4(color.rgb, alpha * w);\n" - "}\n"; - -static const gchar *glass_vertex_source = - "uniform float yrot;\n" - "uniform float aspect;\n" - "const float fovy = 80.0;\n" - "const float znear = 1.0;\n" - "const float zfar = 5000.0;\n" - "varying float alpha;\n" - "void main () {\n" - " float f = 1.0/(tan(radians(fovy/2.0)));\n" - " float rot = radians (yrot);\n" - " // replacement for gluPerspective\n" - " mat4 perspective = mat4 (\n" - " f/aspect, 0.0, 0.0, 0.0,\n" - " 0.0, f, 0.0, 0.0,\n" - " 0.0, 0.0, (znear+zfar)/(znear-zfar), 2.0*znear*zfar/(znear-zfar),\n" - " 0.0, 0.0, -1.0, 0.0 );\n" - " mat4 trans = mat4 (\n" - " 1.0, 0.0, 0.0, 0.0,\n" - " 0.0, 1.0, 0.0, 0.0,\n" - " 0.0, 0.0, 1.0, -3.0,\n" - " 0.0, 0.0, 0.0, 1.0 );\n" - " mat4 rotation = mat4 (\n" - " cos(rot), 0.0, sin(rot), 0.0,\n" - " 0.0, 1.0, 0.0, 0.0,\n" - " -sin(rot), 0.0, cos(rot), 0.0,\n" - " 0.0, 0.0, 0.0, 1.0 );\n" - " gl_Position = trans * perspective * rotation * gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" - " alpha = gl_Color.a;\n" - "}\n"; - -static const gchar * passthrough_vertex = - "void main () {\n" - " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" - " gl_FrontColor = gl_Color;\n" - "}\n"; - -static const gchar * passthrough_fragment = - "void main () {\n" - " gl_FragColor = gl_Color;\n" - "}\n"; -/* *INDENT-ON* */ - -static void -gst_gl_filter_glass_class_init (GstGLFilterGlassClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_filter_glass_set_property; - gobject_class->get_property = gst_gl_filter_glass_get_property; - - gst_element_class_set_metadata (element_class, "OpenGL glass filter", - "Filter/Effect/Video", "Glass Filter", - "Julien Isorce <julien.isorce@gmail.com>"); - - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_filter_glass_filter_texture; - GST_GL_FILTER_CLASS (klass)->init_fbo = gst_gl_filter_glass_init_shader; - GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_glass_reset; - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = GST_GL_API_OPENGL; -} - -static void -gst_gl_filter_glass_init (GstGLFilterGlass * filter) -{ - filter->shader = NULL; - filter->timestamp = 0; -} - -static gboolean -gst_gl_filter_glass_reset (GstBaseTransform * trans) -{ - GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (trans); - - //blocking call, wait the opengl thread has destroyed the shader - if (glass_filter->shader) - gst_object_unref (glass_filter->shader); - glass_filter->shader = NULL; - if (glass_filter->passthrough_shader) - gst_object_unref (glass_filter->passthrough_shader); - glass_filter->passthrough_shader = NULL; - - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (trans); -} - -static void -gst_gl_filter_glass_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - //GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filter_glass_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - //GstGLFilterGlass *filter = GST_GL_FILTER_GLASS (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_filter_glass_init_shader (GstGLFilter * filter) -{ - gboolean ret; - GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); - - //blocking call, wait the opengl thread has compiled the shader - ret = - gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, - glass_vertex_source, glass_fragment_source, &glass_filter->shader); - if (ret) - ret = - gst_gl_context_gen_shader (GST_GL_BASE_FILTER (filter)->context, - passthrough_vertex, passthrough_fragment, - &glass_filter->passthrough_shader); - - return ret; -} - -static gboolean -gst_gl_filter_glass_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); - - glass_filter->in_tex = in_tex; - - gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex, - gst_gl_filter_glass_callback, glass_filter); - - return TRUE; -} - -static gint64 -get_time (void) -{ - static GTimeVal val; - g_get_current_time (&val); - - return (val.tv_sec * G_USEC_PER_SEC) + val.tv_usec; -} - -static void -gst_gl_filter_glass_draw_background_gradient (GstGLFilterGlass * glass) -{ - GstGLFilter *filter = GST_GL_FILTER (glass); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - -/* *INDENT-OFF* */ - gfloat mesh[] = { - /* | Vertex | Color | */ - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, - -1.0f, 0.8f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, - 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.2f, 1.0f, - }; -/* *INDENT-ON* */ - - GLushort indices[] = { - 0, 1, 2, - 0, 2, 3, - 2, 3, 4, - 2, 4, 5 - }; - - gl->ClientActiveTexture (GL_TEXTURE0); - gl->EnableClientState (GL_VERTEX_ARRAY); - gl->EnableClientState (GL_COLOR_ARRAY); - - gl->VertexPointer (3, GL_FLOAT, 7 * sizeof (gfloat), mesh); - gl->ColorPointer (4, GL_FLOAT, 7 * sizeof (gfloat), &mesh[3]); - - gl->DrawElements (GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, indices); - - gl->DisableClientState (GL_VERTEX_ARRAY); - gl->DisableClientState (GL_COLOR_ARRAY); -} - -static void -gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter, - gint width, gint height, guint texture, - gfloat center_x, gfloat center_y, - gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation) -{ - GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (filter); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gfloat topy = reversed ? center_y - 1.0f : center_y + 1.0f; - gfloat bottomy = reversed ? center_y + 1.0f : center_y - 1.0f; - -/* *INDENT-OFF* */ - gfloat mesh[] = { - /*| Vertex |TexCoord0| Colour |*/ - center_x-1.6, topy, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, start_alpha, - center_x+1.6, topy, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, start_alpha, - center_x+1.6, bottomy, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, stop_alpha, - center_x-1.6, bottomy, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, stop_alpha, - }; -/* *INDENT-ON* */ - - GLushort indices[] = { - 0, 1, 2, - 0, 2, 3 - }; - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, texture); - - gst_gl_shader_set_uniform_1i (glass_filter->shader, "tex", 0); - gst_gl_shader_set_uniform_1f (glass_filter->shader, "yrot", rotation); - gst_gl_shader_set_uniform_1f (glass_filter->shader, "aspect", - (gfloat) width / (gfloat) height); - - gl->ClientActiveTexture (GL_TEXTURE0); - gl->EnableClientState (GL_TEXTURE_COORD_ARRAY); - gl->EnableClientState (GL_VERTEX_ARRAY); - gl->EnableClientState (GL_COLOR_ARRAY); - - gl->VertexPointer (3, GL_FLOAT, 9 * sizeof (gfloat), mesh); - gl->TexCoordPointer (2, GL_FLOAT, 9 * sizeof (gfloat), &mesh[3]); - gl->ColorPointer (4, GL_FLOAT, 9 * sizeof (gfloat), &mesh[5]); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - - gl->DisableClientState (GL_TEXTURE_COORD_ARRAY); - gl->DisableClientState (GL_VERTEX_ARRAY); - gl->DisableClientState (GL_COLOR_ARRAY); -} - -static gboolean -gst_gl_filter_glass_callback (gpointer stuff) -{ - static gint64 start_time = 0; - gfloat rotation; - - GstGLFilter *filter = GST_GL_FILTER (stuff); - GstGLFilterGlass *glass_filter = GST_GL_FILTER_GLASS (stuff); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - gint width = GST_VIDEO_INFO_WIDTH (&filter->out_info); - gint height = GST_VIDEO_INFO_HEIGHT (&filter->out_info); - guint texture = glass_filter->in_tex->tex_id; - - if (start_time == 0) - start_time = get_time (); - else { - gint64 time_left = - (glass_filter->timestamp / 1000) - (get_time () - start_time); - time_left -= 1000000 / 25; - if (time_left > 2000) { - GST_LOG ("escape"); - return FALSE; - } - } - - gst_gl_shader_use (glass_filter->passthrough_shader); - - gst_gl_filter_glass_draw_background_gradient (glass_filter); - - //Rotation - if (start_time != 0) { - gint64 time_passed = get_time () - start_time; - rotation = sin (time_passed / 1200000.0) * 45.0f; - } else { - rotation = 0.0f; - } - - gl->Enable (GL_BLEND); - gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - gst_gl_shader_use (glass_filter->shader); - - //Reflection - gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, - 0.0f, 2.0f, 0.3f, 0.0f, TRUE, rotation); - - //Main video - gst_gl_filter_glass_draw_video_plane (filter, width, height, texture, - 0.0f, 0.0f, 1.0f, 1.0f, FALSE, rotation); - - gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context); - - gl->Disable (GL_BLEND); - - return TRUE; -} diff --git a/ext/gl/gstglfilterglass.h b/ext/gl/gstglfilterglass.h deleted file mode 100644 index 1f1c91d2f..000000000 --- a/ext/gl/gstglfilterglass.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_FILTERGLASS_H_ -#define _GST_GL_FILTERGLASS_H_ - -#include <gst/gl/gstglfilter.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_FILTER_GLASS (gst_gl_filter_glass_get_type()) -#define GST_GL_FILTER_GLASS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_GLASS,GstGLFilterGlass)) -#define GST_IS_GL_FILTER_GLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_GLASS)) -#define GST_GL_FILTER_GLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_GLASS,GstGLFilterGlassClass)) -#define GST_IS_GL_FILTER_GLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_GLASS)) -#define GST_GL_FILTER_GLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_GLASS,GstGLFilterGlassClass)) - -typedef struct _GstGLFilterGlass GstGLFilterGlass; -typedef struct _GstGLFilterGlassClass GstGLFilterGlassClass; - -struct _GstGLFilterGlass -{ - GstGLFilter filter; - GstGLShader *passthrough_shader; - GstGLShader *shader; - gint64 timestamp; - GstGLMemory *in_tex; - GstGLMemory *out_tex; -}; - -struct _GstGLFilterGlassClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_filter_glass_get_type (void); - -G_END_DECLS - -#endif /* _GST_GLFILTERGLASS_H_ */ diff --git a/ext/gl/gstglfiltershader.c b/ext/gl/gstglfiltershader.c deleted file mode 100644 index df5040fea..000000000 --- a/ext/gl/gstglfiltershader.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * glshader gstreamer plugin - * Copyrithg (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch> - * - * 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-glshader - * @title: glshader - * - * OpenGL fragment shader filter - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! glshader fragment="\"`cat myshader.frag`\"" ! glimagesink - * ]| - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * Depending on the exact OpenGL version chosen and the exact requirements of - * the OpenGL implementation, a #version header may be required. - * - * The following is a simple OpenGL ES (also usable with OpenGL 3 core contexts) - * passthrough shader with the required inputs. - * |[ - * #version 100 - * #ifdef GL_ES - * precision mediump float; - * #endif - * varying vec2 v_texcoord; - * uniform sampler2D tex; - * uniform float time; - * uniform float width; - * uniform float height; - * - * void main () { - * gl_FragColor = texture2D( tex, v_texcoord ); - * } - * ]| - * - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gl/gstglfuncs.h> - -#include "gstglfiltershader.h" -#if HAVE_GRAPHENE -#include <graphene-gobject.h> -#endif - -enum -{ - PROP_0, - PROP_SHADER, - PROP_VERTEX, - PROP_FRAGMENT, - PROP_UNIFORMS, - PROP_UPDATE_SHADER, - PROP_LAST, -}; - -enum -{ - SIGNAL_0, - SIGNAL_CREATE_SHADER, - SIGNAL_LAST, -}; - -static guint gst_gl_shader_signals[SIGNAL_LAST] = { 0 }; - -#define GST_CAT_DEFAULT gst_gl_filtershader_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_filtershader_debug, "glshader", 0, "glshader element"); -#define gst_gl_filtershader_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLFilterShader, gst_gl_filtershader, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_filtershader_finalize (GObject * object); -static void gst_gl_filtershader_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_filtershader_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static gboolean gst_gl_filtershader_gl_start (GstGLBaseFilter * base); -static void gst_gl_filtershader_gl_stop (GstGLBaseFilter * base); -static gboolean gst_gl_filtershader_filter (GstGLFilter * filter, - GstBuffer * inbuf, GstBuffer * outbuf); -static gboolean gst_gl_filtershader_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); -static gboolean gst_gl_filtershader_hcallback (GstGLFilter * filter, - GstGLMemory * in_tex, gpointer stuff); - -static void -gst_gl_filtershader_class_init (GstGLFilterShaderClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->finalize = gst_gl_filtershader_finalize; - gobject_class->set_property = gst_gl_filtershader_set_property; - gobject_class->get_property = gst_gl_filtershader_get_property; - - g_object_class_install_property (gobject_class, PROP_SHADER, - g_param_spec_object ("shader", "Shader object", - "GstGLShader to use", GST_TYPE_GL_SHADER, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_VERTEX, - g_param_spec_string ("vertex", "Vertex Source", - "GLSL vertex source", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_FRAGMENT, - g_param_spec_string ("fragment", "Fragment Source", - "GLSL fragment source", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /* FIXME: add other stages */ - - g_object_class_install_property (gobject_class, PROP_UNIFORMS, - g_param_spec_boxed ("uniforms", "GLSL Uniforms", - "GLSL Uniforms", GST_TYPE_STRUCTURE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_UPDATE_SHADER, - g_param_spec_boolean ("update-shader", "Update Shader", - "Emit the \'create-shader\' signal for the next frame", - FALSE, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); - - /* - * GstGLFilterShader::create-shader: - * @object: the #GstGLFilterShader - * - * Ask's the application for a shader to render with as a result of - * inititialization or setting the 'update-shader' property. - * - * Returns: a new #GstGLShader for use in the rendering pipeline - */ - gst_gl_shader_signals[SIGNAL_CREATE_SHADER] = - g_signal_new ("create-shader", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_GL_SHADER, 0); - - gst_element_class_set_metadata (element_class, - "OpenGL fragment shader filter", "Filter/Effect", - "Perform operations with a GLSL shader", "<matthew@centricular.com>"); - - GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtershader_filter; - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_filtershader_filter_texture; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_filtershader_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_filtershader_gl_stop; - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_filtershader_init (GstGLFilterShader * filtershader) -{ - filtershader->new_source = TRUE; -} - -static void -gst_gl_filtershader_finalize (GObject * object) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object); - - g_free (filtershader->vertex); - filtershader->vertex = NULL; - - g_free (filtershader->fragment); - filtershader->fragment = NULL; - - if (filtershader->uniforms) - gst_structure_free (filtershader->uniforms); - filtershader->uniforms = NULL; - - G_OBJECT_CLASS (gst_gl_filtershader_parent_class)->finalize (object); -} - -static void -gst_gl_filtershader_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object); - - switch (prop_id) { - case PROP_SHADER: - GST_OBJECT_LOCK (filtershader); - gst_object_replace ((GstObject **) & filtershader->shader, - g_value_dup_object (value)); - filtershader->new_source = FALSE; - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_VERTEX: - GST_OBJECT_LOCK (filtershader); - g_free (filtershader->vertex); - filtershader->vertex = g_value_dup_string (value); - filtershader->new_source = TRUE; - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_FRAGMENT: - GST_OBJECT_LOCK (filtershader); - g_free (filtershader->fragment); - filtershader->fragment = g_value_dup_string (value); - filtershader->new_source = TRUE; - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_UNIFORMS: - GST_OBJECT_LOCK (filtershader); - if (filtershader->uniforms) - gst_structure_free (filtershader->uniforms); - filtershader->uniforms = g_value_dup_boxed (value); - filtershader->new_uniforms = TRUE; - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_UPDATE_SHADER: - GST_OBJECT_LOCK (filtershader); - filtershader->update_shader = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (filtershader); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filtershader_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object); - - switch (prop_id) { - case PROP_SHADER: - GST_OBJECT_LOCK (filtershader); - g_value_set_object (value, filtershader->shader); - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_VERTEX: - GST_OBJECT_LOCK (filtershader); - g_value_set_string (value, filtershader->vertex); - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_FRAGMENT: - GST_OBJECT_LOCK (filtershader); - g_value_set_string (value, filtershader->fragment); - GST_OBJECT_UNLOCK (filtershader); - break; - case PROP_UNIFORMS: - GST_OBJECT_LOCK (filtershader); - g_value_set_boxed (value, filtershader->uniforms); - GST_OBJECT_UNLOCK (filtershader); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_filtershader_gl_stop (GstGLBaseFilter * base) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (base); - - if (filtershader->shader) - gst_object_unref (filtershader->shader); - filtershader->shader = NULL; - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base); -} - -static gboolean -gst_gl_filtershader_gl_start (GstGLBaseFilter * base) -{ - return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base); -} - -static inline gboolean -_gst_clock_time_to_double (GstClockTime time, gdouble * result) -{ - if (!GST_CLOCK_TIME_IS_VALID (time)) - return FALSE; - - *result = (gdouble) time / GST_SECOND; - - return TRUE; -} - -static inline gboolean -_gint64_time_val_to_double (gint64 time, gdouble * result) -{ - if (time == -1) - return FALSE; - - *result = (gdouble) time / GST_USECOND; - - return TRUE; -} - -static gboolean -gst_gl_filtershader_filter (GstGLFilter * filter, GstBuffer * inbuf, - GstBuffer * outbuf) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter); - - if (!_gst_clock_time_to_double (GST_BUFFER_PTS (inbuf), &filtershader->time)) { - if (!_gst_clock_time_to_double (GST_BUFFER_DTS (inbuf), - &filtershader->time)) - _gint64_time_val_to_double (g_get_monotonic_time (), &filtershader->time); - } - - return gst_gl_filter_filter_texture (filter, inbuf, outbuf); -} - -static gboolean -gst_gl_filtershader_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter); - - gst_gl_filter_render_to_target (filter, in_tex, out_tex, - gst_gl_filtershader_hcallback, NULL); - - if (!filtershader->shader) - return FALSE; - - return TRUE; -} - -static gboolean -_set_uniform (GQuark field_id, const GValue * value, gpointer user_data) -{ - GstGLShader *shader = user_data; - const gchar *field_name = g_quark_to_string (field_id); - - if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_INT)) { - gst_gl_shader_set_uniform_1i (shader, field_name, g_value_get_int (value)); - } else if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLOAT)) { - gst_gl_shader_set_uniform_1f (shader, field_name, - g_value_get_float (value)); -#if HAVE_GRAPHENE - } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC2)) { - graphene_vec2_t *vec2 = g_value_get_boxed (value); - float x = graphene_vec2_get_x (vec2); - float y = graphene_vec2_get_y (vec2); - gst_gl_shader_set_uniform_2f (shader, field_name, x, y); - } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC3)) { - graphene_vec3_t *vec3 = g_value_get_boxed (value); - float x = graphene_vec3_get_x (vec3); - float y = graphene_vec3_get_y (vec3); - float z = graphene_vec3_get_z (vec3); - gst_gl_shader_set_uniform_3f (shader, field_name, x, y, z); - } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC4)) { - graphene_vec4_t *vec4 = g_value_get_boxed (value); - float x = graphene_vec4_get_x (vec4); - float y = graphene_vec4_get_y (vec4); - float z = graphene_vec4_get_z (vec4); - float w = graphene_vec4_get_w (vec4); - gst_gl_shader_set_uniform_4f (shader, field_name, x, y, z, w); - } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_MATRIX)) { - graphene_matrix_t *matrix = g_value_get_boxed (value); - float matrix_f[16]; - graphene_matrix_to_float (matrix, matrix_f); - gst_gl_shader_set_uniform_matrix_4fv (shader, field_name, 1, FALSE, - matrix_f); -#endif - } else { - /* FIXME: Add support for unsigned ints, non 4x4 matrices, etc */ - GST_FIXME ("Don't know how to set the \'%s\' paramater. Unknown type", - field_name); - return TRUE; - } - - return TRUE; -} - -static void -_update_uniforms (GstGLFilterShader * filtershader) -{ - if (filtershader->new_uniforms && filtershader->uniforms) { - gst_gl_shader_use (filtershader->shader); - - gst_structure_foreach (filtershader->uniforms, - (GstStructureForeachFunc) _set_uniform, filtershader->shader); - filtershader->new_uniforms = FALSE; - } -} - -static GstGLShader * -_maybe_recompile_shader (GstGLFilterShader * filtershader) -{ - GstGLContext *context = GST_GL_BASE_FILTER (filtershader)->context; - GstGLShader *shader; - GError *error = NULL; - - GST_OBJECT_LOCK (filtershader); - - if (!filtershader->shader || filtershader->update_shader) { - filtershader->update_shader = FALSE; - GST_OBJECT_UNLOCK (filtershader); - g_signal_emit (filtershader, gst_gl_shader_signals[SIGNAL_CREATE_SHADER], 0, - &shader); - GST_OBJECT_LOCK (filtershader); - - if (shader) { - if (filtershader->shader) - gst_object_unref (filtershader->shader); - filtershader->new_source = FALSE; - filtershader->shader = gst_object_ref (shader); - filtershader->new_uniforms = TRUE; - _update_uniforms (filtershader); - GST_OBJECT_UNLOCK (filtershader); - return shader; - } - } - - if (filtershader->shader) { - shader = gst_object_ref (filtershader->shader); - _update_uniforms (filtershader); - GST_OBJECT_UNLOCK (filtershader); - return shader; - } - - if (filtershader->new_source) { - GstGLSLStage *stage; - - shader = gst_gl_shader_new (context); - - if (filtershader->vertex) { - if (!(stage = gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER, - GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE, - filtershader->vertex))) { - g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE, - "Failed to create shader vertex stage"); - goto print_error; - } - } else { - stage = gst_glsl_stage_new_default_vertex (context); - } - - if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) { - gst_object_unref (stage); - goto print_error; - } - - if (filtershader->fragment) { - if (!(stage = gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER, - GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE, - filtershader->fragment))) { - g_set_error (&error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE, - "Failed to create shader fragment stage"); - goto print_error; - } - } else { - stage = gst_glsl_stage_new_default_fragment (context); - } - - if (!gst_gl_shader_compile_attach_stage (shader, stage, &error)) { - gst_object_unref (stage); - goto print_error; - } - - if (!gst_gl_shader_link (shader, &error)) { - goto print_error; - } - if (filtershader->shader) - gst_object_unref (filtershader->shader); - filtershader->shader = gst_object_ref (shader); - filtershader->new_source = FALSE; - filtershader->new_uniforms = TRUE; - _update_uniforms (filtershader); - - GST_OBJECT_UNLOCK (filtershader); - return shader; - } else if (filtershader->shader) { - _update_uniforms (filtershader); - shader = gst_object_ref (filtershader->shader); - GST_OBJECT_UNLOCK (filtershader); - return shader; - } - - return NULL; - -print_error: - if (shader) { - gst_object_unref (shader); - shader = NULL; - } - - GST_OBJECT_UNLOCK (filtershader); - GST_ELEMENT_ERROR (filtershader, RESOURCE, NOT_FOUND, - ("%s", error->message), (NULL)); - return NULL; -} - -static gboolean -gst_gl_filtershader_hcallback (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - GstGLShader *shader; - - if (!(shader = _maybe_recompile_shader (filtershader))) - return FALSE; - - gl->ClearColor (0.0, 0.0, 0.0, 1.0); - gl->Clear (GL_COLOR_BUFFER_BIT); - - gst_gl_shader_use (shader); - - /* FIXME: propertise these */ - gst_gl_shader_set_uniform_1i (shader, "tex", 0); - gst_gl_shader_set_uniform_1f (shader, "width", - GST_VIDEO_INFO_WIDTH (&filter->out_info)); - gst_gl_shader_set_uniform_1f (shader, "height", - GST_VIDEO_INFO_HEIGHT (&filter->out_info)); - gst_gl_shader_set_uniform_1f (shader, "time", filtershader->time); - - /* FIXME: propertise these */ - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (shader, "a_texcoord"); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_filter_draw_fullscreen_quad (filter); - - gst_object_unref (shader); - - return TRUE; -} diff --git a/ext/gl/gstglfiltershader.h b/ext/gl/gstglfiltershader.h deleted file mode 100644 index adf14109c..000000000 --- a/ext/gl/gstglfiltershader.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * glshader gstreamer plugin - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch> - * - * 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_GL_FILTERSHADER_H_ -#define _GST_GL_FILTERSHADER_H_ - -#include <gst/gl/gstglfilter.h> - -#define GST_TYPE_GL_FILTERSHADER (gst_gl_filtershader_get_type()) -#define GST_GL_FILTERSHADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTERSHADER,GstGLFilterShader)) -#define GST_IS_GL_FILTERSHADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTERSHADER)) -#define GST_GL_FILTERSHADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTERSHADER,GstGLFilterShaderClass)) -#define GST_IS_GL_FILTERSHADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTERSHADER)) -#define GST_GL_FILTERSHADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTERSHADER,GstGLFilterShaderClass)) - -typedef struct _GstGLFilterShader GstGLFilterShader; -typedef struct _GstGLFilterShaderClass GstGLFilterShaderClass; - -struct _GstGLFilterShader -{ - GstGLFilter filter; - - /* properties */ - GstGLShader *shader; - gchar *vertex; - gchar *fragment; - gboolean update_shader; /* update the shader on the next draw */ - GstStructure *uniforms; - - gboolean new_source; - gboolean new_uniforms; - gdouble time; - - gint attr_position_loc; - gint attr_texture_loc; -}; - -struct _GstGLFilterShaderClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_filtershader_get_type (void); - -#endif /* _GST_GL_FILTERSHADER_H_ */ diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c deleted file mode 100644 index 46bfaec24..000000000 --- a/ext/gl/gstglimagesink.c +++ /dev/null @@ -1,2381 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2003 Julien Moutte <julien@moutte.net> - * Copyright (C) 2005,2006,2007 David A. Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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-glimagesink - * @title: glimagesink - * - * glimagesink renders video frames to a drawable on a local or remote - * display using OpenGL. This element can receive a Window ID from the - * application through the VideoOverlay interface and will then render video - * frames in this drawable. - * If no Window ID was provided by the application, the element will - * create its own internal window and render into it. - * - * See the #GstGLDisplay documentation for a list of environment variables that - * can override window/platform detection. - * - * ## Scaling - * - * Depends on the driver, OpenGL handles hardware accelerated - * scaling of video frames. This means that the element will just accept - * incoming video frames no matter their geometry and will then put them to the - * drawable scaling them on the fly. Using the #GstGLImageSink:force-aspect-ratio - * property it is possible to enforce scaling with a constant aspect ratio, - * which means drawing black borders around the video frame. - * - * ## Events - * - * Through the gl thread, glimagesink handle some events coming from the drawable - * to manage its appearance even when the data is not flowing (GST_STATE_PAUSED). - * That means that even when the element is paused, it will receive expose events - * from the drawable and draw the latest frame with correct borders/aspect-ratio. - * - * ## Examples - * |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw ! glimagesink - * ]| A pipeline to test hardware scaling. - * No special opengl extension is used in this pipeline, that's why it should work - * with OpenGL >= 1.1. That's the case if you are using the MESA3D driver v1.3. - * |[ - * gst-launch-1.0 -v videotestsrc ! video/x-raw,format=I420 ! glimagesink - * ]| A pipeline to test hardware scaling and hardware colorspace conversion. - * When your driver supports GLSL (OpenGL Shading Language needs OpenGL >= 2.1), - * the 4 following format YUY2, UYVY, I420, YV12 and AYUV are converted to RGB32 - * through some fragment shaders and using one framebuffer (FBO extension OpenGL >= 1.4). - * If your driver does not support GLSL but supports MESA_YCbCr extension then - * the you can use YUY2 and UYVY. In this case the colorspace conversion is automatically - * made when loading the texture and therefore no framebuffer is used. - * |[ - * gst-launch-1.0 -v gltestsrc ! glimagesink - * ]| A pipeline 100% OpenGL. - * No special opengl extension is used in this pipeline, that's why it should work - * with OpenGL >= 1.1. That's the case if you are using the MESA3D driver v1.3. - * |[ - * gst-plugins-bas/tests/examples/gl/generic/cube - * ]| The graphic FPS scene can be greater than the input video FPS. - * The graphic scene can be written from a client code through the - * two glfilterapp properties. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/video/videooverlay.h> -#include <gst/video/navigation.h> -#include <gst/video/gstvideoaffinetransformationmeta.h> - -#include "gstglimagesink.h" -#include "gstglsinkbin.h" -#include "gstglutils.h" - -#include <gst/gl/gstglviewconvert.h> - -GST_DEBUG_CATEGORY (gst_debug_glimage_sink); -#define GST_CAT_DEFAULT gst_debug_glimage_sink - -#define DEFAULT_SHOW_PREROLL_FRAME TRUE -#define DEFAULT_HANDLE_EVENTS TRUE -#define DEFAULT_FORCE_ASPECT_RATIO TRUE -#define DEFAULT_IGNORE_ALPHA TRUE - -#define DEFAULT_MULTIVIEW_MODE GST_VIDEO_MULTIVIEW_MODE_MONO -#define DEFAULT_MULTIVIEW_FLAGS GST_VIDEO_MULTIVIEW_FLAGS_NONE -#define DEFAULT_MULTIVIEW_DOWNMIX GST_GL_STEREO_DOWNMIX_ANAGLYPH_GREEN_MAGENTA_DUBOIS - -typedef GstGLSinkBin GstGLImageSinkBin; -typedef GstGLSinkBinClass GstGLImageSinkBinClass; - -G_DEFINE_TYPE (GstGLImageSinkBin, gst_gl_image_sink_bin, GST_TYPE_GL_SINK_BIN); - -enum -{ - PROP_BIN_0, - PROP_BIN_ROTATE_METHOD, - PROP_BIN_FORCE_ASPECT_RATIO, - PROP_BIN_PIXEL_ASPECT_RATIO, - PROP_BIN_HANDLE_EVENTS, - PROP_BIN_CONTEXT, - PROP_BIN_IGNORE_ALPHA, - PROP_BIN_SHOW_PREROLL_FRAME, - PROP_BIN_OUTPUT_MULTIVIEW_LAYOUT, - PROP_BIN_OUTPUT_MULTIVIEW_FLAGS, - PROP_BIN_OUTPUT_MULTIVIEW_DOWNMIX_MODE -}; - -enum -{ - SIGNAL_BIN_0, - SIGNAL_BIN_CLIENT_DRAW, - SIGNAL_BIN_CLIENT_RESHAPE, - SIGNAL_BIN_LAST, -}; - -static guint gst_gl_image_sink_bin_signals[SIGNAL_BIN_LAST] = { 0 }; - -static void -gst_gl_image_sink_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec) -{ - g_object_set_property (G_OBJECT (GST_GL_SINK_BIN (object)->sink), - param_spec->name, value); -} - -static void -gst_gl_image_sink_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec) -{ - g_object_get_property (G_OBJECT (GST_GL_SINK_BIN (object)->sink), - param_spec->name, value); -} - -static gboolean -_on_client_reshape (GstGLImageSink * sink, GstGLContext * context, - guint width, guint height, gpointer data) -{ - gboolean ret; - - g_signal_emit (data, gst_gl_image_sink_bin_signals[SIGNAL_BIN_CLIENT_RESHAPE], - 0, context, width, height, &ret); - - return ret; -} - -static gboolean -_on_client_draw (GstGLImageSink * sink, GstGLContext * context, - GstSample * sample, gpointer data) -{ - gboolean ret; - - g_signal_emit (data, gst_gl_image_sink_bin_signals[SIGNAL_BIN_CLIENT_DRAW], 0, - context, sample, &ret); - - return ret; -} - -#define DEFAULT_ROTATE_METHOD GST_GL_ROTATE_METHOD_IDENTITY - -#define GST_TYPE_GL_ROTATE_METHOD (gst_gl_rotate_method_get_type()) - -static const GEnumValue rotate_methods[] = { - {GST_GL_ROTATE_METHOD_IDENTITY, "Identity (no rotation)", "none"}, - {GST_GL_ROTATE_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"}, - {GST_GL_ROTATE_METHOD_180, "Rotate 180 degrees", "rotate-180"}, - {GST_GL_ROTATE_METHOD_90L, "Rotate counter-clockwise 90 degrees", - "counterclockwise"}, - {GST_GL_ROTATE_METHOD_FLIP_HORIZ, "Flip horizontally", "horizontal-flip"}, - {GST_GL_ROTATE_METHOD_FLIP_VERT, "Flip vertically", "vertical-flip"}, - {GST_GL_ROTATE_METHOD_FLIP_UL_LR, - "Flip across upper left/lower right diagonal", "upper-left-diagonal"}, - {GST_GL_ROTATE_METHOD_FLIP_UR_LL, - "Flip across upper right/lower left diagonal", "upper-right-diagonal"}, - {GST_GL_ROTATE_METHOD_AUTO, - "Select rotate method based on image-orientation tag", "automatic"}, - {0, NULL, NULL}, -}; - -static GType -gst_gl_rotate_method_get_type (void) -{ - static GType rotate_method_type = 0; - - if (!rotate_method_type) { - rotate_method_type = g_enum_register_static ("GstGLRotateMethod", - rotate_methods); - } - return rotate_method_type; -} - -static void -gst_gl_image_sink_bin_init (GstGLImageSinkBin * self) -{ - GstGLImageSink *sink = g_object_new (GST_TYPE_GLIMAGE_SINK, NULL); - - g_signal_connect (sink, "client-reshape", (GCallback) _on_client_reshape, - self); - g_signal_connect (sink, "client-draw", (GCallback) _on_client_draw, self); - - gst_gl_sink_bin_finish_init_with_element (GST_GL_SINK_BIN (self), - GST_ELEMENT (sink)); -} - -static void -gst_gl_image_sink_bin_class_init (GstGLImageSinkBinClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->get_property = gst_gl_image_sink_bin_get_property; - gobject_class->set_property = gst_gl_image_sink_bin_set_property; - - /* gl sink */ - g_object_class_install_property (gobject_class, PROP_BIN_ROTATE_METHOD, - g_param_spec_enum ("rotate-method", - "rotate method", - "rotate method", - GST_TYPE_GL_ROTATE_METHOD, DEFAULT_ROTATE_METHOD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BIN_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", - DEFAULT_FORCE_ASPECT_RATIO, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BIN_HANDLE_EVENTS, - g_param_spec_boolean ("handle-events", "Handle XEvents", - "When enabled, XEvents will be selected and handled", - DEFAULT_HANDLE_EVENTS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BIN_IGNORE_ALPHA, - g_param_spec_boolean ("ignore-alpha", "Ignore Alpha", - "When enabled, alpha will be ignored and converted to black", - DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BIN_CONTEXT, - g_param_spec_object ("context", "OpenGL context", "Get OpenGL context", - GST_TYPE_GL_CONTEXT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BIN_PIXEL_ASPECT_RATIO, - gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio", - "The pixel aspect ratio of the device", 0, 1, G_MAXINT, 1, 1, 1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* video sink */ - g_object_class_install_property (gobject_class, PROP_BIN_SHOW_PREROLL_FRAME, - g_param_spec_boolean ("show-preroll-frame", "Show preroll frame", - "Whether to render video frames during preroll", - DEFAULT_SHOW_PREROLL_FRAME, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_BIN_OUTPUT_MULTIVIEW_LAYOUT, - g_param_spec_enum ("output-multiview-mode", "Output Multiview Mode", - "Choose output mode for multiview/3D video", - GST_TYPE_VIDEO_MULTIVIEW_MODE, DEFAULT_MULTIVIEW_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_BIN_OUTPUT_MULTIVIEW_FLAGS, - g_param_spec_flags ("output-multiview-flags", "Output Multiview Flags", - "Output multiview layout modifier flags", - GST_TYPE_VIDEO_MULTIVIEW_FLAGS, DEFAULT_MULTIVIEW_FLAGS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_BIN_OUTPUT_MULTIVIEW_DOWNMIX_MODE, - g_param_spec_enum ("output-multiview-downmix-mode", - "Mode for mono downmixed output", - "Output anaglyph type to generate when downmixing to mono", - GST_TYPE_GL_STEREO_DOWNMIX_MODE_TYPE, DEFAULT_MULTIVIEW_DOWNMIX, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gst_gl_image_sink_bin_signals[SIGNAL_BIN_CLIENT_DRAW] = - g_signal_new ("client-draw", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 2, - GST_TYPE_GL_CONTEXT, GST_TYPE_SAMPLE); - - gst_gl_image_sink_bin_signals[SIGNAL_BIN_CLIENT_RESHAPE] = - g_signal_new ("client-reshape", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 3, GST_TYPE_GL_CONTEXT, G_TYPE_UINT, G_TYPE_UINT); -} - -#define GST_GLIMAGE_SINK_GET_LOCK(glsink) \ - (GST_GLIMAGE_SINK(glsink)->drawing_lock) -#define GST_GLIMAGE_SINK_LOCK(glsink) \ - (g_mutex_lock(&GST_GLIMAGE_SINK_GET_LOCK (glsink))) -#define GST_GLIMAGE_SINK_UNLOCK(glsink) \ - (g_mutex_unlock(&GST_GLIMAGE_SINK_GET_LOCK (glsink))) - -#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)) -#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1)) -#define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0)) -#define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) -#define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) - -#define SUPPORTED_GL_APIS GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3 - -static void gst_glimage_sink_thread_init_redisplay (GstGLImageSink * gl_sink); -static void gst_glimage_sink_cleanup_glthread (GstGLImageSink * gl_sink); -static void gst_glimage_sink_on_close (GstGLImageSink * gl_sink); -static void gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, - gint width, gint height); -static void gst_glimage_sink_on_draw (GstGLImageSink * gl_sink); -static gboolean gst_glimage_sink_redisplay (GstGLImageSink * gl_sink); - -static void gst_glimage_sink_finalize (GObject * object); -static void gst_glimage_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec); -static void gst_glimage_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec); - -static gboolean gst_glimage_sink_event (GstBaseSink * sink, GstEvent * event); -static gboolean gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query); -static void gst_glimage_sink_set_context (GstElement * element, - GstContext * context); - -static GstStateChangeReturn -gst_glimage_sink_change_state (GstElement * element, GstStateChange transition); - -static void gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, - GstClockTime * start, GstClockTime * end); -static gboolean gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps); -static GstCaps *gst_glimage_sink_get_caps (GstBaseSink * bsink, - GstCaps * filter); -static GstFlowReturn gst_glimage_sink_prepare (GstBaseSink * bsink, - GstBuffer * buf); -static GstFlowReturn gst_glimage_sink_show_frame (GstVideoSink * bsink, - GstBuffer * buf); -static gboolean gst_glimage_sink_propose_allocation (GstBaseSink * bsink, - GstQuery * query); - -static void gst_glimage_sink_video_overlay_init (GstVideoOverlayInterface * - iface); -static void gst_glimage_sink_set_window_handle (GstVideoOverlay * overlay, - guintptr id); -static void gst_glimage_sink_expose (GstVideoOverlay * overlay); -static void gst_glimage_sink_set_render_rectangle (GstVideoOverlay * overlay, - gint x, gint y, gint width, gint height); -static void gst_glimage_sink_handle_events (GstVideoOverlay * overlay, - gboolean handle_events); -static gboolean update_output_format (GstGLImageSink * glimage_sink); - -#define GST_GL_SINK_CAPS \ - "video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " \ - "format = (string) RGBA, " \ - "width = " GST_VIDEO_SIZE_RANGE ", " \ - "height = " GST_VIDEO_SIZE_RANGE ", " \ - "framerate = " GST_VIDEO_FPS_RANGE ", " \ - "texture-target = (string) { 2D, external-oes } " \ - " ; " \ - "video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "," \ - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), " \ - "format = (string) RGBA, " \ - "width = " GST_VIDEO_SIZE_RANGE ", " \ - "height = " GST_VIDEO_SIZE_RANGE ", " \ - "framerate = " GST_VIDEO_FPS_RANGE ", " \ - "texture-target = (string) { 2D, external-oes } " - -static GstStaticPadTemplate gst_glimage_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_SINK_CAPS)); - -enum -{ - ARG_0, - ARG_DISPLAY, - PROP_ROTATE_METHOD, - PROP_FORCE_ASPECT_RATIO, - PROP_PIXEL_ASPECT_RATIO, - PROP_CONTEXT, - PROP_HANDLE_EVENTS, - PROP_IGNORE_ALPHA, - PROP_OUTPUT_MULTIVIEW_LAYOUT, - PROP_OUTPUT_MULTIVIEW_FLAGS, - PROP_OUTPUT_MULTIVIEW_DOWNMIX_MODE -}; - -enum -{ - SIGNAL_0, - CLIENT_DRAW_SIGNAL, - CLIENT_RESHAPE_SIGNAL, - LAST_SIGNAL -}; - -static guint gst_glimage_sink_signals[LAST_SIGNAL] = { 0 }; - -static void -_display_size_to_stream_size (GstGLImageSink * gl_sink, gdouble x, - gdouble y, gdouble * stream_x, gdouble * stream_y) -{ - gdouble stream_width, stream_height; - - stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&gl_sink->out_info); - stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&gl_sink->out_info); - - /* from display coordinates to stream coordinates */ - if (gl_sink->display_rect.w > 0) - *stream_x = - (x - gl_sink->display_rect.x) / gl_sink->display_rect.w * stream_width; - else - *stream_x = 0.; - - /* clip to stream size */ - if (*stream_x < 0.) - *stream_x = 0.; - if (*stream_x > GST_VIDEO_INFO_WIDTH (&gl_sink->out_info)) - *stream_x = GST_VIDEO_INFO_WIDTH (&gl_sink->out_info); - - /* same for y-axis */ - if (gl_sink->display_rect.h > 0) - *stream_y = - (y - gl_sink->display_rect.y) / gl_sink->display_rect.h * stream_height; - else - *stream_y = 0.; - - if (*stream_y < 0.) - *stream_y = 0.; - if (*stream_y > GST_VIDEO_INFO_HEIGHT (&gl_sink->out_info)) - *stream_y = GST_VIDEO_INFO_HEIGHT (&gl_sink->out_info); - - GST_TRACE ("transform %fx%f into %fx%f", x, y, *stream_x, *stream_y); -} - -/* rotate 90 */ -static const gfloat clockwise_matrix[] = { - 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* rotate 180 */ -static const gfloat clockwise_180_matrix[] = { - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* rotate 270 */ -static const gfloat counterclockwise_matrix[] = { - 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* horizontal-flip */ -static const gfloat horizontal_flip_matrix[] = { - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* vertical-flip */ -static const gfloat vertical_flip_matrix[] = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* upper-left-diagonal */ -static const gfloat upper_left_matrix[] = { - 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -/* upper-right-diagonal */ -static const gfloat upper_right_matrix[] = { - 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, -}; - -static void -gst_glimage_sink_set_rotate_method (GstGLImageSink * gl_sink, - GstGLRotateMethod method, gboolean from_tag) -{ - GstGLRotateMethod tag_method = DEFAULT_ROTATE_METHOD; - GST_GLIMAGE_SINK_LOCK (gl_sink); - if (from_tag) - tag_method = method; - else - gl_sink->rotate_method = method; - - if (gl_sink->rotate_method == GST_GL_ROTATE_METHOD_AUTO) - method = tag_method; - else - method = gl_sink->rotate_method; - - if (method != gl_sink->current_rotate_method) { - GST_DEBUG_OBJECT (gl_sink, "Changing method from %s to %s", - rotate_methods[gl_sink->current_rotate_method].value_nick, - rotate_methods[method].value_nick); - - switch (method) { - case GST_GL_ROTATE_METHOD_IDENTITY: - gl_sink->transform_matrix = NULL; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_90R: - gl_sink->transform_matrix = clockwise_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_180: - gl_sink->transform_matrix = clockwise_180_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_90L: - gl_sink->transform_matrix = counterclockwise_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_FLIP_HORIZ: - gl_sink->transform_matrix = horizontal_flip_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_FLIP_VERT: - gl_sink->transform_matrix = vertical_flip_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_FLIP_UL_LR: - gl_sink->transform_matrix = upper_left_matrix; - gl_sink->output_mode_changed = TRUE; - break; - case GST_GL_ROTATE_METHOD_FLIP_UR_LL: - gl_sink->transform_matrix = upper_right_matrix; - gl_sink->output_mode_changed = TRUE; - break; - default: - g_assert_not_reached (); - break; - } - - gl_sink->current_rotate_method = method; - } - GST_GLIMAGE_SINK_UNLOCK (gl_sink); -} - -static void -gst_glimage_sink_navigation_send_event (GstNavigation * navigation, GstStructure - * structure) -{ - GstGLImageSink *sink = GST_GLIMAGE_SINK (navigation); - gboolean handled = FALSE; - GstEvent *event = NULL; - GstGLWindow *window; - guint width, height; - gdouble x, y; - - if (!sink->context) { - gst_structure_free (structure); - return; - } - - window = gst_gl_context_get_window (sink->context); - g_return_if_fail (GST_IS_GL_WINDOW (window)); - - width = GST_VIDEO_SINK_WIDTH (sink); - height = GST_VIDEO_SINK_HEIGHT (sink); - gst_gl_window_get_surface_dimensions (window, &width, &height); - - /* Converting pointer coordinates to the non scaled geometry */ - if (width != 0 && gst_structure_get_double (structure, "pointer_x", &x) - && height != 0 && gst_structure_get_double (structure, "pointer_y", &y)) { - gdouble stream_x, stream_y; - - _display_size_to_stream_size (sink, x, y, &stream_x, &stream_y); - - gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, - stream_x, "pointer_y", G_TYPE_DOUBLE, stream_y, NULL); - } - - event = gst_event_new_navigation (structure); - if (event) { - gst_event_ref (event); - handled = gst_pad_push_event (GST_VIDEO_SINK_PAD (sink), event); - - if (!handled) - gst_element_post_message ((GstElement *) sink, - gst_navigation_message_new_event ((GstObject *) sink, event)); - - gst_event_unref (event); - } - gst_object_unref (window); -} - -static void -gst_glimage_sink_navigation_interface_init (GstNavigationInterface * iface) -{ - iface->send_event = gst_glimage_sink_navigation_send_event; -} - -#define gst_glimage_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLImageSink, gst_glimage_sink, - GST_TYPE_VIDEO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, - gst_glimage_sink_video_overlay_init); - G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, - gst_glimage_sink_navigation_interface_init); - GST_DEBUG_CATEGORY_INIT (gst_debug_glimage_sink, "glimagesink", 0, - "OpenGL Video Sink")); - -static void -gst_glimage_sink_class_init (GstGLImageSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstVideoSinkClass *gstvideosink_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstvideosink_class = (GstVideoSinkClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->set_property = gst_glimage_sink_set_property; - gobject_class->get_property = gst_glimage_sink_get_property; - - g_object_class_install_property (gobject_class, PROP_ROTATE_METHOD, - g_param_spec_enum ("rotate-method", - "rotate method", - "rotate method", - GST_TYPE_GL_ROTATE_METHOD, DEFAULT_ROTATE_METHOD, - 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", "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", - DEFAULT_FORCE_ASPECT_RATIO, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO, - gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio", - "The pixel aspect ratio of the device", 0, 1, G_MAXINT, 1, 1, 1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CONTEXT, - g_param_spec_object ("context", "OpenGL context", "Get OpenGL context", - GST_TYPE_GL_CONTEXT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS, - g_param_spec_boolean ("handle-events", "Handle XEvents", - "When enabled, XEvents will be selected and handled", - DEFAULT_HANDLE_EVENTS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_IGNORE_ALPHA, - g_param_spec_boolean ("ignore-alpha", "Ignore Alpha", - "When enabled, alpha will be ignored and converted to black", - DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_OUTPUT_MULTIVIEW_LAYOUT, - g_param_spec_enum ("output-multiview-mode", - "Output Multiview Mode", - "Choose output mode for multiview/3D video", - GST_TYPE_VIDEO_MULTIVIEW_MODE, DEFAULT_MULTIVIEW_MODE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OUTPUT_MULTIVIEW_FLAGS, - g_param_spec_flags ("output-multiview-flags", - "Output Multiview Flags", - "Output multiview layout modifier flags", - GST_TYPE_VIDEO_MULTIVIEW_FLAGS, DEFAULT_MULTIVIEW_FLAGS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_OUTPUT_MULTIVIEW_DOWNMIX_MODE, - g_param_spec_enum ("output-multiview-downmix-mode", - "Mode for mono downmixed output", - "Output anaglyph type to generate when downmixing to mono", - GST_TYPE_GL_STEREO_DOWNMIX_MODE_TYPE, DEFAULT_MULTIVIEW_DOWNMIX, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, "OpenGL video sink", - "Sink/Video", "A videosink based on OpenGL", - "Julien Isorce <julien.isorce@gmail.com>"); - - /** - * GstGLImageSink::client-draw: - * @object: the #GstGLImageSink - * @texture: the #guint id of the texture. - * @width: the #guint width of the texture. - * @height: the #guint height of the texture. - * - * Will be emitted before actually drawing the texture. The client should - * redraw the surface/contents with the @texture, @width and @height and - * and return %TRUE. - * - * Returns: whether the texture was redrawn by the signal. If not, a - * default redraw will occur. - */ - gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL] = - g_signal_new ("client-draw", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 2, GST_TYPE_GL_CONTEXT, GST_TYPE_SAMPLE); - - /** - * GstGLImageSink::client-reshape: - * @object: the #GstGLImageSink - * @width: the #guint width of the texture. - * @height: the #guint height of the texture. - * - * The client should resize the surface/window/viewport with the @width and - * @height and return %TRUE. - * - * Returns: whether the content area was resized by the signal. If not, a - * default viewport resize will occur. - */ - gst_glimage_sink_signals[CLIENT_RESHAPE_SIGNAL] = - g_signal_new ("client-reshape", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - G_TYPE_BOOLEAN, 3, GST_TYPE_GL_CONTEXT, G_TYPE_UINT, G_TYPE_UINT); - - gst_element_class_add_static_pad_template (element_class, - &gst_glimage_sink_template); - - gobject_class->finalize = gst_glimage_sink_finalize; - - gstelement_class->change_state = gst_glimage_sink_change_state; - gstelement_class->set_context = gst_glimage_sink_set_context; - gstbasesink_class->event = gst_glimage_sink_event; - gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_glimage_sink_query); - gstbasesink_class->set_caps = gst_glimage_sink_set_caps; - gstbasesink_class->get_caps = gst_glimage_sink_get_caps; - gstbasesink_class->get_times = gst_glimage_sink_get_times; - gstbasesink_class->prepare = gst_glimage_sink_prepare; - gstbasesink_class->propose_allocation = gst_glimage_sink_propose_allocation; - - gstvideosink_class->show_frame = - GST_DEBUG_FUNCPTR (gst_glimage_sink_show_frame); -} - -static void -gst_glimage_sink_init (GstGLImageSink * glimage_sink) -{ - glimage_sink->window_id = 0; - glimage_sink->new_window_id = 0; - glimage_sink->display = NULL; - glimage_sink->keep_aspect_ratio = TRUE; - glimage_sink->par_n = 0; - glimage_sink->par_d = 1; - glimage_sink->redisplay_texture = 0; - glimage_sink->handle_events = TRUE; - glimage_sink->ignore_alpha = TRUE; - glimage_sink->overlay_compositor = NULL; - - glimage_sink->mview_output_mode = DEFAULT_MULTIVIEW_MODE; - glimage_sink->mview_output_flags = DEFAULT_MULTIVIEW_FLAGS; - glimage_sink->mview_downmix_mode = DEFAULT_MULTIVIEW_DOWNMIX; - - glimage_sink->current_rotate_method = DEFAULT_ROTATE_METHOD; - glimage_sink->transform_matrix = NULL; - - g_mutex_init (&glimage_sink->drawing_lock); -} - -static void -gst_glimage_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLImageSink *glimage_sink; - - g_return_if_fail (GST_IS_GLIMAGE_SINK (object)); - - glimage_sink = GST_GLIMAGE_SINK (object); - - switch (prop_id) { - case PROP_ROTATE_METHOD: - gst_glimage_sink_set_rotate_method (glimage_sink, - g_value_get_enum (value), FALSE); - break; - case PROP_FORCE_ASPECT_RATIO: - { - glimage_sink->keep_aspect_ratio = g_value_get_boolean (value); - break; - } - case PROP_PIXEL_ASPECT_RATIO: - { - glimage_sink->par_n = gst_value_get_fraction_numerator (value); - glimage_sink->par_d = gst_value_get_fraction_denominator (value); - break; - } - case PROP_HANDLE_EVENTS: - gst_glimage_sink_handle_events (GST_VIDEO_OVERLAY (glimage_sink), - g_value_get_boolean (value)); - break; - case PROP_IGNORE_ALPHA: - glimage_sink->ignore_alpha = g_value_get_boolean (value); - break; - case PROP_OUTPUT_MULTIVIEW_LAYOUT: - GST_GLIMAGE_SINK_LOCK (glimage_sink); - glimage_sink->mview_output_mode = g_value_get_enum (value); - glimage_sink->output_mode_changed = TRUE; - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - break; - case PROP_OUTPUT_MULTIVIEW_FLAGS: - GST_GLIMAGE_SINK_LOCK (glimage_sink); - glimage_sink->mview_output_flags = g_value_get_flags (value); - glimage_sink->output_mode_changed = TRUE; - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - break; - case PROP_OUTPUT_MULTIVIEW_DOWNMIX_MODE: - GST_GLIMAGE_SINK_LOCK (glimage_sink); - glimage_sink->mview_downmix_mode = g_value_get_enum (value); - glimage_sink->output_mode_changed = TRUE; - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_glimage_sink_finalize (GObject * object) -{ - GstGLImageSink *glimage_sink; - - g_return_if_fail (GST_IS_GLIMAGE_SINK (object)); - - glimage_sink = GST_GLIMAGE_SINK (object); - g_mutex_clear (&glimage_sink->drawing_lock); - - GST_DEBUG ("finalized"); - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_glimage_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLImageSink *glimage_sink; - - g_return_if_fail (GST_IS_GLIMAGE_SINK (object)); - - glimage_sink = GST_GLIMAGE_SINK (object); - - switch (prop_id) { - case PROP_ROTATE_METHOD: - g_value_set_enum (value, glimage_sink->current_rotate_method); - break; - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, glimage_sink->keep_aspect_ratio); - break; - case PROP_PIXEL_ASPECT_RATIO: - gst_value_set_fraction (value, glimage_sink->par_n, glimage_sink->par_d); - break; - case PROP_CONTEXT: - g_value_set_object (value, glimage_sink->context); - break; - case PROP_HANDLE_EVENTS: - g_value_set_boolean (value, glimage_sink->handle_events); - break; - case PROP_IGNORE_ALPHA: - g_value_set_boolean (value, glimage_sink->ignore_alpha); - break; - case PROP_OUTPUT_MULTIVIEW_LAYOUT: - g_value_set_enum (value, glimage_sink->mview_output_mode); - break; - case PROP_OUTPUT_MULTIVIEW_FLAGS: - g_value_set_flags (value, glimage_sink->mview_output_flags); - break; - case PROP_OUTPUT_MULTIVIEW_DOWNMIX_MODE: - g_value_set_enum (value, glimage_sink->mview_downmix_mode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_glimage_sink_key_event_cb (GstGLWindow * window, char *event_name, char - *key_string, GstGLImageSink * gl_sink) -{ - GST_DEBUG_OBJECT (gl_sink, "event %s key %s pressed", event_name, key_string); - gst_navigation_send_key_event (GST_NAVIGATION (gl_sink), - event_name, key_string); -} - -static void -gst_glimage_sink_mouse_event_cb (GstGLWindow * window, char *event_name, - int button, double posx, double posy, GstGLImageSink * gl_sink) -{ - GST_DEBUG_OBJECT (gl_sink, "event %s at %g, %g", event_name, posx, posy); - gst_navigation_send_mouse_event (GST_NAVIGATION (gl_sink), - event_name, button, posx, posy); -} - -static gboolean -_ensure_gl_setup (GstGLImageSink * gl_sink) -{ - GError *error = NULL; - - GST_TRACE_OBJECT (gl_sink, "Ensuring setup"); - - if (!gl_sink->context) { - GST_OBJECT_LOCK (gl_sink->display); - do { - GstGLContext *other_context = NULL; - GstGLWindow *window = NULL; - - if (gl_sink->context) { - gst_object_unref (gl_sink->context); - gl_sink->context = NULL; - } - - GST_DEBUG_OBJECT (gl_sink, - "No current context, creating one for %" GST_PTR_FORMAT, - gl_sink->display); - - if (gl_sink->other_context) { - other_context = gst_object_ref (gl_sink->other_context); - } else { - other_context = - gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL); - } - - if (!gst_gl_display_create_context (gl_sink->display, - other_context, &gl_sink->context, &error)) { - if (other_context) - gst_object_unref (other_context); - GST_OBJECT_UNLOCK (gl_sink->display); - goto context_error; - } - - GST_DEBUG_OBJECT (gl_sink, - "created context %" GST_PTR_FORMAT " from other context %" - GST_PTR_FORMAT, gl_sink->context, gl_sink->other_context); - - window = gst_gl_context_get_window (gl_sink->context); - - GST_DEBUG_OBJECT (gl_sink, "got window %" GST_PTR_FORMAT, window); - - if (!gl_sink->window_id && !gl_sink->new_window_id) - gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (gl_sink)); - - GST_DEBUG_OBJECT (gl_sink, - "window_id : %" G_GUINTPTR_FORMAT " , new_window_id : %" - G_GUINTPTR_FORMAT, gl_sink->window_id, gl_sink->new_window_id); - - if (gl_sink->window_id != gl_sink->new_window_id) { - gl_sink->window_id = gl_sink->new_window_id; - GST_DEBUG_OBJECT (gl_sink, "Setting window handle on gl window"); - gst_gl_window_set_window_handle (window, gl_sink->window_id); - } - - gst_gl_window_handle_events (window, gl_sink->handle_events); - - /* setup callbacks */ - gst_gl_window_set_resize_callback (window, - GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize), - gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); - gst_gl_window_set_draw_callback (window, - GST_GL_WINDOW_CB (gst_glimage_sink_on_draw), - gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); - gst_gl_window_set_close_callback (window, - GST_GL_WINDOW_CB (gst_glimage_sink_on_close), - gst_object_ref (gl_sink), (GDestroyNotify) gst_object_unref); - gl_sink->key_sig_id = g_signal_connect (window, "key-event", G_CALLBACK - (gst_glimage_sink_key_event_cb), gl_sink); - gl_sink->mouse_sig_id = - g_signal_connect (window, "mouse-event", - G_CALLBACK (gst_glimage_sink_mouse_event_cb), gl_sink); - - if (gl_sink->x >= 0 && gl_sink->y >= 0 && gl_sink->width > 0 && - gl_sink->height > 0) { - gst_gl_window_set_render_rectangle (window, gl_sink->x, gl_sink->y, - gl_sink->width, gl_sink->height); - } - - if (other_context) - gst_object_unref (other_context); - gst_object_unref (window); - } while (!gst_gl_display_add_context (gl_sink->display, gl_sink->context)); - GST_OBJECT_UNLOCK (gl_sink->display); - } else - GST_TRACE_OBJECT (gl_sink, "Already have a context"); - - return TRUE; - -context_error: - { - GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message), - (NULL)); - - if (gl_sink->context) { - gst_object_unref (gl_sink->context); - gl_sink->context = NULL; - } - - g_clear_error (&error); - - return FALSE; - } -} - -static gboolean -gst_glimage_sink_event (GstBaseSink * sink, GstEvent * event) -{ - GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (sink); - GstTagList *taglist; - gchar *orientation; - gboolean ret; - - GST_DEBUG_OBJECT (gl_sink, "handling %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_TAG: - gst_event_parse_tag (event, &taglist); - - if (gst_tag_list_get_string (taglist, "image-orientation", &orientation)) { - if (!g_strcmp0 ("rotate-0", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, - GST_GL_ROTATE_METHOD_IDENTITY, TRUE); - else if (!g_strcmp0 ("rotate-90", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_90R, - TRUE); - else if (!g_strcmp0 ("rotate-180", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_180, - TRUE); - else if (!g_strcmp0 ("rotate-270", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_90L, - TRUE); - else if (!g_strcmp0 ("flip-rotate-0", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, - GST_GL_ROTATE_METHOD_FLIP_HORIZ, TRUE); - else if (!g_strcmp0 ("flip-rotate-90", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, - GST_GL_ROTATE_METHOD_FLIP_UR_LL, TRUE); - else if (!g_strcmp0 ("flip-rotate-180", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, - GST_GL_ROTATE_METHOD_FLIP_VERT, TRUE); - else if (!g_strcmp0 ("flip-rotate-270", orientation)) - gst_glimage_sink_set_rotate_method (gl_sink, - GST_GL_ROTATE_METHOD_FLIP_UL_LR, TRUE); - - g_free (orientation); - } - break; - default: - break; - } - - ret = GST_BASE_SINK_CLASS (parent_class)->event (sink, event); - - return ret; -} - -static gboolean -gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (bsink); - gboolean res = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) glimage_sink, query, - glimage_sink->display, glimage_sink->context, - glimage_sink->other_context)) - return TRUE; - break; - } - case GST_QUERY_DRAIN: - { - GstBuffer *buf[2]; - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - glimage_sink->redisplay_texture = 0; - buf[0] = glimage_sink->stored_buffer[0]; - buf[1] = glimage_sink->stored_buffer[1]; - glimage_sink->stored_buffer[0] = glimage_sink->stored_buffer[1] = NULL; - glimage_sink->stored_sync_meta = glimage_sink->next_sync_meta = NULL; - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - gst_buffer_replace (buf, NULL); - gst_buffer_replace (buf + 1, NULL); - - gst_buffer_replace (&glimage_sink->input_buffer, NULL); - gst_buffer_replace (&glimage_sink->input_buffer2, NULL); - gst_buffer_replace (&glimage_sink->next_buffer, NULL); - gst_buffer_replace (&glimage_sink->next_buffer2, NULL); - gst_buffer_replace (&glimage_sink->next_sync, NULL); - - res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); - break; - } - default: - res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query); - break; - } - - return res; -} - -static void -gst_glimage_sink_set_context (GstElement * element, GstContext * context) -{ - GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (element); - - gst_gl_handle_set_context (element, context, &gl_sink->display, - &gl_sink->other_context); - - if (gl_sink->display) - gst_gl_display_filter_gl_api (gl_sink->display, SUPPORTED_GL_APIS); - - GST_ELEMENT_CLASS (parent_class)->set_context (element, context); -} - -static GstStateChangeReturn -gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) -{ - GstGLImageSink *glimage_sink; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - GST_DEBUG ("changing state: %s => %s", - gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), - gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); - - glimage_sink = GST_GLIMAGE_SINK (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_gl_ensure_element_data (glimage_sink, &glimage_sink->display, - &glimage_sink->other_context)) - return GST_STATE_CHANGE_FAILURE; - - gst_gl_display_filter_gl_api (glimage_sink->display, SUPPORTED_GL_APIS); - - if (!_ensure_gl_setup (glimage_sink)) - return GST_STATE_CHANGE_FAILURE; - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - g_atomic_int_set (&glimage_sink->to_quit, 0); - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - 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_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - GstBuffer *buf[2]; - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - /* mark the redisplay_texture as unavailable (=0) - * to avoid drawing - */ - glimage_sink->redisplay_texture = 0; - buf[0] = glimage_sink->stored_buffer[0]; - buf[1] = glimage_sink->stored_buffer[1]; - glimage_sink->stored_buffer[0] = glimage_sink->stored_buffer[1] = NULL; - glimage_sink->stored_sync_meta = glimage_sink->next_sync_meta = NULL; - - if (glimage_sink->stored_sync) - gst_buffer_unref (glimage_sink->stored_sync); - glimage_sink->stored_sync = NULL; - - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - gst_buffer_replace (buf, NULL); - gst_buffer_replace (buf + 1, NULL); - - gst_object_replace ((GstObject **) & glimage_sink->convert_views, NULL); - gst_buffer_replace (&glimage_sink->input_buffer, NULL); - gst_buffer_replace (&glimage_sink->input_buffer2, NULL); - gst_buffer_replace (&glimage_sink->next_buffer, NULL); - gst_buffer_replace (&glimage_sink->next_buffer2, NULL); - gst_buffer_replace (&glimage_sink->next_sync, NULL); - - glimage_sink->window_id = 0; - /* but do not reset glimage_sink->new_window_id */ - - GST_VIDEO_SINK_WIDTH (glimage_sink) = 1; - GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1; - /* Clear cached caps */ - if (glimage_sink->out_caps) { - gst_caps_unref (glimage_sink->out_caps); - glimage_sink->out_caps = NULL; - } - if (glimage_sink->in_caps) { - gst_caps_unref (glimage_sink->in_caps); - glimage_sink->in_caps = NULL; - } - break; - } - case GST_STATE_CHANGE_READY_TO_NULL: - if (glimage_sink->overlay_compositor) { - gst_object_unref (glimage_sink->overlay_compositor); - glimage_sink->overlay_compositor = NULL; - } - - if (glimage_sink->context) { - GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context); - - gst_gl_window_send_message (window, - GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink); - - gst_gl_window_set_resize_callback (window, NULL, NULL, NULL); - gst_gl_window_set_draw_callback (window, NULL, NULL, NULL); - gst_gl_window_set_close_callback (window, NULL, NULL, NULL); - - if (glimage_sink->key_sig_id) - g_signal_handler_disconnect (window, glimage_sink->key_sig_id); - glimage_sink->key_sig_id = 0; - if (glimage_sink->mouse_sig_id) - g_signal_handler_disconnect (window, glimage_sink->mouse_sig_id); - glimage_sink->mouse_sig_id = 0; - - gst_object_unref (window); - gst_object_unref (glimage_sink->context); - glimage_sink->context = NULL; - } - - glimage_sink->window_id = 0; - - if (glimage_sink->other_context) { - gst_object_unref (glimage_sink->other_context); - glimage_sink->other_context = NULL; - } - - if (glimage_sink->display) { - gst_object_unref (glimage_sink->display); - glimage_sink->display = NULL; - } - break; - default: - break; - } - - return ret; -} - -static void -gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, - GstClockTime * start, GstClockTime * end) -{ - GstGLImageSink *glimagesink; - - glimagesink = GST_GLIMAGE_SINK (bsink); - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - *start = GST_BUFFER_TIMESTAMP (buf); - if (GST_BUFFER_DURATION_IS_VALID (buf)) - *end = *start + GST_BUFFER_DURATION (buf); - else { - if (GST_VIDEO_INFO_FPS_N (&glimagesink->out_info) > 0) { - *end = *start + - gst_util_uint64_scale_int (GST_SECOND, - GST_VIDEO_INFO_FPS_D (&glimagesink->out_info), - GST_VIDEO_INFO_FPS_N (&glimagesink->out_info)); - } - } - } -} - -static GstCaps * -gst_glimage_sink_get_caps (GstBaseSink * bsink, GstCaps * filter) -{ - GstCaps *tmp = NULL; - GstCaps *result = NULL; - - tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink)); - - if (filter) { - GST_DEBUG_OBJECT (bsink, "intersecting with filter caps %" GST_PTR_FORMAT, - filter); - - result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (tmp); - } else { - result = tmp; - } - - result = gst_gl_overlay_compositor_add_caps (result); - - GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result); - - return result; -} - -static gboolean -configure_display_from_info (GstGLImageSink * glimage_sink, - GstVideoInfo * vinfo) -{ - gint width; - gint height; - gboolean ok; - gint par_n, par_d; - gint display_par_n, display_par_d; - guint display_ratio_num, display_ratio_den; - - width = GST_VIDEO_INFO_WIDTH (vinfo); - height = GST_VIDEO_INFO_HEIGHT (vinfo); - - par_n = GST_VIDEO_INFO_PAR_N (vinfo); - par_d = GST_VIDEO_INFO_PAR_D (vinfo); - - if (!par_n) - par_n = 1; - - /* get display's PAR */ - if (glimage_sink->par_n != 0 && glimage_sink->par_d != 0) { - display_par_n = glimage_sink->par_n; - display_par_d = glimage_sink->par_d; - } else { - display_par_n = 1; - display_par_d = 1; - } - - ok = gst_video_calculate_display_ratio (&display_ratio_num, - &display_ratio_den, width, height, par_n, par_d, display_par_n, - display_par_d); - - if (!ok) - return FALSE; - - GST_TRACE ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, - display_par_d); - - if (height % display_ratio_den == 0) { - GST_DEBUG ("keeping video height"); - GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; - } else if (width % display_ratio_num == 0) { - GST_DEBUG ("keeping video width"); - GST_VIDEO_SINK_WIDTH (glimage_sink) = width; - GST_VIDEO_SINK_HEIGHT (glimage_sink) = (guint) - gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num); - } else { - GST_DEBUG ("approximating while keeping video height"); - GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint) - gst_util_uint64_scale_int (height, display_ratio_num, - display_ratio_den); - GST_VIDEO_SINK_HEIGHT (glimage_sink) = height; - } - GST_DEBUG ("scaling to %dx%d", GST_VIDEO_SINK_WIDTH (glimage_sink), - GST_VIDEO_SINK_HEIGHT (glimage_sink)); - - return TRUE; -} - -/* Called with GST_GLIMAGE_SINK lock held, to - * copy in_info to out_info and update out_caps */ -static gboolean -update_output_format (GstGLImageSink * glimage_sink) -{ - GstVideoInfo *out_info = &glimage_sink->out_info; - gboolean input_is_mono = FALSE; - GstVideoMultiviewMode mv_mode; - GstGLWindow *window = NULL; - GstGLTextureTarget previous_target; - GstStructure *s; - const gchar *target_str; - GstCaps *out_caps; - gboolean ret; - - *out_info = glimage_sink->in_info; - previous_target = glimage_sink->texture_target; - - mv_mode = GST_VIDEO_INFO_MULTIVIEW_MODE (&glimage_sink->in_info); - - if (mv_mode == GST_VIDEO_MULTIVIEW_MODE_NONE || - mv_mode == GST_VIDEO_MULTIVIEW_MODE_MONO || - mv_mode == GST_VIDEO_MULTIVIEW_MODE_LEFT || - mv_mode == GST_VIDEO_MULTIVIEW_MODE_RIGHT) - input_is_mono = TRUE; - - if (input_is_mono == FALSE && - glimage_sink->mview_output_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) { - /* Input is multiview, and output wants a conversion - configure 3d converter now, - * otherwise defer it until either the caps or the 3D output mode changes */ - gst_video_multiview_video_info_change_mode (out_info, - glimage_sink->mview_output_mode, glimage_sink->mview_output_flags); - - if (glimage_sink->convert_views == NULL) { - glimage_sink->convert_views = gst_gl_view_convert_new (); - gst_gl_view_convert_set_context (glimage_sink->convert_views, - glimage_sink->context); - } - } else { - if (glimage_sink->convert_views) { - gst_object_unref (glimage_sink->convert_views); - glimage_sink->convert_views = NULL; - } - } - - ret = configure_display_from_info (glimage_sink, out_info); - - if (glimage_sink->convert_views) { - /* Match actual output window size for pixel-aligned output, - * even though we can't necessarily match the starting left/right - * view parity properly */ - glimage_sink->out_info.width = MAX (1, glimage_sink->display_rect.w); - glimage_sink->out_info.height = MAX (1, glimage_sink->display_rect.h); - GST_LOG_OBJECT (glimage_sink, "Set 3D output scale to %d,%d", - glimage_sink->display_rect.w, glimage_sink->display_rect.h); - } - - s = gst_caps_get_structure (glimage_sink->in_caps, 0); - target_str = gst_structure_get_string (s, "texture-target"); - - if (!target_str) - target_str = GST_GL_TEXTURE_TARGET_2D_STR; - - glimage_sink->texture_target = gst_gl_texture_target_from_string (target_str); - if (!glimage_sink->texture_target) - return FALSE; - - out_caps = gst_video_info_to_caps (out_info); - gst_caps_set_features (out_caps, 0, - gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); - gst_caps_set_simple (out_caps, "texture-target", G_TYPE_STRING, - target_str, NULL); - - if (glimage_sink->convert_views) { - gst_caps_set_simple (out_caps, "texture-target", G_TYPE_STRING, - GST_GL_TEXTURE_TARGET_2D_STR, NULL); - - glimage_sink->texture_target = GST_GL_TEXTURE_TARGET_2D; - - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - gst_gl_view_convert_set_caps (glimage_sink->convert_views, - glimage_sink->in_caps, out_caps); - g_object_set (glimage_sink->convert_views, "downmix-mode", - glimage_sink->mview_downmix_mode, NULL); - GST_GLIMAGE_SINK_LOCK (glimage_sink); - } - - if (glimage_sink->out_caps) - gst_caps_unref (glimage_sink->out_caps); - glimage_sink->out_caps = out_caps; - - if (previous_target != GST_GL_TEXTURE_TARGET_NONE && - glimage_sink->texture_target != previous_target) { - /* regenerate the shader for the changed target */ - GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context); - gst_gl_window_send_message (window, - GST_GL_WINDOW_CB (gst_glimage_sink_cleanup_glthread), glimage_sink); - gst_object_unref (window); - } - - glimage_sink->output_mode_changed = FALSE; - - if (glimage_sink->context) - window = gst_gl_context_get_window (glimage_sink->context); - if (window) { - gst_gl_window_queue_resize (window); - gst_object_unref (window); - } - - return ret; -} - -static gboolean -gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) -{ - GstGLImageSink *glimage_sink; - gboolean ok; - GstVideoInfo vinfo; - - GST_DEBUG_OBJECT (bsink, "set caps with %" GST_PTR_FORMAT, caps); - - glimage_sink = GST_GLIMAGE_SINK (bsink); - - ok = gst_video_info_from_caps (&vinfo, caps); - if (!ok) - return FALSE; - - if (!_ensure_gl_setup (glimage_sink)) - return FALSE; - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - if (glimage_sink->in_caps) - gst_caps_unref (glimage_sink->in_caps); - glimage_sink->in_caps = gst_caps_ref (caps); - glimage_sink->in_info = vinfo; - ok = update_output_format (glimage_sink); - - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - return ok; -} - -/* Take the input_buffer and run it through 3D conversion if needed. - * Called with glimagesink lock, but might drop it temporarily */ -static gboolean -prepare_next_buffer (GstGLImageSink * glimage_sink) -{ - GstBuffer *in_buffer, *next_buffer, *old_buffer; - GstBuffer *in_buffer2 = NULL, *next_buffer2 = NULL, *old_buffer2; - GstBuffer *next_sync = NULL, *old_sync; - GstGLSyncMeta *sync_meta; - GstVideoFrame gl_frame; - GstGLViewConvert *convert_views = NULL; - GstVideoInfo *info; - - if (glimage_sink->input_buffer == NULL) - return TRUE; /* No input buffer to process */ - - if (GST_VIDEO_INFO_MULTIVIEW_MODE (&glimage_sink->in_info) == - GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME) { - if (glimage_sink->input_buffer2 == NULL) - return TRUE; /* Need 2nd input buffer to process */ - in_buffer2 = gst_buffer_ref (glimage_sink->input_buffer2); - } - - in_buffer = gst_buffer_ref (glimage_sink->input_buffer); - if (glimage_sink->convert_views && - (GST_VIDEO_INFO_MULTIVIEW_MODE (&glimage_sink->in_info) != - GST_VIDEO_INFO_MULTIVIEW_MODE (&glimage_sink->out_info) || - GST_VIDEO_INFO_MULTIVIEW_FLAGS (&glimage_sink->in_info) != - GST_VIDEO_INFO_MULTIVIEW_FLAGS (&glimage_sink->out_info))) - convert_views = gst_object_ref (glimage_sink->convert_views); - - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - if (convert_views) { - info = &glimage_sink->out_info; - - if (gst_gl_view_convert_submit_input_buffer (glimage_sink->convert_views, - GST_BUFFER_IS_DISCONT (in_buffer), in_buffer) != GST_FLOW_OK) { - gst_buffer_replace (&in_buffer2, NULL); - goto fail; - } - if (in_buffer2) { - if (gst_gl_view_convert_submit_input_buffer (glimage_sink->convert_views, - GST_BUFFER_IS_DISCONT (in_buffer2), in_buffer2) != GST_FLOW_OK) { - goto fail; - } - } - - if (gst_gl_view_convert_get_output (glimage_sink->convert_views, - &next_buffer) != GST_FLOW_OK) - goto fail; - if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) == - GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME) { - if (gst_gl_view_convert_get_output (glimage_sink->convert_views, - &next_buffer2) != GST_FLOW_OK) - goto fail; - } - gst_object_unref (convert_views); - convert_views = NULL; - - if (next_buffer == NULL) { - /* Not ready to paint a buffer yet */ - GST_GLIMAGE_SINK_LOCK (glimage_sink); - return TRUE; - } - } else { - next_buffer = in_buffer; - info = &glimage_sink->in_info; - } - - if (!glimage_sink->overlay_compositor) { - if (!(glimage_sink->overlay_compositor = - gst_gl_overlay_compositor_new (glimage_sink->context))) { - gst_buffer_unref (next_buffer); - goto fail; - } - } - - gst_gl_overlay_compositor_upload_overlays (glimage_sink->overlay_compositor, - next_buffer); - - sync_meta = gst_buffer_get_gl_sync_meta (next_buffer); - - if (!sync_meta) { - next_sync = gst_buffer_new (); - sync_meta = gst_buffer_add_gl_sync_meta (glimage_sink->context, next_sync); - gst_gl_sync_meta_set_sync_point (sync_meta, glimage_sink->context); - } - - /* in_buffer invalid now */ - if (!gst_video_frame_map (&gl_frame, info, next_buffer, - GST_MAP_READ | GST_MAP_GL)) { - gst_buffer_unref (next_buffer); - GST_ERROR ("Failed to map video frame."); - goto fail; - } - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - glimage_sink->next_tex = *(guint *) gl_frame.data[0]; - - old_buffer = glimage_sink->next_buffer; - glimage_sink->next_buffer = next_buffer; - old_buffer2 = glimage_sink->next_buffer2; - glimage_sink->next_buffer2 = next_buffer2; - - old_sync = glimage_sink->next_sync; - glimage_sink->next_sync = next_sync; - glimage_sink->next_sync_meta = sync_meta; - - /* Need to drop the lock again, to avoid a deadlock if we're - * dropping the last ref on this buffer and it goes back to our - * allocator */ - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - if (old_buffer) - gst_buffer_unref (old_buffer); - if (old_buffer2) - gst_buffer_unref (old_buffer2); - if (old_sync) - gst_buffer_unref (old_sync); - gst_video_frame_unmap (&gl_frame); - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - - return TRUE; - -fail: - if (convert_views) - gst_object_unref (convert_views); - GST_GLIMAGE_SINK_LOCK (glimage_sink); - return FALSE; -} - -static GstFlowReturn -gst_glimage_sink_prepare (GstBaseSink * bsink, GstBuffer * buf) -{ - GstGLImageSink *glimage_sink; - GstGLSyncMeta *sync_meta; - GstBuffer **target; - GstBuffer *old_input; - - glimage_sink = GST_GLIMAGE_SINK (bsink); - - GST_TRACE ("preparing buffer:%p", buf); - - if (GST_VIDEO_SINK_WIDTH (glimage_sink) < 1 || - GST_VIDEO_SINK_HEIGHT (glimage_sink) < 1) { - return GST_FLOW_NOT_NEGOTIATED; - } - - if (!_ensure_gl_setup (glimage_sink)) - return GST_FLOW_NOT_NEGOTIATED; - - sync_meta = gst_buffer_get_gl_sync_meta (buf); - if (sync_meta) - gst_gl_sync_meta_wait (sync_meta, glimage_sink->context); - - GST_GLIMAGE_SINK_LOCK (glimage_sink); - if (glimage_sink->window_resized) { - glimage_sink->window_resized = FALSE; - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - GST_DEBUG_OBJECT (glimage_sink, "Sending reconfigure event on sinkpad."); - gst_pad_push_event (GST_BASE_SINK (glimage_sink)->sinkpad, - gst_event_new_reconfigure ()); - GST_GLIMAGE_SINK_LOCK (glimage_sink); - } - - target = &glimage_sink->input_buffer; - if (GST_VIDEO_INFO_MULTIVIEW_MODE (&glimage_sink->in_info) == - GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME && - !GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE)) { - target = &glimage_sink->input_buffer2; - } - old_input = *target; - *target = gst_buffer_ref (buf); - - if (glimage_sink->output_mode_changed) - update_output_format (glimage_sink); - - if (!prepare_next_buffer (glimage_sink)) { - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - if (old_input) - gst_buffer_unref (old_input); - goto convert_views_failed; - } - GST_GLIMAGE_SINK_UNLOCK (glimage_sink); - - if (old_input) - gst_buffer_unref (old_input); - - if (glimage_sink->window_id != glimage_sink->new_window_id) { - GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context); - - glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_window_set_window_handle (window, glimage_sink->window_id); - - gst_object_unref (window); - } - - return GST_FLOW_OK; -convert_views_failed: - { - GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, - ("%s", "Failed to convert multiview video buffer"), (NULL)); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_glimage_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) -{ - GstGLImageSink *glimage_sink; - - GST_TRACE ("rendering buffer:%p", buf); - - glimage_sink = GST_GLIMAGE_SINK (vsink); - - GST_TRACE ("redisplay texture:%u of size:%ux%u, window size:%ux%u", - glimage_sink->next_tex, GST_VIDEO_INFO_WIDTH (&glimage_sink->out_info), - GST_VIDEO_INFO_HEIGHT (&glimage_sink->out_info), - GST_VIDEO_SINK_WIDTH (glimage_sink), - GST_VIDEO_SINK_HEIGHT (glimage_sink)); - - /* Ask the underlying window to redraw its content */ - if (!gst_glimage_sink_redisplay (glimage_sink)) - goto redisplay_failed; - - GST_TRACE ("post redisplay"); - - if (g_atomic_int_get (&glimage_sink->to_quit) != 0) { - GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, - ("%s", "Quit requested"), (NULL)); - return GST_FLOW_ERROR; - } - - return GST_FLOW_OK; - -/* ERRORS */ -redisplay_failed: - { - GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, - ("%s", "Window redisplay failed"), (NULL)); - return GST_FLOW_ERROR; - } -} - -static void -gst_glimage_sink_video_overlay_init (GstVideoOverlayInterface * iface) -{ - iface->set_window_handle = gst_glimage_sink_set_window_handle; - iface->set_render_rectangle = gst_glimage_sink_set_render_rectangle; - iface->handle_events = gst_glimage_sink_handle_events; - iface->expose = gst_glimage_sink_expose; -} - -static void -gst_glimage_sink_set_window_handle (GstVideoOverlay * overlay, guintptr id) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); - guintptr window_id = (guintptr) id; - - g_return_if_fail (GST_IS_GLIMAGE_SINK (overlay)); - - GST_DEBUG ("set_xwindow_id %" G_GUINT64_FORMAT, (guint64) window_id); - - glimage_sink->new_window_id = window_id; -} - - -static void -gst_glimage_sink_expose (GstVideoOverlay * overlay) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); - - /* redisplay opengl scene */ - if (glimage_sink->display) { - if (glimage_sink->window_id - && glimage_sink->window_id != glimage_sink->new_window_id) { - GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context); - - glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_window_set_window_handle (window, glimage_sink->window_id); - - gst_object_unref (window); - } - - gst_glimage_sink_redisplay (glimage_sink); - } -} - -static void -gst_glimage_sink_handle_events (GstVideoOverlay * overlay, - gboolean handle_events) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); - - glimage_sink->handle_events = handle_events; - if (G_LIKELY (glimage_sink->context)) { - GstGLWindow *window; - window = gst_gl_context_get_window (glimage_sink->context); - gst_gl_window_handle_events (window, handle_events); - gst_object_unref (window); - } -} - -static void -gst_glimage_sink_set_render_rectangle (GstVideoOverlay * overlay, - gint x, gint y, gint width, gint height) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); - - if (G_LIKELY (glimage_sink->context)) { - GstGLWindow *window; - window = gst_gl_context_get_window (glimage_sink->context); - gst_gl_window_set_render_rectangle (window, x, y, width, height); - gst_object_unref (window); - } - - glimage_sink->x = x; - glimage_sink->y = y; - glimage_sink->width = width; - glimage_sink->height = height; -} - -static gboolean -gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (bsink); - GstStructure *config; - GstCaps *caps; - GstBufferPool *pool = NULL; - GstVideoInfo info; - guint size; - gboolean need_pool; - GstStructure *allocation_meta = NULL; - - if (!_ensure_gl_setup (glimage_sink)) - return FALSE; - - gst_query_parse_allocation (query, &caps, &need_pool); - - if (caps == NULL) - goto no_caps; - - if (!gst_video_info_from_caps (&info, caps)) - goto invalid_caps; - - /* the normal size of a frame */ - size = info.size; - - if (need_pool) { - GST_DEBUG_OBJECT (glimage_sink, "create new pool"); - - pool = gst_gl_buffer_pool_new (glimage_sink->context); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_GL_SYNC_META); - - if (!gst_buffer_pool_set_config (pool, config)) { - g_object_unref (pool); - goto config_failed; - } - } - - /* we need at least 2 buffer because we hold on to the last one */ - gst_query_add_allocation_pool (query, pool, size, 2, 0); - if (pool) - g_object_unref (pool); - - if (glimage_sink->context->gl_vtable->FenceSync) - gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0); - - if (glimage_sink->window_width != 0 && glimage_sink->window_height != 0) { - allocation_meta = - gst_structure_new ("GstVideoOverlayCompositionMeta", - "width", G_TYPE_UINT, glimage_sink->window_width, - "height", G_TYPE_UINT, glimage_sink->window_height, NULL); - GST_DEBUG ("sending alloc query with size %dx%d", - glimage_sink->window_width, glimage_sink->window_height); - } - - gst_query_add_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta); - gst_query_add_allocation_meta (query, - GST_VIDEO_AFFINE_TRANSFORMATION_META_API_TYPE, 0); - - if (allocation_meta) - gst_structure_free (allocation_meta); - - return TRUE; - - /* ERRORS */ -no_caps: - { - GST_WARNING_OBJECT (bsink, "no caps specified"); - return FALSE; - } -invalid_caps: - { - GST_WARNING_OBJECT (bsink, "invalid caps specified"); - return FALSE; - } -config_failed: - { - GST_WARNING_OBJECT (bsink, "failed setting config"); - return FALSE; - } -} - -/* *INDENT-OFF* */ -static const GLfloat vertices[] = { - 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 1.0f -}; - -static const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; -/* *INDENT-ON* */ - -static void -_bind_buffer (GstGLImageSink * gl_sink) -{ - const GstGLFuncs *gl = gl_sink->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, gl_sink->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, gl_sink->vertex_buffer); - - /* Load the vertex position */ - gl->VertexAttribPointer (gl_sink->attr_position, 3, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) 0); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (gl_sink->attr_texture, 2, GL_FLOAT, GL_FALSE, - 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); - - gl->EnableVertexAttribArray (gl_sink->attr_position); - gl->EnableVertexAttribArray (gl_sink->attr_texture); -} - -static void -_unbind_buffer (GstGLImageSink * gl_sink) -{ - const GstGLFuncs *gl = gl_sink->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (gl_sink->attr_position); - gl->DisableVertexAttribArray (gl_sink->attr_texture); -} - -/* Called in the gl thread */ -static void -gst_glimage_sink_thread_init_redisplay (GstGLImageSink * gl_sink) -{ - const GstGLFuncs *gl = gl_sink->context->gl_vtable; - GError *error = NULL; - GstGLSLStage *frag_stage, *vert_stage; - - vert_stage = gst_glsl_stage_new_with_string (gl_sink->context, - GL_VERTEX_SHADER, GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - gst_gl_shader_string_vertex_mat4_vertex_transform); - if (gl_sink->texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) { - frag_stage = gst_glsl_stage_new_with_string (gl_sink->context, - GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE, - GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, - gst_gl_shader_string_fragment_external_oes_default); - } else { - frag_stage = gst_glsl_stage_new_default_fragment (gl_sink->context); - } - if (!vert_stage || !frag_stage) { - GST_ERROR_OBJECT (gl_sink, "Failed to retreive fragment shader for " - "texture target"); - if (vert_stage) - gst_object_unref (vert_stage); - if (frag_stage) - gst_object_unref (frag_stage); - gst_glimage_sink_cleanup_glthread (gl_sink); - return; - } - - if (!(gl_sink->redisplay_shader = - gst_gl_shader_new_link_with_stages (gl_sink->context, &error, - vert_stage, frag_stage, NULL))) { - GST_ERROR_OBJECT (gl_sink, "Failed to link shader: %s", error->message); - gst_glimage_sink_cleanup_glthread (gl_sink); - return; - } - - gl_sink->attr_position = - gst_gl_shader_get_attribute_location (gl_sink->redisplay_shader, - "a_position"); - gl_sink->attr_texture = - gst_gl_shader_get_attribute_location (gl_sink->redisplay_shader, - "a_texcoord"); - - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &gl_sink->vao); - gl->BindVertexArray (gl_sink->vao); - } - - if (!gl_sink->vertex_buffer) { - gl->GenBuffers (1, &gl_sink->vertex_buffer); - gl->BindBuffer (GL_ARRAY_BUFFER, gl_sink->vertex_buffer); - gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); - } - - if (!gl_sink->vbo_indices) { - gl->GenBuffers (1, &gl_sink->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, gl_sink->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, - GL_STATIC_DRAW); - } - - if (gl->GenVertexArrays) { - _bind_buffer (gl_sink); - gl->BindVertexArray (0); - } - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); -} - -static void -gst_glimage_sink_cleanup_glthread (GstGLImageSink * gl_sink) -{ - const GstGLFuncs *gl = gl_sink->context->gl_vtable; - - if (gl_sink->redisplay_shader) { - gst_object_unref (gl_sink->redisplay_shader); - gl_sink->redisplay_shader = NULL; - } - - if (gl_sink->vao) { - gl->DeleteVertexArrays (1, &gl_sink->vao); - gl_sink->vao = 0; - } - - if (gl_sink->vertex_buffer) { - gl->DeleteBuffers (1, &gl_sink->vertex_buffer); - gl_sink->vertex_buffer = 0; - } - - if (gl_sink->vbo_indices) { - gl->DeleteBuffers (1, &gl_sink->vbo_indices); - gl_sink->vbo_indices = 0; - } - - if (gl_sink->overlay_compositor) - gst_gl_overlay_compositor_free_overlays (gl_sink->overlay_compositor); -} - -/* Called with object lock held */ -static void -gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height) -{ - /* Here gl_sink members (ex:gl_sink->out_info) have a life time of set_caps. - * It means that they cannot change between two set_caps - */ - const GstGLFuncs *gl; - gboolean do_reshape; - - GST_DEBUG_OBJECT (gl_sink, "GL Window resized to %ux%u", width, height); - - /* check if a client reshape callback is registered */ - g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_RESHAPE_SIGNAL], 0, - gl_sink->context, width, height, &do_reshape); - GST_GLIMAGE_SINK_LOCK (gl_sink); - - gl = gl_sink->context->gl_vtable; - width = MAX (1, width); - height = MAX (1, height); - - /* Check if we would suggest a different width/height now */ - gl_sink->window_resized = ((gl_sink->window_width != width) - || (gl_sink->window_height != height)) - && (gl_sink->window_width != 0) - && (gl_sink->window_height != 0); - - gl_sink->window_width = width; - gl_sink->window_height = height; - - gst_gl_insert_debug_marker (gl_sink->context, "%s window resize to %ix%i", - GST_OBJECT_NAME (gl_sink), width, height); - - /* default reshape */ - if (!do_reshape) { - if (gl_sink->keep_aspect_ratio) { - GstVideoRectangle src, dst, result; - - src.x = 0; - src.y = 0; - if (gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_90R - || gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_90L - || gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_FLIP_UL_LR - || gl_sink->current_rotate_method == - GST_GL_ROTATE_METHOD_FLIP_UR_LL) { - src.h = GST_VIDEO_SINK_WIDTH (gl_sink); - src.w = GST_VIDEO_SINK_HEIGHT (gl_sink); - } else { - src.w = GST_VIDEO_SINK_WIDTH (gl_sink); - src.h = GST_VIDEO_SINK_HEIGHT (gl_sink); - } - - dst.x = 0; - dst.y = 0; - dst.w = width; - dst.h = height; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - gl_sink->output_mode_changed |= (result.w != gl_sink->display_rect.w); - gl_sink->output_mode_changed |= (result.h != gl_sink->display_rect.h); - gl_sink->display_rect = result; - } else { - gl_sink->output_mode_changed |= (width != gl_sink->display_rect.w); - gl_sink->output_mode_changed |= (height != gl_sink->display_rect.h); - - gl_sink->display_rect.x = 0; - gl_sink->display_rect.y = 0; - gl_sink->display_rect.w = width; - gl_sink->display_rect.h = height; - } - - gl->Viewport (gl_sink->display_rect.x, gl_sink->display_rect.y, - gl_sink->display_rect.w, gl_sink->display_rect.h); - GST_DEBUG_OBJECT (gl_sink, "GL output area now %u,%u %ux%u", - gl_sink->display_rect.x, gl_sink->display_rect.y, - gl_sink->display_rect.w, gl_sink->display_rect.h); - } - GST_GLIMAGE_SINK_UNLOCK (gl_sink); -} - -static void -gst_glimage_sink_on_draw (GstGLImageSink * gl_sink) -{ - /* Here gl_sink members (ex:gl_sink->out_info) have a life time of set_caps. - * It means that they cannot not change between two set_caps as well as - * for the redisplay_texture size. - * Whereas redisplay_texture id changes every sink_render - */ - - const GstGLFuncs *gl = NULL; - GstGLWindow *window = NULL; - gboolean do_redisplay = FALSE; - GstSample *sample = NULL; - guint gl_target = gst_gl_texture_target_to_gl (gl_sink->texture_target); - - g_return_if_fail (GST_IS_GLIMAGE_SINK (gl_sink)); - - gl = gl_sink->context->gl_vtable; - - GST_GLIMAGE_SINK_LOCK (gl_sink); - - /* check if texture is ready for being drawn */ - if (!gl_sink->redisplay_texture) { - GST_GLIMAGE_SINK_UNLOCK (gl_sink); - return; - } - - window = gst_gl_context_get_window (gl_sink->context); - window->is_drawing = TRUE; - - /* opengl scene */ - gst_gl_insert_debug_marker (gl_sink->context, "%s element drawing texture %u", - GST_OBJECT_NAME (gl_sink), gl_sink->redisplay_texture); - GST_TRACE ("redrawing texture:%u", gl_sink->redisplay_texture); - - if (gl_sink->stored_sync_meta) - gst_gl_sync_meta_wait (gl_sink->stored_sync_meta, - gst_gl_context_get_current ()); - - /* make sure that the environnement is clean */ - gst_gl_context_clear_shader (gl_sink->context); - gl->BindTexture (gl_target, 0); - - sample = gst_sample_new (gl_sink->stored_buffer[0], - gl_sink->out_caps, &GST_BASE_SINK (gl_sink)->segment, NULL); - g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL], 0, - gl_sink->context, sample, &do_redisplay); - gst_sample_unref (sample); - - if (gl_sink->stored_buffer[1]) { - sample = gst_sample_new (gl_sink->stored_buffer[1], - gl_sink->out_caps, &GST_BASE_SINK (gl_sink)->segment, NULL); - g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL], 0, - gl_sink->context, sample, &do_redisplay); - gst_sample_unref (sample); - } - - if (!do_redisplay) { - gfloat alpha = gl_sink->ignore_alpha ? 1.0f : 0.0f; - - gl->ClearColor (0.0, 0.0, 0.0, alpha); - gl->Clear (GL_COLOR_BUFFER_BIT); - - if (gl_sink->ignore_alpha) { - gl->BlendColor (0.0, 0.0, 0.0, alpha); - gl->BlendFunc (GL_SRC_ALPHA, GL_CONSTANT_COLOR); - gl->BlendEquation (GL_FUNC_ADD); - gl->Enable (GL_BLEND); - } - - gst_gl_shader_use (gl_sink->redisplay_shader); - - if (gl->GenVertexArrays) - gl->BindVertexArray (gl_sink->vao); - _bind_buffer (gl_sink); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (gl_target, gl_sink->redisplay_texture); - gst_gl_shader_set_uniform_1i (gl_sink->redisplay_shader, "tex", 0); - { - GstVideoAffineTransformationMeta *af_meta; - gfloat matrix[16]; - - af_meta = - gst_buffer_get_video_affine_transformation_meta - (gl_sink->stored_buffer[0]); - - if (gl_sink->transform_matrix) { - gfloat tmp[16]; - - gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, tmp); - gst_gl_multiply_matrix4 (tmp, gl_sink->transform_matrix, matrix); - } else { - gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, matrix); - } - - gst_gl_shader_set_uniform_matrix_4fv (gl_sink->redisplay_shader, - "u_transformation", 1, FALSE, matrix); - } - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - - gl->BindTexture (gl_target, 0); - gst_gl_context_clear_shader (gl_sink->context); - - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (gl_sink); - - if (gl_sink->ignore_alpha) - gl->Disable (GL_BLEND); - - gst_gl_overlay_compositor_draw_overlays (gl_sink->overlay_compositor); - } - /* end default opengl scene */ - window->is_drawing = FALSE; - gst_object_unref (window); - - GST_GLIMAGE_SINK_UNLOCK (gl_sink); -} - -static void -gst_glimage_sink_on_close (GstGLImageSink * gl_sink) -{ - GstGLWindow *window; - - GST_WARNING_OBJECT (gl_sink, "Output window was closed"); - - window = gst_gl_context_get_window (gl_sink->context); - - if (gl_sink->key_sig_id) - g_signal_handler_disconnect (window, gl_sink->key_sig_id); - gl_sink->key_sig_id = 0; - if (gl_sink->mouse_sig_id) - g_signal_handler_disconnect (window, gl_sink->mouse_sig_id); - gl_sink->mouse_sig_id = 0; - - g_atomic_int_set (&gl_sink->to_quit, 1); - - gst_object_unref (window); -} - -static gboolean -gst_glimage_sink_redisplay (GstGLImageSink * gl_sink) -{ - GstGLWindow *window; - GstBuffer *old_stored_buffer[2], *old_sync; - gulong handler_id; - - window = gst_gl_context_get_window (gl_sink->context); - if (!window) - return FALSE; - - handler_id = - g_signal_handler_find (GST_ELEMENT_PARENT (gl_sink), G_SIGNAL_MATCH_ID, - gst_gl_image_sink_bin_signals[SIGNAL_BIN_CLIENT_DRAW], 0, - NULL, NULL, NULL); - - if (G_UNLIKELY (!gl_sink->redisplay_shader) && (!handler_id - || !gl_sink->other_context)) { - gst_gl_window_send_message (window, - GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), gl_sink); - - /* if the shader is still null it means it failed to be useable */ - if (G_UNLIKELY (!gl_sink->redisplay_shader)) { - gst_object_unref (window); - return FALSE; - } - - gst_gl_window_set_preferred_size (window, GST_VIDEO_SINK_WIDTH (gl_sink), - GST_VIDEO_SINK_HEIGHT (gl_sink)); - gst_gl_window_show (window); - } - - /* Recreate the output texture if needed */ - GST_GLIMAGE_SINK_LOCK (gl_sink); - if (gl_sink->window_resized) { - gl_sink->window_resized = FALSE; - GST_GLIMAGE_SINK_UNLOCK (gl_sink); - GST_DEBUG_OBJECT (gl_sink, "Sending reconfigure event on sinkpad."); - gst_pad_push_event (GST_BASE_SINK (gl_sink)->sinkpad, - gst_event_new_reconfigure ()); - GST_GLIMAGE_SINK_LOCK (gl_sink); - } - - if (gl_sink->output_mode_changed && gl_sink->input_buffer != NULL) { - GST_DEBUG ("Recreating output after mode/size change"); - update_output_format (gl_sink); - prepare_next_buffer (gl_sink); - } - - if (gl_sink->next_buffer == NULL) { - /* Nothing to display yet */ - GST_GLIMAGE_SINK_UNLOCK (gl_sink); - gst_object_unref (window); - return TRUE; - } - - /* Avoid to release the texture while drawing */ - gl_sink->redisplay_texture = gl_sink->next_tex; - old_stored_buffer[0] = gl_sink->stored_buffer[0]; - old_stored_buffer[1] = gl_sink->stored_buffer[1]; - gl_sink->stored_buffer[0] = gst_buffer_ref (gl_sink->next_buffer); - if (gl_sink->next_buffer2) - gl_sink->stored_buffer[1] = gst_buffer_ref (gl_sink->next_buffer2); - else - gl_sink->stored_buffer[1] = NULL; - - old_sync = gl_sink->stored_sync; - if (gl_sink->next_sync) - gl_sink->stored_sync = gst_buffer_ref (gl_sink->next_sync); - else - gl_sink->stored_sync = NULL; - gl_sink->stored_sync_meta = gl_sink->next_sync_meta; - GST_GLIMAGE_SINK_UNLOCK (gl_sink); - - gst_buffer_replace (old_stored_buffer, NULL); - gst_buffer_replace (old_stored_buffer + 1, NULL); - if (old_sync) - gst_buffer_unref (old_sync); - - /* Drawing is asynchronous: gst_gl_window_draw is not blocking - * It means that it does not wait for stuff to be executed in other threads - */ - gst_gl_window_draw (window); - gst_object_unref (window); - - return TRUE; -} diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h deleted file mode 100644 index 12166ecd4..000000000 --- a/ext/gl/gstglimagesink.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2003 Julien Moutte <julien@moutte.net> - * Copyright (C) 2005,2006,2007 David A. Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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 _GLIMAGESINK_H_ -#define _GLIMAGESINK_H_ - -#include <gst/gst.h> -#include <gst/video/gstvideosink.h> -#include <gst/video/video.h> - -#include <gst/gl/gl.h> -#include <gst/gl/gstglfuncs.h> - -G_BEGIN_DECLS - -GST_DEBUG_CATEGORY_EXTERN (gst_debug_glimage_sink); - -#define GST_TYPE_GLIMAGE_SINK \ - (gst_glimage_sink_get_type()) -#define GST_GLIMAGE_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GLIMAGE_SINK,GstGLImageSink)) -#define GST_GLIMAGE_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GLIMAGE_SINK,GstGLImageSinkClass)) -#define GST_IS_GLIMAGE_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GLIMAGE_SINK)) -#define GST_IS_GLIMAGE_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GLIMAGE_SINK)) - -typedef enum -{ - GST_GL_ROTATE_METHOD_IDENTITY, - GST_GL_ROTATE_METHOD_90R, - GST_GL_ROTATE_METHOD_180, - GST_GL_ROTATE_METHOD_90L, - GST_GL_ROTATE_METHOD_FLIP_HORIZ, - GST_GL_ROTATE_METHOD_FLIP_VERT, - GST_GL_ROTATE_METHOD_FLIP_UL_LR, - GST_GL_ROTATE_METHOD_FLIP_UR_LL, - GST_GL_ROTATE_METHOD_AUTO, -}GstGLRotateMethod; - -typedef struct _GstGLImageSink GstGLImageSink; -typedef struct _GstGLImageSinkClass GstGLImageSinkClass; - -struct _GstGLImageSink -{ - GstVideoSink video_sink; - - guintptr window_id; - guintptr new_window_id; - gulong mouse_sig_id; - gulong key_sig_id; - - /* GstVideoOverlay::set_render_rectangle() cache */ - gint x; - gint y; - gint width; - gint height; - - /* Input info before 3d stereo output conversion, if any */ - GstVideoInfo in_info; - GstCaps *in_caps; - - /* format/caps we actually hand off to the app */ - GstVideoInfo out_info; - GstCaps *out_caps; - GstGLTextureTarget texture_target; - - GstGLDisplay *display; - GstGLContext *context; - GstGLContext *other_context; - gboolean handle_events; - gboolean ignore_alpha; - - GstGLViewConvert *convert_views; - - /* Original input RGBA buffer, ready for display, - * or possible reconversion through the views filter */ - GstBuffer *input_buffer; - /* Secondary view buffer - when operating in frame-by-frame mode */ - GstBuffer *input_buffer2; - - guint next_tex; - GstBuffer *next_buffer; - GstBuffer *next_buffer2; /* frame-by-frame 2nd view */ - GstBuffer *next_sync; - GstGLSyncMeta *next_sync_meta; - - volatile gint to_quit; - gboolean keep_aspect_ratio; - gint par_n, par_d; - - /* avoid replacing the stored_buffer while drawing */ - GMutex drawing_lock; - GstBuffer *stored_buffer[2]; - GstBuffer *stored_sync; - GstGLSyncMeta *stored_sync_meta; - GLuint redisplay_texture; - - /* protected with drawing_lock */ - gboolean window_resized; - guint window_width; - guint window_height; - - GstVideoRectangle display_rect; - - GstGLShader *redisplay_shader; - GLuint vao; - GLuint vbo_indices; - GLuint vertex_buffer; - GLint attr_position; - GLint attr_texture; - - GstVideoMultiviewMode mview_output_mode; - GstVideoMultiviewFlags mview_output_flags; - gboolean output_mode_changed; - GstGLStereoDownmix mview_downmix_mode; - - GstGLOverlayCompositor *overlay_compositor; - - /* current video flip method */ - GstGLRotateMethod current_rotate_method; - GstGLRotateMethod rotate_method; - const gfloat *transform_matrix; -}; - -struct _GstGLImageSinkClass -{ - GstVideoSinkClass video_sink_class; -}; - -GType gst_glimage_sink_get_type(void); -GType gst_gl_image_sink_bin_get_type(void); - -G_END_DECLS - -#endif - diff --git a/ext/gl/gstgloverlay.c b/ext/gl/gstgloverlay.c deleted file mode 100644 index 864ea64da..000000000 --- a/ext/gl/gstgloverlay.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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-gloverlay - * @title: gloverlay - * - * Overlay GL video texture with a PNG image - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! gloverlay location=image.jpg ! glimagesink - * ]| - * FBO (Frame Buffer Object) is required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/base/gsttypefindhelper.h> -#include <gst/gl/gstglconfig.h> - -#include "gstgloverlay.h" -#include "effects/gstgleffectssources.h" -#include "gstglutils.h" - -#include <stdio.h> -#include <stdlib.h> -#ifdef _MSC_VER -#define HAVE_BOOLEAN -#endif -#include <jpeglib.h> -#include <png.h> - -#if PNG_LIBPNG_VER >= 10400 -#define int_p_NULL NULL -#define png_infopp_NULL NULL -#endif - -#define GST_CAT_DEFAULT gst_gl_overlay_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_debug, "gloverlay", 0, "gloverlay element"); - -#define gst_gl_overlay_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLOverlay, gst_gl_overlay, GST_TYPE_GL_FILTER, - DEBUG_INIT); - -static gboolean gst_gl_overlay_set_caps (GstGLFilter * filter, - GstCaps * incaps, GstCaps * outcaps); - -static void gst_gl_overlay_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_overlay_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void gst_gl_overlay_before_transform (GstBaseTransform * trans, - GstBuffer * outbuf); -static gboolean gst_gl_overlay_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static gboolean gst_gl_overlay_load_png (GstGLOverlay * overlay, FILE * fp); -static gboolean gst_gl_overlay_load_jpeg (GstGLOverlay * overlay, FILE * fp); - -enum -{ - PROP_0, - PROP_LOCATION, - PROP_OFFSET_X, - PROP_OFFSET_Y, - PROP_RELATIVE_X, - PROP_RELATIVE_Y, - PROP_OVERLAY_WIDTH, - PROP_OVERLAY_HEIGHT, - PROP_ALPHA -}; - -/* *INDENT-OFF* */ -/* vertex source */ -static const gchar *overlay_v_src = - "attribute vec4 a_position;\n" - "attribute vec2 a_texcoord;\n" - "varying vec2 v_texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = a_position;\n" - " v_texcoord = a_texcoord;\n" - "}"; - -/* fragment source */ -static const gchar *overlay_f_src = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform sampler2D texture;\n" - "uniform float alpha;\n" - "varying vec2 v_texcoord;\n" - "void main()\n" - "{\n" - " vec4 rgba = texture2D( texture, v_texcoord );\n" - " gl_FragColor = vec4(rgba.rgb, rgba.a * alpha);\n" - "}\n"; -/* *INDENT-ON* */ - -/* init resources that need a gl context */ -static gboolean -gst_gl_overlay_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (base_filter); - - if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter)) - return FALSE; - - return gst_gl_context_gen_shader (base_filter->context, overlay_v_src, - overlay_f_src, &overlay->shader); -} - -/* free resources that need a gl context */ -static void -gst_gl_overlay_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (base_filter); - const GstGLFuncs *gl = base_filter->context->gl_vtable; - - if (overlay->shader) { - gst_object_unref (overlay->shader); - overlay->shader = NULL; - } - - if (overlay->image_memory) { - gst_memory_unref ((GstMemory *) overlay->image_memory); - overlay->image_memory = NULL; - } - - if (overlay->vao) { - gl->DeleteVertexArrays (1, &overlay->vao); - overlay->vao = 0; - } - - if (overlay->vbo) { - gl->DeleteBuffers (1, &overlay->vbo); - overlay->vbo = 0; - } - - if (overlay->vbo_indices) { - gl->DeleteBuffers (1, &overlay->vbo_indices); - overlay->vbo_indices = 0; - } - - if (overlay->overlay_vao) { - gl->DeleteVertexArrays (1, &overlay->overlay_vao); - overlay->overlay_vao = 0; - } - - if (overlay->overlay_vbo) { - gl->DeleteBuffers (1, &overlay->overlay_vbo); - overlay->overlay_vbo = 0; - } - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static void -gst_gl_overlay_class_init (GstGLOverlayClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_overlay_set_property; - gobject_class->get_property = gst_gl_overlay_get_property; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_overlay_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_overlay_gl_stop; - - GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_overlay_set_caps; - GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_overlay_filter_texture; - - GST_BASE_TRANSFORM_CLASS (klass)->before_transform = - GST_DEBUG_FUNCPTR (gst_gl_overlay_before_transform); - - g_object_class_install_property (gobject_class, PROP_LOCATION, - g_param_spec_string ("location", "location", - "Location of image file to overlay", NULL, GST_PARAM_CONTROLLABLE - | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OFFSET_X, - g_param_spec_int ("offset-x", "X Offset", - "For positive value, horizontal offset of overlay image in pixels from" - " left of video image. For negative value, horizontal offset of overlay" - " image in pixels from right of video image", G_MININT, G_MAXINT, 0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OFFSET_Y, - g_param_spec_int ("offset-y", "Y Offset", - "For positive value, vertical offset of overlay image in pixels from" - " top of video image. For negative value, vertical offset of overlay" - " image in pixels from bottom of video image", G_MININT, G_MAXINT, 0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_RELATIVE_X, - g_param_spec_double ("relative-x", "Relative X Offset", - "Horizontal offset of overlay image in fractions of video image " - "width, from top-left corner of video image", 0.0, 1.0, 0.0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_RELATIVE_Y, - g_param_spec_double ("relative-y", "Relative Y Offset", - "Vertical offset of overlay image in fractions of video image " - "height, from top-left corner of video image", 0.0, 1.0, 0.0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OVERLAY_WIDTH, - g_param_spec_int ("overlay-width", "Overlay Width", - "Width of overlay image in pixels (0 = same as overlay image)", 0, - G_MAXINT, 0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OVERLAY_HEIGHT, - g_param_spec_int ("overlay-height", "Overlay Height", - "Height of overlay image in pixels (0 = same as overlay image)", 0, - G_MAXINT, 0, - GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE - | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_ALPHA, - g_param_spec_double ("alpha", "Alpha", "Global alpha of overlay image", - 0.0, 1.0, 1.0, GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING - | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, - "Gstreamer OpenGL Overlay", "Filter/Effect/Video", - "Overlay GL video texture with a JPEG/PNG image", - "Filippo Argiolas <filippo.argiolas@gmail.com>, " - "Matthew Waters <matthew@centricular.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_GLES2 | GST_GL_API_OPENGL3; -} - -static void -gst_gl_overlay_init (GstGLOverlay * overlay) -{ - overlay->offset_x = 0; - overlay->offset_y = 0; - - overlay->relative_x = 0.0; - overlay->relative_y = 0.0; - - overlay->overlay_width = 0; - overlay->overlay_height = 0; - - overlay->alpha = 1.0; -} - -static void -gst_gl_overlay_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (object); - - switch (prop_id) { - case PROP_LOCATION: - g_free (overlay->location); - overlay->location_has_changed = TRUE; - overlay->location = g_value_dup_string (value); - break; - case PROP_OFFSET_X: - overlay->offset_x = g_value_get_int (value); - overlay->geometry_change = TRUE; - break; - case PROP_OFFSET_Y: - overlay->offset_y = g_value_get_int (value); - overlay->geometry_change = TRUE; - break; - case PROP_RELATIVE_X: - overlay->relative_x = g_value_get_double (value); - overlay->geometry_change = TRUE; - break; - case PROP_RELATIVE_Y: - overlay->relative_y = g_value_get_double (value); - overlay->geometry_change = TRUE; - break; - case PROP_OVERLAY_WIDTH: - overlay->overlay_width = g_value_get_int (value); - overlay->geometry_change = TRUE; - break; - case PROP_OVERLAY_HEIGHT: - overlay->overlay_height = g_value_get_int (value); - overlay->geometry_change = TRUE; - break; - case PROP_ALPHA: - overlay->alpha = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_overlay_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (object); - - switch (prop_id) { - case PROP_LOCATION: - g_value_set_string (value, overlay->location); - break; - case PROP_OFFSET_X: - g_value_set_int (value, overlay->offset_x); - break; - case PROP_OFFSET_Y: - g_value_set_int (value, overlay->offset_y); - break; - case PROP_RELATIVE_X: - g_value_set_double (value, overlay->relative_x); - break; - case PROP_RELATIVE_Y: - g_value_set_double (value, overlay->relative_y); - break; - case PROP_OVERLAY_WIDTH: - g_value_set_int (value, overlay->overlay_width); - break; - case PROP_OVERLAY_HEIGHT: - g_value_set_int (value, overlay->overlay_height); - break; - case PROP_ALPHA: - g_value_set_double (value, overlay->alpha); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_overlay_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (filter); - GstStructure *s = gst_caps_get_structure (incaps, 0); - gint width = 0; - gint height = 0; - - gst_structure_get_int (s, "width", &width); - gst_structure_get_int (s, "height", &height); - - overlay->window_width = width; - overlay->window_height = height; - - return TRUE; -} - -static void -_unbind_buffer (GstGLOverlay * overlay) -{ - GstGLFilter *filter = GST_GL_FILTER (overlay); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (overlay)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (filter->draw_attr_position_loc); - gl->DisableVertexAttribArray (filter->draw_attr_texture_loc); -} - -static void -_bind_buffer (GstGLOverlay * overlay, GLuint vbo) -{ - GstGLFilter *filter = GST_GL_FILTER (overlay); - const GstGLFuncs *gl = GST_GL_BASE_FILTER (overlay)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, vbo); - - gl->EnableVertexAttribArray (filter->draw_attr_position_loc); - gl->EnableVertexAttribArray (filter->draw_attr_texture_loc); - - gl->VertexAttribPointer (filter->draw_attr_position_loc, 3, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), (void *) 0); - gl->VertexAttribPointer (filter->draw_attr_texture_loc, 2, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat))); -} - -/* *INDENT-OFF* */ -float v_vertices[] = { -/*| Vertex | TexCoord |*/ - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -}; - -static const GLushort indices[] = { 0, 1, 2, 0, 2, 3, }; -/* *INDENT-ON* */ - -static gboolean -gst_gl_overlay_callback (GstGLFilter * filter, GstGLMemory * in_tex, - gpointer stuff) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (filter); - GstMapInfo map_info; - guint image_tex; - gboolean memory_mapped = FALSE; - const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - gboolean ret = FALSE; - -#if GST_GL_HAVE_OPENGL - if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context) & - GST_GL_API_OPENGL) { - - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - } -#endif - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex)); - - gst_gl_shader_use (overlay->shader); - - gst_gl_shader_set_uniform_1f (overlay->shader, "alpha", 1.0f); - gst_gl_shader_set_uniform_1i (overlay->shader, "texture", 0); - - filter->draw_attr_position_loc = - gst_gl_shader_get_attribute_location (overlay->shader, "a_position"); - filter->draw_attr_texture_loc = - gst_gl_shader_get_attribute_location (overlay->shader, "a_texcoord"); - - gst_gl_filter_draw_fullscreen_quad (filter); - - if (!overlay->image_memory) - goto out; - - if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info, - GST_MAP_READ | GST_MAP_GL) || map_info.data == NULL) - goto out; - - memory_mapped = TRUE; - image_tex = *(guint *) map_info.data; - - if (!overlay->overlay_vbo) { - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &overlay->overlay_vao); - gl->BindVertexArray (overlay->overlay_vao); - } - - gl->GenBuffers (1, &overlay->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, - GL_STATIC_DRAW); - - gl->GenBuffers (1, &overlay->overlay_vbo); - gl->BindBuffer (GL_ARRAY_BUFFER, overlay->overlay_vbo); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->vbo_indices); - overlay->geometry_change = TRUE; - } - - if (gl->GenVertexArrays) { - gl->BindVertexArray (overlay->overlay_vao); - } - - if (overlay->geometry_change) { - gint render_width, render_height; - gfloat x, y, image_width, image_height; - - /* *INDENT-OFF* */ - float vertices[] = { - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0, 1.0f, - }; - /* *INDENT-ON* */ - - /* scale from [0, 1] -> [-1, 1] */ - x = ((gfloat) overlay->offset_x / (gfloat) overlay->window_width + - overlay->relative_x) * 2.0f - 1.0; - y = ((gfloat) overlay->offset_y / (gfloat) overlay->window_height + - overlay->relative_y) * 2.0f - 1.0; - /* scale from [0, 1] -> [0, 2] */ - render_width = - overlay->overlay_width > - 0 ? overlay->overlay_width : overlay->image_width; - render_height = - overlay->overlay_height > - 0 ? overlay->overlay_height : overlay->image_height; - image_width = - ((gfloat) render_width / (gfloat) overlay->window_width) * 2.0f; - image_height = - ((gfloat) render_height / (gfloat) overlay->window_height) * 2.0f; - - vertices[0] = vertices[15] = x; - vertices[5] = vertices[10] = x + image_width; - vertices[1] = vertices[6] = y; - vertices[11] = vertices[16] = y + image_height; - - gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); - } - - _bind_buffer (overlay, overlay->overlay_vbo); - - gl->BindTexture (GL_TEXTURE_2D, image_tex); - gst_gl_shader_set_uniform_1f (overlay->shader, "alpha", overlay->alpha); - - gl->Enable (GL_BLEND); - gl->BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gl->BlendEquation (GL_FUNC_ADD); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - - gl->Disable (GL_BLEND); - ret = TRUE; - -out: - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (overlay); - - gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context); - - if (memory_mapped) - gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info); - - overlay->geometry_change = FALSE; - - return ret; -} - -static gboolean -load_file (GstGLOverlay * overlay) -{ - FILE *fp; - guint8 buff[16]; - gsize n_read; - GstCaps *caps; - GstStructure *structure; - gboolean success = FALSE; - - if (overlay->location == NULL) - return TRUE; - - if ((fp = fopen (overlay->location, "rb")) == NULL) { - GST_ELEMENT_ERROR (overlay, RESOURCE, NOT_FOUND, ("Can't open file"), - ("File: %s", overlay->location)); - return FALSE; - } - - n_read = fread (buff, 1, sizeof (buff), fp); - if (n_read != sizeof (buff)) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Can't read file header"), - ("File: %s", overlay->location)); - goto out; - } - - caps = gst_type_find_helper_for_data (GST_OBJECT (overlay), buff, - sizeof (buff), NULL); - - if (caps == NULL) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Can't find file type"), - ("File: %s", overlay->location)); - goto out; - } - - fseek (fp, 0, SEEK_SET); - - structure = gst_caps_get_structure (caps, 0); - if (gst_structure_has_name (structure, "image/jpeg")) { - success = gst_gl_overlay_load_jpeg (overlay, fp); - } else if (gst_structure_has_name (structure, "image/png")) { - success = gst_gl_overlay_load_png (overlay, fp); - } else { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("Image type not supported"), - ("File: %s", overlay->location)); - } - -out: - fclose (fp); - gst_caps_replace (&caps, NULL); - - return success; -} - -static gboolean -gst_gl_overlay_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex, - GstGLMemory * out_tex) -{ - GstGLOverlay *overlay = GST_GL_OVERLAY (filter); - - if (overlay->location_has_changed) { - if (overlay->image_memory) { - gst_memory_unref ((GstMemory *) overlay->image_memory); - overlay->image_memory = NULL; - } - - if (!load_file (overlay)) - return FALSE; - - overlay->location_has_changed = FALSE; - } - - gst_gl_filter_render_to_target (filter, in_tex, out_tex, - gst_gl_overlay_callback, overlay); - - return TRUE; -} - -static void -gst_gl_overlay_before_transform (GstBaseTransform * trans, GstBuffer * outbuf) -{ - GstClockTime stream_time; - - stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (outbuf)); - - if (GST_CLOCK_TIME_IS_VALID (stream_time)) - gst_object_sync_values (GST_OBJECT (trans), stream_time); -} - -static void -user_warning_fn (png_structp png_ptr, png_const_charp warning_msg) -{ - g_warning ("%s\n", warning_msg); -} - -static gboolean -gst_gl_overlay_load_jpeg (GstGLOverlay * overlay, FILE * fp) -{ - GstGLBaseMemoryAllocator *mem_allocator; - GstGLVideoAllocationParams *params; - GstVideoInfo v_info; - GstVideoAlignment v_align; - GstMapInfo map_info; - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - JSAMPROW j; - int i; - - jpeg_create_decompress (&cinfo); - cinfo.err = jpeg_std_error (&jerr); - jpeg_stdio_src (&cinfo, fp); - jpeg_read_header (&cinfo, TRUE); - jpeg_start_decompress (&cinfo); - overlay->image_width = cinfo.image_width; - overlay->image_height = cinfo.image_height; - - if (cinfo.num_components == 1) - gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_Y444, - overlay->image_width, overlay->image_height); - else - gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGB, - overlay->image_width, overlay->image_height); - - gst_video_alignment_reset (&v_align); - v_align.stride_align[0] = 32 - 1; - gst_video_info_align (&v_info, &v_align); - - mem_allocator = - GST_GL_BASE_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_default - (GST_GL_BASE_FILTER (overlay)->context)); - params = - gst_gl_video_allocation_params_new (GST_GL_BASE_FILTER (overlay)->context, - NULL, &v_info, 0, &v_align, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - overlay->image_memory = (GstGLMemory *) - gst_gl_base_memory_alloc (mem_allocator, - (GstGLAllocationParams *) params); - gst_gl_allocation_params_free ((GstGLAllocationParams *) params); - gst_object_unref (mem_allocator); - - if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info, - GST_MAP_WRITE)) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, ("failed to map memory"), - ("File: %s", overlay->location)); - return FALSE; - } - - for (i = 0; i < overlay->image_height; ++i) { - j = map_info.data + v_info.stride[0] * i; - jpeg_read_scanlines (&cinfo, &j, 1); - } - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); - gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info); - - return TRUE; -} - -static gboolean -gst_gl_overlay_load_png (GstGLOverlay * overlay, FILE * fp) -{ - GstGLBaseMemoryAllocator *mem_allocator; - GstGLVideoAllocationParams *params; - GstVideoInfo v_info; - GstMapInfo map_info; - - png_structp png_ptr; - png_infop info_ptr; - png_uint_32 width = 0; - png_uint_32 height = 0; - gint bit_depth = 0; - gint color_type = 0; - gint interlace_type = 0; - guint y = 0; - guchar **rows = NULL; - gint filler; - png_byte magic[8]; - gint n_read; - - if (!GST_GL_BASE_FILTER (overlay)->context) - return FALSE; - - /* Read magic number */ - n_read = fread (magic, 1, sizeof (magic), fp); - if (n_read != sizeof (magic)) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("can't read PNG magic number"), ("File: %s", overlay->location)); - return FALSE; - } - - /* Check for valid magic number */ - if (png_sig_cmp (magic, 0, sizeof (magic))) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("not a valid PNG image"), ("File: %s", overlay->location)); - return FALSE; - } - - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (png_ptr == NULL) { - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("failed to initialize the png_struct"), ("File: %s", - overlay->location)); - return FALSE; - } - - png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); - - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL) { - png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("failed to initialize the memory for image information"), - ("File: %s", overlay->location)); - return FALSE; - } - - png_init_io (png_ptr, fp); - - png_set_sig_bytes (png_ptr, sizeof (magic)); - - png_read_info (png_ptr, info_ptr); - - png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, int_p_NULL, int_p_NULL); - - if (color_type == PNG_COLOR_TYPE_RGB) { - filler = 0xff; - png_set_filler (png_ptr, filler, PNG_FILLER_AFTER); - color_type = PNG_COLOR_TYPE_RGB_ALPHA; - } - - if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { - png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("color type is not rgb"), ("File: %s", overlay->location)); - return FALSE; - } - - overlay->image_width = width; - overlay->image_height = height; - - gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, width, height); - mem_allocator = - GST_GL_BASE_MEMORY_ALLOCATOR (gst_gl_memory_allocator_get_default - (GST_GL_BASE_FILTER (overlay)->context)); - params = - gst_gl_video_allocation_params_new (GST_GL_BASE_FILTER (overlay)->context, - NULL, &v_info, 0, NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA); - overlay->image_memory = (GstGLMemory *) - gst_gl_base_memory_alloc (mem_allocator, - (GstGLAllocationParams *) params); - gst_gl_allocation_params_free ((GstGLAllocationParams *) params); - gst_object_unref (mem_allocator); - - if (!gst_memory_map ((GstMemory *) overlay->image_memory, &map_info, - GST_MAP_WRITE)) { - png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL); - GST_ELEMENT_ERROR (overlay, STREAM, DECODE, - ("failed to map memory"), ("File: %s", overlay->location)); - return FALSE; - } - rows = (guchar **) malloc (sizeof (guchar *) * height); - - for (y = 0; y < height; ++y) - rows[y] = (guchar *) (map_info.data + y * width * 4); - - png_read_image (png_ptr, rows); - - free (rows); - gst_memory_unmap ((GstMemory *) overlay->image_memory, &map_info); - - png_read_end (png_ptr, info_ptr); - png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL); - - return TRUE; -} diff --git a/ext/gl/gstgloverlay.h b/ext/gl/gstgloverlay.h deleted file mode 100644 index dad01e4eb..000000000 --- a/ext/gl/gstgloverlay.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com> - * - * 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_GL_OVERLAY_H_ -#define _GST_GL_OVERLAY_H_ - -#include <gst/gl/gstglfilter.h> -#include <gst/gl/gstglfuncs.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_OVERLAY (gst_gl_overlay_get_type()) -#define GST_GL_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GL_OVERLAY,GstGLOverlay)) -#define GST_IS_GL_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GL_OVERLAY)) -#define GST_GL_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) , GST_TYPE_GL_OVERLAY,GstGLOverlayClass)) -#define GST_IS_GL_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) , GST_TYPE_GL_OVERLAY)) -#define GST_GL_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) , GST_TYPE_GL_OVERLAY,GstGLOverlayClass)) - -typedef struct _GstGLOverlay GstGLOverlay; -typedef struct _GstGLOverlayClass GstGLOverlayClass; - -struct _GstGLOverlay -{ - GstGLFilter filter; - - /* properties */ - gchar *location; - gint offset_x; - gint offset_y; - - gdouble relative_x; - gdouble relative_y; - - gint overlay_width; - gint overlay_height; - - gdouble alpha; - - /* <private> */ - GstGLShader *shader; - GstGLMemory *image_memory; - - gboolean location_has_changed; - gint window_width, window_height; - gint image_width, image_height; - - gboolean geometry_change; - - GLuint vao; - GLuint overlay_vao; - GLuint vbo; - GLuint overlay_vbo; - GLuint vbo_indices; - GLuint attr_position; - GLuint attr_texture; -}; - -struct _GstGLOverlayClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_overlay_get_type (void); - -G_END_DECLS - -#endif /* _GST_GL_OVERLAY_H_ */ diff --git a/ext/gl/gstglsinkbin.c b/ext/gl/gstglsinkbin.c deleted file mode 100644 index 310634c32..000000000 --- a/ext/gl/gstglsinkbin.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 - -#include <gst/video/videooverlay.h> -#include <gst/video/navigation.h> -#include <gst/controller/gstproxycontrolbinding.h> - -#include "gstglsinkbin.h" - -GST_DEBUG_CATEGORY (gst_debug_gl_sink_bin); -#define GST_CAT_DEFAULT gst_debug_gl_sink_bin - -static void gst_gl_sink_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec); -static void gst_gl_sink_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec); - -static GstStateChangeReturn gst_gl_sink_bin_change_state (GstElement * element, - GstStateChange transition); - -static void gst_gl_sink_bin_video_overlay_init (gpointer g_iface, - gpointer g_iface_data); -static void gst_gl_sink_bin_navigation_interface_init (gpointer g_iface, - gpointer g_iface_data); -static void gst_gl_sink_bin_color_balance_init (gpointer g_iface, - gpointer g_iface_data); - -#define DEFAULT_SYNC TRUE -#define DEFAULT_MAX_LATENESS -1 -#define DEFAULT_QOS FALSE -#define DEFAULT_ASYNC TRUE -#define DEFAULT_TS_OFFSET 0 -#define DEFAULT_BLOCKSIZE 4096 -#define DEFAULT_RENDER_DELAY 0 -#define DEFAULT_ENABLE_LAST_SAMPLE TRUE -#define DEFAULT_THROTTLE_TIME 0 -#define DEFAULT_MAX_BITRATE 0 - -/* GstGLColorBalance properties */ -#define DEFAULT_PROP_CONTRAST 1.0 -#define DEFAULT_PROP_BRIGHTNESS 0.0 -#define DEFAULT_PROP_HUE 0.0 -#define DEFAULT_PROP_SATURATION 1.0 - -enum -{ - PROP_0, - PROP_FORCE_ASPECT_RATIO, - PROP_SINK, - PROP_SYNC, - PROP_MAX_LATENESS, - PROP_QOS, - PROP_ASYNC, - PROP_TS_OFFSET, - PROP_ENABLE_LAST_SAMPLE, - PROP_LAST_SAMPLE, - PROP_BLOCKSIZE, - PROP_RENDER_DELAY, - PROP_THROTTLE_TIME, - PROP_MAX_BITRATE, - PROP_CONTRAST, - PROP_BRIGHTNESS, - PROP_HUE, - PROP_SATURATION, -}; - -enum -{ - SIGNAL_0, - SIGNAL_CREATE_ELEMENT, - SIGNAL_LAST, -}; - -static guint gst_gl_sink_bin_signals[SIGNAL_LAST] = { 0, }; - -#define gst_gl_sink_bin_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLSinkBin, gst_gl_sink_bin, - GST_TYPE_BIN, G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, - gst_gl_sink_bin_video_overlay_init); - G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, - gst_gl_sink_bin_navigation_interface_init); - G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE, - gst_gl_sink_bin_color_balance_init) - GST_DEBUG_CATEGORY_INIT (gst_debug_gl_sink_bin, "glimagesink", 0, - "OpenGL Video Sink Bin")); - -static void -gst_gl_sink_bin_class_init (GstGLSinkBinClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - GstCaps *upload_caps; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - element_class->change_state = gst_gl_sink_bin_change_state; - - gobject_class->set_property = gst_gl_sink_bin_set_property; - gobject_class->get_property = gst_gl_sink_bin_get_property; - - g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", - "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_SINK, - g_param_spec_object ("sink", - "GL sink element", - "The GL sink chain to use", - GST_TYPE_ELEMENT, - GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /* base sink */ - g_object_class_install_property (gobject_class, PROP_SYNC, - g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_MAX_LATENESS, - g_param_spec_int64 ("max-lateness", "Max Lateness", - "Maximum number of nanoseconds that a buffer can be late before it " - "is dropped (-1 unlimited)", -1, G_MAXINT64, DEFAULT_MAX_LATENESS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_QOS, - g_param_spec_boolean ("qos", "Qos", - "Generate Quality-of-Service events upstream", DEFAULT_QOS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_ASYNC, - g_param_spec_boolean ("async", "Async", - "Go asynchronously to PAUSED", DEFAULT_ASYNC, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_TS_OFFSET, - g_param_spec_int64 ("ts-offset", "TS Offset", - "Timestamp offset in nanoseconds", G_MININT64, G_MAXINT64, - DEFAULT_TS_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE, - g_param_spec_boolean ("enable-last-sample", "Enable Last Buffer", - "Enable the last-sample property", DEFAULT_ENABLE_LAST_SAMPLE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE, - g_param_spec_boxed ("last-sample", "Last Sample", - "The last sample received in the sink", GST_TYPE_SAMPLE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BLOCKSIZE, - g_param_spec_uint ("blocksize", "Block size", - "Size in bytes to pull per buffer (0 = default)", 0, G_MAXUINT, - DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_RENDER_DELAY, - g_param_spec_uint64 ("render-delay", "Render Delay", - "Additional render delay of the sink in nanoseconds", 0, G_MAXUINT64, - DEFAULT_RENDER_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_THROTTLE_TIME, - g_param_spec_uint64 ("throttle-time", "Throttle time", - "The time to keep between rendered buffers (0 = disabled)", 0, - G_MAXUINT64, DEFAULT_THROTTLE_TIME, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_MAX_BITRATE, - g_param_spec_uint64 ("max-bitrate", "Max Bitrate", - "The maximum bits per second to render (0 = disabled)", 0, - G_MAXUINT64, DEFAULT_MAX_BITRATE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* colorbalance */ - g_object_class_install_property (gobject_class, PROP_CONTRAST, - g_param_spec_double ("contrast", "Contrast", "contrast", - 0.0, 2.0, DEFAULT_PROP_CONTRAST, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BRIGHTNESS, - g_param_spec_double ("brightness", "Brightness", "brightness", -1.0, 1.0, - DEFAULT_PROP_BRIGHTNESS, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_HUE, - g_param_spec_double ("hue", "Hue", "hue", -1.0, 1.0, DEFAULT_PROP_HUE, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_SATURATION, - g_param_spec_double ("saturation", "Saturation", "saturation", 0.0, 2.0, - DEFAULT_PROP_SATURATION, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /** - * GstGLSinkBin::create-element: - * @object: the #GstGLSinkBin - * - * Will be emitted when we need the processing element/s that this bin will use - * - * Returns: a new #GstElement - */ - gst_gl_sink_bin_signals[SIGNAL_CREATE_ELEMENT] = - g_signal_new ("create-element", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_ELEMENT, 0); - - gst_element_class_set_metadata (element_class, - "GL Sink Bin", "Sink/Video", - "Infrastructure to process GL textures", - "Matthew Waters <matthew@centricular.com>"); - - upload_caps = gst_gl_upload_get_input_template_caps (); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps)); - gst_caps_unref (upload_caps); -} - -static void -gst_gl_sink_bin_init (GstGLSinkBin * self) -{ - gboolean res = TRUE; - GstPad *pad; - - self->upload = gst_element_factory_make ("glupload", NULL); - self->convert = gst_element_factory_make ("glcolorconvert", NULL); - self->balance = gst_element_factory_make ("glcolorbalance", NULL); - - res &= gst_bin_add (GST_BIN (self), self->upload); - res &= gst_bin_add (GST_BIN (self), self->convert); - res &= gst_bin_add (GST_BIN (self), self->balance); - - res &= gst_element_link_pads (self->upload, "src", self->convert, "sink"); - res &= gst_element_link_pads (self->convert, "src", self->balance, "sink"); - - pad = gst_element_get_static_pad (self->upload, "sink"); - if (!pad) { - res = FALSE; - } else { - GST_DEBUG_OBJECT (self, "setting target sink pad %" GST_PTR_FORMAT, pad); - self->sinkpad = gst_ghost_pad_new ("sink", pad); - gst_element_add_pad (GST_ELEMENT_CAST (self), self->sinkpad); - gst_object_unref (pad); - } - -#define ADD_BINDING(obj,ref,prop) \ - gst_object_add_control_binding (GST_OBJECT (obj), \ - gst_proxy_control_binding_new (GST_OBJECT (obj), prop, \ - GST_OBJECT (ref), prop)); - ADD_BINDING (self->balance, self, "contrast"); - ADD_BINDING (self->balance, self, "brightness"); - ADD_BINDING (self->balance, self, "hue"); - ADD_BINDING (self->balance, self, "saturation"); -#undef ADD_BINDING - - if (!res) { - GST_WARNING_OBJECT (self, "Failed to add/connect the necessary machinery"); - } -} - -static gboolean -_connect_sink_element (GstGLSinkBin * self) -{ - gst_object_set_name (GST_OBJECT (self->sink), "sink"); - - if (gst_bin_add (GST_BIN (self), self->sink) && - gst_element_link_pads (self->balance, "src", self->sink, "sink")) - return TRUE; - - GST_ERROR_OBJECT (self, "Failed to link sink element into the pipeline"); - return FALSE; -} - -static void -gst_gl_sink_bin_set_sink (GstGLSinkBin * self, GstElement * sink) -{ - g_return_if_fail (GST_IS_ELEMENT (sink)); - - if (self->sink) { - gst_bin_remove (GST_BIN (self), self->sink); - self->sink = NULL; - } - - /* We keep an indirect reference when the element is added */ - self->sink = sink; - - if (sink && !_connect_sink_element (self)) - self->sink = NULL; -} - -void -gst_gl_sink_bin_finish_init_with_element (GstGLSinkBin * self, - GstElement * element) -{ - gst_gl_sink_bin_set_sink (self, element); -} - -void -gst_gl_sink_bin_finish_init (GstGLSinkBin * self) -{ - GstGLSinkBinClass *klass = GST_GL_SINK_BIN_GET_CLASS (self); - GstElement *element = NULL; - - if (klass->create_element) - element = klass->create_element (); - - if (element) - gst_gl_sink_bin_set_sink (self, element); -} - -static void -gst_gl_sink_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (object); - - switch (prop_id) { - case PROP_SINK: - gst_gl_sink_bin_set_sink (self, g_value_get_object (value)); - break; - case PROP_CONTRAST: - case PROP_BRIGHTNESS: - case PROP_HUE: - case PROP_SATURATION: - if (self->balance) - g_object_set_property (G_OBJECT (self->balance), pspec->name, value); - break; - default: - if (self->sink) - g_object_set_property (G_OBJECT (self->sink), pspec->name, value); - break; - } -} - -static void -gst_gl_sink_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (object); - - switch (prop_id) { - case PROP_SINK: - g_value_set_object (value, self->sink); - break; - case PROP_CONTRAST: - case PROP_BRIGHTNESS: - case PROP_HUE: - case PROP_SATURATION: - if (self->balance) - g_object_get_property (G_OBJECT (self->balance), pspec->name, value); - break; - default: - if (self->sink) - g_object_get_property (G_OBJECT (self->sink), pspec->name, value); - break; - } -} - -static GstStateChangeReturn -gst_gl_sink_bin_change_state (GstElement * element, GstStateChange transition) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (element); - GstGLSinkBinClass *klass = GST_GL_SINK_BIN_GET_CLASS (self); - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - GST_DEBUG ("changing state: %s => %s", - gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), - gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!self->sink) { - if (klass->create_element) - self->sink = klass->create_element (); - - if (!self->sink) - g_signal_emit (element, - gst_gl_sink_bin_signals[SIGNAL_CREATE_ELEMENT], 0, &self->sink); - - if (!self->sink) { - GST_ERROR_OBJECT (element, "Failed to retrieve element"); - return GST_STATE_CHANGE_FAILURE; - } - if (!_connect_sink_element (self)) - return GST_STATE_CHANGE_FAILURE; - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - default: - break; - } - - return ret; -} - -static void -gst_gl_sink_bin_navigation_send_event (GstNavigation * navigation, GstStructure - * structure) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (navigation); - GstElement *nav = - gst_bin_get_by_interface (GST_BIN (self), GST_TYPE_NAVIGATION); - - if (nav) { - gst_navigation_send_event (GST_NAVIGATION (nav), structure); - structure = NULL; - gst_object_unref (nav); - } else { - GstEvent *event = gst_event_new_navigation (structure); - structure = NULL; - gst_element_send_event (GST_ELEMENT (self), event); - } -} - -static void -gst_gl_sink_bin_navigation_interface_init (gpointer g_iface, - gpointer g_iface_data) -{ - GstNavigationInterface *iface = (GstNavigationInterface *) g_iface; - iface->send_event = gst_gl_sink_bin_navigation_send_event; -} - -static void -gst_gl_sink_bin_overlay_expose (GstVideoOverlay * overlay) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); - GstVideoOverlay *overlay_element = NULL; - - overlay_element = - GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_VIDEO_OVERLAY)); - - if (overlay_element) { - gst_video_overlay_expose (overlay_element); - gst_object_unref (overlay_element); - } -} - -static void -gst_gl_sink_bin_overlay_handle_events (GstVideoOverlay * overlay, - gboolean handle_events) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); - GstVideoOverlay *overlay_element = NULL; - - overlay_element = - GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_VIDEO_OVERLAY)); - - if (overlay_element) { - gst_video_overlay_handle_events (overlay_element, handle_events); - gst_object_unref (overlay_element); - } -} - -static void -gst_gl_sink_bin_overlay_set_render_rectangle (GstVideoOverlay * overlay, gint x, - gint y, gint width, gint height) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); - GstVideoOverlay *overlay_element = NULL; - - overlay_element = - GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_VIDEO_OVERLAY)); - - if (overlay_element) { - gst_video_overlay_set_render_rectangle (overlay_element, x, y, width, - height); - gst_object_unref (overlay_element); - } -} - -static void -gst_gl_sink_bin_overlay_set_window_handle (GstVideoOverlay * overlay, - guintptr handle) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); - GstVideoOverlay *overlay_element = NULL; - - overlay_element = - GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_VIDEO_OVERLAY)); - - if (overlay_element) { - gst_video_overlay_set_window_handle (overlay_element, handle); - gst_object_unref (overlay_element); - } -} - -static void -gst_gl_sink_bin_video_overlay_init (gpointer g_iface, gpointer g_iface_data) -{ - GstVideoOverlayInterface *iface = (GstVideoOverlayInterface *) g_iface; - iface->expose = gst_gl_sink_bin_overlay_expose; - iface->handle_events = gst_gl_sink_bin_overlay_handle_events; - iface->set_render_rectangle = gst_gl_sink_bin_overlay_set_render_rectangle; - iface->set_window_handle = gst_gl_sink_bin_overlay_set_window_handle; -} - -static const GList * -gst_gl_sink_bin_color_balance_list_channels (GstColorBalance * balance) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (balance); - GstColorBalance *balance_element = NULL; - const GList *list = NULL; - - balance_element = - GST_COLOR_BALANCE (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_COLOR_BALANCE)); - - if (balance_element) { - list = gst_color_balance_list_channels (balance_element); - gst_object_unref (balance_element); - } - - return list; -} - -static void -gst_gl_sink_bin_color_balance_set_value (GstColorBalance * balance, - GstColorBalanceChannel * channel, gint value) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (balance); - GstColorBalance *balance_element = NULL; - - balance_element = - GST_COLOR_BALANCE (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_COLOR_BALANCE)); - - if (balance_element) { - gst_color_balance_set_value (balance_element, channel, value); - gst_object_unref (balance_element); - } -} - -static gint -gst_gl_sink_bin_color_balance_get_value (GstColorBalance * balance, - GstColorBalanceChannel * channel) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (balance); - GstColorBalance *balance_element = NULL; - gint val = 0; - - balance_element = - GST_COLOR_BALANCE (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_COLOR_BALANCE)); - - if (balance_element) { - val = gst_color_balance_get_value (balance_element, channel); - gst_object_unref (balance_element); - } - - return val; -} - -static GstColorBalanceType -gst_gl_sink_bin_color_balance_get_balance_type (GstColorBalance * balance) -{ - GstGLSinkBin *self = GST_GL_SINK_BIN (balance); - GstColorBalance *balance_element = NULL; - GstColorBalanceType type = 0; - - balance_element = - GST_COLOR_BALANCE (gst_bin_get_by_interface (GST_BIN (self), - GST_TYPE_COLOR_BALANCE)); - - if (balance_element) { - type = gst_color_balance_get_balance_type (balance_element); - gst_object_unref (balance_element); - } - - return type; -} - -static void -gst_gl_sink_bin_color_balance_init (gpointer g_iface, gpointer g_iface_data) -{ - GstColorBalanceInterface *iface = (GstColorBalanceInterface *) g_iface; - - iface->list_channels = gst_gl_sink_bin_color_balance_list_channels; - iface->set_value = gst_gl_sink_bin_color_balance_set_value; - iface->get_value = gst_gl_sink_bin_color_balance_get_value; - iface->get_balance_type = gst_gl_sink_bin_color_balance_get_balance_type; -} diff --git a/ext/gl/gstglsinkbin.h b/ext/gl/gstglsinkbin.h deleted file mode 100644 index f4529d02c..000000000 --- a/ext/gl/gstglsinkbin.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2003 Julien Moutte <julien@moutte.net> - * Copyright (C) 2005,2006,2007 David A. Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_SINK_BIN_H_ -#define _GST_GL_SINK_BIN_H_ - -#include <gst/gst.h> -#include <gst/video/gstvideosink.h> -#include <gst/video/video.h> - -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -GType gst_gl_sink_bin_get_type(void); -#define GST_TYPE_GL_SINK_BIN \ - (gst_gl_sink_bin_get_type()) -#define GST_GL_SINK_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_SINK_BIN,GstGLSinkBin)) -#define GST_GL_SINK_BIN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_SINK_BIN,GstGLSinkBinClass)) -#define GST_IS_GL_SINK_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_SINK_BIN)) -#define GST_IS_GL_SINK_BIN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_SINK_BIN)) -#define GST_GL_SINK_BIN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_SINK_BIN,GstGLSinkBinClass)) - -typedef struct _GstGLSinkBin GstGLSinkBin; -typedef struct _GstGLSinkBinClass GstGLSinkBinClass; - -struct _GstGLSinkBin -{ - GstBin parent; - - GstPad *sinkpad; - - GstElement *upload; - GstElement *convert; - GstElement *balance; - GstElement *sink; -}; - -struct _GstGLSinkBinClass -{ - GstBinClass parent_class; - - GstElement * (*create_element) (void); -}; - -void gst_gl_sink_bin_finish_init (GstGLSinkBin * self); -void gst_gl_sink_bin_finish_init_with_element (GstGLSinkBin * self, - GstElement * element); - -G_END_DECLS - -#endif diff --git a/ext/gl/gstglsrcbin.c b/ext/gl/gstglsrcbin.c deleted file mode 100644 index da74aaa01..000000000 --- a/ext/gl/gstglsrcbin.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 - -#include "gstglsrcbin.h" - -GST_DEBUG_CATEGORY (gst_debug_gl_src_bin); -#define GST_CAT_DEFAULT gst_debug_gl_src_bin - -static void gst_gl_src_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * param_spec); -static void gst_gl_src_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * param_spec); - -static GstStateChangeReturn gst_gl_src_bin_change_state (GstElement * element, - GstStateChange transition); - -static GstStaticPadTemplate gst_gl_src_bin_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(ANY)")); - -enum -{ - PROP_0, - PROP_SRC, -}; - -enum -{ - SIGNAL_0, - SIGNAL_CREATE_ELEMENT, - SIGNAL_LAST, -}; - -static guint gst_gl_src_bin_signals[SIGNAL_LAST] = { 0, }; - -#define gst_gl_src_bin_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLSrcBin, gst_gl_src_bin, - GST_TYPE_BIN, - GST_DEBUG_CATEGORY_INIT (gst_debug_gl_src_bin, "glsrcbin", 0, - "OpenGL Video Src Bin")); - -static void -gst_gl_src_bin_class_init (GstGLSrcBinClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - element_class->change_state = gst_gl_src_bin_change_state; - - gobject_class->set_property = gst_gl_src_bin_set_property; - gobject_class->get_property = gst_gl_src_bin_get_property; - - g_object_class_install_property (gobject_class, PROP_SRC, - g_param_spec_object ("src", - "GL src element", - "The GL src chain to use", - GST_TYPE_ELEMENT, - GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * GstGLSrcBin::create-element: - * @object: the #GstGLSrcBin - * - * Will be emitted when we need the processing element/s that this bin will use - * - * Returns: a new #GstElement - */ - gst_gl_src_bin_signals[SIGNAL_CREATE_ELEMENT] = - g_signal_new ("create-element", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, - GST_TYPE_ELEMENT, 0); - - gst_element_class_set_metadata (element_class, - "GL Src Bin", "Src/Video", - "Infrastructure to process GL textures", - "Matthew Waters <matthew@centricular.com>"); - - gst_element_class_add_static_pad_template (element_class, - &gst_gl_src_bin_template); -} - -static void -gst_gl_src_bin_init (GstGLSrcBin * self) -{ - gboolean res = TRUE; - GstPad *pad; - - self->download = gst_element_factory_make ("gldownload", NULL); - self->convert = gst_element_factory_make ("glcolorconvert", NULL); - - res &= gst_bin_add (GST_BIN (self), self->download); - res &= gst_bin_add (GST_BIN (self), self->convert); - - res &= gst_element_link_pads (self->convert, "src", self->download, "sink"); - - pad = gst_element_get_static_pad (self->download, "src"); - if (!pad) { - res = FALSE; - } else { - GST_DEBUG_OBJECT (self, "setting target src pad %" GST_PTR_FORMAT, pad); - self->srcpad = gst_ghost_pad_new ("src", pad); - gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); - gst_object_unref (pad); - } - - if (!res) { - GST_WARNING_OBJECT (self, "Failed to add/connect the necessary machinery"); - } -} - -static gboolean -_connect_src_element (GstGLSrcBin * self) -{ - gboolean res = TRUE; - - gst_object_set_name (GST_OBJECT (self->src), "src"); - res &= gst_bin_add (GST_BIN (self), self->src); - - res &= gst_element_link_pads (self->src, "src", self->convert, "sink"); - - if (!res) - GST_ERROR_OBJECT (self, "Failed to link src element into the pipeline"); - - return res; -} - -void -gst_gl_src_bin_finish_init_with_element (GstGLSrcBin * self, - GstElement * element) -{ - g_return_if_fail (GST_IS_ELEMENT (element)); - - self->src = element; - - if (!_connect_src_element (self)) { - gst_object_unref (self->src); - self->src = NULL; - } -} - -void -gst_gl_src_bin_finish_init (GstGLSrcBin * self) -{ - GstGLSrcBinClass *klass = GST_GL_SRC_BIN_GET_CLASS (self); - GstElement *element = NULL; - - if (klass->create_element) - element = klass->create_element (); - - if (element) - gst_gl_src_bin_finish_init_with_element (self, element); -} - -static void -gst_gl_src_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLSrcBin *self = GST_GL_SRC_BIN (object); - - switch (prop_id) { - case PROP_SRC: - { - GstElement *src = g_value_get_object (value); - if (self->src) - gst_bin_remove (GST_BIN (self), self->src); - self->src = src; - if (src) { - gst_object_ref_sink (src); - _connect_src_element (self); - } - break; - } - default: - if (self->src) - g_object_set_property (G_OBJECT (self->src), pspec->name, value); - break; - } -} - -static void -gst_gl_src_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLSrcBin *self = GST_GL_SRC_BIN (object); - - switch (prop_id) { - case PROP_SRC: - g_value_set_object (value, self->src); - break; - default: - if (self->src) - g_object_get_property (G_OBJECT (self->src), pspec->name, value); - break; - } -} - -static GstStateChangeReturn -gst_gl_src_bin_change_state (GstElement * element, GstStateChange transition) -{ - GstGLSrcBin *self = GST_GL_SRC_BIN (element); - GstGLSrcBinClass *klass = GST_GL_SRC_BIN_GET_CLASS (self); - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - GST_DEBUG ("changing state: %s => %s", - gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), - gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!self->src) { - if (klass->create_element) - self->src = klass->create_element (); - - if (!self->src) - g_signal_emit (element, - gst_gl_src_bin_signals[SIGNAL_CREATE_ELEMENT], 0, &self->src); - - if (!self->src) { - GST_ERROR_OBJECT (element, "Failed to retrieve element"); - return GST_STATE_CHANGE_FAILURE; - } - if (!_connect_src_element (self)) - return GST_STATE_CHANGE_FAILURE; - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - default: - break; - } - - return ret; -} diff --git a/ext/gl/gstglsrcbin.h b/ext/gl/gstglsrcbin.h deleted file mode 100644 index 42301688f..000000000 --- a/ext/gl/gstglsrcbin.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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_GL_SRC_BIN_H_ -#define _GST_GL_SRC_BIN_H_ - -#include <gst/gst.h> - -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -GType gst_gl_src_bin_get_type(void); -#define GST_TYPE_GL_SRC_BIN \ - (gst_gl_src_bin_get_type()) -#define GST_GL_SRC_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_SRC_BIN,GstGLSrcBin)) -#define GST_GL_SRC_BIN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_SRC_BIN,GstGLSrcBinClass)) -#define GST_IS_GL_SRC_BIN(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_SRC_BIN)) -#define GST_IS_GL_SRC_BIN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_SRC_BIN)) -#define GST_GL_SRC_BIN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_SRC_BIN,GstGLSrcBinClass)) - -typedef struct _GstGLSrcBin GstGLSrcBin; -typedef struct _GstGLSrcBinClass GstGLSrcBinClass; - -struct _GstGLSrcBin -{ - GstBin parent; - - GstPad *srcpad; - - GstElement *src; - GstElement *convert; - GstElement *download; -}; - -struct _GstGLSrcBinClass -{ - GstBinClass parent_class; - - GstElement * (*create_element) (void); -}; - -void gst_gl_src_bin_finish_init (GstGLSrcBin * self); -void gst_gl_src_bin_finish_init_with_element (GstGLSrcBin * self, - GstElement * element); - -G_END_DECLS - -#endif diff --git a/ext/gl/gstglstereosplit.c b/ext/gl/gstglstereosplit.c deleted file mode 100644 index 933f3c593..000000000 --- a/ext/gl/gstglstereosplit.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Jan Schmidt <jan@centricular.com> - * - * 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-glstereosplit - * @title: glstereosplit - * - * Receive a stereoscopic video stream and split into left/right - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glstereosplit name=s ! queue ! glimagesink s. ! queue ! glimagesink - * ]| - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstglstereosplit.h" - -#define GST_CAT_DEFAULT gst_gl_stereosplit_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define SUPPORTED_GL_APIS GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3 -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_stereosplit_debug, "glstereosplit", 0, "glstereosplit element"); - -G_DEFINE_TYPE_WITH_CODE (GstGLStereoSplit, gst_gl_stereosplit, - GST_TYPE_ELEMENT, DEBUG_INIT); - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA")) - ); - -static GstStaticPadTemplate src_left_template = GST_STATIC_PAD_TEMPLATE ("left", - GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA")) - ); - -static GstStaticPadTemplate src_right_template = -GST_STATIC_PAD_TEMPLATE ("right", - GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES - (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, - "RGBA")) - ); - -static void stereosplit_reset (GstGLStereoSplit * self); -static void stereosplit_finalize (GstGLStereoSplit * self); -static void stereosplit_set_context (GstElement * element, - GstContext * context); -static GstFlowReturn stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, - GstBuffer * buf); -static GstStateChangeReturn stereosplit_change_state (GstElement * element, - GstStateChange transition); -static gboolean stereosplit_sink_query (GstPad * pad, GstObject * parent, - GstQuery * query); -static gboolean stereosplit_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean stereosplit_src_query (GstPad * pad, GstObject * parent, - GstQuery * query); -static gboolean stereosplit_src_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean ensure_context (GstGLStereoSplit * self); - -static void -gst_gl_stereosplit_class_init (GstGLStereoSplitClass * klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_static_metadata (element_class, - "GLStereoSplit", "Codec/Converter", - "Splits a stereoscopic stream into separate left/right streams", - "Jan Schmidt <jan@centricular.com>\n" - "Matthew Waters <matthew@centricular.com>"); - - gobject_class->finalize = (GObjectFinalizeFunc) (stereosplit_finalize); - - element_class->change_state = stereosplit_change_state; - element_class->set_context = stereosplit_set_context; - - gst_element_class_add_static_pad_template (element_class, &sink_template); - gst_element_class_add_static_pad_template (element_class, &src_left_template); - gst_element_class_add_static_pad_template (element_class, - &src_right_template); -} - -static void -gst_gl_stereosplit_init (GstGLStereoSplit * self) -{ - GstPad *pad; - - pad = self->sink_pad = - gst_pad_new_from_static_template (&sink_template, "sink"); - - gst_pad_set_chain_function (pad, (GstPadChainFunction) (stereosplit_chain)); - gst_pad_set_query_function (pad, stereosplit_sink_query); - gst_pad_set_event_function (pad, stereosplit_sink_event); - - gst_element_add_pad (GST_ELEMENT (self), self->sink_pad); - - pad = self->left_pad = - gst_pad_new_from_static_template (&src_left_template, "left"); - gst_pad_set_query_function (pad, stereosplit_src_query); - gst_pad_set_event_function (pad, stereosplit_src_event); - gst_element_add_pad (GST_ELEMENT (self), self->left_pad); - - pad = self->right_pad = - gst_pad_new_from_static_template (&src_right_template, "right"); - gst_pad_set_query_function (pad, stereosplit_src_query); - gst_pad_set_event_function (pad, stereosplit_src_event); - gst_element_add_pad (GST_ELEMENT (self), self->right_pad); - - self->viewconvert = gst_gl_view_convert_new (); -} - -static void -stereosplit_reset (GstGLStereoSplit * self) -{ - if (self->context) - gst_object_replace ((GstObject **) & self->context, NULL); - if (self->display) - gst_object_replace ((GstObject **) & self->display, NULL); -} - -static void -stereosplit_finalize (GstGLStereoSplit * self) -{ - GObjectClass *klass = G_OBJECT_CLASS (gst_gl_stereosplit_parent_class); - - if (self->viewconvert) - gst_object_replace ((GstObject **) & self->viewconvert, NULL); - - klass->finalize ((GObject *) (self)); -} - -static void -stereosplit_set_context (GstElement * element, GstContext * context) -{ - GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element); - - gst_gl_handle_set_context (element, context, &stereosplit->display, - &stereosplit->other_context); - - if (stereosplit->display) - gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS); - - GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->set_context (element, - context); -} - -static GstStateChangeReturn -stereosplit_change_state (GstElement * element, GstStateChange transition) -{ - GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element); - GstStateChangeReturn result; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_gl_ensure_element_data (element, &stereosplit->display, - &stereosplit->other_context)) - return GST_STATE_CHANGE_FAILURE; - - gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS); - break; - default: - break; - } - - result = - GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->change_state - (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - if (stereosplit->other_context) { - gst_object_unref (stereosplit->other_context); - stereosplit->other_context = NULL; - } - - if (stereosplit->display) { - gst_object_unref (stereosplit->display); - stereosplit->display = NULL; - } - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - stereosplit_reset (stereosplit); - break; - default: - break; - } - - return result; -} - -static GstCaps * -stereosplit_transform_caps (GstGLStereoSplit * self, GstPadDirection direction, - GstCaps * caps, GstCaps * filter) -{ - GstCaps *next_caps; - - /* FIXME: Is this the right way to ensure a context here ? */ - if (!ensure_context (self)) - return NULL; - - next_caps = - gst_gl_view_convert_transform_caps (self->viewconvert, direction, caps, - NULL); - - return next_caps; -} - -static GstCaps * -strip_mview_fields (GstCaps * incaps, GstVideoMultiviewFlags keep_flags) -{ - GstCaps *outcaps = gst_caps_make_writable (incaps); - - gint i, n; - - n = gst_caps_get_size (outcaps); - for (i = 0; i < n; i++) { - GstStructure *st = gst_caps_get_structure (outcaps, i); - GstVideoMultiviewFlags flags, mask; - - gst_structure_remove_field (st, "multiview-mode"); - if (gst_structure_get_flagset (st, "multiview-flags", (guint *) & flags, - (guint *) & mask)) { - flags &= keep_flags; - mask = keep_flags; - gst_structure_set (st, "multiview-flags", - GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, flags, mask, NULL); - } - } - - return outcaps; -} - -static gboolean stereosplit_do_bufferpool (GstGLStereoSplit * self, - GstCaps * caps); - -static GstCaps * -stereosplit_get_src_caps (GstGLStereoSplit * split, - GstPad * pad, GstVideoMultiviewMode preferred_mode) -{ - GstCaps *outcaps, *tmp, *templ_caps; - GValue item = G_VALUE_INIT, list = G_VALUE_INIT; - - /* Get the template format */ - templ_caps = gst_pad_get_pad_template_caps (pad); - - /* And limit down to the preferred mode or mono */ - templ_caps = gst_caps_make_writable (templ_caps); - - g_value_init (&item, G_TYPE_STRING); - g_value_init (&list, GST_TYPE_LIST); - g_value_set_static_string (&item, - gst_video_multiview_mode_to_caps_string (preferred_mode)); - gst_value_list_append_value (&list, &item); - g_value_set_static_string (&item, - gst_video_multiview_mode_to_caps_string (GST_VIDEO_MULTIVIEW_MODE_MONO)); - gst_value_list_append_value (&list, &item); - - gst_caps_set_value (templ_caps, "multiview-mode", &list); - - g_value_unset (&list); - g_value_unset (&item); - - /* And intersect with the peer */ - if ((tmp = gst_pad_peer_query_caps (pad, NULL)) == NULL) { - gst_caps_unref (templ_caps); - return NULL; - } - - outcaps = gst_caps_intersect_full (tmp, templ_caps, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (tmp); - gst_caps_unref (templ_caps); - - GST_DEBUG_OBJECT (split, "Src pad %" GST_PTR_FORMAT " caps %" GST_PTR_FORMAT, - pad, outcaps); - return outcaps; -} - -static gboolean -stereosplit_set_output_caps (GstGLStereoSplit * split, GstCaps * sinkcaps) -{ - GstCaps *left = NULL, *right = NULL, *tridcaps = NULL; - GstCaps *tmp, *combined; - gboolean res = FALSE; - - /* Choose some preferred output caps. - * Keep input width/height and PAR, preserve preferred output - * multiview flags for flipping/flopping if any, and set each - * left right pad to either left/mono and right/mono, as they prefer - */ - - /* Calculate what downstream can collectively support */ - left = - stereosplit_get_src_caps (split, split->left_pad, - GST_VIDEO_MULTIVIEW_MODE_LEFT); - if (left == NULL) - goto fail; - right = - stereosplit_get_src_caps (split, split->right_pad, - GST_VIDEO_MULTIVIEW_MODE_RIGHT); - if (right == NULL) - goto fail; - - tridcaps = stereosplit_transform_caps (split, GST_PAD_SINK, sinkcaps, NULL); - - if (!tridcaps || gst_caps_is_empty (tridcaps)) { - GST_ERROR_OBJECT (split, - "Failed to transform input caps %" GST_PTR_FORMAT, sinkcaps); - goto fail; - } - - /* Preserve downstream preferred flipping/flopping */ - tmp = - strip_mview_fields (gst_caps_ref (left), - GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED | - GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED); - combined = gst_caps_intersect (tridcaps, tmp); - gst_caps_unref (tridcaps); - gst_caps_unref (tmp); - tridcaps = combined; - - tmp = - strip_mview_fields (gst_caps_ref (right), - GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED | - GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED); - combined = gst_caps_intersect (tridcaps, tmp); - gst_caps_unref (tridcaps); - gst_caps_unref (tmp); - tridcaps = combined; - - if (G_UNLIKELY (gst_caps_is_empty (tridcaps))) { - gst_caps_unref (tridcaps); - goto fail; - } - - /* Now generate the version for each output pad */ - GST_DEBUG_OBJECT (split, "Attempting to set output caps %" GST_PTR_FORMAT, - tridcaps); - tmp = gst_caps_intersect (tridcaps, left); - gst_caps_unref (left); - left = tmp; - left = gst_caps_fixate (left); - if (!gst_pad_set_caps (split->left_pad, left)) { - GST_ERROR_OBJECT (split, - "Failed to set left output caps %" GST_PTR_FORMAT, left); - goto fail; - } - - tmp = gst_caps_intersect (tridcaps, right); - gst_caps_unref (right); - right = tmp; - right = gst_caps_fixate (right); - if (!gst_pad_set_caps (split->right_pad, right)) { - GST_ERROR_OBJECT (split, - "Failed to set right output caps %" GST_PTR_FORMAT, right); - goto fail; - } - - gst_gl_view_convert_set_context (split->viewconvert, split->context); - - tridcaps = gst_caps_make_writable (tridcaps); - gst_caps_set_simple (tridcaps, "multiview-mode", G_TYPE_STRING, - "separated", "views", G_TYPE_INT, 2, NULL); - tridcaps = gst_caps_fixate (tridcaps); - - if (!gst_gl_view_convert_set_caps (split->viewconvert, sinkcaps, tridcaps)) { - GST_ERROR_OBJECT (split, "Failed to set caps on converter"); - goto fail; - } - - /* FIXME: Provide left and right caps to do_bufferpool */ - stereosplit_do_bufferpool (split, left); - - res = TRUE; - -fail: - if (left) - gst_caps_unref (left); - if (right) - gst_caps_unref (right); - if (tridcaps) - gst_caps_unref (tridcaps); - return res; -} - -static gboolean -_find_local_gl_context (GstGLStereoSplit * split) -{ - if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SRC, - &split->context)) - return TRUE; - if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SINK, - &split->context)) - return TRUE; - return FALSE; -} - -static gboolean -ensure_context (GstGLStereoSplit * self) -{ - GError *error = NULL; - - if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context)) - return FALSE; - - gst_gl_display_filter_gl_api (self->display, SUPPORTED_GL_APIS); - - _find_local_gl_context (self); - - if (!self->context) { - GST_OBJECT_LOCK (self->display); - do { - if (self->context) - gst_object_unref (self->context); - /* just get a GL context. we don't care */ - self->context = - gst_gl_display_get_gl_context_for_thread (self->display, NULL); - if (!self->context) { - if (!gst_gl_display_create_context (self->display, self->other_context, - &self->context, &error)) { - GST_OBJECT_UNLOCK (self->display); - goto context_error; - } - } - } while (!gst_gl_display_add_context (self->display, self->context)); - GST_OBJECT_UNLOCK (self->display); - } - - { - GstGLAPI current_gl_api = gst_gl_context_get_gl_api (self->context); - if ((current_gl_api & (SUPPORTED_GL_APIS)) == 0) - goto unsupported_gl_api; - } - - return TRUE; - -unsupported_gl_api: - { - GstGLAPI gl_api = gst_gl_context_get_gl_api (self->context); - gchar *gl_api_str = gst_gl_api_to_string (gl_api); - gchar *supported_gl_api_str = gst_gl_api_to_string (SUPPORTED_GL_APIS); - GST_ELEMENT_ERROR (self, RESOURCE, BUSY, - ("GL API's not compatible context: %s supported: %s", gl_api_str, - supported_gl_api_str), (NULL)); - - g_free (supported_gl_api_str); - g_free (gl_api_str); - return FALSE; - } -context_error: - { - GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("%s", error->message), - (NULL)); - g_clear_error (&error); - return FALSE; - } -} - -static gboolean -stereosplit_decide_allocation (GstGLStereoSplit * self, GstQuery * query) -{ - if (!ensure_context (self)) - return FALSE; - - return TRUE; - -} - -static gboolean -stereosplit_propose_allocation (GstGLStereoSplit * self, GstQuery * query) -{ - - if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context)) - return FALSE; - - return TRUE; -} - -static gboolean -stereosplit_do_bufferpool (GstGLStereoSplit * self, GstCaps * caps) -{ - GstQuery *query; - - query = gst_query_new_allocation (caps, TRUE); - if (!gst_pad_peer_query (self->left_pad, query)) { - if (!gst_pad_peer_query (self->right_pad, query)) { - GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed on both src pads"); - } - } - - if (!stereosplit_decide_allocation (self, query)) { - gst_query_unref (query); - return FALSE; - } - - gst_query_unref (query); - return TRUE; -} - -static GstFlowReturn -stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf) -{ - GstBuffer *left, *right; - GstBuffer *split_buffer = NULL; - GstFlowReturn ret; - gint i, n_planes; - - n_planes = GST_VIDEO_INFO_N_PLANES (&split->viewconvert->out_info); - - GST_LOG_OBJECT (split, "chaining buffer %" GST_PTR_FORMAT, buf); - - if (gst_gl_view_convert_submit_input_buffer (split->viewconvert, - GST_BUFFER_IS_DISCONT (buf), buf) != GST_FLOW_OK) { - GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s", - "Failed to 3d convert buffer"), - ("Could not get submit input buffer")); - return GST_FLOW_ERROR; - } - - ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s", - "Failed to 3d convert buffer"), ("Could not get output buffer")); - return GST_FLOW_ERROR; - } - if (split_buffer == NULL) - return GST_FLOW_OK; /* Need another input buffer */ - - left = gst_buffer_new (); - gst_buffer_copy_into (left, buf, - GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1); - GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE); - - gst_buffer_add_parent_buffer_meta (left, split_buffer); - - for (i = 0; i < n_planes; i++) { - GstMemory *mem = gst_buffer_get_memory (split_buffer, i); - gst_buffer_append_memory (left, mem); - } - - ret = gst_pad_push (split->left_pad, gst_buffer_ref (left)); - /* Allow unlinked on the first pad - as long as the 2nd isn't unlinked */ - gst_buffer_unref (left); - if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) { - gst_buffer_unref (split_buffer); - return ret; - } - - right = gst_buffer_new (); - gst_buffer_copy_into (right, buf, - GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1); - GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE); - gst_buffer_add_parent_buffer_meta (right, split_buffer); - for (i = n_planes; i < n_planes * 2; i++) { - GstMemory *mem = gst_buffer_get_memory (split_buffer, i); - gst_buffer_append_memory (right, mem); - } - - ret = gst_pad_push (split->right_pad, gst_buffer_ref (right)); - gst_buffer_unref (right); - gst_buffer_unref (split_buffer); - return ret; -} - -static gboolean -stereosplit_src_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) split, query, - split->display, split->context, split->other_context)) - return TRUE; - - return gst_pad_query_default (pad, parent, query); - } - /* FIXME: Handle caps query */ - default: - return gst_pad_query_default (pad, parent, query); - } -} - -static gboolean -stereosplit_src_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - return gst_pad_event_default (pad, parent, event); -} - -static gboolean -stereosplit_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent); - - GST_DEBUG_OBJECT (split, "sink query %s", - gst_query_type_get_name (GST_QUERY_TYPE (query))); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) split, query, - split->display, split->context, split->other_context)) - return TRUE; - - return gst_pad_query_default (pad, parent, query); - } - case GST_QUERY_ALLOCATION: - { - return stereosplit_propose_allocation (split, query); - } - case GST_QUERY_ACCEPT_CAPS: - { - GstCaps *possible, *caps; - gboolean allowed; - - gst_query_parse_accept_caps (query, &caps); - - if (!(possible = gst_pad_query_caps (split->sink_pad, caps))) - return FALSE; - - allowed = gst_caps_is_subset (caps, possible); - gst_caps_unref (possible); - - gst_query_set_accept_caps_result (query, allowed); - return allowed; - } - case GST_QUERY_CAPS: - { - GstCaps *filter, *left, *right, *combined, *ret, *templ_caps; - - gst_query_parse_caps (query, &filter); - - /* Calculate what downstream can collectively support */ - if (!(left = gst_pad_peer_query_caps (split->left_pad, NULL))) - return FALSE; - if (!(right = gst_pad_peer_query_caps (split->right_pad, NULL))) - return FALSE; - - /* Strip out multiview mode and flags that might break the - * intersection, since we can convert. - * We could keep downstream preferred flip/flopping and list - * separated as preferred in the future which might - * theoretically allow us an easier conversion, but it's not essential - */ - left = strip_mview_fields (left, GST_VIDEO_MULTIVIEW_FLAGS_NONE); - right = strip_mview_fields (right, GST_VIDEO_MULTIVIEW_FLAGS_NONE); - - combined = gst_caps_intersect (left, right); - gst_caps_unref (left); - gst_caps_unref (right); - - /* Intersect peer caps with our template formats */ - templ_caps = gst_pad_get_pad_template_caps (split->left_pad); - ret = - gst_caps_intersect_full (combined, templ_caps, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (templ_caps); - - gst_caps_unref (combined); - combined = ret; - - if (!combined || gst_caps_is_empty (combined)) { - gst_caps_unref (combined); - return FALSE; - } - - /* Convert from the src pad caps to input formats we support */ - ret = stereosplit_transform_caps (split, GST_PAD_SRC, combined, filter); - gst_caps_unref (combined); - combined = ret; - - /* Intersect with the sink pad template then */ - templ_caps = gst_pad_get_pad_template_caps (split->sink_pad); - ret = - gst_caps_intersect_full (combined, templ_caps, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (templ_caps); - - GST_LOG_OBJECT (split, "Returning sink pad caps %" GST_PTR_FORMAT, ret); - - gst_query_set_caps_result (query, ret); - return !gst_caps_is_empty (ret); - } - default: - return gst_pad_query_default (pad, parent, query); - } -} - -static gboolean -stereosplit_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstGLStereoSplit *split = GST_GL_STEREOSPLIT (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - - return stereosplit_set_output_caps (split, caps); - } - default: - return gst_pad_event_default (pad, parent, event); - } -} diff --git a/ext/gl/gstglstereosplit.h b/ext/gl/gstglstereosplit.h deleted file mode 100644 index 279bd2681..000000000 --- a/ext/gl/gstglstereosplit.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Jan Schmidt <jan@centricular.com> - * - * 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_GL_STEREOSPLIT_H__ -#define __GST_GL_STEREOSPLIT_H__ - -#include <gst/gst.h> -#include <gst/video/video.h> -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_STEREOSPLIT (gst_gl_stereosplit_get_type()) -#define GST_GL_STEREOSPLIT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_STEREOSPLIT,GstGLStereoSplit)) -#define GST_IS_GL_STEREOSPLIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_STEREOSPLIT)) -#define GST_GL_STEREOSPLIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_STEREOSPLIT,GstGLStereoSplitClass)) -#define GST_IS_GL_STEREOSPLIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_STEREOSPLIT)) -#define GST_GL_STEREOSPLIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_STEREOSPLIT,GstGLStereoSplitClass)) - -typedef struct _GstGLStereoSplit GstGLStereoSplit; -typedef struct _GstGLStereoSplitClass GstGLStereoSplitClass; - -struct _GstGLStereoSplit -{ - GstElement parent; - - GstPad *sink_pad; - GstPad *left_pad; - GstPad *right_pad; - - GstGLDisplay *display; - GstGLContext *context; - GstGLContext *other_context; - - GstGLViewConvert *viewconvert; -}; - -struct _GstGLStereoSplitClass -{ - GstElementClass parent_class; -}; - -GType gst_gl_stereosplit_get_type (void); - -G_END_DECLS - -#endif diff --git a/ext/gl/gstgltestsrc.c b/ext/gl/gstgltestsrc.c deleted file mode 100644 index b0abea507..000000000 --- a/ext/gl/gstgltestsrc.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * Copyright (C) 2002,2007 David A. Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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-gltestsrc - * @title: gltestsrc - * - * The gltestsrc element is used to produce test video texture. - * The video test produced can be controlled with the "pattern" - * property. - * - * ## Example launch line - * - * |[ - * gst-launch-1.0 -v gltestsrc pattern=smpte ! glimagesink - * ]| - * Shows original SMPTE color bars in a window. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gl/gstglfuncs.h> -#include <gst/gst-i18n-plugin.h> - -#include "gstgltestsrc.h" -#include "gltestsrc.h" - -#define USE_PEER_BUFFERALLOC -#define SUPPORTED_GL_APIS (GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2) - -GST_DEBUG_CATEGORY_STATIC (gl_test_src_debug); -#define GST_CAT_DEFAULT gl_test_src_debug - -enum -{ - PROP_0, - PROP_PATTERN, - PROP_TIMESTAMP_OFFSET, - PROP_IS_LIVE - /* FILL ME */ -}; - -/* *INDENT-OFF* */ -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " - "format = (string) RGBA, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE "," - "texture-target = (string) 2D") - ); -/* *INDENT-ON* */ - -#define gst_gl_test_src_parent_class parent_class -G_DEFINE_TYPE (GstGLTestSrc, gst_gl_test_src, GST_TYPE_PUSH_SRC); - -static void gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, - int pattern_type); -static void gst_gl_test_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_test_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps); -static GstCaps *gst_gl_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps); - -static gboolean gst_gl_test_src_is_seekable (GstBaseSrc * psrc); -static gboolean gst_gl_test_src_do_seek (GstBaseSrc * bsrc, - GstSegment * segment); -static gboolean gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query); -static void gst_gl_test_src_set_context (GstElement * element, - GstContext * context); -static GstStateChangeReturn gst_gl_test_src_change_state (GstElement * element, - GstStateChange transition); - -static void gst_gl_test_src_get_times (GstBaseSrc * basesrc, - GstBuffer * buffer, GstClockTime * start, GstClockTime * end); -static GstFlowReturn gst_gl_test_src_fill (GstPushSrc * psrc, - GstBuffer * buffer); -static gboolean gst_gl_test_src_start (GstBaseSrc * basesrc); -static gboolean gst_gl_test_src_stop (GstBaseSrc * basesrc); -static gboolean gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, - GstQuery * query); - -static gboolean gst_gl_test_src_callback (gpointer stuff); - -static gboolean gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc); - -#define GST_TYPE_GL_TEST_SRC_PATTERN (gst_gl_test_src_pattern_get_type ()) -static GType -gst_gl_test_src_pattern_get_type (void) -{ - static GType gl_test_src_pattern_type = 0; - static const GEnumValue pattern_types[] = { - {GST_GL_TEST_SRC_SMPTE, "SMPTE 100% color bars", "smpte"}, - {GST_GL_TEST_SRC_SNOW, "Random (television snow)", "snow"}, - {GST_GL_TEST_SRC_BLACK, "100% Black", "black"}, - {GST_GL_TEST_SRC_WHITE, "100% White", "white"}, - {GST_GL_TEST_SRC_RED, "Red", "red"}, - {GST_GL_TEST_SRC_GREEN, "Green", "green"}, - {GST_GL_TEST_SRC_BLUE, "Blue", "blue"}, - {GST_GL_TEST_SRC_CHECKERS1, "Checkers 1px", "checkers-1"}, - {GST_GL_TEST_SRC_CHECKERS2, "Checkers 2px", "checkers-2"}, - {GST_GL_TEST_SRC_CHECKERS4, "Checkers 4px", "checkers-4"}, - {GST_GL_TEST_SRC_CHECKERS8, "Checkers 8px", "checkers-8"}, - {GST_GL_TEST_SRC_CIRCULAR, "Circular", "circular"}, - {GST_GL_TEST_SRC_BLINK, "Blink", "blink"}, - {GST_GL_TEST_SRC_MANDELBROT, "Mandelbrot Fractal", "mandelbrot"}, - {0, NULL, NULL} - }; - - if (!gl_test_src_pattern_type) { - gl_test_src_pattern_type = - g_enum_register_static ("GstGLTestSrcPattern", pattern_types); - } - return gl_test_src_pattern_type; -} - -static void -gst_gl_test_src_class_init (GstGLTestSrcClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSrcClass *gstbasesrc_class; - GstPushSrcClass *gstpushsrc_class; - GstElementClass *element_class; - - GST_DEBUG_CATEGORY_INIT (gl_test_src_debug, "gltestsrc", 0, - "Video Test Source"); - - gobject_class = (GObjectClass *) klass; - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstpushsrc_class = (GstPushSrcClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->set_property = gst_gl_test_src_set_property; - gobject_class->get_property = gst_gl_test_src_get_property; - - g_object_class_install_property (gobject_class, PROP_PATTERN, - g_param_spec_enum ("pattern", "Pattern", - "Type of test pattern to generate", GST_TYPE_GL_TEST_SRC_PATTERN, - GST_GL_TEST_SRC_SMPTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", - "Timestamp offset", - "An offset added to timestamps set on buffers (in ns)", G_MININT64, - G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_IS_LIVE, - g_param_spec_boolean ("is-live", "Is Live", - "Whether to act as a live source", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, "Video test source", - "Source/Video", "Creates a test video stream", - "David A. Schleef <ds@schleef.org>"); - - gst_element_class_add_static_pad_template (element_class, &src_factory); - - element_class->set_context = gst_gl_test_src_set_context; - element_class->change_state = gst_gl_test_src_change_state; - - gstbasesrc_class->set_caps = gst_gl_test_src_setcaps; - gstbasesrc_class->is_seekable = gst_gl_test_src_is_seekable; - gstbasesrc_class->do_seek = gst_gl_test_src_do_seek; - gstbasesrc_class->query = gst_gl_test_src_query; - gstbasesrc_class->get_times = gst_gl_test_src_get_times; - gstbasesrc_class->start = gst_gl_test_src_start; - gstbasesrc_class->stop = gst_gl_test_src_stop; - gstbasesrc_class->fixate = gst_gl_test_src_fixate; - gstbasesrc_class->decide_allocation = gst_gl_test_src_decide_allocation; - - gstpushsrc_class->fill = gst_gl_test_src_fill; -} - -static void -gst_gl_test_src_init (GstGLTestSrc * src) -{ - gst_gl_test_src_set_pattern (src, GST_GL_TEST_SRC_SMPTE); - - src->timestamp_offset = 0; - - /* we operate in time */ - gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); - gst_base_src_set_live (GST_BASE_SRC (src), FALSE); -} - -static GstCaps * -gst_gl_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps) -{ - GstStructure *structure; - - GST_DEBUG ("fixate"); - - caps = gst_caps_make_writable (caps); - - structure = gst_caps_get_structure (caps, 0); - - gst_structure_fixate_field_nearest_int (structure, "width", 320); - gst_structure_fixate_field_nearest_int (structure, "height", 240); - gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); - - caps = GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps); - - return caps; -} - -static void -gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, gint pattern_type) -{ - gltestsrc->set_pattern = pattern_type; -} - -static void -gst_gl_test_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (object); - - switch (prop_id) { - case PROP_PATTERN: - gst_gl_test_src_set_pattern (src, g_value_get_enum (value)); - break; - case PROP_TIMESTAMP_OFFSET: - src->timestamp_offset = g_value_get_int64 (value); - break; - case PROP_IS_LIVE: - gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); - break; - default: - break; - } -} - -static void -gst_gl_test_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (object); - - switch (prop_id) { - case PROP_PATTERN: - g_value_set_enum (value, src->set_pattern); - break; - case PROP_TIMESTAMP_OFFSET: - g_value_set_int64 (value, src->timestamp_offset); - break; - case PROP_IS_LIVE: - g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps) -{ - GstGLTestSrc *gltestsrc = GST_GL_TEST_SRC (bsrc); - - GST_DEBUG ("setcaps"); - - if (!gst_video_info_from_caps (&gltestsrc->out_info, caps)) - goto wrong_caps; - - gltestsrc->negotiated = TRUE; - - gst_caps_replace (&gltestsrc->out_caps, caps); - - return TRUE; - -/* ERRORS */ -wrong_caps: - { - GST_WARNING ("wrong caps"); - return FALSE; - } -} - -static void -gst_gl_test_src_set_context (GstElement * element, GstContext * context) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (element); - - gst_gl_handle_set_context (element, context, &src->display, - &src->other_context); - - if (src->display) - gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS); - - GST_ELEMENT_CLASS (parent_class)->set_context (element, context); -} - -static gboolean -gst_gl_test_src_query (GstBaseSrc * bsrc, GstQuery * query) -{ - gboolean res = FALSE; - GstGLTestSrc *src; - - src = GST_GL_TEST_SRC (bsrc); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONTEXT: - { - if (gst_gl_handle_context_query ((GstElement *) src, query, - src->display, src->context, src->other_context)) - return TRUE; - break; - } - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = - gst_video_info_convert (&src->out_info, src_fmt, src_val, dest_fmt, - &dest_val); - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - - return res; - } - default: - break; - } - - return GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); -} - -static void -gst_gl_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, - GstClockTime * start, GstClockTime * end) -{ - /* for live sources, sync on the timestamp of the buffer */ - if (gst_base_src_is_live (basesrc)) { - GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); - - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { - /* get duration to calculate end time */ - GstClockTime duration = GST_BUFFER_DURATION (buffer); - - if (GST_CLOCK_TIME_IS_VALID (duration)) - *end = timestamp + duration; - *start = timestamp; - } - } else { - *start = -1; - *end = -1; - } -} - -static gboolean -gst_gl_test_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) -{ - GstClockTime time; - GstGLTestSrc *src; - - src = GST_GL_TEST_SRC (bsrc); - - segment->time = segment->start; - time = segment->position; - - /* now move to the time indicated */ - if (src->out_info.fps_n) { - src->n_frames = gst_util_uint64_scale (time, - src->out_info.fps_n, src->out_info.fps_d * GST_SECOND); - } else - src->n_frames = 0; - - if (src->out_info.fps_n) { - src->running_time = gst_util_uint64_scale (src->n_frames, - src->out_info.fps_d * GST_SECOND, src->out_info.fps_n); - } else { - /* FIXME : Not sure what to set here */ - src->running_time = 0; - } - - g_return_val_if_fail (src->running_time <= time, FALSE); - - return TRUE; -} - -static gboolean -gst_gl_test_src_is_seekable (GstBaseSrc * psrc) -{ - /* we're seekable... */ - return TRUE; -} - -static gboolean -gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc) -{ - if (gst_gl_context_get_gl_api (gltestsrc->context)) { - /* blocking call, wait until the opengl thread has compiled the shader */ -// if (gltestsrc->vertex_src == NULL) -// return FALSE; -// return gst_gl_context_gen_shader (gltestsrc->context, gltestsrc->vertex_src, -// gltestsrc->fragment_src, &gltestsrc->shader); - } - return TRUE; -} - -static void -_fill_gl (GstGLContext * context, GstGLTestSrc * src) -{ - src->gl_result = gst_gl_framebuffer_draw_to_texture (src->fbo, src->out_tex, - gst_gl_test_src_callback, src); -} - -static GstFlowReturn -gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (psrc); - GstClockTime next_time; - GstVideoFrame out_frame; - GstGLSyncMeta *sync_meta; - - if (G_UNLIKELY (!src->negotiated || !src->context)) - goto not_negotiated; - - /* 0 framerate and we are at the second frame, eos */ - if (G_UNLIKELY (GST_VIDEO_INFO_FPS_N (&src->out_info) == 0 - && src->n_frames == 1)) - goto eos; - - if (!gst_video_frame_map (&out_frame, &src->out_info, buffer, - GST_MAP_WRITE | GST_MAP_GL)) { - return GST_FLOW_NOT_NEGOTIATED; - } - - src->out_tex = (GstGLMemory *) out_frame.map[0].memory; - - gst_gl_context_thread_add (src->context, (GstGLContextThreadFunc) _fill_gl, - src); - if (!src->gl_result) { - gst_video_frame_unmap (&out_frame); - goto gl_error; - } - gst_video_frame_unmap (&out_frame); - if (!src->gl_result) - goto gl_error; - - sync_meta = gst_buffer_get_gl_sync_meta (buffer); - if (sync_meta) - gst_gl_sync_meta_set_sync_point (sync_meta, src->context); - - GST_BUFFER_TIMESTAMP (buffer) = src->timestamp_offset + src->running_time; - GST_BUFFER_OFFSET (buffer) = src->n_frames; - src->n_frames++; - GST_BUFFER_OFFSET_END (buffer) = src->n_frames; - if (src->out_info.fps_n) { - next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND, - src->out_info.fps_d, src->out_info.fps_n); - GST_BUFFER_DURATION (buffer) = next_time - src->running_time; - } else { - next_time = src->timestamp_offset; - /* NONE means forever */ - GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; - } - - src->running_time = next_time; - - return GST_FLOW_OK; - -gl_error: - { - GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (_("failed to draw pattern")), - (_("A GL error occurred"))); - return GST_FLOW_NOT_NEGOTIATED; - } -not_negotiated: - { - GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), - (_("format wasn't negotiated before get function"))); - return GST_FLOW_NOT_NEGOTIATED; - } -eos: - { - GST_DEBUG_OBJECT (src, "eos: 0 framerate, frame %d", (gint) src->n_frames); - return GST_FLOW_EOS; - } -} - -static gboolean -gst_gl_test_src_start (GstBaseSrc * basesrc) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc); - - if (!gst_gl_ensure_element_data (src, &src->display, &src->other_context)) - return FALSE; - - gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS); - - src->running_time = 0; - src->n_frames = 0; - src->negotiated = FALSE; - - return TRUE; -} - -static void -gst_gl_test_src_gl_stop (GstGLContext * context, GstGLTestSrc * src) -{ - if (src->fbo) - gst_object_unref (src->fbo); - src->fbo = NULL; - - if (src->shader) - gst_object_unref (src->shader); - src->shader = NULL; - - - if (src->src_impl) - src->src_funcs->free (src->src_impl); - src->src_impl = NULL; -} - -static gboolean -gst_gl_test_src_stop (GstBaseSrc * basesrc) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc); - - if (src->context) - gst_gl_context_thread_add (src->context, - (GstGLContextThreadFunc) gst_gl_test_src_gl_stop, src); - - gst_caps_replace (&src->out_caps, NULL); - - if (src->context) - gst_object_unref (src->context); - src->context = NULL; - - return TRUE; -} - -static gboolean -_find_local_gl_context (GstGLTestSrc * src) -{ - if (gst_gl_query_local_gl_context (GST_ELEMENT (src), GST_PAD_SRC, - &src->context)) - return TRUE; - return FALSE; -} - -static void -_src_generate_fbo_gl (GstGLContext * context, GstGLTestSrc * src) -{ - src->fbo = gst_gl_framebuffer_new_with_default_depth (src->context, - GST_VIDEO_INFO_WIDTH (&src->out_info), - GST_VIDEO_INFO_HEIGHT (&src->out_info)); -} - -static gboolean -gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc); - GstBufferPool *pool = NULL; - GstStructure *config; - GstCaps *caps; - guint min, max, size; - gboolean update_pool; - GError *error = NULL; - - if (!gst_gl_ensure_element_data (src, &src->display, &src->other_context)) - return FALSE; - - gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS); - - _find_local_gl_context (src); - - if (!src->context) { - GST_OBJECT_LOCK (src->display); - do { - if (src->context) { - gst_object_unref (src->context); - src->context = NULL; - } - /* just get a GL context. we don't care */ - src->context = - gst_gl_display_get_gl_context_for_thread (src->display, NULL); - if (!src->context) { - if (!gst_gl_display_create_context (src->display, src->other_context, - &src->context, &error)) { - GST_OBJECT_UNLOCK (src->display); - goto context_error; - } - } - } while (!gst_gl_display_add_context (src->display, src->context)); - GST_OBJECT_UNLOCK (src->display); - } - - if ((gst_gl_context_get_gl_api (src->context) & SUPPORTED_GL_APIS) == 0) - goto unsupported_gl_api; - - gst_gl_context_thread_add (src->context, - (GstGLContextThreadFunc) _src_generate_fbo_gl, src); - if (!src->fbo) - goto context_error; - - gst_query_parse_allocation (query, &caps, NULL); - - if (gst_query_get_n_allocation_pools (query) > 0) { - gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); - - update_pool = TRUE; - } else { - GstVideoInfo vinfo; - - gst_video_info_init (&vinfo); - gst_video_info_from_caps (&vinfo, caps); - size = vinfo.size; - min = max = 0; - update_pool = FALSE; - } - - if (!pool || !GST_IS_GL_BUFFER_POOL (pool)) { - /* can't use this pool */ - if (pool) - gst_object_unref (pool); - pool = gst_gl_buffer_pool_new (src->context); - } - config = gst_buffer_pool_get_config (pool); - - gst_buffer_pool_config_set_params (config, caps, size, min, max); - gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); - if (gst_query_find_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL)) - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_GL_SYNC_META); - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META); - - gst_buffer_pool_set_config (pool, config); - - if (update_pool) - gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); - else - gst_query_add_allocation_pool (query, pool, size, min, max); - - gst_gl_test_src_init_shader (src); - - gst_object_unref (pool); - - return TRUE; - -unsupported_gl_api: - { - GstGLAPI gl_api = gst_gl_context_get_gl_api (src->context); - gchar *gl_api_str = gst_gl_api_to_string (gl_api); - gchar *supported_gl_api_str = gst_gl_api_to_string (SUPPORTED_GL_APIS); - GST_ELEMENT_ERROR (src, RESOURCE, BUSY, - ("GL API's not compatible context: %s supported: %s", gl_api_str, - supported_gl_api_str), (NULL)); - - g_free (supported_gl_api_str); - g_free (gl_api_str); - return FALSE; - } -context_error: - { - if (error) { - GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s", error->message), - (NULL)); - g_clear_error (&error); - } else { - GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), (NULL)); - } - if (src->context) - gst_object_unref (src->context); - src->context = NULL; - return FALSE; - } -} - -static gboolean -gst_gl_test_src_callback (gpointer stuff) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (stuff); - const struct SrcFuncs *funcs; - - funcs = src->src_funcs; - - if (!funcs || src->set_pattern != src->active_pattern) { - if (src->src_impl && funcs) - funcs->free (src->src_impl); - src->src_funcs = funcs = - gst_gl_test_src_get_src_funcs_for_pattern (src->set_pattern); - if (funcs == NULL) { - GST_ERROR_OBJECT (src, "Could not find an implementation of the " - "requested pattern"); - return FALSE; - } - src->src_impl = funcs->new (src); - if (!(src->gl_result = - funcs->init (src->src_impl, src->context, &src->out_info))) { - GST_ERROR_OBJECT (src, "Failed to initialize pattern"); - return FALSE; - } - src->active_pattern = src->set_pattern; - } - - return funcs->fill_bound_fbo (src->src_impl); -} - -static GstStateChangeReturn -gst_gl_test_src_change_state (GstElement * element, GstStateChange transition) -{ - GstGLTestSrc *src = GST_GL_TEST_SRC (element); - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - GST_DEBUG_OBJECT (src, "changing state: %s => %s", - gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), - gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_gl_ensure_element_data (element, &src->display, - &src->other_context)) - return GST_STATE_CHANGE_FAILURE; - - gst_gl_display_filter_gl_api (src->display, SUPPORTED_GL_APIS); - 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 (src->other_context) { - gst_object_unref (src->other_context); - src->other_context = NULL; - } - - if (src->display) { - gst_object_unref (src->display); - src->display = NULL; - } - break; - default: - break; - } - - return ret; -} diff --git a/ext/gl/gstgltestsrc.h b/ext/gl/gstgltestsrc.h deleted file mode 100644 index df4abb74a..000000000 --- a/ext/gl/gstgltestsrc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * Copyright (C) 2002,2007 David A. Schleef <ds@schleef.org> - * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> - * - * 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_GL_TEST_SRC_H__ -#define __GST_GL_TEST_SRC_H__ - -#include <gst/gst.h> -#include <gst/base/gstpushsrc.h> - -#include <gst/gl/gl.h> - -#include "gltestsrc.h" - -G_BEGIN_DECLS - -#define GST_TYPE_GL_TEST_SRC \ - (gst_gl_test_src_get_type()) -#define GST_GL_TEST_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_TEST_SRC,GstGLTestSrc)) -#define GST_GL_TEST_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_TEST_SRC,GstGLTestSrcClass)) -#define GST_IS_GL_TEST_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_TEST_SRC)) -#define GST_IS_GL_TEST_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_TEST_SRC)) - -typedef struct _GstGLTestSrcClass GstGLTestSrcClass; - -/** - * GstGLTestSrc: - * - * Opaque data structure. - */ -struct _GstGLTestSrc { - GstPushSrc element; - - /*< private >*/ - - /* type of output */ - GstGLTestSrcPattern set_pattern; - GstGLTestSrcPattern active_pattern; - - /* video state */ - GstVideoInfo out_info; - - GstGLFramebuffer *fbo; - GstGLMemory *out_tex; - - GstGLShader *shader; - - GstBufferPool *pool; - - GstGLDisplay *display; - GstGLContext *context, *other_context; - gint64 timestamp_offset; /* base offset */ - GstClockTime running_time; /* total running time */ - gint64 n_frames; /* total frames sent */ - gboolean negotiated; - - gboolean gl_result; - const struct SrcFuncs *src_funcs; - gpointer src_impl; - - GstCaps *out_caps; -}; - -struct _GstGLTestSrcClass { - GstPushSrcClass parent_class; -}; - -GType gst_gl_test_src_get_type (void); - -G_END_DECLS - -#endif /* __GST_GL_TEST_SRC_H__ */ diff --git a/ext/gl/gstgltransformation.c b/ext/gl/gstgltransformation.c deleted file mode 100644 index bb4bd2c6f..000000000 --- a/ext/gl/gstgltransformation.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2014 Lubosz Sarnecki <lubosz@gmail.com> - * Copyright (C) 2016 Matthew Waters <matthew@centricular.com> - * - * 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-gltransformation - * @title: gltransformation - * - * Transforms video on the GPU. - * - * ## Examples - * |[ - * gst-launch-1.0 gltestsrc ! gltransformation rotation-z=45 ! glimagesink - * ]| A pipeline to rotate by 45 degrees - * |[ - * gst-launch-1.0 gltestsrc ! gltransformation translation-x=0.5 ! glimagesink - * ]| Translate the video by 0.5 - * |[ - * gst-launch-1.0 gltestsrc ! gltransformation scale-y=0.5 scale-x=0.5 ! glimagesink - * ]| Resize the video by 0.5 - * |[ - * gst-launch-1.0 gltestsrc ! gltransformation rotation-x=-45 ortho=True ! glimagesink - * ]| Rotate the video around the X-Axis by -45° with an orthographic projection - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstgltransformation.h" - -#include <gst/gl/gstglapi.h> -#include <graphene-gobject.h> -#include "gstglutils.h" - -#define GST_CAT_DEFAULT gst_gl_transformation_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define gst_gl_transformation_parent_class parent_class - -#define VEC4_FORMAT "%f,%f,%f,%f" -#define VEC4_ARGS(v) graphene_vec4_get_x (v), graphene_vec4_get_y (v), graphene_vec4_get_z (v), graphene_vec4_get_w (v) -#define VEC3_FORMAT "%f,%f,%f" -#define VEC3_ARGS(v) graphene_vec3_get_x (v), graphene_vec3_get_y (v), graphene_vec3_get_z (v) -#define VEC2_FORMAT "%f,%f" -#define VEC2_ARGS(v) graphene_vec2_get_x (v), graphene_vec2_get_y (v) -#define POINT3D_FORMAT "%f,%f,%f" -#define POINT3D_ARGS(p) (p)->x, (p)->y, (p)->z - -enum -{ - PROP_0, - PROP_FOV, - PROP_ORTHO, - PROP_TRANSLATION_X, - PROP_TRANSLATION_Y, - PROP_TRANSLATION_Z, - PROP_ROTATION_X, - PROP_ROTATION_Y, - PROP_ROTATION_Z, - PROP_SCALE_X, - PROP_SCALE_Y, - PROP_MVP, - PROP_PIVOT_X, - PROP_PIVOT_Y, - PROP_PIVOT_Z, -}; - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_transformation_debug, "gltransformation", 0, "gltransformation element"); - -G_DEFINE_TYPE_WITH_CODE (GstGLTransformation, gst_gl_transformation, - GST_TYPE_GL_FILTER, DEBUG_INIT); - -static void gst_gl_transformation_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_transformation_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_transformation_set_caps (GstGLFilter * filter, - GstCaps * incaps, GstCaps * outcaps); -static gboolean gst_gl_transformation_src_event (GstBaseTransform * trans, - GstEvent * event); -static gboolean gst_gl_transformation_filter_meta (GstBaseTransform * trans, - GstQuery * query, GType api, const GstStructure * params); -static gboolean gst_gl_transformation_decide_allocation (GstBaseTransform * - trans, GstQuery * query); - -static void gst_gl_transformation_gl_stop (GstGLBaseFilter * filter); -static gboolean gst_gl_transformation_gl_start (GstGLBaseFilter * base_filter); -static gboolean gst_gl_transformation_callback (gpointer stuff); -static void gst_gl_transformation_build_mvp (GstGLTransformation * - transformation); - -static GstFlowReturn -gst_gl_transformation_prepare_output_buffer (GstBaseTransform * trans, - GstBuffer * inbuf, GstBuffer ** outbuf); -static gboolean gst_gl_transformation_filter (GstGLFilter * filter, - GstBuffer * inbuf, GstBuffer * outbuf); -static gboolean gst_gl_transformation_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex); - -static void -gst_gl_transformation_class_init (GstGLTransformationClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - GstBaseTransformClass *base_transform_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - base_transform_class = GST_BASE_TRANSFORM_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_transformation_set_property; - gobject_class->get_property = gst_gl_transformation_get_property; - - base_transform_class->src_event = gst_gl_transformation_src_event; - base_transform_class->decide_allocation = - gst_gl_transformation_decide_allocation; - base_transform_class->filter_meta = gst_gl_transformation_filter_meta; - - GST_GL_BASE_FILTER_CLASS (klass)->gl_start = gst_gl_transformation_gl_start; - GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = gst_gl_transformation_gl_stop; - - GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_transformation_set_caps; - GST_GL_FILTER_CLASS (klass)->filter = gst_gl_transformation_filter; - GST_GL_FILTER_CLASS (klass)->filter_texture = - gst_gl_transformation_filter_texture; - GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer = - gst_gl_transformation_prepare_output_buffer; - - g_object_class_install_property (gobject_class, PROP_FOV, - g_param_spec_float ("fov", "Fov", "Field of view angle in degrees", - 0.0, G_MAXFLOAT, 90.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ORTHO, - g_param_spec_boolean ("ortho", "Orthographic", - "Use orthographic projection", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Rotation */ - g_object_class_install_property (gobject_class, PROP_ROTATION_X, - g_param_spec_float ("rotation-x", "X Rotation", - "Rotates the video around the X-Axis in degrees.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ROTATION_Y, - g_param_spec_float ("rotation-y", "Y Rotation", - "Rotates the video around the Y-Axis in degrees.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ROTATION_Z, - g_param_spec_float ("rotation-z", "Z Rotation", - "Rotates the video around the Z-Axis in degrees.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Translation */ - g_object_class_install_property (gobject_class, PROP_TRANSLATION_X, - g_param_spec_float ("translation-x", "X Translation", - "Translates the video at the X-Axis, in universal [0-1] coordinate.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_TRANSLATION_Y, - g_param_spec_float ("translation-y", "Y Translation", - "Translates the video at the Y-Axis, in universal [0-1] coordinate.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_TRANSLATION_Z, - g_param_spec_float ("translation-z", "Z Translation", - "Translates the video at the Z-Axis, in universal [0-1] coordinate.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Scale */ - g_object_class_install_property (gobject_class, PROP_SCALE_X, - g_param_spec_float ("scale-x", "X Scale", - "Scale multiplier for the X-Axis.", - -G_MAXFLOAT, G_MAXFLOAT, 1.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_SCALE_Y, - g_param_spec_float ("scale-y", "Y Scale", - "Scale multiplier for the Y-Axis.", - -G_MAXFLOAT, G_MAXFLOAT, 1.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Pivot */ - g_object_class_install_property (gobject_class, PROP_PIVOT_X, - g_param_spec_float ("pivot-x", "X Pivot", - "Rotation pivot point X coordinate, where 0 is the center," - " -1 the left border, +1 the right border and <-1, >1 outside.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_PIVOT_Y, - g_param_spec_float ("pivot-y", "Y Pivot", - "Rotation pivot point X coordinate, where 0 is the center," - " -1 the left border, +1 the right border and <-1, >1 outside.", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_PIVOT_Z, - g_param_spec_float ("pivot-z", "Z Pivot", - "Relevant for rotation in 3D space. You look into the negative Z axis direction", - -G_MAXFLOAT, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* MVP */ - g_object_class_install_property (gobject_class, PROP_MVP, - g_param_spec_boxed ("mvp-matrix", - "Modelview Projection Matrix", - "The final Graphene 4x4 Matrix for transformation", - GRAPHENE_TYPE_MATRIX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_metadata (element_class, "OpenGL transformation filter", - "Filter/Effect/Video", "Transform video on the GPU", - "Lubosz Sarnecki <lubosz@gmail.com>\n" - "Matthew Waters <matthew@centricular.com>"); - - GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api = - GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2; -} - -static void -gst_gl_transformation_init (GstGLTransformation * filter) -{ - filter->shader = NULL; - filter->fov = 90; - filter->aspect = 1.0; - filter->znear = 0.1f; - filter->zfar = 100.0; - - filter->xscale = 1.0; - filter->yscale = 1.0; - - filter->in_tex = 0; - - gst_gl_transformation_build_mvp (filter); -} - -static void -gst_gl_transformation_build_mvp (GstGLTransformation * transformation) -{ - GstGLFilter *filter = GST_GL_FILTER (transformation); - graphene_matrix_t modelview_matrix; - - if (!filter->out_info.finfo) { - graphene_matrix_init_identity (&transformation->model_matrix); - graphene_matrix_init_identity (&transformation->view_matrix); - graphene_matrix_init_identity (&transformation->projection_matrix); - } else { - graphene_point3d_t translation_vector = - GRAPHENE_POINT3D_INIT (transformation->xtranslation * 2.0 * - transformation->aspect, - transformation->ytranslation * 2.0, - transformation->ztranslation * 2.0); - - graphene_point3d_t pivot_vector = - GRAPHENE_POINT3D_INIT (-transformation->xpivot * transformation->aspect, - transformation->ypivot, - -transformation->zpivot); - - graphene_point3d_t negative_pivot_vector; - - graphene_vec3_t center; - graphene_vec3_t up; - - gboolean current_passthrough; - gboolean passthrough; - - graphene_vec3_init (&transformation->camera_position, 0.f, 0.f, 1.f); - graphene_vec3_init (¢er, 0.f, 0.f, 0.f); - graphene_vec3_init (&up, 0.f, 1.f, 0.f); - - /* Translate into pivot origin */ - graphene_matrix_init_translate (&transformation->model_matrix, - &pivot_vector); - - /* Scale */ - graphene_matrix_scale (&transformation->model_matrix, - transformation->xscale, transformation->yscale, 1.0f); - - /* Rotation */ - graphene_matrix_rotate (&transformation->model_matrix, - transformation->xrotation, graphene_vec3_x_axis ()); - graphene_matrix_rotate (&transformation->model_matrix, - transformation->yrotation, graphene_vec3_y_axis ()); - graphene_matrix_rotate (&transformation->model_matrix, - transformation->zrotation, graphene_vec3_z_axis ()); - - /* Translate back from pivot origin */ - graphene_point3d_scale (&pivot_vector, -1.0, &negative_pivot_vector); - graphene_matrix_translate (&transformation->model_matrix, - &negative_pivot_vector); - - /* Translation */ - graphene_matrix_translate (&transformation->model_matrix, - &translation_vector); - - if (transformation->ortho) { - graphene_matrix_init_ortho (&transformation->projection_matrix, - -transformation->aspect, transformation->aspect, - -1, 1, transformation->znear, transformation->zfar); - } else { - graphene_matrix_init_perspective (&transformation->projection_matrix, - transformation->fov, - transformation->aspect, transformation->znear, transformation->zfar); - } - - graphene_matrix_init_look_at (&transformation->view_matrix, - &transformation->camera_position, ¢er, &up); - - current_passthrough = - gst_base_transform_is_passthrough (GST_BASE_TRANSFORM (transformation)); - passthrough = transformation->xtranslation == 0. - && transformation->ytranslation == 0. - && transformation->ztranslation == 0. && transformation->xrotation == 0. - && transformation->yrotation == 0. && transformation->zrotation == 0. - && transformation->xscale == 1. && transformation->yscale == 1. - && gst_video_info_is_equal (&filter->in_info, &filter->out_info); - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (transformation), - passthrough); - if (current_passthrough != passthrough) { - gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (transformation)); - } - } - - graphene_matrix_multiply (&transformation->model_matrix, - &transformation->view_matrix, &modelview_matrix); - graphene_matrix_multiply (&modelview_matrix, - &transformation->projection_matrix, &transformation->mvp_matrix); - - graphene_matrix_inverse (&transformation->model_matrix, - &transformation->inv_model_matrix); - graphene_matrix_inverse (&transformation->view_matrix, - &transformation->inv_view_matrix); - graphene_matrix_inverse (&transformation->projection_matrix, - &transformation->inv_projection_matrix); -} - -static void -gst_gl_transformation_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLTransformation *filter = GST_GL_TRANSFORMATION (object); - - switch (prop_id) { - case PROP_FOV: - filter->fov = g_value_get_float (value); - break; - case PROP_ORTHO: - filter->ortho = g_value_get_boolean (value); - break; - case PROP_TRANSLATION_X: - filter->xtranslation = g_value_get_float (value); - break; - case PROP_TRANSLATION_Y: - filter->ytranslation = g_value_get_float (value); - break; - case PROP_TRANSLATION_Z: - filter->ztranslation = g_value_get_float (value); - break; - case PROP_ROTATION_X: - filter->xrotation = g_value_get_float (value); - break; - case PROP_ROTATION_Y: - filter->yrotation = g_value_get_float (value); - break; - case PROP_ROTATION_Z: - filter->zrotation = g_value_get_float (value); - break; - case PROP_SCALE_X: - filter->xscale = g_value_get_float (value); - break; - case PROP_SCALE_Y: - filter->yscale = g_value_get_float (value); - break; - case PROP_PIVOT_X: - filter->xpivot = g_value_get_float (value); - break; - case PROP_PIVOT_Y: - filter->ypivot = g_value_get_float (value); - break; - case PROP_PIVOT_Z: - filter->zpivot = g_value_get_float (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - gst_gl_transformation_build_mvp (filter); -} - -static void -gst_gl_transformation_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLTransformation *filter = GST_GL_TRANSFORMATION (object); - - switch (prop_id) { - case PROP_FOV: - g_value_set_float (value, filter->fov); - break; - case PROP_ORTHO: - g_value_set_boolean (value, filter->ortho); - break; - case PROP_TRANSLATION_X: - g_value_set_float (value, filter->xtranslation); - break; - case PROP_TRANSLATION_Y: - g_value_set_float (value, filter->ytranslation); - break; - case PROP_TRANSLATION_Z: - g_value_set_float (value, filter->ztranslation); - break; - case PROP_ROTATION_X: - g_value_set_float (value, filter->xrotation); - break; - case PROP_ROTATION_Y: - g_value_set_float (value, filter->yrotation); - break; - case PROP_ROTATION_Z: - g_value_set_float (value, filter->zrotation); - break; - case PROP_SCALE_X: - g_value_set_float (value, filter->xscale); - break; - case PROP_SCALE_Y: - g_value_set_float (value, filter->yscale); - break; - case PROP_PIVOT_X: - g_value_set_float (value, filter->xpivot); - break; - case PROP_PIVOT_Y: - g_value_set_float (value, filter->ypivot); - break; - case PROP_PIVOT_Z: - g_value_set_float (value, filter->zpivot); - break; - case PROP_MVP: - /* FIXME: need to decompose this to support navigation events */ - g_value_set_boxed (value, (gconstpointer) & filter->mvp_matrix); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_gl_transformation_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter); - - transformation->aspect = - (gdouble) GST_VIDEO_INFO_WIDTH (&filter->out_info) / - (gdouble) GST_VIDEO_INFO_HEIGHT (&filter->out_info); - - transformation->caps_change = TRUE; - - gst_gl_transformation_build_mvp (transformation); - - return TRUE; -} - -static void -_intersect_plane_and_ray (graphene_plane_t * video_plane, graphene_ray_t * ray, - graphene_point3d_t * result) -{ - float t = graphene_ray_get_distance_to_plane (ray, video_plane); - GST_TRACE ("Calculated a distance of %f to the plane", t); - graphene_ray_get_position_at (ray, t, result); -} - -static void -_screen_coord_to_world_ray (GstGLTransformation * transformation, float x, - float y, graphene_ray_t * ray) -{ - GstGLFilter *filter = GST_GL_FILTER (transformation); - gfloat w = (gfloat) GST_VIDEO_INFO_WIDTH (&filter->in_info); - gfloat h = (gfloat) GST_VIDEO_INFO_HEIGHT (&filter->in_info); - graphene_vec3_t ray_eye_vec3, ray_world_dir, *ray_origin, *ray_direction; - graphene_vec3_t ray_ortho_dir; - graphene_point3d_t ray_clip, ray_eye; - graphene_vec2_t screen_coord; - - /* GL is y-flipped. i.e. 0, 0 is the bottom left corner in screen space */ - graphene_vec2_init (&screen_coord, (2. * x / w - 1.) / transformation->aspect, - 1. - 2. * y / h); - - graphene_point3d_init (&ray_clip, graphene_vec2_get_x (&screen_coord), - graphene_vec2_get_y (&screen_coord), -1.); - graphene_matrix_transform_point3d (&transformation->inv_projection_matrix, - &ray_clip, &ray_eye); - - graphene_vec3_init (&ray_eye_vec3, ray_eye.x, ray_eye.y, -1.); - - if (transformation->ortho) { - graphene_vec3_init (&ray_ortho_dir, 0., 0., 1.); - - ray_origin = &ray_eye_vec3; - ray_direction = &ray_ortho_dir; - } else { - graphene_matrix_transform_vec3 (&transformation->inv_view_matrix, - &ray_eye_vec3, &ray_world_dir); - graphene_vec3_normalize (&ray_world_dir, &ray_world_dir); - - ray_origin = &transformation->camera_position; - ray_direction = &ray_world_dir; - } - - graphene_ray_init_from_vec3 (ray, ray_origin, ray_direction); - - GST_TRACE_OBJECT (transformation, "Calculated ray origin: " VEC3_FORMAT - " direction: " VEC3_FORMAT " from screen coordinates: " VEC2_FORMAT - " with %s projection", - VEC3_ARGS (ray_origin), VEC3_ARGS (ray_direction), - VEC2_ARGS (&screen_coord), - transformation->ortho ? "ortho" : "perspection"); -} - -static void -_init_world_video_plane (GstGLTransformation * transformation, - graphene_plane_t * video_plane) -{ - graphene_point3d_t bottom_left, bottom_right, top_left, top_right; - graphene_point3d_t world_bottom_left, world_bottom_right; - graphene_point3d_t world_top_left, world_top_right; - - graphene_point3d_init (&top_left, -transformation->aspect, 1., 0.); - graphene_point3d_init (&top_right, transformation->aspect, 1., 0.); - graphene_point3d_init (&bottom_left, -transformation->aspect, -1., 0.); - graphene_point3d_init (&bottom_right, transformation->aspect, -1., 0.); - - graphene_matrix_transform_point3d (&transformation->model_matrix, - &bottom_left, &world_bottom_left); - graphene_matrix_transform_point3d (&transformation->model_matrix, - &bottom_right, &world_bottom_right); - graphene_matrix_transform_point3d (&transformation->model_matrix, - &top_left, &world_top_left); - graphene_matrix_transform_point3d (&transformation->model_matrix, - &top_right, &world_top_right); - - graphene_plane_init_from_points (video_plane, &world_bottom_left, - &world_top_right, &world_top_left); -} - -static gboolean -_screen_coord_to_model_coord (GstGLTransformation * transformation, - double x, double y, double *res_x, double *res_y) -{ - GstGLFilter *filter = GST_GL_FILTER (transformation); - double w = (double) GST_VIDEO_INFO_WIDTH (&filter->in_info); - double h = (double) GST_VIDEO_INFO_HEIGHT (&filter->in_info); - graphene_point3d_t world_point, model_coord; - graphene_plane_t video_plane; - graphene_ray_t ray; - double new_x, new_y; - - _init_world_video_plane (transformation, &video_plane); - _screen_coord_to_world_ray (transformation, x, y, &ray); - _intersect_plane_and_ray (&video_plane, &ray, &world_point); - graphene_matrix_transform_point3d (&transformation->inv_model_matrix, - &world_point, &model_coord); - - /* ndc to pixels. We render the frame Y-flipped so need to unflip the - * y coordinate */ - new_x = (model_coord.x + 1.) * w / 2; - new_y = (1. - model_coord.y) * h / 2; - - if (new_x < 0. || new_x > w || new_y < 0. || new_y > h) - /* coords off video surface */ - return FALSE; - - GST_DEBUG_OBJECT (transformation, "converted %f,%f to %f,%f", x, y, new_x, - new_y); - - if (res_x) - *res_x = new_x; - if (res_y) - *res_y = new_y; - - return TRUE; -} - -#if 0 -/* debugging facilities for transforming vertices from model space to screen - * space */ -static void -_ndc_to_viewport (GstGLTransformation * transformation, graphene_vec3_t * ndc, - int x, int y, int w, int h, float near, float far, graphene_vec3_t * result) -{ - GstGLFilter *filter = GST_GL_FILTER (transformation); - /* center of the viewport */ - int o_x = x + w / 2; - int o_y = y + h / 2; - - graphene_vec3_init (result, graphene_vec3_get_x (ndc) * w / 2 + o_x, - graphene_vec3_get_y (ndc) * h / 2 + o_y, - (far - near) * graphene_vec3_get_z (ndc) / 2 + (far + near) / 2); -} - -static void -_perspective_division (graphene_vec4_t * clip, graphene_vec3_t * result) -{ - float w = graphene_vec4_get_w (clip); - - graphene_vec3_init (result, graphene_vec4_get_x (clip) / w, - graphene_vec4_get_y (clip) / w, graphene_vec4_get_z (clip) / w); -} - -static void -_vertex_to_screen_coord (GstGLTransformation * transformation, - graphene_vec4_t * vertex, graphene_vec3_t * view) -{ - GstGLFilter *filter = GST_GL_FILTER (transformation); - gint w = GST_VIDEO_INFO_WIDTH (&filter->in_info); - gint h = GST_VIDEO_INFO_HEIGHT (&filter->in_info); - graphene_vec4_t clip; - graphene_vec3_t ndc; - - graphene_matrix_transform_vec4 (&transformation->mvp_matrix, vertex, &clip); - _perspective_division (&clip, &ndc); - _ndc_to_viewport (transformation, &ndc, 0, 0, w, h, 0., 1., view); -} -#endif - -static gboolean -gst_gl_transformation_src_event (GstBaseTransform * trans, GstEvent * event) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (trans); - GstStructure *structure; - gboolean ret; - - GST_DEBUG_OBJECT (trans, "handling %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NAVIGATION:{ - gdouble x, y; - event = - GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event))); - - structure = (GstStructure *) gst_event_get_structure (event); - if (gst_structure_get_double (structure, "pointer_x", &x) && - gst_structure_get_double (structure, "pointer_y", &y)) { - gdouble new_x, new_y; - - if (!_screen_coord_to_model_coord (transformation, x, y, &new_x, - &new_y)) { - gst_event_unref (event); - return TRUE; - } - - gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, new_x, - "pointer_y", G_TYPE_DOUBLE, new_y, NULL); - } - break; - } - default: - break; - } - - ret = GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event); - - return ret; -} - -static gboolean -gst_gl_transformation_filter_meta (GstBaseTransform * trans, GstQuery * query, - GType api, const GstStructure * params) -{ - if (api == GST_VIDEO_AFFINE_TRANSFORMATION_META_API_TYPE) - return TRUE; - - if (api == GST_GL_SYNC_META_API_TYPE) - return TRUE; - - return FALSE; -} - -static gboolean -gst_gl_transformation_decide_allocation (GstBaseTransform * trans, - GstQuery * query) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (trans); - - if (!GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (trans, - query)) - return FALSE; - - if (gst_query_find_allocation_meta (query, - GST_VIDEO_AFFINE_TRANSFORMATION_META_API_TYPE, NULL)) { - transformation->downstream_supports_affine_meta = TRUE; - } else { - transformation->downstream_supports_affine_meta = FALSE; - } - - return TRUE; -} - -static void -gst_gl_transformation_gl_stop (GstGLBaseFilter * base_filter) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (base_filter); - const GstGLFuncs *gl = base_filter->context->gl_vtable; - - if (transformation->vao) { - gl->DeleteVertexArrays (1, &transformation->vao); - transformation->vao = 0; - } - - if (transformation->vertex_buffer) { - gl->DeleteBuffers (1, &transformation->vertex_buffer); - transformation->vertex_buffer = 0; - } - - if (transformation->vbo_indices) { - gl->DeleteBuffers (1, &transformation->vbo_indices); - transformation->vbo_indices = 0; - } - - if (transformation->shader) { - gst_object_unref (transformation->shader); - transformation->shader = NULL; - } - - GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter); -} - -static gboolean -gst_gl_transformation_gl_start (GstGLBaseFilter * base_filter) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (base_filter); - - if (!GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter)) - return FALSE; - - if (gst_gl_context_get_gl_api (base_filter->context)) { - /* blocking call, wait until the opengl thread has compiled the shader */ - return gst_gl_context_gen_shader (base_filter->context, - gst_gl_shader_string_vertex_mat4_vertex_transform, - gst_gl_shader_string_fragment_default, &transformation->shader); - } - return TRUE; -} - -static GstFlowReturn -gst_gl_transformation_prepare_output_buffer (GstBaseTransform * trans, - GstBuffer * inbuf, GstBuffer ** outbuf) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (trans); - GstGLFilter *filter = GST_GL_FILTER (trans); - - if (transformation->downstream_supports_affine_meta && - gst_video_info_is_equal (&filter->in_info, &filter->out_info)) { - GstVideoAffineTransformationMeta *af_meta; - graphene_matrix_t upstream_matrix, tmp, tmp2, inv_aspect, yflip; - float upstream[16], downstream[16]; - - *outbuf = gst_buffer_make_writable (inbuf); - - af_meta = gst_buffer_get_video_affine_transformation_meta (inbuf); - if (!af_meta) - af_meta = gst_buffer_add_video_affine_transformation_meta (*outbuf); - - GST_LOG_OBJECT (trans, "applying transformation to existing affine " - "transformation meta"); - - gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, upstream); - - /* apply the transformation to the existing affine meta */ - graphene_matrix_init_from_float (&upstream_matrix, upstream); - graphene_matrix_init_scale (&inv_aspect, transformation->aspect, -1., 1.); - graphene_matrix_init_scale (&yflip, 1., -1., 1.); - - /* invert the aspect effects */ - graphene_matrix_multiply (&upstream_matrix, &inv_aspect, &tmp2); - /* apply the transformation */ - graphene_matrix_multiply (&tmp2, &transformation->mvp_matrix, &tmp); - /* and undo yflip */ - graphene_matrix_multiply (&tmp, &yflip, &tmp2); - - graphene_matrix_to_float (&tmp2, downstream); - gst_gl_set_affine_transformation_meta_from_ndc_ext (af_meta, downstream); - - return GST_FLOW_OK; - } - - return GST_BASE_TRANSFORM_CLASS (parent_class)->prepare_output_buffer (trans, - inbuf, outbuf); -} - -static gboolean -gst_gl_transformation_filter (GstGLFilter * filter, - GstBuffer * inbuf, GstBuffer * outbuf) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter); - - if (transformation->downstream_supports_affine_meta && - gst_video_info_is_equal (&filter->in_info, &filter->out_info)) { - return TRUE; - } else { - return gst_gl_filter_filter_texture (filter, inbuf, outbuf); - } -} - -static gboolean -gst_gl_transformation_filter_texture (GstGLFilter * filter, - GstGLMemory * in_tex, GstGLMemory * out_tex) -{ - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter); - - transformation->in_tex = in_tex; - - gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex, - (GstGLFramebufferFunc) gst_gl_transformation_callback, transformation); - - return TRUE; -} - -static const GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - -static void -_upload_vertices (GstGLTransformation * transformation) -{ - const GstGLFuncs *gl = - GST_GL_BASE_FILTER (transformation)->context->gl_vtable; - -/* *INDENT-OFF* */ - GLfloat vertices[] = { - -transformation->aspect, -1.0, 0.0, 1.0, 0.0, 0.0, - transformation->aspect, -1.0, 0.0, 1.0, 1.0, 0.0, - transformation->aspect, 1.0, 0.0, 1.0, 1.0, 1.0, - -transformation->aspect, 1.0, 0.0, 1.0, 0.0, 1.0, - }; - /* *INDENT-ON* */ - - gl->BindBuffer (GL_ARRAY_BUFFER, transformation->vertex_buffer); - - gl->BufferData (GL_ARRAY_BUFFER, 4 * 6 * sizeof (GLfloat), vertices, - GL_STATIC_DRAW); -} - -static void -_bind_buffer (GstGLTransformation * transformation) -{ - const GstGLFuncs *gl = - GST_GL_BASE_FILTER (transformation)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, transformation->vbo_indices); - gl->BindBuffer (GL_ARRAY_BUFFER, transformation->vertex_buffer); - - /* Load the vertex position */ - gl->VertexAttribPointer (transformation->attr_position, 4, GL_FLOAT, - GL_FALSE, 6 * sizeof (GLfloat), (void *) 0); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (transformation->attr_texture, 2, GL_FLOAT, GL_FALSE, - 6 * sizeof (GLfloat), (void *) (4 * sizeof (GLfloat))); - - gl->EnableVertexAttribArray (transformation->attr_position); - gl->EnableVertexAttribArray (transformation->attr_texture); -} - -static void -_unbind_buffer (GstGLTransformation * transformation) -{ - const GstGLFuncs *gl = - GST_GL_BASE_FILTER (transformation)->context->gl_vtable; - - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); - gl->BindBuffer (GL_ARRAY_BUFFER, 0); - - gl->DisableVertexAttribArray (transformation->attr_position); - gl->DisableVertexAttribArray (transformation->attr_texture); -} - -static gboolean -gst_gl_transformation_callback (gpointer stuff) -{ - GstGLFilter *filter = GST_GL_FILTER (stuff); - GstGLTransformation *transformation = GST_GL_TRANSFORMATION (filter); - GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable; - - GLfloat temp_matrix[16]; - - gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context); - gl->BindTexture (GL_TEXTURE_2D, 0); - - gl->ClearColor (0.f, 0.f, 0.f, 0.f); - gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - gst_gl_shader_use (transformation->shader); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, transformation->in_tex->tex_id); - gst_gl_shader_set_uniform_1i (transformation->shader, "texture", 0); - - graphene_matrix_to_float (&transformation->mvp_matrix, temp_matrix); - gst_gl_shader_set_uniform_matrix_4fv (transformation->shader, - "u_transformation", 1, GL_FALSE, temp_matrix); - - if (!transformation->vertex_buffer) { - transformation->attr_position = - gst_gl_shader_get_attribute_location (transformation->shader, - "a_position"); - - transformation->attr_texture = - gst_gl_shader_get_attribute_location (transformation->shader, - "a_texcoord"); - - if (gl->GenVertexArrays) { - gl->GenVertexArrays (1, &transformation->vao); - gl->BindVertexArray (transformation->vao); - } - - gl->GenBuffers (1, &transformation->vertex_buffer); - - gl->GenBuffers (1, &transformation->vbo_indices); - gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, transformation->vbo_indices); - gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices, - GL_STATIC_DRAW); - - transformation->caps_change = TRUE; - } - - if (gl->GenVertexArrays) - gl->BindVertexArray (transformation->vao); - - if (transformation->caps_change) - _upload_vertices (transformation); - _bind_buffer (transformation); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - - if (gl->GenVertexArrays) - gl->BindVertexArray (0); - _unbind_buffer (transformation); - - gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context); - transformation->caps_change = FALSE; - - return TRUE; -} diff --git a/ext/gl/gstgltransformation.h b/ext/gl/gstgltransformation.h deleted file mode 100644 index 205f1a48f..000000000 --- a/ext/gl/gstgltransformation.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2014 Lubosz Sarnecki <lubosz@gmail.com> - * - * 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_GL_TRANSFORMATION_H_ -#define _GST_GL_TRANSFORMATION_H_ - -#include <gst/gl/gstglfilter.h> -#include <gst/gl/gstglfuncs.h> -#include <graphene.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_TRANSFORMATION (gst_gl_transformation_get_type()) -#define GST_GL_TRANSFORMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_TRANSFORMATION,GstGLTransformation)) -#define GST_IS_GL_TRANSFORMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_TRANSFORMATION)) -#define GST_GL_TRANSFORMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_TRANSFORMATION,GstGLTransformationClass)) -#define GST_IS_GL_TRANSFORMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_TRANSFORMATION)) -#define GST_GL_TRANSFORMATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_TRANSFORMATION,GstGLTransformationClass)) - -typedef struct _GstGLTransformation GstGLTransformation; -typedef struct _GstGLTransformationClass GstGLTransformationClass; - -struct _GstGLTransformation -{ - GstGLFilter filter; - - GstGLShader *shader; - GLuint vao; - GLuint vbo_indices; - GLuint vertex_buffer; - GLint attr_position; - GLint attr_texture; - - GstGLMemory *in_tex; - GstGLMemory *out_tex; - - gfloat xrotation; - gfloat yrotation; - gfloat zrotation; - - gfloat xscale; - gfloat yscale; - - gfloat xtranslation; - gfloat ytranslation; - gfloat ztranslation; - - gfloat xpivot; - gfloat ypivot; - gfloat zpivot; - - /* perspective */ - gfloat fov; - gfloat aspect; - gfloat znear; - gfloat zfar; - gboolean ortho; - - graphene_matrix_t model_matrix; - graphene_matrix_t view_matrix; - graphene_matrix_t projection_matrix; - graphene_matrix_t inv_model_matrix; - graphene_matrix_t inv_view_matrix; - graphene_matrix_t inv_projection_matrix; - graphene_matrix_t mvp_matrix; - - graphene_vec3_t camera_position; - - gboolean downstream_supports_affine_meta; - gboolean caps_change; -}; - -struct _GstGLTransformationClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_transformation_get_type (void); - -G_END_DECLS - -#endif /* _GST_GL_TRANSFORMATION_H_ */ diff --git a/ext/gl/gstgluploadelement.c b/ext/gl/gstgluploadelement.c deleted file mode 100644 index f9e52f681..000000000 --- a/ext/gl/gstgluploadelement.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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 - -#include <stdio.h> - -#include <gst/gl/gl.h> -#include "gstgluploadelement.h" - -GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_element_debug); -#define GST_CAT_DEFAULT gst_gl_upload_element_debug - -#define gst_gl_upload_element_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLUploadElement, gst_gl_upload_element, - GST_TYPE_GL_BASE_FILTER, - GST_DEBUG_CATEGORY_INIT (gst_gl_upload_element_debug, "gluploadelement", 0, - "glupload Element");); - -static gboolean gst_gl_upload_element_get_unit_size (GstBaseTransform * trans, - GstCaps * caps, gsize * size); -static GstCaps *_gst_gl_upload_element_transform_caps (GstBaseTransform * bt, - GstPadDirection direction, GstCaps * caps, GstCaps * filter); -static gboolean _gst_gl_upload_element_set_caps (GstBaseTransform * bt, - GstCaps * in_caps, GstCaps * out_caps); -static gboolean gst_gl_upload_element_filter_meta (GstBaseTransform * trans, - GstQuery * query, GType api, const GstStructure * params); -static gboolean _gst_gl_upload_element_propose_allocation (GstBaseTransform * - bt, GstQuery * decide_query, GstQuery * query); -static gboolean _gst_gl_upload_element_decide_allocation (GstBaseTransform * - trans, GstQuery * query); -static GstFlowReturn -gst_gl_upload_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * buffer, GstBuffer ** outbuf); -static GstFlowReturn gst_gl_upload_element_transform (GstBaseTransform * bt, - GstBuffer * buffer, GstBuffer * outbuf); -static gboolean gst_gl_upload_element_stop (GstBaseTransform * bt); - -static GstStaticPadTemplate gst_gl_upload_element_src_pad_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(ANY)")); - -static void -gst_gl_upload_element_finalize (GObject * object) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (object); - - if (upload->upload) - gst_object_unref (upload->upload); - upload->upload = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_gl_upload_element_class_init (GstGLUploadElementClass * klass) -{ - GstBaseTransformClass *bt_class = GST_BASE_TRANSFORM_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstCaps *upload_caps; - - bt_class->transform_caps = _gst_gl_upload_element_transform_caps; - bt_class->set_caps = _gst_gl_upload_element_set_caps; - bt_class->filter_meta = gst_gl_upload_element_filter_meta; - bt_class->propose_allocation = _gst_gl_upload_element_propose_allocation; - bt_class->decide_allocation = _gst_gl_upload_element_decide_allocation; - bt_class->get_unit_size = gst_gl_upload_element_get_unit_size; - bt_class->prepare_output_buffer = gst_gl_upload_element_prepare_output_buffer; - bt_class->transform = gst_gl_upload_element_transform; - bt_class->stop = gst_gl_upload_element_stop; - - bt_class->passthrough_on_same_caps = TRUE; - - gst_element_class_add_static_pad_template (element_class, - &gst_gl_upload_element_src_pad_template); - - upload_caps = gst_gl_upload_get_input_template_caps (); - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, upload_caps)); - gst_caps_unref (upload_caps); - - gst_element_class_set_metadata (element_class, - "OpenGL uploader", "Filter/Video", - "Uploads data into OpenGL", "Matthew Waters <matthew@centricular.com>"); - - gobject_class->finalize = gst_gl_upload_element_finalize; -} - -static void -gst_gl_upload_element_init (GstGLUploadElement * upload) -{ - gst_base_transform_set_prefer_passthrough (GST_BASE_TRANSFORM (upload), TRUE); -} - -static gboolean -gst_gl_upload_element_stop (GstBaseTransform * bt) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - - if (upload->upload) { - gst_object_unref (upload->upload); - upload->upload = NULL; - } - - gst_caps_replace (&upload->in_caps, NULL); - gst_caps_replace (&upload->out_caps, NULL); - - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt); -} - -static gboolean -gst_gl_upload_element_get_unit_size (GstBaseTransform * trans, GstCaps * caps, - gsize * size) -{ - gboolean ret = FALSE; - GstVideoInfo info; - - ret = gst_video_info_from_caps (&info, caps); - if (ret) - *size = GST_VIDEO_INFO_SIZE (&info); - - return TRUE; -} - -static GstCaps * -_gst_gl_upload_element_transform_caps (GstBaseTransform * bt, - GstPadDirection direction, GstCaps * caps, GstCaps * filter) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - GstGLContext *context = GST_GL_BASE_FILTER (bt)->context; - - if (upload->upload == NULL) - upload->upload = gst_gl_upload_new (NULL); - - return gst_gl_upload_transform_caps (upload->upload, context, direction, caps, - filter); -} - -static gboolean -gst_gl_upload_element_filter_meta (GstBaseTransform * trans, GstQuery * query, - GType api, const GstStructure * params) -{ - /* propose all metadata upstream */ - return TRUE; -} - -static gboolean -_gst_gl_upload_element_propose_allocation (GstBaseTransform * bt, - GstQuery * decide_query, GstQuery * query) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - gboolean ret; - - if (!upload->upload) - return FALSE; - - ret = GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (bt, - decide_query, query); - gst_gl_upload_propose_allocation (upload->upload, decide_query, query); - - return ret; -} - -static gboolean -_gst_gl_upload_element_decide_allocation (GstBaseTransform * trans, - GstQuery * query) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (trans); - GstGLContext *context; - gboolean ret; - - ret = - GST_BASE_TRANSFORM_CLASS - (gst_gl_upload_element_parent_class)->decide_allocation (trans, query); - if (!ret) - return FALSE; - - /* GstGLBaseFilter populates ->context in ::decide_allocation so now it's the - * time to set the ->upload context */ - context = GST_GL_BASE_FILTER (trans)->context; - gst_gl_upload_set_context (upload->upload, context); - - return gst_gl_upload_set_caps (upload->upload, upload->in_caps, - upload->out_caps); -} - -static gboolean -_gst_gl_upload_element_set_caps (GstBaseTransform * bt, GstCaps * in_caps, - GstCaps * out_caps) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - - gst_caps_replace (&upload->in_caps, in_caps); - gst_caps_replace (&upload->out_caps, out_caps); - - if (upload->upload) - return gst_gl_upload_set_caps (upload->upload, in_caps, out_caps); - - return TRUE; -} - -GstFlowReturn -gst_gl_upload_element_prepare_output_buffer (GstBaseTransform * bt, - GstBuffer * buffer, GstBuffer ** outbuf) -{ - GstGLUploadElement *upload = GST_GL_UPLOAD_ELEMENT (bt); - GstGLUploadReturn ret; - GstBaseTransformClass *bclass; - - bclass = GST_BASE_TRANSFORM_GET_CLASS (bt); - - if (gst_base_transform_is_passthrough (bt)) { - *outbuf = buffer; - return GST_FLOW_OK; - } - - if (!upload->upload) - return GST_FLOW_NOT_NEGOTIATED; - - ret = gst_gl_upload_perform_with_buffer (upload->upload, buffer, outbuf); - if (ret == GST_GL_UPLOAD_RECONFIGURE) { - gst_base_transform_reconfigure_src (bt); - return GST_FLOW_OK; - } - - if (ret != GST_GL_UPLOAD_DONE || *outbuf == NULL) { - GST_ELEMENT_ERROR (bt, RESOURCE, NOT_FOUND, ("%s", - "Failed to upload buffer"), (NULL)); - if (*outbuf) - gst_buffer_unref (*outbuf); - return GST_FLOW_ERROR; - } - - /* basetransform doesn't unref if they're the same */ - if (buffer == *outbuf) - gst_buffer_unref (*outbuf); - else - bclass->copy_metadata (bt, buffer, *outbuf); - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_gl_upload_element_transform (GstBaseTransform * bt, GstBuffer * buffer, - GstBuffer * outbuf) -{ - return GST_FLOW_OK; -} diff --git a/ext/gl/gstgluploadelement.h b/ext/gl/gstgluploadelement.h deleted file mode 100644 index 615773cce..000000000 --- a/ext/gl/gstgluploadelement.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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_GL_UPLOAD_ELEMENT_H__ -#define __GST_GL_UPLOAD_ELEMENT_H__ - -#include <gst/video/video.h> - -#include <gst/gl/gstgl_fwd.h> - -G_BEGIN_DECLS - -GType gst_gl_upload_element_get_type (void); -#define GST_TYPE_GL_UPLOAD_ELEMENT (gst_gl_upload_element_get_type()) -#define GST_GL_UPLOAD_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_UPLOAD_ELEMENT,GstGLUploadElement)) -#define GST_GL_UPLOAD_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_UPLOAD_ELEMENT,GstGLUploadElementClass)) -#define GST_IS_GL_UPLOAD_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_UPLOAD_ELEMENT)) -#define GST_IS_GL_UPLOAD_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_UPLOAD_ELEMENT)) -#define GST_GL_UPLOAD_ELEMENT_CAST(obj) ((GstGLUploadElement*)(obj)) - -typedef struct _GstGLUploadElement GstGLUploadElement; -typedef struct _GstGLUploadElementClass GstGLUploadElementClass; -typedef struct _GstGLUploadElementPrivate GstGLUploadElementPrivate; - -/** - * GstGLUploadElement - * - * Opaque #GstGLUploadElement object - */ -struct _GstGLUploadElement -{ - /* <private> */ - GstGLBaseFilter parent; - - GstGLUpload *upload; - GstCaps *in_caps; - GstCaps *out_caps; -}; - -/** - * GstGLUploadElementClass: - * - * The #GstGLUploadElementClass struct only contains private data - */ -struct _GstGLUploadElementClass -{ - GstGLBaseFilterClass object_class; -}; - -G_END_DECLS - -#endif /* __GST_GL_UPLOAD_ELEMENT_H__ */ diff --git a/ext/gl/gstglvideoflip.c b/ext/gl/gstglvideoflip.c deleted file mode 100644 index d5bb2ac57..000000000 --- a/ext/gl/gstglvideoflip.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2016 Matthew Waters <matthew@centricular.com> - * - * 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-glvideo_flip - * @title: glvideo_flip - * - * Transforms video on the GPU. - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! glvideoflip method=clockwise ! glimagesinkelement - * ]| This pipeline flips the test image 90 degrees clockwise. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstglvideoflip.h" - -#define GST_CAT_DEFAULT gst_gl_video_flip_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -#define DEFAULT_METHOD GST_GL_VIDEO_FLIP_METHOD_IDENTITY - -enum -{ - PROP_0, - PROP_METHOD, - PROP_VIDEO_DIRECTION -}; - -static GstStaticPadTemplate _sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " - "format = (string) RGBA, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE ", " - "texture-target = (string) 2D")); - -static GstStaticPadTemplate _src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " - "format = (string) RGBA, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " - "framerate = " GST_VIDEO_FPS_RANGE ", " - "texture-target = (string) 2D")); - -#define GST_TYPE_GL_VIDEO_FLIP_METHOD (gst_video_flip_method_get_type()) -static const GEnumValue video_flip_methods[] = { - {GST_GL_VIDEO_FLIP_METHOD_IDENTITY, "Identity (no rotation)", "none"}, - {GST_GL_VIDEO_FLIP_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"}, - {GST_GL_VIDEO_FLIP_METHOD_180, "Rotate 180 degrees", "rotate-180"}, - {GST_GL_VIDEO_FLIP_METHOD_90L, "Rotate counter-clockwise 90 degrees", - "counterclockwise"}, - {GST_GL_VIDEO_FLIP_METHOD_FLIP_HORIZ, "Flip horizontally", "horizontal-flip"}, - {GST_GL_VIDEO_FLIP_METHOD_FLIP_VERT, "Flip vertically", "vertical-flip"}, - {GST_GL_VIDEO_FLIP_METHOD_FLIP_UL_LR, - "Flip across upper left/lower right diagonal", "upper-left-diagonal"}, - {GST_GL_VIDEO_FLIP_METHOD_FLIP_UR_LL, - "Flip across upper right/lower left diagonal", "upper-right-diagonal"}, - {GST_GL_VIDEO_FLIP_METHOD_AUTO, - "Select flip method based on image-orientation tag", "automatic"}, - {0, NULL, NULL}, -}; - -static GType -gst_video_flip_method_get_type (void) -{ - static GType video_flip_method_type = 0; - - if (!video_flip_method_type) { - video_flip_method_type = g_enum_register_static ("GstGLVideoFlipMethod", - video_flip_methods); - } - return video_flip_method_type; -} - -static void gst_gl_video_flip_finalize (GObject * object); -static void gst_gl_video_flip_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_gl_video_flip_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstPadProbeReturn _input_sink_probe (GstPad * pad, - GstPadProbeInfo * info, gpointer user_data); -static GstPadProbeReturn _trans_src_probe (GstPad * pad, GstPadProbeInfo * info, - gpointer user_data); - -static void -gst_gl_video_flip_video_direction_interface_init (GstVideoDirectionInterface - * iface); - -#define gst_gl_video_flip_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstGLVideoFlip, gst_gl_video_flip, - GST_TYPE_BIN, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, - "glvideoflip", 0, "glvideoflip element"); - G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_DIRECTION, - gst_gl_video_flip_video_direction_interface_init);); - -static void -gst_gl_video_flip_video_direction_interface_init (GstVideoDirectionInterface - * iface) -{ - /* We implement the video-direction property */ -} - -static void -gst_gl_video_flip_class_init (GstGLVideoFlipClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = gst_gl_video_flip_finalize; - gobject_class->set_property = gst_gl_video_flip_set_property; - gobject_class->get_property = gst_gl_video_flip_get_property; - - g_object_class_install_property (gobject_class, PROP_METHOD, - g_param_spec_enum ("method", "method", - "method (deprecated, use video-direction instead)", - GST_TYPE_GL_VIDEO_FLIP_METHOD, DEFAULT_METHOD, - GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - g_object_class_override_property (gobject_class, PROP_VIDEO_DIRECTION, - "video-direction"); - - gst_element_class_add_static_pad_template (element_class, &_src_template); - gst_element_class_add_static_pad_template (element_class, &_sink_template); - - gst_element_class_set_metadata (element_class, "OpenGL video flip filter", - "Filter/Effect/Video", "Flip video on the GPU", - "Matthew Waters <matthew@centricular.com>"); -} - -static void -gst_gl_video_flip_init (GstGLVideoFlip * flip) -{ - gboolean res = TRUE; - GstPad *pad; - - flip->aspect = 1.0; - - flip->input_capsfilter = gst_element_factory_make ("capsfilter", NULL); - res &= gst_bin_add (GST_BIN (flip), flip->input_capsfilter); - - flip->transformation = gst_element_factory_make ("gltransformation", NULL); - g_object_set (flip->transformation, "ortho", TRUE, NULL); - res &= gst_bin_add (GST_BIN (flip), flip->transformation); - - flip->output_capsfilter = gst_element_factory_make ("capsfilter", NULL); - res &= gst_bin_add (GST_BIN (flip), flip->output_capsfilter); - - res &= - gst_element_link_pads (flip->input_capsfilter, "src", - flip->transformation, "sink"); - res &= - gst_element_link_pads (flip->transformation, "src", - flip->output_capsfilter, "sink"); - - pad = gst_element_get_static_pad (flip->input_capsfilter, "sink"); - if (!pad) { - res = FALSE; - } else { - GST_DEBUG_OBJECT (flip, "setting target sink pad %" GST_PTR_FORMAT, pad); - flip->sinkpad = gst_ghost_pad_new ("sink", pad); - flip->sink_probe = gst_pad_add_probe (flip->sinkpad, - GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | - GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, - (GstPadProbeCallback) _input_sink_probe, flip, NULL); - gst_element_add_pad (GST_ELEMENT_CAST (flip), flip->sinkpad); - gst_object_unref (pad); - } - - pad = gst_element_get_static_pad (flip->transformation, "src"); - flip->src_probe = gst_pad_add_probe (pad, - GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, - (GstPadProbeCallback) _trans_src_probe, flip, NULL); - gst_object_unref (pad); - - pad = gst_element_get_static_pad (flip->output_capsfilter, "src"); - if (!pad) { - res = FALSE; - } else { - GST_DEBUG_OBJECT (flip, "setting target sink pad %" GST_PTR_FORMAT, pad); - flip->srcpad = gst_ghost_pad_new ("src", pad); - gst_element_add_pad (GST_ELEMENT_CAST (flip), flip->srcpad); - gst_object_unref (pad); - } - - if (!res) { - GST_WARNING_OBJECT (flip, "Failed to add/connect the necessary machinery"); - } -} - -static void -gst_gl_video_flip_finalize (GObject * object) -{ - GstGLVideoFlip *flip = GST_GL_VIDEO_FLIP (object); - - gst_caps_replace (&flip->input_caps, NULL); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -/* Caps negotiation happens like this: - * - * 1. caps/accept-caps queries bypass the capsfilters on either side of the - * transformation element so the fixed caps don't get in the way. - * 2. Receiving a caps event on the sink pad will set fixed caps on either side - * of the transformation element. - */ -static GstCaps * -_transform_caps (GstGLVideoFlip * vf, GstPadDirection direction, GstCaps * caps) -{ - GstCaps *output = gst_caps_copy (caps); - gint i; - - for (i = 0; i < gst_caps_get_size (output); i++) { - GstStructure *structure = gst_caps_get_structure (output, i); - gint width, height; - gint par_n, par_d; - - if (gst_structure_get_int (structure, "width", &width) && - gst_structure_get_int (structure, "height", &height)) { - - switch (vf->active_method) { - case GST_VIDEO_ORIENTATION_90R: - case GST_VIDEO_ORIENTATION_90L: - case GST_VIDEO_ORIENTATION_UL_LR: - case GST_VIDEO_ORIENTATION_UR_LL: - gst_structure_set (structure, "width", G_TYPE_INT, height, - "height", G_TYPE_INT, width, NULL); - if (gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_n, &par_d)) { - if (par_n != 1 || par_d != 1) { - GValue val = { 0, }; - - g_value_init (&val, GST_TYPE_FRACTION); - gst_value_set_fraction (&val, par_d, par_n); - gst_structure_set_value (structure, "pixel-aspect-ratio", &val); - g_value_unset (&val); - } - } - break; - case GST_VIDEO_ORIENTATION_IDENTITY: - case GST_VIDEO_ORIENTATION_180: - case GST_VIDEO_ORIENTATION_HORIZ: - case GST_VIDEO_ORIENTATION_VERT: - break; - default: - g_assert_not_reached (); - break; - } - } - } - - return output; -} - -/* with object lock */ -static void -_set_active_method (GstGLVideoFlip * vf, GstVideoOrientationMethod method, - GstCaps * caps) -{ - gfloat rot_z = 0., scale_x = 1.0, scale_y = 1.0; - GstCaps *output_caps, *templ; - GstPad *srcpad; - - switch (method) { - case GST_VIDEO_ORIENTATION_IDENTITY: - break; - case GST_VIDEO_ORIENTATION_90R: - scale_x *= vf->aspect; - scale_y *= 1. / vf->aspect; - rot_z = 90.; - break; - case GST_VIDEO_ORIENTATION_180: - rot_z = 180.; - break; - case GST_VIDEO_ORIENTATION_90L: - scale_x *= vf->aspect; - scale_y *= 1. / vf->aspect; - rot_z = 270.; - break; - case GST_VIDEO_ORIENTATION_HORIZ: - scale_x *= -1.; - break; - case GST_VIDEO_ORIENTATION_UR_LL: - scale_x *= -vf->aspect; - scale_y *= 1. / vf->aspect; - rot_z = 90.; - break; - case GST_VIDEO_ORIENTATION_VERT: - scale_x *= -1.; - rot_z = 180.; - break; - case GST_VIDEO_ORIENTATION_UL_LR: - scale_x *= -vf->aspect; - scale_y *= 1. / vf->aspect; - rot_z = 270.; - break; - default: - break; - } - vf->active_method = method; - - output_caps = _transform_caps (vf, GST_PAD_SINK, caps); - gst_caps_replace (&vf->input_caps, caps); - - srcpad = gst_element_get_static_pad (vf->transformation, "src"); - templ = gst_pad_get_pad_template_caps (srcpad); - gst_object_unref (srcpad); - - gst_caps_append (output_caps, gst_caps_ref (templ)); - GST_OBJECT_UNLOCK (vf); - - g_object_set (vf->input_capsfilter, "caps", gst_caps_ref (caps), NULL); - g_object_set (vf->output_capsfilter, "caps", output_caps, NULL); - g_object_set (vf->transformation, "rotation-z", rot_z, "scale-x", scale_x, - "scale-y", scale_y, NULL); - GST_OBJECT_LOCK (vf); -} - -static void -gst_gl_video_flip_set_method (GstGLVideoFlip * vf, - GstVideoOrientationMethod method, gboolean from_tag) -{ - GST_OBJECT_LOCK (vf); - - if (method == GST_VIDEO_ORIENTATION_CUSTOM) { - GST_WARNING_OBJECT (vf, "unsupported custom orientation"); - GST_OBJECT_UNLOCK (vf); - return; - } - - /* Store updated method */ - if (from_tag) - vf->tag_method = method; - else - vf->method = method; - - /* Get the new method */ - if (vf->method == GST_VIDEO_ORIENTATION_AUTO) - method = vf->tag_method; - else - method = vf->method; - - if (vf->input_caps) - _set_active_method (vf, method, vf->input_caps); - else { - /* just store the configured method here. The actual transform configuration - * will be done once caps are configured. See caps handling in - * _input_sink_probe. */ - vf->active_method = method; - } - - GST_OBJECT_UNLOCK (vf); -} - -static void -gst_gl_video_flip_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLVideoFlip *vf = GST_GL_VIDEO_FLIP (object); - - switch (prop_id) { - case PROP_METHOD: - case PROP_VIDEO_DIRECTION: - gst_gl_video_flip_set_method (vf, g_value_get_enum (value), FALSE); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_video_flip_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLVideoFlip *vf = GST_GL_VIDEO_FLIP (object); - - switch (prop_id) { - case PROP_METHOD: - case PROP_VIDEO_DIRECTION: - g_value_set_enum (value, vf->method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstPadProbeReturn -_input_sink_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) -{ - GstGLVideoFlip *vf = GST_GL_VIDEO_FLIP (user_data); - - if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) { - GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_TAG:{ - GstTagList *taglist; - gchar *orientation; - - gst_event_parse_tag (event, &taglist); - - if (gst_tag_list_get_string (taglist, "image-orientation", - &orientation)) { - if (!g_strcmp0 ("rotate-0", orientation)) - gst_gl_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_IDENTITY, - TRUE); - else if (!g_strcmp0 ("rotate-90", orientation)) - gst_gl_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_90R, TRUE); - else if (!g_strcmp0 ("rotate-180", orientation)) - gst_gl_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_180, TRUE); - else if (!g_strcmp0 ("rotate-270", orientation)) - gst_gl_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_90L, TRUE); - else if (!g_strcmp0 ("flip-rotate-0", orientation)) - gst_gl_video_flip_set_method (vf, - GST_VIDEO_ORIENTATION_HORIZ, TRUE); - else if (!g_strcmp0 ("flip-rotate-90", orientation)) - gst_gl_video_flip_set_method (vf, - GST_VIDEO_ORIENTATION_UR_LL, TRUE); - else if (!g_strcmp0 ("flip-rotate-180", orientation)) - gst_gl_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_VERT, TRUE); - else if (!g_strcmp0 ("flip-rotate-270", orientation)) - gst_gl_video_flip_set_method (vf, - GST_VIDEO_ORIENTATION_UL_LR, TRUE); - - g_free (orientation); - } - break; - } - case GST_EVENT_CAPS:{ - GstCaps *caps; - GstVideoInfo v_info; - - gst_event_parse_caps (event, &caps); - GST_OBJECT_LOCK (vf); - if (gst_video_info_from_caps (&v_info, caps)) - vf->aspect = - (gfloat) GST_VIDEO_INFO_WIDTH (&v_info) / - (gfloat) GST_VIDEO_INFO_HEIGHT (&v_info); - else - vf->aspect = 1.0; - _set_active_method (vf, vf->active_method, caps); - GST_OBJECT_UNLOCK (vf); - break; - } - default: - break; - } - } else if (GST_PAD_PROBE_INFO_TYPE (info) & - GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) { - GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info); - - switch (GST_QUERY_TYPE (query)) { - /* bypass the capsfilter */ - case GST_QUERY_CAPS: - case GST_QUERY_ACCEPT_CAPS:{ - GstPad *pad = gst_element_get_static_pad (vf->transformation, "sink"); - if (gst_pad_query (pad, query)) { - gst_object_unref (pad); - return GST_PAD_PROBE_HANDLED; - } else { - gst_object_unref (pad); - return GST_PAD_PROBE_DROP; - } - } - default: - break; - } - } - - return GST_PAD_PROBE_OK; -} - -static GstPadProbeReturn -_trans_src_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) -{ - GstGLVideoFlip *vf = GST_GL_VIDEO_FLIP (user_data); - - if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) { - GstQuery *query = GST_PAD_PROBE_INFO_QUERY (info); - - switch (GST_QUERY_TYPE (query)) { - /* bypass the capsfilter */ - case GST_QUERY_CAPS: - case GST_QUERY_ACCEPT_CAPS:{ - if (gst_pad_peer_query (vf->srcpad, query)) - return GST_PAD_PROBE_HANDLED; - else - return GST_PAD_PROBE_DROP; - } - default: - break; - } - } - - return GST_PAD_PROBE_OK; -} diff --git a/ext/gl/gstglvideoflip.h b/ext/gl/gstglvideoflip.h deleted file mode 100644 index 36f8da07d..000000000 --- a/ext/gl/gstglvideoflip.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2016 Matthew Waters <matthew@centricular.com> - * - * 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_GL_VIDEO_FLIP_H_ -#define _GST_GL_VIDEO_FLIP_H_ - -#include <gst/gl/gl.h> - -G_BEGIN_DECLS - -#define GST_TYPE_GL_VIDEO_FLIP (gst_gl_video_flip_get_type()) -#define GST_GL_VIDEO_FLIP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_VIDEO_FLIP,GstGLVideoFlip)) -#define GST_IS_GL_VIDEO_FLIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_VIDEO_FLIP)) -#define GST_GL_VIDEO_FLIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_VIDEO_FLIP,GstGLVideoFlipClass)) -#define GST_IS_GL_VIDEO_FLIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_VIDEO_FLIP)) -#define GST_GL_VIDEO_FLIP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_VIDEO_FLIP,GstGLVideoFlipClass)) - -/** - * GstVideoFlipMethod: - * @GST_GL_VIDEO_FLIP_METHOD_IDENTITY: Identity (no rotation) - * @GST_GL_VIDEO_FLIP_METHOD_90R: Rotate clockwise 90 degrees - * @GST_GL_VIDEO_FLIP_METHOD_180: Rotate 180 degrees - * @GST_GL_VIDEO_FLIP_METHOD_90L: Rotate counter-clockwise 90 degrees - * @GST_GL_VIDEO_FLIP_METHOD_FLIP_HORIZ: Flip horizontally - * @GST_GL_VIDEO_FLIP_METHOD_FLIP_VERT: Flip vertically - * @GST_GL_VIDEO_FLIP_METHOD_FLIP_UL_LR: Flip across upper left/lower right diagonal - * @GST_GL_VIDEO_FLIP_METHOD_FLIP_UR_LL: Flip across upper right/lower left diagonal - * @GST_GL_VIDEO_FLIP_METHOD_AUTO: Select flip method based on image-orientation tag - * - * The different flip methods. - */ -typedef enum { - GST_GL_VIDEO_FLIP_METHOD_IDENTITY, - GST_GL_VIDEO_FLIP_METHOD_90R, - GST_GL_VIDEO_FLIP_METHOD_180, - GST_GL_VIDEO_FLIP_METHOD_90L, - GST_GL_VIDEO_FLIP_METHOD_FLIP_HORIZ, - GST_GL_VIDEO_FLIP_METHOD_FLIP_VERT, - GST_GL_VIDEO_FLIP_METHOD_FLIP_UL_LR, - GST_GL_VIDEO_FLIP_METHOD_FLIP_UR_LL, - GST_GL_VIDEO_FLIP_METHOD_AUTO, -} GstGLVideoFlipMethod; - -typedef struct _GstGLVideoFlip GstGLVideoFlip; -typedef struct _GstGLVideoFlipClass GstGLVideoFlipClass; - -struct _GstGLVideoFlip -{ - GstBin bin; - - GstPad *srcpad; - GstPad *sinkpad; - - GstElement *input_capsfilter; - GstElement *transformation; - GstElement *output_capsfilter; - - gulong sink_probe; - gulong src_probe; - - GstCaps *input_caps; - - /* properties */ - GstVideoOrientationMethod method; - GstVideoOrientationMethod tag_method; - GstVideoOrientationMethod active_method; - - gfloat aspect; -}; - -struct _GstGLVideoFlipClass -{ - GstBinClass filter_class; -}; - -GType gst_gl_video_flip_get_type (void); - -G_END_DECLS - -#endif /* _GST_GL_VIDEO_FLIP_H_ */ diff --git a/ext/gl/gstglviewconvert.c b/ext/gl/gstglviewconvert.c deleted file mode 100644 index 203df6b97..000000000 --- a/ext/gl/gstglviewconvert.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Julien Isorce <julien.isorce@mail.com> - * Copyright (C) 2014 Jan Schmidt <jan@centricular.com> - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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-glviewconvert - * @title: glviewconvert - * - * Convert stereoscopic video between different representations using fragment shaders. - * - * The element can use either property settings or caps negotiation to choose the - * input and output formats to process. - * - * ## Examples - * |[ - * gst-launch-1.0 videotestsrc ! glupload ! glviewconvert ! glimagesink - * ]| Simple placebo example demonstrating identity passthrough of mono video - * |[ - * gst-launch-1.0 videotestsrc pattern=checkers-1 ! glupload ! \ - * glviewconvert input-mode-override=side-by-side ! glimagesink -v - * ]| Force re-interpretation of the input checkers pattern as a side-by-side stereoscopic - * image and display in glimagesink. - * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/base/gstbasetransform.h> - -#include "gstglviewconvert.h" - -#define GST_CAT_DEFAULT gst_gl_view_convert_element_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); - -enum -{ - PROP_0, - PROP_INPUT_LAYOUT, - PROP_INPUT_FLAGS, - PROP_OUTPUT_LAYOUT, - PROP_OUTPUT_FLAGS, - PROP_OUTPUT_DOWNMIX_MODE -}; - -#define DEFAULT_DOWNMIX GST_GL_STEREO_DOWNMIX_ANAGLYPH_GREEN_MAGENTA_DUBOIS - -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_view_convert_element_debug, "glview_convertelement", 0, "glview_convert element"); - -G_DEFINE_TYPE_WITH_CODE (GstGLViewConvertElement, gst_gl_view_convert_element, - GST_TYPE_GL_FILTER, DEBUG_INIT); -#define parent_class gst_gl_view_convert_element_parent_class - -static void gst_gl_view_convert_dispose (GObject * object); -static void gst_gl_view_convert_element_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_gl_view_convert_element_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static gboolean gst_gl_view_convert_element_stop (GstBaseTransform * bt); -static gboolean -gst_gl_view_convert_element_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps); -static GstCaps *gst_gl_view_convert_element_transform_internal_caps (GstGLFilter - * filter, GstPadDirection direction, GstCaps * caps, GstCaps * filter_caps); -static GstCaps *gst_gl_view_convert_element_fixate_caps (GstBaseTransform * - trans, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); -static GstFlowReturn -gst_gl_view_convert_element_submit_input_buffer (GstBaseTransform * trans, - gboolean is_discont, GstBuffer * input); -static GstFlowReturn -gst_gl_view_convert_element_generate_output_buffer (GstBaseTransform * bt, - GstBuffer ** outbuf); - -static void -gst_gl_view_convert_element_class_init (GstGLViewConvertElementClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = (GObjectClass *) klass; - element_class = GST_ELEMENT_CLASS (klass); - - gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass)); - - gobject_class->set_property = gst_gl_view_convert_element_set_property; - gobject_class->get_property = gst_gl_view_convert_element_get_property; - gobject_class->dispose = gst_gl_view_convert_dispose; - - gst_element_class_set_metadata (element_class, - "OpenGL Multiview/3D conversion filter", "Filter", - "Convert stereoscopic/multiview video formats", - "Jan Schmidt <jan@centricular.com>\n" - "Matthew Waters <matthew@centricular.com>"); - - GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_view_convert_element_set_caps; - - GST_GL_FILTER_CLASS (klass)->transform_internal_caps = - gst_gl_view_convert_element_transform_internal_caps; - GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_view_convert_element_stop; - GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = - gst_gl_view_convert_element_fixate_caps; - GST_BASE_TRANSFORM_CLASS (klass)->submit_input_buffer = - gst_gl_view_convert_element_submit_input_buffer; - GST_BASE_TRANSFORM_CLASS (klass)->generate_output = - gst_gl_view_convert_element_generate_output_buffer; - - g_object_class_install_property (gobject_class, PROP_INPUT_LAYOUT, - g_param_spec_enum ("input-mode-override", - "Input Multiview Mode Override", - "Override any input information about multiview layout", - GST_TYPE_VIDEO_MULTIVIEW_FRAME_PACKING, - GST_VIDEO_MULTIVIEW_MODE_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_INPUT_FLAGS, - g_param_spec_flags ("input-flags-override", - "Input Multiview Flags Override", - "Override any input information about multiview layout flags", - GST_TYPE_VIDEO_MULTIVIEW_FLAGS, GST_VIDEO_MULTIVIEW_FLAGS_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OUTPUT_LAYOUT, - g_param_spec_enum ("output-mode-override", - "Output Multiview Mode Override", - "Override automatic output mode selection for multiview layout", - GST_TYPE_VIDEO_MULTIVIEW_MODE, GST_VIDEO_MULTIVIEW_MODE_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OUTPUT_FLAGS, - g_param_spec_flags ("output-flags-override", - "Output Multiview Flags Override", - "Override automatic negotiation for output multiview layout flags", - GST_TYPE_VIDEO_MULTIVIEW_FLAGS, GST_VIDEO_MULTIVIEW_FLAGS_NONE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_OUTPUT_DOWNMIX_MODE, - g_param_spec_enum ("downmix-mode", "Mode for mono downmixed output", - "Output anaglyph type to generate when downmixing to mono", - GST_TYPE_GL_STEREO_DOWNMIX_MODE_TYPE, DEFAULT_DOWNMIX, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_gl_view_convert_element_init (GstGLViewConvertElement * convert) -{ - convert->viewconvert = gst_gl_view_convert_new (); -} - -static void -gst_gl_view_convert_dispose (GObject * object) -{ - GstGLViewConvertElement *convert = GST_GL_VIEW_CONVERT_ELEMENT (object); - - if (convert->viewconvert) { - gst_object_unref (convert->viewconvert); - convert->viewconvert = NULL; - } - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static gboolean -gst_gl_view_convert_element_set_caps (GstGLFilter * filter, GstCaps * incaps, - GstCaps * outcaps) -{ - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (filter); - GstCapsFeatures *gl_features; - gboolean ret; - - GST_DEBUG_OBJECT (filter, "incaps %" GST_PTR_FORMAT - " outcaps %" GST_PTR_FORMAT, incaps, outcaps); - /* The view_convert component needs RGBA caps */ - incaps = gst_caps_copy (incaps); - outcaps = gst_caps_copy (outcaps); - - gst_caps_set_simple (incaps, "format", G_TYPE_STRING, "RGBA", NULL); - gl_features = - gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY); - gst_caps_set_features (incaps, 0, gl_features); - - gst_caps_set_simple (outcaps, "format", G_TYPE_STRING, "RGBA", NULL); - gl_features = - gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY); - gst_caps_set_features (outcaps, 0, gl_features); - - ret = gst_gl_view_convert_set_caps (viewconvert_filter->viewconvert, - incaps, outcaps); - - gst_caps_unref (incaps); - gst_caps_unref (outcaps); - - return ret; -} - -static GstCaps * -gst_gl_view_convert_element_transform_internal_caps (GstGLFilter * filter, - GstPadDirection direction, GstCaps * caps, GstCaps * filter_caps) -{ - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (filter); - GstCaps *result; - - GST_DEBUG_OBJECT (filter, "dir %s transforming caps: %" GST_PTR_FORMAT, - direction == GST_PAD_SINK ? "sink" : "src", caps); - - result = - gst_gl_view_convert_transform_caps (viewconvert_filter->viewconvert, - direction, caps, NULL); - - GST_DEBUG_OBJECT (filter, "returning caps: %" GST_PTR_FORMAT, result); - - return result; -} - -static GstCaps * -gst_gl_view_convert_element_fixate_caps (GstBaseTransform * trans, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) -{ - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (trans); - - othercaps = gst_gl_view_convert_fixate_caps (viewconvert_filter->viewconvert, - direction, caps, othercaps); - - if (gst_caps_is_empty (othercaps)) - return othercaps; - - /* Let GLfilter do the rest */ - return - GST_BASE_TRANSFORM_CLASS - (gst_gl_view_convert_element_parent_class)->fixate_caps (trans, direction, - caps, othercaps); -} - -static gboolean -gst_gl_view_convert_element_stop (GstBaseTransform * bt) -{ - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (bt); - - gst_gl_view_convert_reset (viewconvert_filter->viewconvert); - - return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt); -} - -static void -gst_gl_view_convert_element_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstGLViewConvertElement *convert = GST_GL_VIEW_CONVERT_ELEMENT (object); - - switch (prop_id) { - case PROP_INPUT_LAYOUT: - case PROP_INPUT_FLAGS: - g_object_set_property (G_OBJECT (convert->viewconvert), pspec->name, - value); - gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (convert)); - break; - case PROP_OUTPUT_LAYOUT: - case PROP_OUTPUT_FLAGS: - g_object_set_property (G_OBJECT (convert->viewconvert), pspec->name, - value); - gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (convert)); - break; - case PROP_OUTPUT_DOWNMIX_MODE: - g_object_set_property (G_OBJECT (convert->viewconvert), pspec->name, - value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_gl_view_convert_element_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstGLViewConvertElement *convert = GST_GL_VIEW_CONVERT_ELEMENT (object); - - switch (prop_id) { - case PROP_INPUT_LAYOUT: - case PROP_INPUT_FLAGS: - case PROP_OUTPUT_LAYOUT: - case PROP_OUTPUT_FLAGS: - case PROP_OUTPUT_DOWNMIX_MODE: - g_object_get_property (G_OBJECT (convert->viewconvert), pspec->name, - value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstFlowReturn -gst_gl_view_convert_element_submit_input_buffer (GstBaseTransform * trans, - gboolean is_discont, GstBuffer * input) -{ - GstGLContext *context = GST_GL_BASE_FILTER (trans)->context; - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (trans); - GstFlowReturn ret; - - ret = - GST_BASE_TRANSFORM_CLASS (parent_class)->submit_input_buffer (trans, - is_discont, input); - if (ret != GST_FLOW_OK || trans->queued_buf == NULL) - return ret; - - gst_gl_view_convert_set_context (viewconvert_filter->viewconvert, context); - - /* Takes the ref to the input buffer */ - ret = - gst_gl_view_convert_submit_input_buffer (viewconvert_filter->viewconvert, - is_discont, input); - trans->queued_buf = NULL; - - return ret; -} - -static GstFlowReturn -gst_gl_view_convert_element_generate_output_buffer (GstBaseTransform * bt, - GstBuffer ** outbuf_ptr) -{ - GstGLFilter *filter = GST_GL_FILTER (bt); - GstGLViewConvertElement *viewconvert_filter = - GST_GL_VIEW_CONVERT_ELEMENT (bt); - GstFlowReturn ret = GST_FLOW_OK; - - ret = gst_gl_view_convert_get_output (viewconvert_filter->viewconvert, - outbuf_ptr); - - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (filter, RESOURCE, SETTINGS, - ("failed to perform view conversion on input buffer"), (NULL)); - return ret; - } - - return ret; -} diff --git a/ext/gl/gstglviewconvert.h b/ext/gl/gstglviewconvert.h deleted file mode 100644 index 5ccc58f61..000000000 --- a/ext/gl/gstglviewconvert.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2014 Jan Schmidt <jan@centricular.com> - * Copyright (C) 2015 Matthew Waters <matthew@centricular.com> - * - * 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_GL_VIEW_CONVERT_ELEMENT_H_ -#define _GST_GL_VIEW_CONVERT_ELEMENT_H_ - -#include <gst/gl/gstglfilter.h> - -G_BEGIN_DECLS -#define GST_TYPE_GL_VIEW_CONVERT_ELEMENT (gst_gl_view_convert_element_get_type()) -#define GST_GL_VIEW_CONVERT_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_VIEW_CONVERT_ELEMENT,GstGLViewConvertElement)) -#define GST_IS_GL_VIEW_CONVERT_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_VIEW_CONVERT_ELEMENT)) -#define GST_GL_VIEW_CONVERT_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_VIEW_CONVERT_ELEMENT,GstGLViewConvertElementClass)) -#define GST_IS_GL_VIEW_CONVERT_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_VIEW_CONVERT_ELEMENT)) -#define GST_GL_VIEW_CONVERT_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_VIEW_CONVERT_ELEMENT,GstGLViewConvertElementClass)) - -typedef struct _GstGLViewConvertElement GstGLViewConvertElement; -typedef struct _GstGLViewConvertElementClass GstGLViewConvertElementClass; - -struct _GstGLViewConvertElement -{ - GstGLFilter filter; - - GstGLViewConvert *viewconvert; -}; - -struct _GstGLViewConvertElementClass -{ - GstGLFilterClass filter_class; -}; - -GType gst_gl_view_convert_element_get_type (void); - -G_END_DECLS -#endif /* _GST_GL_VIEW_CONVERT_H_ */ diff --git a/ext/gl/gstopengl.c b/ext/gl/gstopengl.c index 75f8d3332..e3291fd55 100644 --- a/ext/gl/gstopengl.c +++ b/ext/gl/gstopengl.c @@ -22,14 +22,15 @@ */ /** - * SECTION:plugin-opengl - * @title: GstOpengl + * SECTION:plugin-openglmixers + * @title: OpenGL Mixers * - * Cross-platform OpenGL plugin. + * Cross-platform OpenGL mixer plugin. * * ## Debugging * * ## Examples + * FIXME: update with a mixer example * |[ * gst-launch-1.0 --gst-debug=gldisplay:3 videotestsrc ! glimagesink * ]| A debugging pipeline. @@ -43,53 +44,14 @@ #include "config.h" #endif -#include "gstglimagesink.h" -#include "gstgluploadelement.h" -#include "gstgldownloadelement.h" -#include "gstglcolorconvertelement.h" -#include "gstglcolorbalance.h" -#include "gstglfilterbin.h" -#include "gstglsinkbin.h" -#include "gstglsrcbin.h" #include "gstglmixerbin.h" - -#include "gstglfiltercube.h" -#include "gstgleffects.h" -#include "gstglcolorscale.h" #include "gstglvideomixer.h" -#include "gstglfiltershader.h" -#include "gstglfilterapp.h" -#include "gstglstereosplit.h" #include "gstglstereomix.h" -#include "gstglviewconvert.h" -#include "gstgltestsrc.h" -#include "gstgldeinterlace.h" - -#if HAVE_GRAPHENE -#include "gstgltransformation.h" -#include "gstglvideoflip.h" -#endif -#if HAVE_JPEG -#if HAVE_PNG -#include "gstgloverlay.h" -#endif /* HAVE_PNG */ -#endif /* HAVE_JPEG */ #if GST_GL_HAVE_OPENGL -#include "gstglfilterglass.h" -/* #include "gstglfilterreflectedscreen.h" */ #include "gstglmosaic.h" -#if HAVE_PNG -#include "gstgldifferencematte.h" -/* #include "gstglbumper.h" */ -#endif /* HAVE_PNG */ #endif /* GST_GL_HAVE_OPENGL */ -#if GST_GL_HAVE_WINDOW_COCOA -/* avoid including Cocoa/CoreFoundation from a C file... */ -extern GType gst_ca_opengl_layer_sink_bin_get_type (void); -#endif - #if GST_GL_HAVE_WINDOW_DISPMANX extern void bcm_host_init (void); #endif @@ -98,14 +60,13 @@ extern void bcm_host_init (void); #include <X11/Xlib.h> #endif -#define GST_CAT_DEFAULT gst_gl_gstgl_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); +GST_DEBUG_CATEGORY_STATIC (glmixers_debug); +#define GST_CAT_DEFAULT glmixers_debug -/* Register filters that make up the gstgl plugin */ static gboolean plugin_init (GstPlugin * plugin) { - GST_DEBUG_CATEGORY_INIT (gst_gl_gstgl_debug, "gstopengl", 0, "gstopengl"); + GST_DEBUG_CATEGORY_INIT (glmixers_debug, "openglmixers", 0, "OpenGL Mixers"); #if GST_GL_HAVE_WINDOW_DISPMANX GST_DEBUG ("Initialize BCM host"); @@ -117,81 +78,10 @@ plugin_init (GstPlugin * plugin) XInitThreads (); #endif - if (!gst_element_register (plugin, "glimagesink", - GST_RANK_SECONDARY, gst_gl_image_sink_bin_get_type ())) { - return FALSE; - } - - if (!gst_element_register (plugin, "glimagesinkelement", - GST_RANK_NONE, gst_glimage_sink_get_type ())) { - return FALSE; - } - - if (!gst_element_register (plugin, "glupload", - GST_RANK_NONE, GST_TYPE_GL_UPLOAD_ELEMENT)) { - return FALSE; - } - - if (!gst_element_register (plugin, "gldownload", - GST_RANK_NONE, GST_TYPE_GL_DOWNLOAD_ELEMENT)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glcolorconvert", - GST_RANK_NONE, GST_TYPE_GL_COLOR_CONVERT_ELEMENT)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glcolorbalance", - GST_RANK_NONE, GST_TYPE_GL_COLOR_BALANCE)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glfilterbin", - GST_RANK_NONE, GST_TYPE_GL_FILTER_BIN)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glsinkbin", - GST_RANK_NONE, GST_TYPE_GL_SINK_BIN)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glsrcbin", - GST_RANK_NONE, GST_TYPE_GL_SRC_BIN)) { - return FALSE; - } - if (!gst_element_register (plugin, "glmixerbin", GST_RANK_NONE, GST_TYPE_GL_MIXER_BIN)) { return FALSE; } - - if (!gst_element_register (plugin, "glfiltercube", - GST_RANK_NONE, GST_TYPE_GL_FILTER_CUBE)) { - return FALSE; - } -#if HAVE_GRAPHENE - if (!gst_element_register (plugin, "gltransformation", - GST_RANK_NONE, GST_TYPE_GL_TRANSFORMATION)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glvideoflip", - GST_RANK_NONE, GST_TYPE_GL_VIDEO_FLIP)) { - return FALSE; - } -#endif - - if (!gst_gl_effects_register_filters (plugin, GST_RANK_NONE)) { - return FALSE; - }; - - if (!gst_element_register (plugin, "glcolorscale", - GST_RANK_NONE, GST_TYPE_GL_COLORSCALE)) { - return FALSE; - } - if (!gst_element_register (plugin, "glvideomixer", GST_RANK_NONE, gst_gl_video_mixer_bin_get_type ())) { return FALSE; @@ -201,89 +91,22 @@ plugin_init (GstPlugin * plugin) GST_RANK_NONE, gst_gl_video_mixer_get_type ())) { return FALSE; } - - if (!gst_element_register (plugin, "glshader", - GST_RANK_NONE, gst_gl_filtershader_get_type ())) { - return FALSE; - } - - if (!gst_element_register (plugin, "glfilterapp", - GST_RANK_NONE, GST_TYPE_GL_FILTER_APP)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glviewconvert", - GST_RANK_NONE, GST_TYPE_GL_VIEW_CONVERT_ELEMENT)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glstereosplit", - GST_RANK_NONE, GST_TYPE_GL_STEREOSPLIT)) { - return FALSE; - } - if (!gst_element_register (plugin, "glstereomix", GST_RANK_NONE, GST_TYPE_GL_STEREO_MIX)) { return FALSE; } - - if (!gst_element_register (plugin, "gltestsrc", - GST_RANK_NONE, GST_TYPE_GL_TEST_SRC)) { - return FALSE; - } - - if (!gst_element_register (plugin, "gldeinterlace", - GST_RANK_NONE, GST_TYPE_GL_DEINTERLACE)) { - return FALSE; - } -#if HAVE_JPEG -#if HAVE_PNG - if (!gst_element_register (plugin, "gloverlay", - GST_RANK_NONE, gst_gl_overlay_get_type ())) { - return FALSE; - } -#endif /* HAVE_PNG */ -#endif /* HAVE_JPEG */ #if GST_GL_HAVE_OPENGL - if (!gst_element_register (plugin, "glfilterglass", - GST_RANK_NONE, GST_TYPE_GL_FILTER_GLASS)) { - return FALSE; - } -#if 0 - if (!gst_element_register (plugin, "glfilterreflectedscreen", - GST_RANK_NONE, GST_TYPE_GL_FILTER_REFLECTED_SCREEN)) { - return FALSE; - } -#endif if (!gst_element_register (plugin, "glmosaic", GST_RANK_NONE, GST_TYPE_GL_MOSAIC)) { return FALSE; } -#if HAVE_PNG - if (!gst_element_register (plugin, "gldifferencematte", - GST_RANK_NONE, gst_gl_differencematte_get_type ())) { - return FALSE; - } -#if 0 - if (!gst_element_register (plugin, "glbumper", - GST_RANK_NONE, gst_gl_bumper_get_type ())) { - return FALSE; - } -#endif -#endif /* HAVE_PNG */ #endif /* GST_GL_HAVE_OPENGL */ -#if GST_GL_HAVE_WINDOW_COCOA - if (!gst_element_register (plugin, "caopengllayersink", - GST_RANK_NONE, gst_ca_opengl_layer_sink_bin_get_type ())) { - return FALSE; - } -#endif return TRUE; } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - opengl, - "OpenGL plugin", + openglmixers, + "OpenGL mixers", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/gl/meson.build b/ext/gl/meson.build index a3b327964..dbc696c04 100644 --- a/ext/gl/meson.build +++ b/ext/gl/meson.build @@ -1,98 +1,22 @@ opengl_sources = [ 'gstopengl.c', 'gstglbasemixer.c', - 'gstgluploadelement.c', - 'gstgldownloadelement.c', - 'gstglcolorconvertelement.c', - 'gstglfilterbin.c', 'gstglmixerbin.c', - 'gstglsinkbin.c', - 'gstglsrcbin.c', - 'gstglimagesink.c', - 'gstglfiltercube.c', - 'gstgleffects.c', - 'effects/gstgleffectscurves.c', - 'effects/gstgleffectssources.c', - 'effects/gstgleffectidentity.c', - 'effects/gstgleffectmirror.c', - 'effects/gstgleffectsqueeze.c', - 'effects/gstgleffectstretch.c', - 'effects/gstgleffectfisheye.c', - 'effects/gstgleffecttwirl.c', - 'effects/gstgleffectbulge.c', - 'effects/gstgleffecttunnel.c', - 'effects/gstgleffectsquare.c', - 'effects/gstgleffectlumatocurve.c', - 'effects/gstgleffectrgbtocurve.c', - 'effects/gstgleffectsin.c', - 'effects/gstgleffectxray.c', - 'effects/gstgleffectglow.c', - 'effects/gstgleffectblur.c', - 'effects/gstgleffectsobel.c', - 'effects/gstgleffectlaplacian.c', - 'gstglcolorscale.c', - 'gstglcolorbalance.c', 'gstglmixer.c', 'gstglvideomixer.c', - 'gstglfiltershader.c', - 'gstglfilterapp.c', - 'gstglviewconvert.c', - 'gstglstereosplit.c', - 'gstgldeinterlace.c', 'gstglstereomix.c', - 'gltestsrc.c', - 'gstgltestsrc.c', - 'gstglutils.c' ] if build_gstgl and gstgl_dep.found() optional_deps = [] - opengl_defines = ['-DGST_USE_UNSTABLE_API'] + opengl_defines = [] if gl_dep.found() # have desktop GL opengl_sources += [ - 'gstglfilterglass.c', 'gstglmosaic.c', ] endif - graphene_dep = dependency('graphene-1.0', version : '>=1.4.0', required : false) - if graphene_dep.found() - optional_deps += graphene_dep - opengl_defines += '-DHAVE_GRAPHENE=1' - opengl_sources += [ - 'gstgltransformation.c', - 'gstglvideoflip.c', - ] - endif - - png_dep = dependency('libpng', version : '>=1.0', required : false) - jpeg_dep = cc.find_library('jpeg-mmx', required : false) - if not jpeg_dep.found() - jpeg_dep = cc.find_library('jpeg', required : false) - endif - - if png_dep.found() - optional_deps += png_dep - opengl_defines += '-DHAVE_PNG=1' - opengl_sources += [ - 'gstgldifferencematte.c', - ] - if jpeg_dep.found() - optional_deps += jpeg_dep - opengl_defines += '-DHAVE_JPEG=1' - opengl_sources += [ - 'gstgloverlay.c', - ] - endif - endif - - if false # have cocoa - opengl_sources += [ - 'caopengllayersink.m', - ] - endif - if x11_dep.found() # for XInitThreads() optional_deps += x11_dep @@ -106,12 +30,12 @@ if build_gstgl and gstgl_dep.found() optional_deps += gstallocators_dep endif - gstopengl = library('gstopengl', + gstopenglmixers = library('gstopenglmixers', opengl_sources, c_args : gst_plugins_bad_args + opengl_defines, link_args : noseh_link_args, include_directories : [configinc], - dependencies : [gstgl_dep, gstbadvideo_dep, gstvideo_dep, + dependencies : [gstbadvideo_dep, gstgl_dep, gstvideo_dep, gstbase_dep, gstcontroller_dep, libm] + optional_deps, install : true, install_dir : plugins_install_dir, |