From: Filippo Argiolas Date: Mon, 18 Aug 2008 18:25:25 +0000 (+0200) Subject: [191/906] little cleanup. add first draft of gstgldifferencematte. still doesn't... X-Git-Tag: 1.19.3~507^2~12341 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3faa9438198569f6e9d956caf07a1cd9f5a9632f;p=platform%2Fupstream%2Fgstreamer.git [191/906] little cleanup. add first draft of gstgldifferencematte. still doesn't work --- diff --git a/gst/gl/Makefile.am b/gst/gl/Makefile.am index 520215f..b868db6 100644 --- a/gst/gl/Makefile.am +++ b/gst/gl/Makefile.am @@ -45,7 +45,7 @@ libgstopengl_la_SOURCES = \ effects/gstgleffectglow.c if HAVE_GDKPIXBUF -libgstopengl_la_SOURCES += gstglpixbufoverlay.c +libgstopengl_la_SOURCES += gstglpixbufoverlay.c gstgldifferencematte.c endif # check order of CFLAGS and LIBS, shouldn't the order be the other way around diff --git a/gst/gl/effects/gstgleffectssources.c b/gst/gl/effects/gstgleffectssources.c index 0b88396..ce31a25 100644 --- a/gst/gl/effects/gstgleffectssources.c +++ b/gst/gl/effects/gstgleffectssources.c @@ -18,6 +18,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include /* A common file for sources is needed since shader sources can be @@ -346,3 +347,24 @@ const gchar *sin_fragment_source = " float alpha = a - b;" " gl_FragColor = color * alpha + luma * (1.0 - alpha);" "}"; + +const gchar *interpolate_fragment_source = + "#extension GL_ARB_texture_rectangle : enable\n" + "uniform sampler2DRect base;" + "uniform sampler2DRect blend;" + "void main () {" + "vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" + "vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" + "vec4 white = vec4(1.0);" + "gl_FragColor = blendcolor + (1.0 - blendcolor.a) * basecolor;" + "}"; + +const gchar *difference_fragment_source = + "#extension GL_ARB_texture_rectangle : enable\n" + "uniform sampler2DRect saved;" + "uniform sampler2DRect current;" + "void main () {" + "vec4 savedcolor = texture2DRect (saved, gl_TexCoord[0].st);" + "vec4 currentcolor = texture2DRect (current, gl_TexCoord[0].st);" + "gl_FragColor = vec4 (step (0.12, length (savedcolor - currentcolor)));" + "}"; diff --git a/gst/gl/effects/gstgleffectssources.h b/gst/gl/effects/gstgleffectssources.h index f3f364d..250c7e8 100644 --- a/gst/gl/effects/gstgleffectssources.h +++ b/gst/gl/effects/gstgleffectssources.h @@ -18,8 +18,6 @@ * Boston, MA 02111-1307, USA. */ -#include - #ifndef __GST_GL_EFFECTS_SOURCES_H__ #define __GST_GL_EFFECTS_SOURCES_H__ @@ -38,5 +36,7 @@ const gchar *sum_fragment_source; const gchar *luma_to_curve_fragment_source; const gchar *rgb_to_curve_fragment_source; const gchar *sin_fragment_source; +const gchar *interpolate_fragment_source; +const gchar *difference_fragment_source; #endif /* __GST_GL_EFFECTS_SOURCES_H__ */ diff --git a/gst/gl/gstgldifferencematte.c b/gst/gl/gstgldifferencematte.c new file mode 100644 index 0000000..bf5bf13 --- /dev/null +++ b/gst/gl/gstgldifferencematte.c @@ -0,0 +1,350 @@ +/* + * GStreamer + * Copyright (C) 2008 Filippo Argiolas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#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)) + +struct _GstGLDifferenceMatte +{ + GstGLFilter filter; + + GstGLShader *shader[4]; + + gchar *location; + gboolean bg_has_changed; + + GdkPixbuf *pixbuf; + GLuint savedbgtexture; + GLuint newbgtexture; + GLuint midtexture[4]; +}; + +struct _GstGLDifferenceMatteClass +{ + GstGLFilterClass filter_class; +}; + +typedef struct _GstGLDifferenceMatte GstGLDifferenceMatte; +typedef struct _GstGLDifferenceMatteClass GstGLDifferenceMatteClass; + +#define GST_CAT_DEFAULT gst_gl_differencematte_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_gl_differencematte_debug, "gldifferencematte", 0, "gldifferencematte element"); + +GST_BOILERPLATE_FULL (GstGLDifferenceMatte, gst_gl_differencematte, GstGLFilter, + 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 void gst_gl_differencematte_init_resources (GstGLFilter* filter); +static void gst_gl_differencematte_reset_resources (GstGLFilter* filter); + +static gboolean gst_gl_differencematte_filter (GstGLFilter * filter, + GstGLBuffer * inbuf, GstGLBuffer * outbuf); + +static const GstElementDetails element_details = GST_ELEMENT_DETAILS ( + "Gstreamer OpenGL DifferenceMatte", + "Filter/Effect", + "Saves a background frame and replace it with a pixbuf", + "Filippo Argiolas "); + +enum +{ + PROP_0, + PROP_LOCATION, +}; + + +/* init resources that need a gl context */ +static void +gst_gl_differencematte_init_gl_resources (GstGLFilter *filter) +{ + GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); + gint i; + + for (i=0; i<3; i++) + differencematte->shader[i] = gst_gl_shader_new (); + + g_return_if_fail ( + gst_gl_shader_compile_and_check (differencematte->shader[0], + difference_fragment_source, + GST_GL_SHADER_FRAGMENT_SOURCE)); + g_return_if_fail ( + gst_gl_shader_compile_and_check (differencematte->shader[1], + hconv9_fragment_source, + GST_GL_SHADER_FRAGMENT_SOURCE)); + + g_return_if_fail ( + gst_gl_shader_compile_and_check (differencematte->shader[1], + vconv9_fragment_source, + GST_GL_SHADER_FRAGMENT_SOURCE)); + g_return_if_fail ( + gst_gl_shader_compile_and_check (differencematte->shader[1], + interpolate_fragment_source, + GST_GL_SHADER_FRAGMENT_SOURCE)); +} + +/* free resources that need a gl context */ +static void +gst_gl_differencematte_reset_gl_resources (GstGLFilter *filter) +{ + GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); + gint i; + + glDeleteTextures (1, &differencematte->savedbgtexture); + glDeleteTextures (1, &differencematte->newbgtexture); + for (i=0; i<3; i++) + g_object_unref (differencematte->shader[i]); +} + +static void +gst_gl_differencematte_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details (element_class, &element_details); +} + +static void +gst_gl_differencematte_class_init (GstGLDifferenceMatteClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + gobject_class->set_property = gst_gl_differencematte_set_property; + gobject_class->get_property = gst_gl_differencematte_get_property; + + GST_GL_FILTER_CLASS (klass)->filter = gst_gl_differencematte_filter; + GST_GL_FILTER_CLASS (klass)->display_init_cb = gst_gl_differencematte_init_gl_resources; + GST_GL_FILTER_CLASS (klass)->display_reset_cb = gst_gl_differencematte_reset_gl_resources; + GST_GL_FILTER_CLASS (klass)->onStart = gst_gl_differencematte_init_resources; + GST_GL_FILTER_CLASS (klass)->onStop = gst_gl_differencematte_reset_resources; + + g_object_class_install_property (gobject_class, + PROP_LOCATION, + g_param_spec_string ("location", + "Background image location", + "Background image location" + "(when set a snapshot of the background will be taken)", + NULL, G_PARAM_READWRITE)); +} + +void +gst_gl_differencematte_draw_texture (GstGLDifferenceMatte * differencematte, GLuint tex) +{ + GstGLFilter *filter = GST_GL_FILTER (differencematte); + + glActiveTexture (GL_TEXTURE0); + glEnable (GL_TEXTURE_RECTANGLE_ARB); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex); + + glBegin (GL_QUADS); + + glTexCoord2f (0.0, 0.0); + glVertex2f (-1.0, -1.0); + glTexCoord2f (filter->width, 0.0); + glVertex2f (1.0, -1.0); + glTexCoord2f (filter->width, filter->height); + glVertex2f (1.0, 1.0); + glTexCoord2f (0.0, filter->height); + glVertex2f (-1.0, 1.0); + + glEnd (); +} + +static void +gst_gl_differencematte_init (GstGLDifferenceMatte * differencematte, + GstGLDifferenceMatteClass * klass) +{ + 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; +} + +static void +gst_gl_differencematte_reset_resources (GstGLFilter* filter) +{ +// GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter); +} + +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: + if (differencematte->location != NULL) 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 +gst_gl_differencematte_init_resources (GstGLFilter* filter) +{ +// GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (filter); +} + +static void +gst_gl_differencematte_save_texture (gint width, gint height, guint texture, gpointer stuff) +{ + GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + + gst_gl_differencematte_draw_texture (differencematte, texture); +} + +static void +gst_gl_differencematte_callback (gint width, gint height, guint texture, gpointer stuff) +{ + GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE (stuff); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + + gst_gl_shader_use (differencematte->shader[0]); + + glActiveTexture (GL_TEXTURE0); + glEnable (GL_TEXTURE_RECTANGLE_ARB); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); + glDisable(GL_TEXTURE_RECTANGLE_ARB); + + gst_gl_shader_set_uniform_1i (differencematte->shader[0], "current", 0); + + glActiveTexture (GL_TEXTURE2); + glEnable (GL_TEXTURE_RECTANGLE_ARB); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture); + glDisable (GL_TEXTURE_RECTANGLE_ARB); + + gst_gl_shader_set_uniform_1i (differencematte->shader[0], "saved", 2); + + gst_gl_differencematte_draw_texture (differencematte, texture); +} + +static void init_pixbuf_texture (GstGLDisplay *display, gpointer data) +{ + GstGLDifferenceMatte *differencematte = GST_GL_DIFFERENCEMATTE (data); + GstGLFilter *filter = GST_GL_FILTER (data); + + glDeleteTextures (1, &differencematte->newbgtexture); + glGenTextures (1, &differencematte->newbgtexture); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, differencematte->newbgtexture); + glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, + filter->width, filter->height, 0, + gdk_pixbuf_get_has_alpha (differencematte->pixbuf) ? GL_RGBA : GL_RGB, + GL_UNSIGNED_BYTE, gdk_pixbuf_get_pixels (differencematte->pixbuf)); + + if (differencematte->savedbgtexture == 0) { + glGenTextures (1, &differencematte->savedbgtexture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, differencematte->savedbgtexture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } +} + +static gboolean +gst_gl_differencematte_filter (GstGLFilter* filter, GstGLBuffer* inbuf, + GstGLBuffer* outbuf) +{ + GstGLDifferenceMatte* differencematte = GST_GL_DIFFERENCEMATTE(filter); + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (differencematte->bg_has_changed && (differencematte->location != NULL)) { + pixbuf = gdk_pixbuf_new_from_file (differencematte->location, &error); + if (pixbuf) { + differencematte->pixbuf = gdk_pixbuf_scale_simple (pixbuf, + filter->width, + filter->height, + GDK_INTERP_BILINEAR); + gdk_pixbuf_unref (pixbuf); + if (differencematte->pixbuf != NULL) { + gst_gl_display_thread_add (filter->display, init_pixbuf_texture, differencematte); + /* save current frame, needed to calculate difference between + * this frame and next ones */ + gst_gl_filter_render_to_target (filter, inbuf->texture, + differencematte->savedbgtexture, + gst_gl_differencematte_save_texture, + differencematte); + gdk_pixbuf_unref (differencematte->pixbuf); + } + } else { + if (error != NULL && error->message != NULL) + g_warning ("unable to load %s: %s", differencematte->location, error->message); + } + differencematte->bg_has_changed = FALSE; + } + + gst_gl_filter_render_to_target (filter, inbuf->texture, outbuf->texture, + gst_gl_differencematte_callback, differencematte); + + return TRUE; +} diff --git a/gst/gl/gstglpixbufoverlay.c b/gst/gl/gstglpixbufoverlay.c index 1d47040..e49e763 100644 --- a/gst/gl/gstglpixbufoverlay.c +++ b/gst/gl/gstglpixbufoverlay.c @@ -23,6 +23,7 @@ #endif #include +#include #include #define GST_TYPE_GL_PIXBUFOVERLAY (gst_gl_pixbufoverlay_get_type()) @@ -79,17 +80,6 @@ static const GstElementDetails element_details = GST_ELEMENT_DETAILS ( "Overlay GL video texture with a gdkpixbuf", "Filippo Argiolas "); -static const gchar *interpolate_fragment_source = - "#extension GL_ARB_texture_rectangle : enable\n" - "uniform sampler2DRect base;" - "uniform sampler2DRect blend;" - "void main () {" - "vec4 basecolor = texture2DRect (base, gl_TexCoord[0].st);" - "vec4 blendcolor = texture2DRect (blend, gl_TexCoord[0].st);" - "vec4 white = vec4(1.0);" - "gl_FragColor = blendcolor + (1 - blendcolor.a) * basecolor;" - "}"; - enum { PROP_0, @@ -206,7 +196,6 @@ gst_gl_pixbufoverlay_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: if (pixbufoverlay->location != NULL) g_free (pixbufoverlay->location); - g_message ("\nHEERE\n"); pixbufoverlay->pbuf_has_changed = TRUE; pixbufoverlay->location = g_value_dup_string (value); break; @@ -288,8 +277,6 @@ gst_gl_pixbufoverlay_filter (GstGLFilter* filter, GstGLBuffer* inbuf, GError *error = NULL; if (pixbufoverlay->pbuf_has_changed && (pixbufoverlay->location != NULL)) { - g_message ("RECEIVED: %s", pixbufoverlay->location); - pixbuf = gdk_pixbuf_new_from_file (pixbufoverlay->location, &error); if (pixbuf) { pixbufoverlay->pixbuf = gdk_pixbuf_scale_simple (pixbuf, diff --git a/gst/gl/gstopengl.c b/gst/gl/gstopengl.c index bfdf923..6b8c3e9 100644 --- a/gst/gl/gstopengl.c +++ b/gst/gl/gstopengl.c @@ -40,6 +40,7 @@ GType gst_gl_filter_edge_get_type (void); GType gst_gl_filter_laplacian_get_type (void); #ifdef HAVE_GDKPIXBUF GType gst_gl_pixbufoverlay_get_type (void); +GType gst_gl_differencematte_get_type (void); #endif #define GST_CAT_DEFAULT gst_gl_gstgl_debug @@ -70,6 +71,11 @@ plugin_init (GstPlugin * plugin) GST_RANK_NONE, gst_gl_pixbufoverlay_get_type())) { return FALSE; } + if (!gst_element_register (plugin, "gldifferencematte", + GST_RANK_NONE, gst_gl_differencematte_get_type())) { + return FALSE; + } + #endif if (!gst_element_register (plugin, "gleffects",