From 23e47de3324577cc2cb76a11f21ba80cceac14fc Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 2 Jul 2003 05:22:47 +0000 Subject: [PATCH] GstVideofilter abstract class for video filters Original commit message from CVS: GstVideofilter abstract class for video filters --- gst/videofilter/Makefile.am | 25 ++ gst/videofilter/gstvideofilter.c | 584 +++++++++++++++++++++++++++++++++++++ gst/videofilter/gstvideofilter.h | 109 +++++++ gst/videofilter/gstvideotemplate.c | 272 +++++++++++++++++ gst/videofilter/gstvideotemplate.h | 61 ++++ gst/videofilter/make_filter | 42 +++ 6 files changed, 1093 insertions(+) create mode 100644 gst/videofilter/Makefile.am create mode 100644 gst/videofilter/gstvideofilter.c create mode 100644 gst/videofilter/gstvideofilter.h create mode 100644 gst/videofilter/gstvideotemplate.c create mode 100644 gst/videofilter/gstvideotemplate.h create mode 100755 gst/videofilter/make_filter diff --git a/gst/videofilter/Makefile.am b/gst/videofilter/Makefile.am new file mode 100644 index 0000000..0fd9bfd --- /dev/null +++ b/gst/videofilter/Makefile.am @@ -0,0 +1,25 @@ +plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@ + +plugin_LTLIBRARIES = libgstvideofilter.la +noinst_LTLIBRARIES = libgstvideoexample.la + +noinst_HEADERS = gstvideofilter.h gstvideoexample.h + +EXTRA_DIST = gstvideotemplate.c gstvideotemplate.h make_filter + +libgstvideofilter_la_SOURCES = gstvideofilter.c +libgstvideofilter_la_CFLAGS = $(GST_CFLAGS) +libgstvideofilter_la_LIBADD = +libgstvideofilter_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +libgstvideoexample_la_SOURCES = gstvideoexample.c +libgstvideoexample_la_CFLAGS = $(GST_CFLAGS) +libgstvideoexample_la_LIBADD = +libgstvideoexample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + + +# no, this doesn't work if $(srcdir) != (builddir) +gstvideoexample.c gstvideoexample.h: $(srcdir)/make_filter \ + $(srcdir)/gstvideotemplate.c $(srcdir)/gstvideotemplate.h + $(srcdir)/make_filter Videoexample + diff --git a/gst/videofilter/gstvideofilter.c b/gst/videofilter/gstvideofilter.c new file mode 100644 index 0000000..7f8f10a --- /dev/null +++ b/gst/videofilter/gstvideofilter.c @@ -0,0 +1,584 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> 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. + */ + + +/*#define DEBUG_ENABLED */ +#include + + + +#if 0 +/* elementfactory information */ +static GstElementDetails videofilter_details = { + "Video scaler", + "Filter/Video", + "LGPL", + "Resizes video", + VERSION, + "David Schleef ", + "(C) 2003", +}; +#endif + +/* GstVideofilter signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_METHOD, + /* FILL ME */ +}; + +static void gst_videofilter_class_init (GstVideofilterClass *klass); +static void gst_videofilter_init (GstVideofilter *videofilter); + +static void gst_videofilter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void gst_videofilter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + +static void gst_videofilter_chain (GstPad *pad, GstBuffer *buf); +GstCaps * gst_videofilter_class_get_capslist(GstVideofilterClass *klass); +static void gst_videofilter_setup(GstVideofilter *videofilter); + +static GstElementClass *parent_class = NULL; + +GType +gst_videofilter_get_type (void) +{ + static GType videofilter_type = 0; + + if (!videofilter_type) { + static const GTypeInfo videofilter_info = { + sizeof(GstVideofilterClass), NULL, + NULL, + (GClassInitFunc)gst_videofilter_class_init, + NULL, + NULL, + sizeof(GstVideofilter), + 0, + (GInstanceInitFunc)gst_videofilter_init, + }; + videofilter_type = g_type_register_static(GST_TYPE_ELEMENT, + "GstVideofilter", &videofilter_info, G_TYPE_FLAG_ABSTRACT); + } + return videofilter_type; +} + +static void +gst_videofilter_class_init (GstVideofilterClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_videofilter_set_property; + gobject_class->get_property = gst_videofilter_get_property; + + klass->formats = g_ptr_array_new(); +} + +#if 0 +static GstPadTemplate * +gst_videofilter_src_template_factory(void) +{ + static GstPadTemplate *templ = NULL; + + if(!templ){ + GstCaps *caps = GST_CAPS_NEW("src","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(caps, gst_videofilter_get_capslist ()); + + templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + } + return templ; +} + +static GstPadTemplate * +gst_videofilter_sink_template_factory(void) +{ + static GstPadTemplate *templ = NULL; + + if(!templ){ + GstCaps *caps = GST_CAPS_NEW("sink","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(caps, gst_videofilter_get_capslist ()); + + templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + } + return templ; +} +#endif + +static GstCaps *gst_videofilter_format_get_caps(GstVideofilterFormat *format) +{ + unsigned int fourcc; + GstCaps *caps; + + if(format->filter_func==NULL) + return NULL; + + fourcc = GST_MAKE_FOURCC(format->fourcc[0],format->fourcc[1],format->fourcc[2],format->fourcc[3]); + + if(format->bpp){ + caps = GST_CAPS_NEW ("videoflip", "video/raw", + "format", GST_PROPS_FOURCC (fourcc), + "depth", GST_PROPS_INT(format->bpp), + "bpp", GST_PROPS_INT(format->depth), + "endianness", GST_PROPS_INT(format->endianness), + "red_mask", GST_PROPS_INT(format->red_mask), + "green_mask", GST_PROPS_INT(format->green_mask), + "blue_mask", GST_PROPS_INT(format->blue_mask)); + }else{ + caps = GST_CAPS_NEW ("videoflip", "video/raw", + "format", GST_PROPS_FOURCC (fourcc)); + } + + return caps; +} + +GstCaps * gst_videofilter_class_get_capslist(GstVideofilterClass *klass) +{ + static GstCaps *capslist = NULL; + GstCaps *caps; + int i; + + if (capslist){ + gst_caps_ref(capslist); + return capslist; + } + + for(i=0;iformats->len;i++){ + caps = gst_videofilter_format_get_caps(g_ptr_array_index(klass->formats,i)); + capslist = gst_caps_append(capslist, caps); + } + + gst_caps_ref(capslist); + return capslist; +} + +static GstCaps * +gst_videofilter_sink_getcaps (GstPad *pad, GstCaps *caps) +{ + GstVideofilter *videofilter; + GstVideofilterClass *klass; + GstCaps *capslist = NULL; + GstCaps *peercaps; + GstCaps *sizecaps; + int i; + + GST_DEBUG("gst_videofilter_sink_getcaps"); + videofilter = GST_VIDEOFILTER (gst_pad_get_parent (pad)); + + klass = GST_VIDEOFILTER_CLASS(G_OBJECT_GET_CLASS(videofilter)); + + /* get list of peer's caps */ + peercaps = gst_pad_get_allowed_caps (videofilter->srcpad); + g_print("peercaps: %s\n", gst_caps_to_string(peercaps)); + + /* FIXME videofilter doesn't allow passthru of video formats it + * doesn't understand. */ + /* Look through our list of caps and find those that match with + * the peer's formats. Create a list of them. */ + /* FIXME optimize if peercaps == NULL */ + for(i=0;iformats->len;i++){ + GstCaps *icaps; + GstCaps *fromcaps = gst_videofilter_format_get_caps(g_ptr_array_index( + klass->formats,i)); + + g_print("testing caps: %s\n", gst_caps_to_string(fromcaps)); + + icaps = gst_caps_intersect(fromcaps, peercaps); + //if(gst_caps_is_always_compatible(fromcaps, peercaps)){ + if(icaps != NULL){ + capslist = gst_caps_append(capslist, fromcaps); + g_print("(yes)\n"); + }else{ + g_print("(no)\n"); + } + //gst_caps_unref (fromcaps); + if(icaps) gst_caps_unref (icaps); + } + gst_caps_unref (peercaps); + + sizecaps = GST_CAPS_NEW("videofilter_size","video/raw", + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + caps = gst_caps_intersect(capslist, sizecaps); + gst_caps_unref (sizecaps); + + g_print("getcaps: %s\n",gst_caps_to_string(caps)); + + return caps; +} + +static GstPadLinkReturn +gst_videofilter_src_link (GstPad *pad, GstCaps *caps) +{ + GstVideofilter *videofilter; + GstPadLinkReturn ret; + GstCaps *peercaps; + + GST_DEBUG("gst_videofilter_src_link"); + videofilter = GST_VIDEOFILTER (gst_pad_get_parent (pad)); + + if (!GST_CAPS_IS_FIXED (caps)) { + return GST_PAD_LINK_DELAYED; + } + + gst_caps_debug(caps,"ack"); + + videofilter->format = gst_videofilter_find_format_by_caps (videofilter,caps); + g_return_val_if_fail(videofilter->format, GST_PAD_LINK_REFUSED); + + gst_caps_get_int (caps, "width", &videofilter->to_width); + gst_caps_get_int (caps, "height", &videofilter->to_height); + + GST_DEBUG("width %d height %d",videofilter->to_width,videofilter->to_height); + + peercaps = gst_caps_copy(caps); + + gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT)); + gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT)); + + ret = gst_pad_try_set_caps (videofilter->srcpad, peercaps); + + gst_caps_unref(peercaps); + + if(ret==GST_PAD_LINK_OK){ + caps = gst_pad_get_caps (videofilter->srcpad); + + gst_caps_get_int (caps, "width", &videofilter->from_width); + gst_caps_get_int (caps, "height", &videofilter->from_height); + //gst_videofilter_setup(videofilter); + } + + return ret; +} + +static GstPadLinkReturn +gst_videofilter_sink_link (GstPad *pad, GstCaps *caps) +{ + GstVideofilter *videofilter; + GstPadLinkReturn ret; + GstCaps *peercaps; + + GST_DEBUG("gst_videofilter_sink_link"); + videofilter = GST_VIDEOFILTER (gst_pad_get_parent (pad)); + + if (!GST_CAPS_IS_FIXED (caps)) { + return GST_PAD_LINK_DELAYED; + } + + videofilter->format = gst_videofilter_find_format_by_caps (videofilter,caps); + g_print("sink_link: %s\n",gst_caps_to_string(caps)); + g_return_val_if_fail(videofilter->format, GST_PAD_LINK_REFUSED); + + gst_caps_get_int (caps, "width", &videofilter->from_width); + gst_caps_get_int (caps, "height", &videofilter->from_height); + + gst_videofilter_setup(videofilter); + + peercaps = gst_caps_copy(caps); + + gst_caps_set(peercaps, "width", GST_PROPS_INT (videofilter->to_width)); + gst_caps_set(peercaps, "height", GST_PROPS_INT (videofilter->to_height)); + + ret = gst_pad_try_set_caps (videofilter->srcpad, peercaps); + + gst_caps_unref(peercaps); + + if(ret==GST_PAD_LINK_OK || ret==GST_PAD_LINK_DONE){ + caps = gst_pad_get_caps (videofilter->srcpad); + + //gst_caps_get_int (caps, "width", &videofilter->to_width); + //gst_caps_get_int (caps, "height", &videofilter->to_height); + //gst_videofilter_setup(videofilter); + } + + g_print("returning %d\n",ret); + + return ret; +} + +static void +gst_videofilter_init (GstVideofilter *videofilter) +{ + GST_DEBUG("gst_videofilter_init"); + +} + +void +gst_videofilter_postinit (GstVideofilter *videofilter) +{ + /* sinkpad and srcpad should be inited by subclass */ + + /* FIXME */ + //videofilter->sinkpad = NULL; + gst_element_add_pad(GST_ELEMENT(videofilter),videofilter->sinkpad); + gst_pad_set_chain_function(videofilter->sinkpad,gst_videofilter_chain); + gst_pad_set_link_function(videofilter->sinkpad,gst_videofilter_sink_link); + gst_pad_set_getcaps_function(videofilter->sinkpad,gst_videofilter_sink_getcaps); + + /* FIXME */ + //videofilter->srcpad = NULL; + gst_element_add_pad(GST_ELEMENT(videofilter),videofilter->srcpad); + gst_pad_set_link_function(videofilter->srcpad,gst_videofilter_src_link); + //gst_pad_set_getcaps_function(videofilter->srcpad,gst_videofilter_getcaps); + + videofilter->inited = FALSE; +} + + +static void +gst_videofilter_chain (GstPad *pad, GstBuffer *buf) +{ + GstVideofilter *videofilter; + guchar *data; + gulong size; + GstBuffer *outbuf; + + GST_DEBUG ("gst_videofilter_chain"); + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + videofilter = GST_VIDEOFILTER (gst_pad_get_parent (pad)); + //g_return_if_fail (videofilter->inited); + + data = GST_BUFFER_DATA(buf); + size = GST_BUFFER_SIZE(buf); + + if(videofilter->passthru){ + gst_pad_push(videofilter->srcpad, buf); + return; + } + + GST_DEBUG ("gst_videofilter_chain: got buffer of %ld bytes in '%s'",size, + GST_OBJECT_NAME (videofilter)); + + GST_DEBUG("size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d", + size, + videofilter->from_width, videofilter->from_height, + videofilter->to_width, videofilter->to_height, + size, videofilter->from_buf_size, + videofilter->to_buf_size); + + g_return_if_fail (size == videofilter->from_buf_size); + + outbuf = gst_buffer_new(); + /* FIXME: handle bufferpools */ + GST_BUFFER_SIZE(outbuf) = videofilter->to_buf_size; + GST_BUFFER_DATA(outbuf) = g_malloc (videofilter->to_buf_size); + GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf); + + g_return_if_fail(videofilter->format); + GST_DEBUG ("format %s",videofilter->format->fourcc); + + videofilter->in_buf = buf; + videofilter->out_buf = outbuf; + + videofilter->format->filter_func(videofilter, GST_BUFFER_DATA(outbuf), data); + + GST_DEBUG ("gst_videofilter_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf), + GST_OBJECT_NAME (videofilter)); + + gst_pad_push(videofilter->srcpad, outbuf); + + gst_buffer_unref(buf); +} + +static void +gst_videofilter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstVideofilter *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOFILTER(object)); + src = GST_VIDEOFILTER(object); + + GST_DEBUG("gst_videofilter_set_property"); + switch (prop_id) { + default: + break; + } +} + +static void +gst_videofilter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstVideofilter *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOFILTER(object)); + src = GST_VIDEOFILTER(object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +int gst_videofilter_get_input_width(GstVideofilter *videofilter) +{ + g_return_val_if_fail(GST_IS_VIDEOFILTER(videofilter),0); + + return videofilter->from_width; +} + +int gst_videofilter_get_input_height(GstVideofilter *videofilter) +{ + g_return_val_if_fail(GST_IS_VIDEOFILTER(videofilter),0); + + return videofilter->from_height; +} + +void gst_videofilter_set_output_size(GstVideofilter *videofilter, + int width, int height) +{ + int ret; + GstCaps *srccaps; + + g_return_if_fail(GST_IS_VIDEOFILTER(videofilter)); + + videofilter->to_width = width; + videofilter->to_height = height; + + videofilter->to_buf_size = (videofilter->to_width * videofilter->to_height + * videofilter->format->depth)/8; + + srccaps = gst_caps_copy(gst_pad_get_caps(videofilter->srcpad)); + + gst_caps_set(srccaps, "width", GST_PROPS_INT (videofilter->to_width)); + gst_caps_set(srccaps, "height", GST_PROPS_INT (videofilter->to_height)); + + ret = gst_pad_try_set_caps (videofilter->srcpad, srccaps); + + g_print("try_set_caps() returned %d\n", ret); + +} + +static void gst_videofilter_setup(GstVideofilter *videofilter) +{ + GstVideofilterClass *klass; + + klass = GST_VIDEOFILTER_CLASS(G_OBJECT_GET_CLASS(videofilter)); + + if(klass->setup){ + klass->setup(videofilter); + } + + if(videofilter->to_width == 0){ + videofilter->to_width = videofilter->from_width; + } + if(videofilter->to_height == 0){ + videofilter->to_height = videofilter->from_height; + } + + g_return_if_fail(videofilter->format != NULL); + g_return_if_fail(videofilter->from_width > 0); + g_return_if_fail(videofilter->from_height > 0); + g_return_if_fail(videofilter->to_width > 0); + g_return_if_fail(videofilter->to_height > 0); + + videofilter->from_buf_size = (videofilter->from_width * videofilter->from_height * + videofilter->format->depth) / 8; + videofilter->to_buf_size = (videofilter->to_width * videofilter->to_height * + videofilter->format->depth) / 8; + + videofilter->inited = TRUE; +} + +GstVideofilterFormat *gst_videofilter_find_format_by_caps(GstVideofilter *videofilter, + GstCaps *caps) +{ + int i; + GstCaps *c; + GstVideofilterClass *klass; + GstVideofilterFormat *format; + + klass = GST_VIDEOFILTER_CLASS(G_OBJECT_GET_CLASS(videofilter)); + + g_return_val_if_fail(caps != NULL, NULL); + + for(i=0;iformats->len;i++){ + format = g_ptr_array_index(klass->formats,i); + c = gst_videofilter_format_get_caps(format); + + if(c){ + if(gst_caps_is_always_compatible(caps, c)){ + gst_caps_unref(c); + return format; + } + } + gst_caps_unref(c); + } + + return NULL; +} + +void gst_videofilter_class_add_format(GstVideofilterClass *videofilterclass, + GstVideofilterFormat *format) +{ + g_ptr_array_add(videofilterclass->formats, format); +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ +#if 0 + GstElementFactory *factory; + + /* create an elementfactory for the videofilter element */ + factory = gst_element_factory_new("videofilter",GST_TYPE_VIDEOFILTER, + &videofilter_details); + g_return_val_if_fail(factory != NULL, FALSE); + + /* FIXME: we need to init the class before we can call the + * pad template factories */ + gst_element_factory_add_pad_template (factory, + GST_PAD_TEMPLATE_GET (gst_videofilter_sink_template_factory)); + gst_element_factory_add_pad_template (factory, + GST_PAD_TEMPLATE_GET (gst_videofilter_src_template_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); +#endif + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "gstvideofilter", + plugin_init +}; diff --git a/gst/videofilter/gstvideofilter.h b/gst/videofilter/gstvideofilter.h new file mode 100644 index 0000000..2b7d9f9 --- /dev/null +++ b/gst/videofilter/gstvideofilter.h @@ -0,0 +1,109 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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_VIDEOFILTER_H__ +#define __GST_VIDEOFILTER_H__ + + +#include +#include + + +G_BEGIN_DECLS + +typedef struct _GstVideofilter GstVideofilter; +typedef struct _GstVideofilterClass GstVideofilterClass; + +typedef void (*GstVideofilterFilterFunc)(GstVideofilter *filter, + void *out_data, void *in_data); + +typedef void (*GstVideofilterSetupFunc)(GstVideofilter *filter); + +typedef struct _GstVideofilterFormat GstVideofilterFormat; +struct _GstVideofilterFormat { + char *fourcc; + int depth; + GstVideofilterFilterFunc filter_func; + int bpp; + unsigned int endianness; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; +}; + +#define GST_TYPE_VIDEOFILTER \ + (gst_videofilter_get_type()) +#define GST_VIDEOFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEOFILTER,GstVideofilter)) +#define GST_VIDEOFILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEOFILTER,GstVideofilterClass)) +#define GST_IS_VIDEOFILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEOFILTER)) +#define GST_IS_VIDEOFILTER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEOFILTER)) + +struct _GstVideofilter { + GstElement element; + + GstPad *sinkpad,*srcpad; + + /* video state */ + gboolean inited; + GstVideofilterFormat *format; + gint to_width; + gint to_height; + gint from_width; + gint from_height; + gboolean passthru; + + /* private */ + gint from_buf_size; + gint to_buf_size; + + GstBuffer *in_buf; + GstBuffer *out_buf; +}; + +struct _GstVideofilterClass { + GstElementClass parent_class; + + GPtrArray *formats; + GstVideofilterSetupFunc setup; +}; + +GType gst_videofilter_get_type(void); + +int gst_videofilter_get_input_width(GstVideofilter *videofilter); +int gst_videofilter_get_input_height(GstVideofilter *videofilter); +void gst_videofilter_set_output_size(GstVideofilter *videofilter, + int width, int height); +GstVideofilterFormat *gst_videofilter_find_format_by_caps(GstVideofilter *filter, + GstCaps *caps); +GstCaps *gst_videofilter_class_get_capslist(GstVideofilterClass *videofilterclass); + +void gst_videofilter_postinit(GstVideofilter *videofilter); + +void gst_videofilter_class_add_format(GstVideofilterClass *videofilterclass, + GstVideofilterFormat *format); + +G_END_DECLS + +#endif /* __GST_VIDEOFILTER_H__ */ + diff --git a/gst/videofilter/gstvideotemplate.c b/gst/videofilter/gstvideotemplate.c new file mode 100644 index 0000000..32ae8ba --- /dev/null +++ b/gst/videofilter/gstvideotemplate.c @@ -0,0 +1,272 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> 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. + */ + + +/*#define DEBUG_ENABLED */ +#include + + +/* elementfactory information */ +static GstElementDetails videotemplate_details = { + "Video Filter Template", + "Filter/Video", + "LGPL", + "Template for a video filter", + VERSION, + "David Schleef ", + "(C) 2003", +}; + +/* GstVideotemplate signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + +static void gst_videotemplate_class_init (GstVideotemplateClass *klass); +static void gst_videotemplate_init (GstVideotemplate *videotemplate); + +static void gst_videotemplate_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void gst_videotemplate_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + +static void gst_videotemplate_planar411(GstVideofilter *videofilter, void *dest, void *src); +static void gst_videotemplate_setup(GstVideofilter *videofilter); + +static GstVideotemplateClass *this_class = NULL; +static GstVideofilterClass *parent_class = NULL; +static GstElementClass *element_class = NULL; + +GType +gst_videotemplate_get_type (void) +{ + static GType videotemplate_type = 0; + + if (!videotemplate_type) { + static const GTypeInfo videotemplate_info = { + sizeof(GstVideotemplateClass), NULL, + NULL, + (GClassInitFunc)gst_videotemplate_class_init, + NULL, + NULL, + sizeof(GstVideotemplate), + 0, + (GInstanceInitFunc)gst_videotemplate_init, + }; + videotemplate_type = g_type_register_static(GST_TYPE_VIDEOFILTER, "GstVideotemplate", &videotemplate_info, 0); + } + return videotemplate_type; +} + +static GstVideofilterFormat gst_videotemplate_formats[] = { + { "I420", 12, gst_videotemplate_planar411, }, +}; + +static void +gst_videotemplate_class_init (GstVideotemplateClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstVideofilterClass *gstvideofilter_class; + int i; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + gstvideofilter_class = (GstVideofilterClass *)klass; + +#if 0 + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_METHOD, + g_param_spec_enum("method","method","method", + GST_TYPE_VIDEOTEMPLATE_METHOD, GST_VIDEOTEMPLATE_METHOD_90R, + G_PARAM_READWRITE)); +#endif + + this_class = klass; + parent_class = g_type_class_ref(GST_TYPE_VIDEOFILTER); + element_class = g_type_class_ref(GST_TYPE_ELEMENT); + + gobject_class->set_property = gst_videotemplate_set_property; + gobject_class->get_property = gst_videotemplate_get_property; + + gstvideofilter_class->setup = gst_videotemplate_setup; + + for(i=0;isinkpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (gst_videotemplate_sink_template_factory), + "sink"); + + videofilter->srcpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (gst_videotemplate_src_template_factory), + "src"); + + gst_videofilter_postinit(GST_VIDEOFILTER(videotemplate)); +} + +static void +gst_videotemplate_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstVideotemplate *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOTEMPLATE(object)); + src = GST_VIDEOTEMPLATE(object); + + GST_DEBUG("gst_videotemplate_set_property"); + switch (prop_id) { +#if 0 + case ARG_METHOD: + src->method = g_value_get_enum (value); + break; +#endif + default: + break; + } +} + +static void +gst_videotemplate_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstVideotemplate *src; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_VIDEOTEMPLATE(object)); + src = GST_VIDEOTEMPLATE(object); + + switch (prop_id) { +#if 0 + case ARG_METHOD: + g_value_set_enum (value, src->method); + break; +#endif + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + if(!gst_library_load("gstvideofilter")) + return FALSE; + + /* create an elementfactory for the videotemplate element */ + factory = gst_element_factory_new("videotemplate",GST_TYPE_VIDEOTEMPLATE, + &videotemplate_details); + g_return_val_if_fail(factory != NULL, FALSE); + + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videotemplate_sink_template_factory)); + gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videotemplate_src_template_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videotemplate", + plugin_init +}; + +static void gst_videotemplate_setup(GstVideofilter *videofilter) +{ + GstVideotemplate *videotemplate; + + g_return_if_fail(GST_IS_VIDEOTEMPLATE(videofilter)); + videotemplate = GST_VIDEOTEMPLATE(videofilter); + + /* if any setup needs to be done, do it here */ + +} + +static void gst_videotemplate_planar411(GstVideofilter *videofilter, + void *dest, void *src) +{ + GstVideotemplate *videotemplate; + + g_return_if_fail(GST_IS_VIDEOTEMPLATE(videofilter)); + videotemplate = GST_VIDEOTEMPLATE(videofilter); + + /* do something interesting here */ +} + diff --git a/gst/videofilter/gstvideotemplate.h b/gst/videofilter/gstvideotemplate.h new file mode 100644 index 0000000..625ac1f --- /dev/null +++ b/gst/videofilter/gstvideotemplate.h @@ -0,0 +1,61 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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_VIDEOTEMPLATE_H__ +#define __GST_VIDEOTEMPLATE_H__ + + +#include +#include + +#include "gstvideofilter.h" + + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEOTEMPLATE \ + (gst_videotemplate_get_type()) +#define GST_VIDEOTEMPLATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEOTEMPLATE,GstVideotemplate)) +#define GST_VIDEOTEMPLATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEOTEMPLATE,GstVideotemplateClass)) +#define GST_IS_VIDEOTEMPLATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEOTEMPLATE)) +#define GST_IS_VIDEOTEMPLATE_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEOTEMPLATE)) + +typedef struct _GstVideotemplate GstVideotemplate; +typedef struct _GstVideotemplateClass GstVideotemplateClass; + +struct _GstVideotemplate { + GstVideofilter videofilter; + +}; + +struct _GstVideotemplateClass { + GstVideofilterClass parent_class; +}; + +GType gst_videotemplate_get_type(void); + +G_END_DECLS + +#endif /* __GST_VIDEOTEMPLATE_H__ */ + diff --git a/gst/videofilter/make_filter b/gst/videofilter/make_filter new file mode 100755 index 0000000..06bb1fe --- /dev/null +++ b/gst/videofilter/make_filter @@ -0,0 +1,42 @@ +#!/usr/bin/perl +# + +if(scalar(@ARGV) < 1){ + print "$0 Objectname\n"; + print " creates gstobjectname.{c,h} implementing GstObjectname,\n"; + print " subclassing GstVideofilter.\n"; + exit(0); +} + +$Template = $ARGV[0]; +($TEMPLATE = $Template) =~ tr/a-z/A-Z/; +($template = $Template) =~ tr/A-Z/a-z/; + +open IN, "gstvideotemplate.c"; +open OUT, ">gst$template.c"; + +@lines = ; +map { s/Videotemplate/$Template/g; + s/videotemplate/$template/g; + s/VIDEOTEMPLATE/$TEMPLATE/g; +} @lines; + +print OUT @lines; + +close IN; +close OUT; + +open IN, "gstvideotemplate.h"; +open OUT, ">gst$template.h"; + +@lines = ; +map { s/Videotemplate/$Template/g; + s/videotemplate/$template/g; + s/VIDEOTEMPLATE/$TEMPLATE/g; +} @lines; + +print OUT @lines; + +close IN; +close OUT; + -- 2.7.4