From e3afdb0bd56de477788447d9b0f2d120330107be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 12 Jun 2009 22:00:20 +0200 Subject: frei0r: Add support for frei0r source/generator plugins --- gst/frei0r/Makefile.am | 5 +- gst/frei0r/gstfrei0r.c | 3 + gst/frei0r/gstfrei0rsrc.c | 407 ++++++++++++++++++++++++++++++++++++++++++++++ gst/frei0r/gstfrei0rsrc.h | 69 ++++++++ 4 files changed, 482 insertions(+), 2 deletions(-) create mode 100644 gst/frei0r/gstfrei0rsrc.c create mode 100644 gst/frei0r/gstfrei0rsrc.h (limited to 'gst/frei0r') diff --git a/gst/frei0r/Makefile.am b/gst/frei0r/Makefile.am index be951cb1..495fd7de 100644 --- a/gst/frei0r/Makefile.am +++ b/gst/frei0r/Makefile.am @@ -2,7 +2,8 @@ plugin_LTLIBRARIES = libgstfrei0r.la libgstfrei0r_la_SOURCES = \ gstfrei0r.c \ - gstfrei0rfilter.c + gstfrei0rfilter.c \ + gstfrei0rsrc.c libgstfrei0r_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) libgstfrei0r_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ @@ -10,4 +11,4 @@ libgstfrei0r_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ libgstfrei0r_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstfrei0r_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gstfrei0r.h gstfrei0rfilter.h frei0r.h +noinst_HEADERS = gstfrei0r.h gstfrei0rfilter.h gstfrei0rsrc.h frei0r.h diff --git a/gst/frei0r/gstfrei0r.c b/gst/frei0r/gstfrei0r.c index a09f0a2d..bcdd290d 100644 --- a/gst/frei0r/gstfrei0r.c +++ b/gst/frei0r/gstfrei0r.c @@ -23,6 +23,7 @@ #include "gstfrei0r.h" #include "gstfrei0rfilter.h" +#include "gstfrei0rsrc.h" #include @@ -477,6 +478,8 @@ register_plugin (GstPlugin * plugin, const gchar * filename) ret = gst_frei0r_filter_register (plugin, &info, &ftable); break; case F0R_PLUGIN_TYPE_SOURCE: + ret = gst_frei0r_src_register (plugin, &info, &ftable); + break; case F0R_PLUGIN_TYPE_MIXER2: case F0R_PLUGIN_TYPE_MIXER3: GST_WARNING diff --git a/gst/frei0r/gstfrei0rsrc.c b/gst/frei0r/gstfrei0rsrc.c new file mode 100644 index 00000000..937e6f92 --- /dev/null +++ b/gst/frei0r/gstfrei0rsrc.c @@ -0,0 +1,407 @@ +/* GStreamer + * Copyright (C) 2009 Sebastian Dröge + * + * 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 "gstfrei0r.h" +#include "gstfrei0rsrc.h" + +typedef struct +{ + f0r_plugin_info_t info; + GstFrei0rFuncTable ftable; +} GstFrei0rSrcClassData; + +static gboolean +gst_frei0r_src_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (src); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src); + + if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width, + &self->height) + || !gst_video_parse_caps_framerate (caps, &self->fps_n, &self->fps_d)) + return FALSE; + + if (self->f0r_instance) { + klass->ftable->destruct (self->f0r_instance); + self->f0r_instance = NULL; + } + + self->f0r_instance = + gst_frei0r_instance_construct (klass->ftable, klass->properties, + klass->n_properties, self->property_cache, self->width, self->height); + + return TRUE; +} + +static GstFlowReturn +gst_frei0r_src_create (GstPushSrc * src, GstBuffer ** buf) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (src); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src); + guint size, newsize; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf = NULL; + gdouble time; + + *buf = NULL; + + if (G_UNLIKELY (!self->f0r_instance)) + return GST_FLOW_NOT_NEGOTIATED; + + newsize = gst_video_format_get_size (self->fmt, self->width, self->height); + + ret = + gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (src), + GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)), + &outbuf); + if (ret != GST_FLOW_OK) + return ret; + + /* Format might have changed */ + size = GST_BUFFER_SIZE (outbuf); + newsize = gst_video_format_get_size (self->fmt, self->width, self->height); + + if (size != newsize) { + gst_buffer_unref (outbuf); + outbuf = gst_buffer_new_and_alloc (newsize); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); + } + + GST_BUFFER_TIMESTAMP (outbuf) = + gst_util_uint64_scale (self->n_frames, GST_SECOND * self->fps_d, + self->fps_n); + GST_BUFFER_OFFSET (outbuf) = self->n_frames; + self->n_frames++; + GST_BUFFER_OFFSET_END (outbuf) = self->n_frames; + GST_BUFFER_DURATION (outbuf) = + gst_util_uint64_scale (self->n_frames, GST_SECOND * self->fps_d, + self->fps_n) - GST_BUFFER_TIMESTAMP (outbuf); + + time = ((gdouble) GST_BUFFER_TIMESTAMP (outbuf)) / GST_SECOND; + + if (klass->ftable->update2) + klass->ftable->update2 (self->f0r_instance, time, NULL, NULL, NULL, + (guint32 *) GST_BUFFER_DATA (outbuf)); + else + klass->ftable->update (self->f0r_instance, time, NULL, + (guint32 *) GST_BUFFER_DATA (outbuf)); + + *buf = outbuf; + + return GST_FLOW_OK; +} + +static void +gst_frei0r_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + /* for live sources, sync on the timestamp of the buffer */ + if (gst_base_src_is_live (basesrc)) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + GstClockTime duration = GST_BUFFER_DURATION (buffer); + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } + } else { + *start = -1; + *end = -1; + } +} + +static gboolean +gst_frei0r_src_start (GstBaseSrc * basesrc) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (basesrc); + + self->n_frames = 0; + + return TRUE; +} + +static gboolean +gst_frei0r_src_is_seekable (GstBaseSrc * psrc) +{ + return TRUE; +} + +static gboolean +gst_frei0r_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) +{ + GstClockTime time; + GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc); + + segment->time = segment->start; + time = segment->last_stop; + + /* now move to the time indicated */ + if (self->fps_n) { + self->n_frames = gst_util_uint64_scale (time, + self->fps_n, self->fps_d * GST_SECOND); + } else { + self->n_frames = 0; + } + + return TRUE; +} + +static gboolean +gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + gboolean res; + GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (self); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (src_fmt == dest_fmt) { + dest_val = src_val; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + /* frames to time */ + if (self->fps_n) { + dest_val = gst_util_uint64_scale (src_val, + self->fps_d * GST_SECOND, self->fps_n); + } else { + dest_val = 0; + } + break; + default: + goto error; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + /* time to frames */ + if (self->fps_n) { + dest_val = gst_util_uint64_scale (src_val, + self->fps_n, self->fps_d * GST_SECOND); + } else { + dest_val = 0; + } + break; + default: + goto error; + } + break; + default: + goto error; + } + done: + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + res = TRUE; + break; + } + default: + res = + GST_BASE_SRC_CLASS (g_type_class_peek_parent (klass))->query (bsrc, + query); + } + return res; + + /* ERROR */ +error: + { + GST_DEBUG_OBJECT (self, "query failed"); + return FALSE; + } +} + +static void +gst_frei0r_src_src_fixate (GstPad * pad, GstCaps * caps) +{ + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_fixate_field_nearest_int (structure, "width", 320); + gst_structure_fixate_field_nearest_int (structure, "height", 240); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); +} + +static void +gst_frei0r_src_finalize (GObject * object) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (object); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object); + + if (self->f0r_instance) { + klass->ftable->destruct (self->f0r_instance); + self->f0r_instance = NULL; + } + + if (self->property_cache) + gst_frei0r_property_cache_free (klass->properties, self->property_cache, + klass->n_properties); + self->property_cache = NULL; + + G_OBJECT_CLASS (g_type_class_peek_parent (klass))->finalize (object); +} + +static void +gst_frei0r_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (object); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object); + + if (!gst_frei0r_get_property (self->f0r_instance, klass->ftable, + klass->properties, klass->n_properties, self->property_cache, prop_id, + value)) + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +} + +static void +gst_frei0r_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstFrei0rSrc *self = GST_FREI0R_SRC (object); + GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object); + + if (!gst_frei0r_set_property (self->f0r_instance, klass->ftable, + klass->properties, klass->n_properties, self->property_cache, prop_id, + value)) + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +} + +static void +gst_frei0r_src_class_init (GstFrei0rSrcClass * klass, + GstFrei0rSrcClassData * class_data) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + GstPushSrcClass *gstpushsrc_class = (GstPushSrcClass *) klass; + GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; + GstPadTemplate *templ; + GstCaps *caps; + gchar *author; + + klass->ftable = &class_data->ftable; + klass->info = &class_data->info; + + gobject_class->finalize = gst_frei0r_src_finalize; + gobject_class->set_property = gst_frei0r_src_set_property; + gobject_class->get_property = gst_frei0r_src_get_property; + + klass->n_properties = klass->info->num_params; + klass->properties = g_new0 (GstFrei0rProperty, klass->n_properties); + + gst_frei0r_klass_install_properties (gobject_class, klass->ftable, + klass->properties, klass->n_properties); + + author = + g_strdup_printf + ("Sebastian Dröge , %s", + class_data->info.author); + gst_element_class_set_details_simple (gstelement_class, class_data->info.name, + "Src/Video", class_data->info.explanation, author); + g_free (author); + + caps = gst_frei0r_caps_from_color_model (class_data->info.color_model); + + templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + gst_element_class_add_pad_template (gstelement_class, templ); + + gstbasesrc_class->set_caps = gst_frei0r_src_set_caps; + gstbasesrc_class->is_seekable = gst_frei0r_src_is_seekable; + gstbasesrc_class->do_seek = gst_frei0r_src_do_seek; + gstbasesrc_class->query = gst_frei0r_src_query; + gstbasesrc_class->get_times = gst_frei0r_src_get_times; + gstbasesrc_class->start = gst_frei0r_src_start; + + gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_frei0r_src_create); +} + +static void +gst_frei0r_src_init (GstFrei0rSrc * self, GstFrei0rSrcClass * klass) +{ + GstPad *pad = GST_BASE_SRC_PAD (self); + + self->property_cache = + gst_frei0r_property_cache_init (klass->properties, klass->n_properties); + + gst_pad_set_fixatecaps_function (pad, gst_frei0r_src_src_fixate); + + gst_base_src_set_format (GST_BASE_SRC_CAST (self), GST_FORMAT_TIME); +} + +gboolean +gst_frei0r_src_register (GstPlugin * plugin, const f0r_plugin_info_t * info, + const GstFrei0rFuncTable * ftable) +{ + GTypeInfo typeinfo = { + sizeof (GstFrei0rSrcClass), + NULL, + NULL, + (GClassInitFunc) gst_frei0r_src_class_init, + NULL, + NULL, + sizeof (GstFrei0rSrc), + 0, + (GInstanceInitFunc) gst_frei0r_src_init + }; + GType type; + gchar *type_name, *tmp; + GstFrei0rSrcClassData *class_data; + + tmp = g_strdup_printf ("frei0r-%s", info->name); + type_name = g_ascii_strdown (tmp, -1); + g_free (tmp); + g_strcanon (type_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-'); + + if (g_type_from_name (type_name)) { + GST_WARNING ("Type '%s' already exists", type_name); + return FALSE; + } + + if (!ftable->init ()) { + GST_ERROR ("Initializing plugin failed"); + return FALSE; + } + + class_data = g_new0 (GstFrei0rSrcClassData, 1); + memcpy (&class_data->info, info, sizeof (f0r_plugin_info_t)); + memcpy (&class_data->ftable, ftable, sizeof (GstFrei0rFuncTable)); + typeinfo.class_data = class_data; + + type = g_type_register_static (GST_TYPE_PUSH_SRC, type_name, &typeinfo, 0); + return (gst_element_register (plugin, type_name, GST_RANK_NONE, type)); +} diff --git a/gst/frei0r/gstfrei0rsrc.h b/gst/frei0r/gstfrei0rsrc.h new file mode 100644 index 00000000..291a644b --- /dev/null +++ b/gst/frei0r/gstfrei0rsrc.h @@ -0,0 +1,69 @@ +/* GStreamer + * Copyright (C) 2009 Sebastian Dröge + * + * 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_FREI0R_SRC_H__ +#define __GST_FREI0R_SRC_H__ + +#include +#include +#include + +#include "frei0r.h" +#include "gstfrei0r.h" + +G_BEGIN_DECLS + +#define GST_FREI0R_SRC(obj) \ + ((GstFrei0rSrc *) obj) +#define GST_FREI0R_SRC_CLASS(klass) \ + ((GstFrei0rSrcClass *) klass) +#define GST_FREI0R_SRC_GET_CLASS(obj) \ + ((GstFrei0rSrcClass *) g_type_class_peek (G_TYPE_FROM_INSTANCE (obj))) + +typedef struct _GstFrei0rSrc GstFrei0rSrc; +typedef struct _GstFrei0rSrcClass GstFrei0rSrcClass; + +struct _GstFrei0rSrc { + GstPushSrc parent; + + f0r_instance_t *f0r_instance; + GstFrei0rPropertyValue *property_cache; + + GstVideoFormat fmt; + gint width, height; + gint fps_n, fps_d; + + guint64 n_frames; +}; + +struct _GstFrei0rSrcClass { + GstPushSrcClass parent; + + f0r_plugin_info_t *info; + GstFrei0rFuncTable *ftable; + + GstFrei0rProperty *properties; + gint n_properties; +}; + +gboolean gst_frei0r_src_register (GstPlugin *plugin, const f0r_plugin_info_t *info, const GstFrei0rFuncTable *ftable); + +G_END_DECLS + +#endif /* __GST_FREI0R_SRC_H__ */ -- cgit v1.2.1