summaryrefslogtreecommitdiff
path: root/gst/videofilter
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2012-10-16 13:47:24 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2012-10-16 13:47:24 +0200
commit9e67891f7251ddb3b44545dc7a16d271f3649989 (patch)
treeb9231a07e29e86a571b9072afec5349fc87d3e1f /gst/videofilter
parentb893197317709282e7668ce464c9dd3efcf6ecc1 (diff)
downloadgstreamer-plugins-good-9e67891f7251ddb3b44545dc7a16d271f3649989.tar.gz
videomedian: copy media to videomedian
Copy the median video filter to videofilters and rename to videomedian.
Diffstat (limited to 'gst/videofilter')
-rw-r--r--gst/videofilter/Makefile.am5
-rw-r--r--gst/videofilter/gstvideomedian.c318
-rw-r--r--gst/videofilter/gstvideomedian.h68
-rw-r--r--gst/videofilter/plugin.c5
4 files changed, 393 insertions, 3 deletions
diff --git a/gst/videofilter/Makefile.am b/gst/videofilter/Makefile.am
index 4a7b9d9a7..0422e1214 100644
--- a/gst/videofilter/Makefile.am
+++ b/gst/videofilter/Makefile.am
@@ -1,6 +1,6 @@
plugin_LTLIBRARIES = libgstvideofilter.la
-noinst_HEADERS = gstvideoflip.h gstvideobalance.h gstgamma.h
+noinst_HEADERS = gstvideoflip.h gstvideobalance.h gstgamma.h gstvideomedian.h
EXTRA_DIST = gstvideotemplate.c make_filter
CLEANFILES = gstvideoexample.c
@@ -8,7 +8,8 @@ CLEANFILES = gstvideoexample.c
libgstvideofilter_la_SOURCES = plugin.c \
gstvideoflip.c \
gstvideobalance.c \
- gstgamma.c
+ gstgamma.c \
+ gstvideomedian.c
libgstvideofilter_la_CFLAGS = $(GST_CFLAGS) \
$(GST_BASE_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS)
diff --git a/gst/videofilter/gstvideomedian.c b/gst/videofilter/gstvideomedian.c
new file mode 100644
index 000000000..0d837cd17
--- /dev/null
+++ b/gst/videofilter/gstvideomedian.c
@@ -0,0 +1,318 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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 <string.h>
+#include "gstvideomedian.h"
+
+static GstStaticPadTemplate video_median_src_factory =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12 }"))
+ );
+
+static GstStaticPadTemplate video_median_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12 }"))
+ );
+
+
+/* Median signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_ACTIVE,
+ PROP_FILTERSIZE,
+ PROP_LUM_ONLY
+};
+
+#define gst_video_median_parent_class parent_class
+G_DEFINE_TYPE (GstVideoMedian, gst_video_median, GST_TYPE_VIDEO_FILTER);
+
+static GstFlowReturn gst_video_median_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame);
+
+static void gst_video_median_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_video_median_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void
+gst_video_median_class_init (GstVideoMedianClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstVideoFilterClass *vfilter_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ vfilter_class = (GstVideoFilterClass *) klass;
+
+ gobject_class->set_property = gst_video_median_set_property;
+ gobject_class->get_property = gst_video_median_get_property;
+
+ /* FIXME: add long property descriptions */
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ACTIVE,
+ g_param_spec_boolean ("active", "active", "active", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTERSIZE,
+ g_param_spec_int ("filtersize", "filtersize", "filtersize", G_MININT,
+ G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LUM_ONLY,
+ g_param_spec_boolean ("lum-only", "lum-only", "lum-only", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&video_median_sink_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&video_median_src_factory));
+ gst_element_class_set_static_metadata (gstelement_class, "Median effect",
+ "Filter/Effect/Video",
+ "Apply a median filter to an image",
+ "Wim Taymans <wim.taymans@gmail.com>");
+
+ vfilter_class->transform_frame =
+ GST_DEBUG_FUNCPTR (gst_video_median_transform_frame);
+}
+
+void
+gst_video_median_init (GstVideoMedian * median)
+{
+ median->filtersize = 5;
+ median->lum_only = TRUE;
+ median->active = TRUE;
+}
+
+#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
+#define PIX_SWAP(a,b) { unsigned char temp=(a);(a)=(b);(b)=temp; }
+
+static void
+median_5 (guint8 * dest, gint dstride, const guint8 * src, gint sstride,
+ gint width, gint height)
+{
+ unsigned char p[5];
+ int i, j, k;
+
+ /* copy the top and bottom rows into the result array */
+ for (i = 0; i < width; i++) {
+ dest[i] = src[i];
+ dest[(height - 1) * dstride + i] = src[(height - 1) * sstride + i];
+ }
+
+ /* process the interior pixels */
+ for (k = 2; k < height; k++) {
+ dest += dstride;
+ src += sstride;
+
+ dest[0] = src[0];
+ for (j = 2, i = 1; j < width; j++, i++) {
+ p[0] = src[i - sstride];
+ p[1] = src[i - 1];
+ p[2] = src[i];
+ p[3] = src[i + 1];
+ p[4] = src[i + sstride];
+ PIX_SORT (p[0], p[1]);
+ PIX_SORT (p[3], p[4]);
+ PIX_SORT (p[0], p[3]);
+ PIX_SORT (p[1], p[4]);
+ PIX_SORT (p[1], p[2]);
+ PIX_SORT (p[2], p[3]);
+ PIX_SORT (p[1], p[2]);
+ dest[i] = p[2];
+ }
+ dest[i] = src[i];
+ }
+}
+
+static void
+median_9 (guint8 * dest, gint dstride, const guint8 * src, gint sstride,
+ gint width, gint height)
+{
+ unsigned char p[9];
+ int i, j, k;
+
+ /*copy the top and bottom rows into the result array */
+ for (i = 0; i < width; i++) {
+ dest[i] = src[i];
+ dest[(height - 1) * dstride + i] = src[(height - 1) * sstride + i];
+ }
+ /* process the interior pixels */
+ for (k = 2; k < height; k++) {
+ dest += dstride;
+ src += sstride;
+
+ dest[0] = src[0];
+ for (j = 2, i = 1; j < width; j++, i++) {
+ p[0] = src[i - sstride - 1];
+ p[1] = src[i - sstride];
+ p[2] = src[i - sstride + 1];
+ p[3] = src[i - 1];
+ p[4] = src[i];
+ p[5] = src[i + 1];
+ p[6] = src[i + sstride - 1];
+ p[7] = src[i + sstride];
+ p[8] = src[i + sstride + 1];
+ PIX_SORT (p[1], p[2]);
+ PIX_SORT (p[4], p[5]);
+ PIX_SORT (p[7], p[8]);
+ PIX_SORT (p[0], p[1]);
+ PIX_SORT (p[3], p[4]);
+ PIX_SORT (p[6], p[7]);
+ PIX_SORT (p[1], p[2]);
+ PIX_SORT (p[4], p[5]);
+ PIX_SORT (p[7], p[8]);
+ PIX_SORT (p[0], p[3]);
+ PIX_SORT (p[5], p[8]);
+ PIX_SORT (p[4], p[7]);
+ PIX_SORT (p[3], p[6]);
+ PIX_SORT (p[1], p[4]);
+ PIX_SORT (p[2], p[5]);
+ PIX_SORT (p[4], p[7]);
+ PIX_SORT (p[4], p[2]);
+ PIX_SORT (p[6], p[4]);
+ PIX_SORT (p[4], p[2]);
+ dest[i] = p[4];
+ }
+ dest[i] = src[i];
+ }
+}
+
+static GstFlowReturn
+gst_video_median_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame)
+{
+ GstVideoMedian *median = GST_VIDEO_MEDIAN (filter);
+
+ if (median->filtersize == 5) {
+ median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0),
+ GST_VIDEO_FRAME_WIDTH (in_frame), GST_VIDEO_FRAME_HEIGHT (in_frame));
+
+ if (median->lum_only) {
+ gst_video_frame_copy_plane (out_frame, in_frame, 1);
+ gst_video_frame_copy_plane (out_frame, in_frame, 2);
+ } else {
+ median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 1),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 1),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 1),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1),
+ GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
+ GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
+ median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 2),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 2),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 2),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 2),
+ GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
+ GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
+ }
+ } else {
+ median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0),
+ GST_VIDEO_FRAME_WIDTH (in_frame), GST_VIDEO_FRAME_HEIGHT (in_frame));
+
+ if (median->lum_only) {
+ gst_video_frame_copy_plane (out_frame, in_frame, 1);
+ gst_video_frame_copy_plane (out_frame, in_frame, 2);
+ } else {
+ median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 1),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 1),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 1),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1),
+ GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
+ GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
+ median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 2),
+ GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 2),
+ GST_VIDEO_FRAME_PLANE_DATA (in_frame, 2),
+ GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 2),
+ GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
+ GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
+ }
+ }
+
+ return GST_FLOW_OK;
+}
+
+static void
+gst_video_median_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstVideoMedian *median;
+ gint argvalue;
+
+ median = GST_VIDEO_MEDIAN (object);
+
+ switch (prop_id) {
+ case PROP_FILTERSIZE:
+ argvalue = g_value_get_int (value);
+ if (argvalue != 5 && argvalue != 9) {
+ g_warning ("median: invalid filtersize (%d), must be 5 or 9\n",
+ argvalue);
+ } else {
+ median->filtersize = argvalue;
+ }
+ break;
+ case PROP_ACTIVE:
+ median->active = g_value_get_boolean (value);
+ break;
+ case PROP_LUM_ONLY:
+ median->lum_only = g_value_get_boolean (value);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gst_video_median_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstVideoMedian *median;
+
+ median = GST_VIDEO_MEDIAN (object);
+
+ switch (prop_id) {
+ case PROP_FILTERSIZE:
+ g_value_set_int (value, median->filtersize);
+ break;
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, median->active);
+ break;
+ case PROP_LUM_ONLY:
+ g_value_set_boolean (value, median->lum_only);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
diff --git a/gst/videofilter/gstvideomedian.h b/gst/videofilter/gstvideomedian.h
new file mode 100644
index 000000000..432ab7ee6
--- /dev/null
+++ b/gst/videofilter/gstvideomedian.h
@@ -0,0 +1,68 @@
+/* GStreamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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_VIDEO_MEDIAN_H__
+#define __GST_VIDEO_MEDIAN_H__
+
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VIDEO_MEDIAN \
+ (gst_video_median_get_type())
+#define GST_VIDEO_MEDIAN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_MEDIAN,GstVideoMedian))
+#define GST_VIDEO_MEDIAN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MEDIAN,GstVideoMedianClass))
+#define GST_IS_VIDEO_MEDIAN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_MEDIAN))
+#define GST_IS_VIDEO_MEDIAN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MEDIAN))
+
+typedef struct _GstVideoMedian GstVideoMedian;
+typedef struct _GstVideoMedianClass GstVideoMedianClass;
+
+struct _GstVideoMedian {
+ GstVideoFilter parent;
+
+ int format;
+ int width;
+ int height;
+
+ int filtersize;
+
+ gboolean active;
+ gboolean lum_only;
+
+ GstPad *sinkpad,*srcpad;
+};
+
+struct _GstVideoMedianClass {
+ GstVideoFilterClass parent_class;
+};
+
+GType gst_video_median_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_VIDEO_MEDIAN_H__ */
diff --git a/gst/videofilter/plugin.c b/gst/videofilter/plugin.c
index 212c3a504..306c3a325 100644
--- a/gst/videofilter/plugin.c
+++ b/gst/videofilter/plugin.c
@@ -26,6 +26,7 @@
#include "gstgamma.h"
#include "gstvideoflip.h"
#include "gstvideobalance.h"
+#include "gstvideomedian.h"
static gboolean
plugin_init (GstPlugin * plugin)
@@ -34,7 +35,9 @@ plugin_init (GstPlugin * plugin)
&& gst_element_register (plugin, "videobalance", GST_RANK_NONE,
GST_TYPE_VIDEO_BALANCE)
&& gst_element_register (plugin, "videoflip", GST_RANK_NONE,
- GST_TYPE_VIDEO_FLIP));
+ GST_TYPE_VIDEO_FLIP)
+ && gst_element_register (plugin, "videomedian", GST_RANK_NONE,
+ GST_TYPE_VIDEO_MEDIAN));
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,