[081/906] start to add a glfilter
authorJulien Isorce <julien.isorce@gmail.com>
Sat, 7 Jun 2008 00:01:18 +0000 (00:01 +0000)
committerMatthew Waters <ystreet00@gmail.com>
Sat, 15 Mar 2014 17:36:19 +0000 (18:36 +0100)
git-svn-id: svn://svn.wobow.com/GStreamer_playground/gst-plugins-gl@493 93df14bb-0f41-7a43-8087-d3e2a2f0e464

gst-libs/gst/gl/gstglbuffer.c
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst/gl/gstglfilter.c [new file with mode: 0644]
gst/gl/gstglfilter.h [new file with mode: 0644]
gst/gl/gstglfiltercube.c [new file with mode: 0644]
gst/gl/gstglfiltercube.h [new file with mode: 0644]
gst/gl/gstglgraphicmaker.c
gst/gl/gstglimagesink.c
gst/gl/gstopengl.c

index 40eb4dd..833318a 100644 (file)
@@ -95,7 +95,7 @@ gst_gl_buffer_new_from_video_format (GstGLDisplay* display,
 {
     GstGLBuffer *buffer;
 
-    g_return_val_if_fail (video_format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
+    //g_return_val_if_fail (video_format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
     g_return_val_if_fail (display != NULL, NULL);
     g_return_val_if_fail (width > 0, NULL);
     g_return_val_if_fail (height > 0, NULL);
@@ -108,10 +108,11 @@ gst_gl_buffer_new_from_video_format (GstGLDisplay* display,
     buffer->video_format = video_format;
     GST_BUFFER_SIZE (buffer) = gst_gl_buffer_format_get_size (video_format, context_width, context_height);
 
-    //blocking call, init texture 
-    gst_gl_display_textureRequested (buffer->display, buffer->video_format, 
-           buffer->width, buffer->height, 
-           &buffer->texture, &buffer->texture_u, &buffer->texture_v) ;
+    //blocking call, init texture
+    if (video_format != GST_VIDEO_FORMAT_UNKNOWN)
+        gst_gl_display_textureRequested (buffer->display, buffer->video_format, 
+               buffer->width, buffer->height, 
+               &buffer->texture, &buffer->texture_u, &buffer->texture_v) ;
 
     return buffer;
 }
index a48e0bf..2d8982e 100644 (file)
@@ -28,6 +28,7 @@
 static void gst_gl_display_finalize (GObject * object);
 static gpointer gst_gl_display_glutThreadFunc (GstGLDisplay* display);
 static void gst_gl_display_glutCreateWindow (GstGLDisplay* display);
+static void gst_gl_display_glutGenerateFBO (GstGLDisplay *display);
 static void gst_gl_display_glutDestroyWindow (GstGLDisplay* display);
 static void gst_gl_display_glutSetVisibleWindow (GstGLDisplay* display);
 static void gst_gl_display_glutPrepareTexture (GstGLDisplay* display);
@@ -93,6 +94,7 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
     display->cond_fill = g_cond_new ();
     display->cond_clear = g_cond_new ();
     display->cond_video = g_cond_new ();
+    display->cond_generateFBO = g_cond_new ();
     display->cond_create = g_cond_new ();
     display->cond_destroy = g_cond_new ();
 
@@ -106,6 +108,12 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
     display->graphicDepthBuffer = 0;
     display->graphicTexture = 0;
 
+    display->requestedFBO = 0;
+    display->requestedDepthBuffer = 0;
+    display->requestedTextureFBO = 0;
+    display->requestedTextureFBOWidth = 0;
+    display->requestedTextureFBOHeight = 0;
+
     display->requestedTexture = 0;
     display->requestedTexture_u = 0;
     display->requestedTexture_v = 0;
@@ -326,6 +334,10 @@ gst_gl_display_finalize (GObject *object)
         g_cond_free (display->cond_video);
         display->cond_video = NULL;
     }
+    if (display->cond_generateFBO) {
+        g_cond_free (display->cond_generateFBO);
+        display->cond_generateFBO = NULL;
+    }
     if (display->cond_create) {
         g_cond_free (display->cond_create);
         display->cond_create = NULL;
@@ -343,7 +355,7 @@ gst_gl_display_finalize (GObject *object)
     if (g_hash_table_size (gst_gl_display_map) == 0)
     {
         g_thread_join (gst_gl_display_glutThread);
-        GST_DEBUG ("Glut thread joined");
+        g_print ("Glut thread joined\n");
         gst_gl_display_glutThread = NULL;
         g_async_queue_unref (gst_gl_display_messageQueue);
         g_hash_table_unref  (gst_gl_display_map);
@@ -370,9 +382,9 @@ gst_gl_display_glutThreadFunc (GstGLDisplay *display)
     gst_gl_display_glutCreateWindow (display);
     gst_gl_display_unlock (display);
 
-    GST_DEBUG ("Glut mainLoop start");
+    g_print ("Glut mainLoop start\n");
     glutMainLoop ();
-    GST_DEBUG ("Glut mainLoop exited");
+    g_print ("Glut mainLoop exited\n");
 
     return NULL;
 }
@@ -397,7 +409,7 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
     display->title =  g_string_append (display->title, buffer);
     glutWinId = glutCreateWindow (display->title->str, display->winId);
 
-    GST_DEBUG ("Context %d created\n", glutWinId);
+    g_print ("Context %d created\n", glutWinId);
 
     if (display->visible)
         glutShowWindow ();
@@ -646,6 +658,53 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
 }
 
 
+/* Called by the idle funtion */
+static void
+gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
+{
+    
+    glutSetWindow (display->glutWinId);
+   
+    //-- generate frame buffer object
+
+    //setup FBO
+    glGenFramebuffersEXT (1, &display->requestedFBO);
+    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->requestedFBO);
+
+    //setup the render buffer for depth        
+    glGenRenderbuffersEXT(1, &display->requestedDepthBuffer);
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, display->requestedDepthBuffer);
+    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+        display->requestedTextureFBOWidth, display->requestedTextureFBOHeight);
+
+    //setup a texture to render to
+    glGenTextures (1, &display->requestedTextureFBO);
+    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->requestedTextureFBO);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 
+        display->requestedTextureFBOWidth, display->requestedTextureFBOHeight, 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);
+
+    //attach the texture to the FBO to renderer to
+    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
+        GL_TEXTURE_RECTANGLE_ARB, display->requestedTextureFBO, 0);
+
+    //attach the depth render buffer to the FBO
+    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
+        GL_RENDERBUFFER_EXT, display->requestedDepthBuffer);
+
+    g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
+        GL_FRAMEBUFFER_COMPLETE_EXT);
+
+    //unbind the FBO
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+    g_cond_signal (display->cond_video);
+}
+
+
 /* Called by the idle function */
 static void
 gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
@@ -695,7 +754,7 @@ gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
     }
 
     g_hash_table_remove (gst_gl_display_map, GINT_TO_POINTER (display->glutWinId)); 
-    GST_DEBUG ("glut window destroyed: %d", display->glutWinId);
+    g_print ("glut window destroyed: %d\n", display->glutWinId);
 
     //if the map is empty, leaveMainloop and join the thread
     if (g_hash_table_size (gst_gl_display_map) == 0)
@@ -806,7 +865,7 @@ gst_gl_display_glut_idle (void)
                 gst_gl_display_glutDispatchAction (msg);  
         }
     }
-    else GST_DEBUG ("timeout reached in idle func");
+    else g_print ("timeout reached in idle func\n");
 }
 
 
@@ -841,6 +900,9 @@ gst_gl_display_glutDispatchAction (GstGLDisplayMsg* msg)
         case GST_GL_DISPLAY_ACTION_REDISPLAY:
             gst_gl_display_glutPostRedisplay (msg->display);
             break;
+        case GST_GL_DISPLAY_ACTION_GENFBO:
+            gst_gl_display_glutGenerateFBO (msg->display);
+            break;
         default:
             g_assert_not_reached ();
     }
@@ -867,6 +929,7 @@ gst_gl_display_checkMsgValidity (GstGLDisplayMsg *msg)
         case GST_GL_DISPLAY_ACTION_CLEAR:          
         case GST_GL_DISPLAY_ACTION_VIDEO:
         case GST_GL_DISPLAY_ACTION_REDISPLAY:
+        case GST_GL_DISPLAY_ACTION_GENFBO:
             //msg is out of date if the associated display is not in the map
             if (!g_hash_table_lookup (gst_gl_display_map, GINT_TO_POINTER (msg->glutWinId)))
                 valid = FALSE;
@@ -1010,7 +1073,7 @@ gst_gl_display_textureRequested (GstGLDisplay * display, GstVideoFormat video_fo
 
 /* Called by gst_gl elements */
 void 
-gst_gl_display_textureChanged (GstGLDisplay * display, GstVideoFormat video_format, 
+gst_gl_display_textureChanged (GstGLDisplay* display, GstVideoFormat video_format, 
                                GLuint texture, GLuint texture_u, GLuint texture_v, 
                                gint width, gint height, gpointer data)
 {
@@ -1030,7 +1093,7 @@ gst_gl_display_textureChanged (GstGLDisplay * display, GstVideoFormat video_form
 
 /* Called by gstglbuffer */
 void 
-gst_gl_display_clearTexture (GstGLDisplay * display, guint texture, 
+gst_gl_display_clearTexture (GstGLDisplay* display, guint texture, 
                              guint texture_u, guint texture_v)
 {
     gst_gl_display_lock (display);
@@ -1076,6 +1139,23 @@ gst_gl_display_postRedisplay (GstGLDisplay* display)
 
 /* Called by gst_gl elements */
 void 
+gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height, 
+                           guint* fbo, guint* depthbuffer, guint* texture)
+{
+    gst_gl_display_lock (display);
+    display->requestedTextureFBOWidth = width;
+    display->requestedTextureFBOHeight = height;
+    gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_GENFBO, display);
+    g_cond_wait (display->cond_generateFBO, display->mutex);
+    *fbo = display->requestedFBO;
+    *depthbuffer = display->requestedDepthBuffer;
+    *texture = display->requestedTextureFBO;
+    gst_gl_display_unlock (display);
+}
+
+
+/* Called by gst_gl elements */
+void 
 gst_gl_display_set_windowId (GstGLDisplay* display, gulong winId)
 {
     static gint glheight = 0;
@@ -1088,7 +1168,7 @@ gst_gl_display_set_windowId (GstGLDisplay* display, gulong winId)
     if (g_hash_table_size (gst_gl_display_map) == 0)
     {
         g_thread_join (gst_gl_display_glutThread);
-        GST_DEBUG ("Glut thread joined when setting winId");
+        g_print ("Glut thread joined when setting winId\n");
         gst_gl_display_glutThread = NULL;
         g_async_queue_unref (gst_gl_display_messageQueue);
         g_hash_table_unref  (gst_gl_display_map);
index f45d4dc..fe5816e 100644 (file)
@@ -50,7 +50,8 @@ typedef enum {
     GST_GL_DISPLAY_ACTION_CHANGE,
     GST_GL_DISPLAY_ACTION_CLEAR,
     GST_GL_DISPLAY_ACTION_VIDEO,
-    GST_GL_DISPLAY_ACTION_REDISPLAY
+    GST_GL_DISPLAY_ACTION_REDISPLAY,
+    GST_GL_DISPLAY_ACTION_GENFBO
        
 } GstGLDisplayAction;
 
@@ -78,20 +79,21 @@ typedef gboolean (* CDCB) ( GLuint, GLuint, GLuint);
 struct _GstGLDisplay {
     GObject object;
 
-    GMutex *mutex;
+    GMutexmutex;
 
        GQueue* texturePool;
     
-    GCond *cond_make;
-    GCond *cond_fill;
-    GCond *cond_clear;
-    GCond *cond_video;
-
-    GCond *cond_create;
-    GCond *cond_destroy;
+    GCond* cond_make;
+    GCond* cond_fill;
+    GCond* cond_clear;
+    GCond* cond_video;
+    GCond* cond_generateFBO;
+
+    GCond* cond_create;
+    GCond* cond_destroy;
     gint glutWinId;
     gulong winId;
-    GString *title;
+    GStringtitle;
     gint win_xpos;
     gint win_ypos;
     gint glcontext_width;
@@ -111,6 +113,13 @@ struct _GstGLDisplay {
     GLuint graphicDepthBuffer;
     GLuint graphicTexture;
 
+    //filter frame buffer object (GL -> GL)
+    GLuint requestedFBO;
+    GLuint requestedDepthBuffer;
+    GLuint requestedTextureFBO;
+    GLuint requestedTextureFBOWidth;
+    GLuint requestedTextureFBOHeight;
+
     GLuint requestedTexture;
     GLuint requestedTexture_u;
     GLuint requestedTexture_v;
@@ -211,6 +220,8 @@ void gst_gl_display_clearTexture (GstGLDisplay* display, guint texture,
 void gst_gl_display_videoChanged (GstGLDisplay* display, GstVideoFormat video_format,
                                   gpointer data);
 gboolean gst_gl_display_postRedisplay (GstGLDisplay* display);
+void gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height, 
+                                guint* fbo, guint* depthbuffer, guint* texture);
 void gst_gl_display_set_windowId (GstGLDisplay* display, gulong winId);
 
 #endif
diff --git a/gst/gl/gstglfilter.c b/gst/gl/gstglfilter.c
new file mode 100644 (file)
index 0000000..0985841
--- /dev/null
@@ -0,0 +1,329 @@
+/* 
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstglfilter.h"
+
+#define GST_CAT_DEFAULT gst_gl_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+
+static GstStaticPadTemplate gst_gl_filter_src_pad_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
+    );
+
+static GstStaticPadTemplate gst_gl_filter_sink_pad_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
+    );
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_filter_debug, "glfilter", 0, "glfilter element");
+
+GST_BOILERPLATE_FULL (GstGLFilter, gst_gl_filter, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
+
+static void gst_gl_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_gl_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static void gst_gl_filter_reset (GstGLFilter * filter);
+static gboolean gst_gl_filter_start (GstBaseTransform * bt);
+static gboolean gst_gl_filter_stop (GstBaseTransform * bt);
+static gboolean gst_gl_filter_get_unit_size (GstBaseTransform * trans,
+    GstCaps * caps, guint * size);
+static GstFlowReturn gst_gl_filter_transform (GstBaseTransform * bt,
+    GstBuffer * inbuf, GstBuffer * outbuf);
+static GstFlowReturn gst_gl_filter_prepare_output_buffer (GstBaseTransform *
+    trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
+static gboolean gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
+    GstCaps * outcaps);
+static gboolean gst_gl_filter_do_transform (GstGLFilter * filter,
+    GstGLBuffer * inbuf, GstGLBuffer * outbuf);
+
+
+static void
+gst_gl_filter_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_gl_filter_src_pad_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_gl_filter_sink_pad_template));
+}
+
+static void
+gst_gl_filter_class_init (GstGLFilterClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_gl_filter_set_property;
+  gobject_class->get_property = gst_gl_filter_get_property;
+
+  GST_BASE_TRANSFORM_CLASS (klass)->transform = gst_gl_filter_transform;
+  GST_BASE_TRANSFORM_CLASS (klass)->start = gst_gl_filter_start;
+  GST_BASE_TRANSFORM_CLASS (klass)->stop = gst_gl_filter_stop;
+  GST_BASE_TRANSFORM_CLASS (klass)->set_caps = gst_gl_filter_set_caps;
+  GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = gst_gl_filter_get_unit_size;
+  GST_BASE_TRANSFORM_CLASS (klass)->prepare_output_buffer =
+      gst_gl_filter_prepare_output_buffer;
+}
+
+static void
+gst_gl_filter_init (GstGLFilter * filter, GstGLFilterClass * klass)
+{
+  //gst_element_create_all_pads (GST_ELEMENT (filter));
+
+  filter->sinkpad = gst_element_get_static_pad (GST_ELEMENT (filter), "sink");
+  filter->srcpad = gst_element_get_static_pad (GST_ELEMENT (filter), "src");
+
+  /*gst_gl_display_requestFBO
+
+  filter->fbo = */
+
+  gst_gl_filter_reset (filter);
+}
+
+static void
+gst_gl_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  //GstGLFilter *filter = GST_GL_FILTER (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_gl_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  //GstGLFilter *filter = GST_GL_FILTER (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_gl_filter_reset (GstGLFilter* filter)
+{
+    if (filter->display) 
+    {
+        g_object_unref (filter->display);
+        filter->display = NULL;
+    }
+    filter->video_format = GST_VIDEO_FORMAT_UNKNOWN;
+    filter->width = 0;
+    filter->height = 0;
+}
+
+static gboolean
+gst_gl_filter_start (GstBaseTransform* bt)
+{
+    return TRUE;
+}
+
+static gboolean
+gst_gl_filter_stop (GstBaseTransform* bt)
+{
+    GstGLFilter *filter = GST_GL_FILTER (bt);
+
+    gst_gl_filter_reset (filter);
+
+    return TRUE;
+}
+
+static gboolean
+gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
+    guint* size)
+{
+    gboolean ret;
+    GstVideoFormat video_format;
+    gint width;
+    gint height;
+
+    ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height);
+    if (ret) 
+        *size = gst_gl_buffer_format_get_size (video_format, width, height);
+
+    return TRUE;
+}
+
+static GstFlowReturn
+gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans,
+    GstBuffer* inbuf, gint size, GstCaps* caps, GstBuffer** buf)
+{
+    GstGLFilter* filter;
+    GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf);
+    GstGLBuffer* gl_outbuf;
+
+    filter = GST_GL_FILTER (trans);
+
+    if (filter->display == NULL)
+        filter->display = g_object_ref (gl_inbuf->display);
+
+    gl_outbuf = gst_gl_buffer_new_from_video_format (filter->display,
+            filter->video_format, 
+            filter->width, filter->height,
+            filter->width, filter->height);
+
+    *buf = GST_BUFFER (gl_outbuf);
+    gst_buffer_set_caps (*buf, caps);
+
+    g_print ("gstglfilter: gst_gl_filter_prepare_output_buffer\n");
+
+    return GST_FLOW_OK;
+}
+
+static gboolean
+gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
+    GstCaps * outcaps)
+{
+    GstGLFilter *filter;
+    gboolean ret;
+
+    filter = GST_GL_FILTER (bt);
+
+    ret = gst_gl_buffer_format_parse_caps (incaps, &filter->video_format,
+      &filter->width, &filter->height);
+
+    if (!ret) 
+    {
+        GST_DEBUG ("bad caps");
+        return FALSE;
+    }
+
+    GST_ERROR ("set_caps %d %d", filter->width, filter->height);
+
+    return ret;
+}
+
+static GstFlowReturn
+gst_gl_filter_transform (GstBaseTransform * bt, GstBuffer * inbuf,
+    GstBuffer * outbuf)
+{
+    GstGLFilter* filter;
+    GstGLBuffer* gl_inbuf = GST_GL_BUFFER (inbuf);
+    GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf);
+
+    filter = GST_GL_FILTER (bt);
+
+    g_print ("gstglfilter: gst_gl_filter_transform\n");
+
+    gst_gl_filter_do_transform (filter, gl_inbuf, gl_outbuf);
+
+    return GST_FLOW_OK;
+}
+
+static gboolean
+gst_gl_filter_do_transform (GstGLFilter * filter,
+    GstGLBuffer * inbuf, GstGLBuffer * outbuf)
+{
+  GstGLDisplay* display = inbuf->display;
+  GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter);
+
+  outbuf->texture = inbuf->texture;
+
+  /*unsigned int fbo;
+
+  gst_gl_display_lock (display);
+
+  glGenFramebuffersEXT (1, &fbo);
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
+
+  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
+      GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, outbuf->texture, 0);
+
+  glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
+  glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
+
+  g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
+      GL_FRAMEBUFFER_COMPLETE_EXT);
+
+  glViewport (0, 0, outbuf->width, outbuf->height);
+
+  glClearColor (0.3, 0.3, 0.3, 1.0);
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+
+  glDisable (GL_CULL_FACE);
+  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+  glColor4f (1, 1, 1, 1);
+
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glActiveTexture (GL_TEXTURE0);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, inbuf->texture);*/
+
+  filter_class->filter (filter, inbuf, outbuf);
+/*
+#if 0
+  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);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+  glColor4f (1, 0, 1, 1);
+  glBegin (GL_QUADS);
+
+  glNormal3f (0, 0, -1);
+
+  glTexCoord2f (inbuf->width, 0);
+  glVertex3f (0.9, -0.9, 0);
+  glTexCoord2f (0, 0);
+  glVertex3f (-1.0, -1.0, 0);
+  glTexCoord2f (0, inbuf->height);
+  glVertex3f (-1.0, 1.0, 0);
+  glTexCoord2f (inbuf->width, inbuf->height);
+  glVertex3f (1.0, 1.0, 0);
+  glEnd ();
+#endif
+
+  glFlush ();
+
+  glDeleteFramebuffersEXT (1, &fbo);
+
+  gst_gl_display_unlock (display);*/
+
+  return TRUE;
+}
diff --git a/gst/gl/gstglfilter.h b/gst/gl/gstglfilter.h
new file mode 100644 (file)
index 0000000..1549547
--- /dev/null
@@ -0,0 +1,64 @@
+/* 
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GST_GL_FILTER_H_
+#define _GST_GL_FILTER_H_
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/video/video.h>
+
+#include "gstglbuffer.h"
+
+#define GST_TYPE_GL_FILTER            (gst_gl_filter_get_type())
+#define GST_GL_FILTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER,GstGLFilter))
+#define GST_IS_GL_FILTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER))
+#define GST_GL_FILTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
+#define GST_IS_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER))
+#define GST_GL_FILTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
+typedef struct _GstGLFilter GstGLFilter;
+typedef struct _GstGLFilterClass GstGLFilterClass;
+
+typedef gboolean (*GstGLFilterProcessFunc) (GstGLFilter *filter,
+    GstGLBuffer *inbuf, GstGLBuffer *outbuf);
+
+struct _GstGLFilter
+{
+  GstBaseTransform base_transform;
+
+  GstPad *srcpad;
+  GstPad *sinkpad;
+
+  GstGLDisplay *display;
+  GstVideoFormat video_format;
+  int width;
+  int height;
+};
+
+struct _GstGLFilterClass
+{
+  GstBaseTransformClass base_transform_class;
+  GstGLFilterProcessFunc filter;
+};
+
+GType gst_gl_filter_get_type(void);
+
+#endif
+
diff --git a/gst/gl/gstglfiltercube.c b/gst/gl/gstglfiltercube.c
new file mode 100644 (file)
index 0000000..fcab2f2
--- /dev/null
@@ -0,0 +1,187 @@
+/* 
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstglfiltercube.h"
+
+#define GST_CAT_DEFAULT gst_gl_filter_cube_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details = 
+    GST_ELEMENT_DETAILS ("OpenGL cube filter",
+        "Filter/Effect",
+        "Put input texture on the cube faces",
+        "Julien Isorce <julien.isorce@gmail.com>");
+
+enum
+{
+  PROP_0
+};
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_filter_cube_debug, "glfiltercube", 0, "glfiltercube element");
+
+GST_BOILERPLATE_FULL (GstGLFilterCube, gst_gl_filter_cube, GstGLFilter,
+    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_filter (GstGLFilter * filter,
+    GstGLBuffer * inbuf, GstGLBuffer * outbuf);
+
+
+static void
+gst_gl_filter_cube_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details (element_class, &element_details);
+}
+
+static void
+gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_gl_filter_cube_set_property;
+  gobject_class->get_property = gst_gl_filter_cube_get_property;
+
+  GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_cube_filter;
+}
+
+static void
+gst_gl_filter_cube_init (GstGLFilterCube * filter,
+    GstGLFilterCubeClass * klass)
+{
+}
+
+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) {
+    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) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_gl_filter_cube_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
+    GstGLBuffer * outbuf)
+{
+  GstGLFilterCube* cube = GST_GL_FILTER_CUBE(filter);
+
+  g_print ("gstglfiltercube: gst_gl_filter_cube_filter\n");
+  /*int i, j;
+  double *vertex_x, *vertex_y;
+
+  glDisable (GL_CULL_FACE);
+  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+  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);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+  glColor4f (1, 0, 1, 1);
+
+
+
+    glMatrixMode (GL_COLOR);
+    glLoadMatrixd (matrix);
+    glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, (1 - GAIN) / 2);
+    glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, (1 - GAIN) / 2);
+    glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, (1 - GAIN) / 2);
+  }
+
+  
+
+#define N 10
+#define SCALE (1.0/N)
+#define NOISE() (0.1*SCALE*g_random_double_range(-1,1))
+  vertex_x = malloc (sizeof (double) * (N + 1) * (N + 1));
+  vertex_y = malloc (sizeof (double) * (N + 1) * (N + 1));
+  for (j = 0; j < N + 1; j++) {
+    for (i = 0; i < N + 1; i++) {
+      vertex_x[j * (N + 1) + i] = i * SCALE + NOISE ();
+      vertex_y[j * (N + 1) + i] = j * SCALE + NOISE ();
+    }
+  }
+  for (j = 0; j < N; j++) {
+    for (i = 0; i < N; i++) {
+      glBegin (GL_QUADS);
+      glNormal3f (0, 0, -1);
+      glTexCoord2f (i * SCALE, j * SCALE);
+      glVertex3f (vertex_x[j * (N + 1) + i], vertex_y[j * (N + 1) + i], 0);
+      glTexCoord2f ((i + 1) * SCALE, j * SCALE);
+      glVertex3f (vertex_x[j * (N + 1) + (i + 1)],
+          vertex_y[j * (N + 1) + (i + 1)], 0);
+      glTexCoord2f ((i + 1) * SCALE, (j + 1) * SCALE);
+      glVertex3f (vertex_x[(j + 1) * (N + 1) + (i + 1)],
+          vertex_y[(j + 1) * (N + 1) + (i + 1)], 0);
+      glTexCoord2f (i * SCALE, (j + 1) * SCALE);
+      glVertex3f (vertex_x[(j + 1) * (N + 1) + i],
+          vertex_y[(j + 1) * (N + 1) + i], 0);
+      glEnd ();
+    }
+  }
+  free (vertex_x);
+  free (vertex_y);
+
+
+  glFlush ();
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  glMatrixMode (GL_TEXTURE);
+  glLoadIdentity ();
+  glMatrixMode (GL_COLOR);
+  glLoadIdentity ();
+  glPixelTransferf (GL_POST_COLOR_MATRIX_RED_SCALE, 1.0);
+  glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
+  glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
+  glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);*/
+
+  return TRUE;
+}
diff --git a/gst/gl/gstglfiltercube.h b/gst/gl/gstglfiltercube.h
new file mode 100644 (file)
index 0000000..37fca09
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GST_GL_FILTERCUBE_H_
+#define _GST_GL_FILTERCUBE_H_
+
+#include "gstglfilter.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;
+
+};
+
+struct _GstGLFilterCubeClass
+{
+  GstGLFilterClass filter_class;
+};
+
+GType gst_gl_glfiltercube_get_type (void);
+
+G_END_DECLS
+
+#endif /* _GST_GLFILTERCUBE_H_ */
index 4b4015e..d487b29 100644 (file)
@@ -199,7 +199,8 @@ gst_gl_graphicmaker_get_property (GObject* object, guint prop_id,
 static void
 gst_gl_graphicmaker_reset (GstGLGraphicmaker* graphicmaker)
 { 
-    if (graphicmaker->display) {
+    if (graphicmaker->display) 
+    {
         g_object_unref (graphicmaker->display);
         graphicmaker->display = NULL;
     }
@@ -322,7 +323,8 @@ gst_gl_graphicmaker_set_caps (GstBaseTransform* bt, GstCaps* incaps,
     ret = gst_video_format_parse_caps (incaps, &graphicmaker->video_format,
         &graphicmaker->width, &graphicmaker->height);
 
-    if (!ret) {
+    if (!ret) 
+    {
       GST_DEBUG ("bad caps");
       return FALSE;
     }
index 1b8ec7e..906ecaa 100644 (file)
@@ -280,55 +280,59 @@ gst_glimage_sink_start (GstBaseSink * bsink)
 static gboolean
 gst_glimage_sink_stop (GstBaseSink * bsink)
 {
-  GstGLImageSink *glimage_sink;
+    GstGLImageSink *glimage_sink;
 
-  GST_DEBUG ("stop");
+    GST_DEBUG ("stop");
 
-  glimage_sink = GST_GLIMAGE_SINK (bsink);
+    glimage_sink = GST_GLIMAGE_SINK (bsink);
 
-  if (glimage_sink->stored_buffer) {
-    gst_buffer_unref (glimage_sink->stored_buffer);
-    glimage_sink->stored_buffer = NULL;
-  }
-  if (glimage_sink->display) {
-       gst_gl_display_setVisibleWindow (glimage_sink->display, FALSE);
-    g_object_unref (glimage_sink->display);
-    glimage_sink->display = NULL;
-  }
+    if (glimage_sink->stored_buffer) 
+    {
+        gst_buffer_unref (glimage_sink->stored_buffer);
+        glimage_sink->stored_buffer = NULL;
+    }
+    if (glimage_sink->display) 
+    {
+        gst_gl_display_setVisibleWindow (glimage_sink->display, FALSE);
+        g_object_unref (glimage_sink->display);
+        glimage_sink->display = NULL;
+    }
 
-  return TRUE;
+    return TRUE;
 }
 
 static gboolean
 gst_glimage_sink_unlock (GstBaseSink * bsink)
 {
-  //GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (bsink);
+    //GstGLImageSink* glimage_sink = GST_GLIMAGE_SINK (bsink);
 
-  GST_DEBUG ("unlock");
+    GST_DEBUG ("unlock");
 
-  return TRUE;
+    return TRUE;
 }
 
 static void
 gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
     GstClockTime * start, GstClockTime * end)
 {
-  GstGLImageSink *glimagesink;
+    GstGLImageSink *glimagesink;
 
-  glimagesink = GST_GLIMAGE_SINK (bsink);
+    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 (glimagesink->fps_n > 0) {
-        *end = *start +
-            gst_util_uint64_scale_int (GST_SECOND, glimagesink->fps_d,
-            glimagesink->fps_n);
-      }
+    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 (glimagesink->fps_n > 0) {
+            *end = *start +
+                gst_util_uint64_scale_int (GST_SECOND, glimagesink->fps_d,
+                glimagesink->fps_n);
+            }
+        }
     }
-  }
 }
 
 
index f19fb53..c588ba2 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 #include "gstglgraphicmaker.h"
+#include "gstglfiltercube.h"
 #include "gstglvideomaker.h"
 #include "gstglimagesink.h"
 
@@ -34,17 +35,22 @@ static gboolean
 plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (gst_gl_gstgl_debug, "gstopengl", 0, "gstopengl");
-  if (!gst_element_register (plugin, "glvideomaker",
-          GST_RANK_NONE, GST_TYPE_GL_VIDEOMAKER)) {
-    return FALSE;
-  }
   
   if (!gst_element_register (plugin, "glgraphicmaker",
           GST_RANK_NONE, GST_TYPE_GL_GRAPHICMAKER)) {
     return FALSE;
   }
 
+  if (!gst_element_register (plugin, "glfiltercube",
+          GST_RANK_NONE, GST_TYPE_GL_FILTER_CUBE)) {
+    return FALSE;
+  }
+
+  if (!gst_element_register (plugin, "glvideomaker",
+          GST_RANK_NONE, GST_TYPE_GL_VIDEOMAKER)) {
+    return FALSE;
+  }
+
   if (!gst_element_register (plugin, "glimagesink",
           GST_RANK_NONE, GST_TYPE_GLIMAGE_SINK)) {
     return FALSE;