From b569848e286b7435997a67e17fa0b21db892131d Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 30 Sep 2003 21:44:53 +0000 Subject: Add new element: frame dropper. This element inserts/drops frames to go from a certain input framerate to a certain o... Original commit message from CVS: Add new element: frame dropper. This element inserts/drops frames to go from a certain input framerate to a certain output framerate. It's extremely simple and that's why it's so cute. --- configure.ac | 5 +- gst/videodrop/Makefile.am | 10 ++ gst/videodrop/gstvideodrop.c | 255 +++++++++++++++++++++++++++++++++++++++++++ gst/videodrop/gstvideodrop.h | 62 +++++++++++ 4 files changed, 330 insertions(+), 2 deletions(-) create mode 100644 gst/videodrop/Makefile.am create mode 100644 gst/videodrop/gstvideodrop.c create mode 100644 gst/videodrop/gstvideodrop.h diff --git a/configure.ac b/configure.ac index a1e0cf46..bf0338ee 100644 --- a/configure.ac +++ b/configure.ac @@ -268,8 +268,8 @@ GST_PLUGINS_ALL="\ monoscope oneton overlay passthrough playondemand qtdemux \ realmedia rtp rtjpeg silence sine smooth smpte \ spectrum speed stereo synaesthesia tcp udp vbidec \ - videocrop videofilter videoflip videoscale videotestsrc \ - volenv volume wavenc wavparse y4m" + videocrop videodrop videofilter videoflip videoscale \ + videotestsrc volenv volume wavenc wavparse y4m" dnl see if we can build C++ plug-ins if test "x$HAVE_CXX" = "xyes"; then @@ -1216,6 +1216,7 @@ gst/tcp/Makefile gst/udp/Makefile gst/vbidec/Makefile gst/videocrop/Makefile +gst/videodrop/Makefile gst/videofilter/Makefile gst/videoflip/Makefile gst/videoscale/Makefile diff --git a/gst/videodrop/Makefile.am b/gst/videodrop/Makefile.am new file mode 100644 index 00000000..536df539 --- /dev/null +++ b/gst/videodrop/Makefile.am @@ -0,0 +1,10 @@ + +plugin_LTLIBRARIES = libgstvideodrop.la + +libgstvideodrop_la_SOURCES = \ + gstvideodrop.c +libgstvideodrop_la_CFLAGS = $(GST_CFLAGS) +libgstvideodrop_la_LIBADD = +libgstvideodrop_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstvideodrop.h diff --git a/gst/videodrop/gstvideodrop.c b/gst/videodrop/gstvideodrop.c new file mode 100644 index 00000000..252d773b --- /dev/null +++ b/gst/videodrop/gstvideodrop.c @@ -0,0 +1,255 @@ +/* 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* elementfactory information */ +static GstElementDetails videodrop_details = { + "Video frame dropper", + "Filter/Video", + "LGPL", + "Re-FPS'es video", + VERSION, + "Ronald Bultje ", + "(C) 2003", +}; + +/* GstVideodrop signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + +GST_PAD_TEMPLATE_FACTORY(src_template, + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_CAPS_NEW( + "framedropper_yuv", + "video/x-raw-yuv", + "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT), + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT), + "format", GST_PROPS_LIST ( + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','V')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('U','Y','V','Y')) + ) + ) +) + +GST_PAD_TEMPLATE_FACTORY(sink_template, + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW( + "framedropper_yuv", + "video/x-raw-yuv", + "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT), + "width", GST_PROPS_INT_RANGE (0, G_MAXINT), + "height", GST_PROPS_INT_RANGE (0, G_MAXINT), + "format", GST_PROPS_LIST ( + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','2')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','U','Y','V')), + GST_PROPS_FOURCC (GST_MAKE_FOURCC ('U','Y','V','Y')) + ) + ) +) + +static void gst_videodrop_class_init (GstVideodropClass *klass); +static void gst_videodrop_init (GstVideodrop *videodrop); +static void gst_videodrop_chain (GstPad *pad, GstBuffer *buf); + +static GstElementClass *parent_class = NULL; +/*static guint gst_videodrop_signals[LAST_SIGNAL] = { 0 }; */ + +GType +gst_videodrop_get_type (void) +{ + static GType videodrop_type = 0; + + if (!videodrop_type) { + static const GTypeInfo videodrop_info = { + sizeof (GstVideodropClass), + NULL, + NULL, + (GClassInitFunc) gst_videodrop_class_init, + NULL, + NULL, + sizeof (GstVideodrop), + 0, + (GInstanceInitFunc) gst_videodrop_init, + }; + + videodrop_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstVideodrop", + &videodrop_info, 0); + } + + return videodrop_type; +} + +static void +gst_videodrop_class_init (GstVideodropClass *klass) +{ + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); +} + +#define gst_caps_get_float_range(caps, name, min, max) \ + gst_props_entry_get_float_range(gst_props_get_entry((caps)->properties, \ + name), \ + min, max) + +static GstPadLinkReturn +gst_videodrop_link (GstPad *pad, GstCaps *caps) +{ + GstVideodrop *videodrop; + GstPadLinkReturn ret; + GstCaps *peercaps; + + videodrop = GST_VIDEODROP (gst_pad_get_parent (pad)); + + videodrop->inited = FALSE; + + if (!GST_CAPS_IS_FIXED (caps)) { + return GST_PAD_LINK_DELAYED; + } + + gst_caps_get_float (caps, "framerate", &videodrop->from_fps); + + /* calc output fps */ + peercaps = gst_pad_get_allowed_caps (videodrop->srcpad); + if (gst_caps_has_fixed_property (peercaps, "framerate")) { + gst_caps_get_float (peercaps, "framerate", &videodrop->to_fps); + } else { + gfloat min, max; + gst_caps_get_float_range (peercaps, "framerate", &min, &max); + if (videodrop->from_fps >= min && + videodrop->from_fps <= max) { + videodrop->to_fps = videodrop->from_fps; + } else { + videodrop->to_fps = max; + } + } + gst_caps_unref (peercaps); + + GST_DEBUG ("%f -> %f fps", + videodrop->from_fps, videodrop->to_fps); + + peercaps = gst_caps_copy (caps); + + peercaps->properties = gst_caps_set (peercaps, "framerate", + GST_PROPS_FLOAT (videodrop->to_fps)); + + if ((ret = gst_pad_try_set_caps (videodrop->srcpad, peercaps)) > 0) { + videodrop->inited = TRUE; + videodrop->total = videodrop->pass = 0; + } + + return ret; +} + +static void +gst_videodrop_init (GstVideodrop *videodrop) +{ + GST_DEBUG ("gst_videodrop_init"); + videodrop->sinkpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (sink_template), + "sink"); + gst_element_add_pad (GST_ELEMENT (videodrop), videodrop->sinkpad); + gst_pad_set_chain_function (videodrop->sinkpad, gst_videodrop_chain); + gst_pad_set_link_function (videodrop->sinkpad, gst_videodrop_link); + + videodrop->srcpad = gst_pad_new_from_template ( + GST_PAD_TEMPLATE_GET (src_template), + "src"); + gst_element_add_pad (GST_ELEMENT(videodrop), videodrop->srcpad); + + videodrop->inited = FALSE; + videodrop->total = videodrop->pass = 0; +} + +static void +gst_videodrop_chain (GstPad *pad, GstBuffer *buf) +{ + GstVideodrop *videodrop; + + GST_DEBUG ("gst_videodrop_chain"); + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + videodrop = GST_VIDEODROP (gst_pad_get_parent (pad)); + + if (GST_IS_EVENT (buf)) { + gst_pad_push (videodrop->srcpad, buf); + return; + } + + videodrop->total++; + while (videodrop->to_fps / videodrop->from_fps > + (gfloat) videodrop->pass / videodrop->total) { + videodrop->pass++; + gst_buffer_ref (buf); + gst_pad_push (videodrop->srcpad, buf); + } + + gst_buffer_unref (buf); +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + /* create an elementfactory for the videodrop element */ + factory = gst_element_factory_new ("videodrop", GST_TYPE_VIDEODROP, + &videodrop_details); + g_return_val_if_fail (factory != NULL, FALSE); + + gst_element_factory_add_pad_template (factory, + GST_PAD_TEMPLATE_GET (sink_template)); + gst_element_factory_add_pad_template (factory, + GST_PAD_TEMPLATE_GET (src_template)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videodrop", + plugin_init +}; diff --git a/gst/videodrop/gstvideodrop.h b/gst/videodrop/gstvideodrop.h new file mode 100644 index 00000000..8b447e30 --- /dev/null +++ b/gst/videodrop/gstvideodrop.h @@ -0,0 +1,62 @@ +/* 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_VIDEODROP_H__ +#define __GST_VIDEODROP_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEODROP \ + (gst_videodrop_get_type()) +#define GST_VIDEODROP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEODROP,GstVideodrop)) +#define GST_VIDEODROP_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEODROP,GstVideodrop)) +#define GST_IS_VIDEODROP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEODROP)) +#define GST_IS_VIDEODROP_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEODROP)) + +typedef struct _GstVideodrop GstVideodrop; +typedef struct _GstVideodropClass GstVideodropClass; + +struct _GstVideodrop { + GstElement element; + + GstPad *sinkpad, *srcpad; + + /* video state */ + gboolean inited; + float from_fps, + to_fps; + guint64 pass, total; +}; + +struct _GstVideodropClass { + GstElementClass parent_class; +}; + +GType gst_videodrop_get_type(void); + +G_END_DECLS + +#endif /* __GST_VIDEODROP_H__ */ -- cgit v1.2.1