[191/906] little cleanup. add first draft of gstgldifferencematte. still doesn't...
authorFilippo Argiolas <filippo.argiolas@gmail.com>
Mon, 18 Aug 2008 18:25:25 +0000 (20:25 +0200)
committerMatthew Waters <ystreet00@gmail.com>
Sat, 15 Mar 2014 17:36:26 +0000 (18:36 +0100)
gst/gl/Makefile.am
gst/gl/effects/gstgleffectssources.c
gst/gl/effects/gstgleffectssources.h
gst/gl/gstgldifferencematte.c [new file with mode: 0644]
gst/gl/gstglpixbufoverlay.c
gst/gl/gstopengl.c

index 520215f..b868db6 100644 (file)
@@ -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
index 0b88396..ce31a25 100644 (file)
@@ -18,6 +18,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <gstgleffects.h>
 #include <gstgleffectssources.h>
 
 /* 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)));"
+  "}";
index f3f364d..250c7e8 100644 (file)
@@ -18,8 +18,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <gstgleffects.h>
-
 #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 (file)
index 0000000..bf5bf13
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gstglfilter.h>
+#include <gstgleffectssources.h>
+#include <gdk-pixbuf/gdk-pixbuf.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))
+
+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 <filippo.argiolas@gmail.com>");
+
+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;
+}
index 1d47040..e49e763 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 #include <gstglfilter.h>
+#include <gstgleffectssources.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #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 <filippo.argiolas@gmail.com>");
 
-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,
index bfdf923..6b8c3e9 100644 (file)
@@ -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",