diff --git a/configure.ac b/configure.ac index e1fe0765c3..d6700d3bde 100644 --- a/configure.ac +++ b/configure.ac @@ -317,6 +317,7 @@ AG_GST_CHECK_PLUGIN(subenc) AG_GST_CHECK_PLUGIN(stereo) AG_GST_CHECK_PLUGIN(tta) AG_GST_CHECK_PLUGIN(valve) +AG_GST_CHECK_PLUGIN(videomaxrate) AG_GST_CHECK_PLUGIN(videomeasure) AG_GST_CHECK_PLUGIN(videosignal) AG_GST_CHECK_PLUGIN(vmnc) @@ -1710,6 +1711,7 @@ gst/subenc/Makefile gst/stereo/Makefile gst/tta/Makefile gst/valve/Makefile +gst/videomaxrate/Makefile gst/videomeasure/Makefile gst/videosignal/Makefile gst/vmnc/Makefile diff --git a/gst/videomaxrate/Makefile.am b/gst/videomaxrate/Makefile.am new file mode 100644 index 0000000000..595941ed5b --- /dev/null +++ b/gst/videomaxrate/Makefile.am @@ -0,0 +1,11 @@ +plugin_LTLIBRARIES = libgstvideomaxrate.la + +libgstvideomaxrate_la_SOURCES = videomaxrate.c + +noinst_HEADERS = videomaxrate.h +libgstvideomaxrate_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstvideomaxrate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \ + $(GST_LIBS) +libgstvideomaxrate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideomaxrate_la_LIBTOOLFLAGS = --tag=disable-static + diff --git a/gst/videomaxrate/videomaxrate.c b/gst/videomaxrate/videomaxrate.c new file mode 100644 index 0000000000..66554081d5 --- /dev/null +++ b/gst/videomaxrate/videomaxrate.c @@ -0,0 +1,190 @@ +/* + * GStreamer - limit video rate + * + * Copyright 2008 Barracuda Networks, Inc. + * + * Copyright 2009 Nokia Corporation + * Copyright 2009 Collabora Ltd, + * @contact: Olivier Crete + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "videomaxrate.h" + +static GstStaticPadTemplate gst_video_max_rate_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") + ); + +static GstStaticPadTemplate gst_video_max_rate_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") + ); + +static gboolean gst_video_max_rate_sink_event (GstPad * pad, GstEvent * event); +static GstCaps *gst_video_max_rate_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_video_max_rate_set_caps (GstBaseTransform * trans, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_video_max_rate_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); + +GST_BOILERPLATE (GstVideoMaxRate, gst_video_max_rate, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void +gst_video_max_rate_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "Video maximum rate adjuster", + "Filter/Effect/Video", + "Drops extra frames", "Justin Karneges "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_video_max_rate_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_video_max_rate_src_template)); +} + +static void +gst_video_max_rate_class_init (GstVideoMaxRateClass * klass) +{ + GstBaseTransformClass *base_class = GST_BASE_TRANSFORM_CLASS (klass); + + base_class->transform_caps = gst_video_max_rate_transform_caps; + base_class->set_caps = gst_video_max_rate_set_caps; + base_class->transform_ip = gst_video_max_rate_transform_ip; +} + +static void +gst_video_max_rate_init (GstVideoMaxRate * videomaxrate, + GstVideoMaxRateClass * gclass) +{ + videomaxrate->to_rate_numerator = -1; + videomaxrate->to_rate_denominator = -1; + videomaxrate->have_last_ts = FALSE; + + gst_pad_set_event_function (GST_BASE_TRANSFORM_SINK_PAD (videomaxrate), + gst_video_max_rate_sink_event); +} + +gboolean +gst_video_max_rate_sink_event (GstPad * pad, GstEvent * event) +{ + GstVideoMaxRate *videomaxrate = GST_VIDEO_MAX_RATE (gst_pad_get_parent (pad)); + gboolean ret; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_FLUSH_STOP: + videomaxrate->have_last_ts = FALSE; + break; + default: + break; + } + + ret = gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (videomaxrate), event); + + gst_object_unref (videomaxrate); + return ret; +} + +GstCaps * +gst_video_max_rate_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstCaps *ret; + GstStructure *structure; + + /* this function is always called with a simple caps */ + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL); + + ret = gst_caps_copy (caps); + + /* set the framerate as a range */ + structure = gst_structure_copy (gst_caps_get_structure (ret, 0)); + gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, + G_MAXINT, 1, NULL); + gst_caps_merge_structure (ret, gst_structure_copy (structure)); + gst_structure_free (structure); + + return ret; +} + +gboolean +gst_video_max_rate_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstVideoMaxRate *videomaxrate = GST_VIDEO_MAX_RATE (trans); + GstStructure *cs; + gint numerator, denominator; + + // keep track of the outbound framerate + cs = gst_caps_get_structure (outcaps, 0); + if (!gst_structure_get_fraction (cs, "framerate", &numerator, &denominator)) + return FALSE; + + videomaxrate->to_rate_numerator = numerator; + videomaxrate->to_rate_denominator = denominator; + + return TRUE; +} + +GstFlowReturn +gst_video_max_rate_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstVideoMaxRate *videomaxrate = GST_VIDEO_MAX_RATE (trans); + GstClockTime ts = GST_BUFFER_TIMESTAMP (buf); + + /* drop frames if they exceed our output rate */ + if (videomaxrate->have_last_ts) { + if (ts < videomaxrate->last_ts + gst_util_uint64_scale (1, + videomaxrate->to_rate_denominator * GST_SECOND, + videomaxrate->to_rate_numerator)) { + return GST_BASE_TRANSFORM_FLOW_DROPPED; + } + } + + videomaxrate->last_ts = ts; + videomaxrate->have_last_ts = TRUE; + return GST_FLOW_OK; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "videomaxrate", GST_RANK_NONE, + GST_TYPE_VIDEO_MAX_RATE); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videomaxrate", + "Drop extra frames", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/videomaxrate/videomaxrate.h b/gst/videomaxrate/videomaxrate.h new file mode 100644 index 0000000000..315d04cf3d --- /dev/null +++ b/gst/videomaxrate/videomaxrate.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Barracuda Networks, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __GST_VIDEOMAXRATE_H__ +#define __GST_VIDEOMAXRATE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_MAX_RATE \ + (gst_video_max_rate_get_type()) +#define GST_VIDEO_MAX_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_MAX_RATE,GstVideoMaxRate)) +#define GST_VIDEO_MAX_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MAX_RATE, \ + GstVideoMaxRateClass)) +#define GST_IS_VIDEO_MAX_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_MAX_RATE)) +#define GST_IS_VIDEO_MAX_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MAX_RATE)) + +typedef struct _GstVideoMaxRate GstVideoMaxRate; +typedef struct _GstVideoMaxRateClass GstVideoMaxRateClass; + +struct _GstVideoMaxRate +{ + GstBaseTransform parent; + + gint to_rate_numerator; + gint to_rate_denominator; + + gboolean have_last_ts; + GstClockTime last_ts; +}; + +struct _GstVideoMaxRateClass +{ + GstBaseTransformClass parent_class; +}; + +GType gst_video_max_rate_get_type(void); + +G_END_DECLS + +#endif /* __GST_VIDEOMAXRATE_H__ */