diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index e762c199b6..375f15476f 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -4,13 +4,15 @@ lib_LTLIBRARIES = libgstgl-@GST_MAJORMINOR@.la libgstgl_@GST_MAJORMINOR@_la_SOURCES = \ glextensions.c \ gstglbuffer.c \ - gstgldisplay.c + gstgldisplay.c \ + gstglfilter.c libgstgl_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/gl libgstgl_@GST_MAJORMINOR@include_HEADERS = \ glextensions.h \ gstglbuffer.h \ - gstgldisplay.h + gstgldisplay.h \ + gstglfilter.h libgstgl_@GST_MAJORMINOR@_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) \ diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c new file mode 100644 index 0000000000..a2175affd6 --- /dev/null +++ b/gst-libs/gst/gl/gstglfilter.c @@ -0,0 +1,323 @@ +/* + * GStreamer + * Copyright (C) 2007 David Schleef + * + * 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 +#include +#include "glextensions.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_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->format = GST_GL_BUFFER_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; + GstGLBufferFormat format; + int width; + int height; + + ret = gst_gl_buffer_format_parse_caps (caps, &format, &width, &height); + if (ret) { + *size = gst_gl_buffer_format_get_size (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 = gl_inbuf->display; + } + + gl_outbuf = gst_gl_buffer_new_with_format (filter->display, + filter->format, filter->width, filter->height); + + *buf = GST_BUFFER (gl_outbuf); + gst_buffer_set_caps (*buf, caps); + + 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->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); + + 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; + unsigned int fbo; + + filter_class = GST_GL_FILTER_GET_CLASS (filter); + + 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-libs/gst/gl/gstglfilter.h b/gst-libs/gst/gl/gstglfilter.h new file mode 100644 index 0000000000..513d6e9b90 --- /dev/null +++ b/gst-libs/gst/gl/gstglfilter.h @@ -0,0 +1,65 @@ +/* + * GStreamer + * Copyright (C) 2007 David Schleef + * + * 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 +#include +#include +#include + +#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; + + /* < private > */ + + GstGLDisplay *display; + GstGLBufferFormat format; + int width; + int height; +}; + +struct _GstGLFilterClass +{ + GstBaseTransformClass base_transform_class; + GstGLFilterProcessFunc filter; +}; + +GType gst_gl_filter_get_type(void); + +#endif +