close #333784 unref the result of gst_pad_get_parent() by: Christophe Fergeau.
[platform/upstream/gstreamer.git] / gst / median / gstmedian.c
index 2c6113d..3f09f08 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include <string.h>
-#include <gstmedian.h>
-
+#include "gstmedian.h"
+#include <gst/video/video.h>
 
+/* elementfactory information */
 static GstElementDetails median_details = {
   "Median effect",
-  "Filter/Effect",
-  "apply a median filter to an image",
-  VERSION,
-  "Wim Taymans <wim.taymans@chello.be>",
-  "(C) 2000",
+  "Filter/Effect/Video",
+  "Apply a median filter to an image",
+  "Wim Taymans <wim.taymans@chello.be>"
 };
 
-GST_PADTEMPLATE_FACTORY (median_src_factory,
-  "src",
-  GST_PAD_SRC,
-  GST_PAD_ALWAYS,
-  GST_CAPS_NEW (
-   "median_src",
-   "video/raw",
-     "format",   GST_PROPS_FOURCC (GST_STR_FOURCC ("I420"))
-  )
-)
-
-GST_PADTEMPLATE_FACTORY (median_sink_factory,
-  "sink",
-  GST_PAD_SINK,
-  GST_PAD_ALWAYS,
-  GST_CAPS_NEW (
-   "median_src",
-   "video/raw",
-     "format",   GST_PROPS_FOURCC (GST_STR_FOURCC ("I420"))
-  )
-)
+static GstStaticPadTemplate median_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
+
+static GstStaticPadTemplate median_sink_factory =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+    );
 
 
 /* Median signals and args */
-enum {
+enum
+{
   /* FILL ME */
   LAST_SIGNAL
 };
 
-enum {
+enum
+{
   ARG_0,
   ARG_ACTIVE,
   ARG_FILTERSIZE,
   ARG_LUM_ONLY
 };
 
-static GType   gst_median_get_type     (void);
-static void    gst_median_class_init   (GstMedianClass *klass);
-static void    gst_median_init         (GstMedian *median);
+static GType gst_median_get_type (void);
+static void gst_median_class_init (GstMedianClass * klass);
+static void gst_median_base_init (GstMedianClass * klass);
+static void gst_median_init (GstMedian * median);
 
-static void    median_5                (unsigned char *src, unsigned char *dest, int height, int width);
-static void    median_9                (unsigned char *src, unsigned char *dest, int height, int width);
-static void    gst_median_chain        (GstPad *pad, GstBuffer *buf);
+static void median_5 (unsigned char *src, unsigned char *dest, int height,
+    int width);
+static void median_9 (unsigned char *src, unsigned char *dest, int height,
+    int width);
+static void gst_median_chain (GstPad * pad, GstData * _data);
 
-static void    gst_median_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void    gst_median_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static void gst_median_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_median_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
 static GstElementClass *parent_class = NULL;
+
 /*static guint gst_median_signals[LAST_SIGNAL] = { 0 }; */
 
 GType
@@ -87,69 +88,93 @@ gst_median_get_type (void)
 
   if (!median_type) {
     static const GTypeInfo median_info = {
-      sizeof(GstMedianClass),      NULL,      NULL,      (GClassInitFunc)gst_median_class_init,
+      sizeof (GstMedianClass),
+      (GBaseInitFunc) gst_median_base_init,
+      NULL,
+      (GClassInitFunc) gst_median_class_init,
       NULL,
       NULL,
-      sizeof(GstMedian),
+      sizeof (GstMedian),
       0,
-      (GInstanceInitFunc)gst_median_init,
+      (GInstanceInitFunc) gst_median_init,
     };
-    median_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMedian", &median_info, 0);
+
+    median_type =
+        g_type_register_static (GST_TYPE_ELEMENT, "GstMedian", &median_info, 0);
   }
   return median_type;
 }
 
 static void
-gst_median_class_init (GstMedianClass *klass)
+gst_median_base_init (GstMedianClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&median_sink_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&median_src_factory));
+  gst_element_class_set_details (element_class, &median_details);
+}
+
+static void
+gst_median_class_init (GstMedianClass * klass)
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
 
-  gobject_class = (GObjectClass*)klass;
-  gstelement_class = (GstElementClass*)klass;
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
 
-  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ACTIVE,
-    g_param_spec_boolean("active","active","active",
-                         TRUE,G_PARAM_READWRITE)); /* CHECKME */
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FILTERSIZE,
-    g_param_spec_int("filtersize","filtersize","filtersize",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LUM_ONLY,
-    g_param_spec_boolean("lum_only","lum_only","lum_only",
-                         TRUE,G_PARAM_READWRITE)); /* CHECKME */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACTIVE, g_param_spec_boolean ("active", "active", "active", TRUE, G_PARAM_READWRITE));   /* CHECKME */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILTERSIZE, g_param_spec_int ("filtersize", "filtersize", "filtersize", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));      /* CHECKME */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LUM_ONLY, g_param_spec_boolean ("lum_only", "lum_only", "lum_only", TRUE, G_PARAM_READWRITE));   /* CHECKME */
 
   gobject_class->set_property = gst_median_set_property;
   gobject_class->get_property = gst_median_get_property;
 }
 
 static gboolean
-gst_median_sinkconnect (GstPad *pad, GstCaps *caps)
+gst_median_link (GstPad * pad, const GstCaps * caps)
 {
-  GstMedian *filter;
-
-  filter = GST_MEDIAN (gst_pad_get_parent (pad));
-
-  if (!GST_CAPS_IS_FIXED (caps))
-    return GST_PAD_CONNECT_DELAYED;
+  GstMedian *filter = GST_MEDIAN (gst_pad_get_parent (pad));
+  GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
+  GstStructure *structure = gst_caps_get_structure (caps, 0);
+  gint w, h;
+  GstPadLinkReturn ret;
+
+  gst_structure_get_int (structure, "width", &w);
+  gst_structure_get_int (structure, "height", &h);
+
+  ret = gst_pad_try_set_caps (otherpad, caps);
+  if (GST_PAD_LINK_SUCCESSFUL (ret)) {
+    filter->width = w;
+    filter->height = h;
+  }
 
-  filter->width = gst_caps_get_int (caps, "width");
-  filter->height = gst_caps_get_int (caps, "height");
+  gst_object_unref (filter);
 
-  return GST_PAD_CONNECT_OK;
+  return ret;
 }
 
-void gst_median_init (GstMedian *median)
+void
+gst_median_init (GstMedian * median)
 {
-  median->sinkpad = gst_pad_new_from_template (
-                 GST_PADTEMPLATE_GET (median_sink_factory), "sink");
-  gst_pad_set_connect_function (median->sinkpad, gst_median_sinkconnect);
+  median->sinkpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&median_sink_factory), "sink");
+  gst_pad_set_getcaps_function (median->sinkpad, gst_pad_proxy_getcaps);
+  gst_pad_set_link_function (median->sinkpad, gst_median_link);
   gst_pad_set_chain_function (median->sinkpad, gst_median_chain);
   gst_element_add_pad (GST_ELEMENT (median), median->sinkpad);
 
-  median->srcpad = gst_pad_new_from_template (
-                 GST_PADTEMPLATE_GET (median_src_factory), "src");
+  median->srcpad =
+      gst_pad_new_from_template (gst_static_pad_template_get
+      (&median_src_factory), "src");
+  gst_pad_set_getcaps_function (median->srcpad, gst_pad_proxy_getcaps);
+  gst_pad_set_link_function (median->sinkpad, gst_median_link);
   gst_element_add_pad (GST_ELEMENT (median), median->srcpad);
 
   median->filtersize = 5;
@@ -172,7 +197,7 @@ median_5 (unsigned char *src, unsigned char *dest, int width, int height)
   nLastRow = height - 1;
 
   /*copy the top and bottom rows into the result array */
-  for (i=0; i<width; i++) {
+  for (i = 0; i < width; i++) {
     dest[i] = src[i];
     dest[nLastRow * width + i] = src[nLastRow * width + i];
   }
@@ -183,22 +208,29 @@ median_5 (unsigned char *src, unsigned char *dest, int width, int height)
 
   /* process the interior pixels */
   i = width + 1;
-  for (k=0; k < nLastRow; k++) {
-    for (j=0; j < nLastCol; j++, i++) {
-      p[0] = src[i-width];
-      p[1] = src[i-1];
+  for (k = 0; k < nLastRow; k++) {
+    for (j = 0; j < nLastCol; j++, i++) {
+      p[0] = src[i - width];
+      p[1] = src[i - 1];
       p[2] = src[i];
-      p[3] = src[i+1];
-      p[4] = src[i+width];
-      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]) ;
+      p[3] = src[i + 1];
+      p[4] = src[i + width];
+      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++];
-    dest[i] = src[i++];
+    dest[i] = src[i];
+    i++;
+    dest[i] = src[i];
+    i++;
   }
-  dest[i] = src[i++];
+  dest[i] = src[i];
+  i++;
 }
 
 static void
@@ -213,7 +245,7 @@ median_9 (unsigned char *src, unsigned char *dest, int width, int height)
   nLastRow = height - 1;
 
   /*copy the top and bottom rows into the result array */
-  for (i=0; i<width; i++) {
+  for (i = 0; i < width; i++) {
     dest[i] = src[i];
     dest[nLastRow * width + i] = src[nLastRow * width + i];
   }
@@ -224,110 +256,132 @@ median_9 (unsigned char *src, unsigned char *dest, int width, int height)
 
   /* process the interior pixels */
   i = width + 1;
-  for (k=0; k < nLastRow; k++) {
-    for (j=0; j < nLastCol; j++, i++) {
-      p[0] = src[i-width-1];
-      p[1] = src[i-width];
-      p[2] = src[i-width+1];
-      p[3] = src[i-1];
+  for (k = 0; k < nLastRow; k++) {
+    for (j = 0; j < nLastCol; j++, i++) {
+      p[0] = src[i - width - 1];
+      p[1] = src[i - width];
+      p[2] = src[i - width + 1];
+      p[3] = src[i - 1];
       p[4] = src[i];
-      p[5] = src[i+1];
-      p[6] = src[i+width-1];
-      p[7] = src[i+width];
-      p[8] = src[i+width+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]) ;
+      p[5] = src[i + 1];
+      p[6] = src[i + width - 1];
+      p[7] = src[i + width];
+      p[8] = src[i + width + 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++];
-    dest[i] = src[i++];
+    dest[i] = src[i];
+    i++;
+    dest[i] = src[i];
+    i++;
   }
-  dest[i] = src[i++];
+  dest[i] = src[i];
+  i++;
 }
 
 static void
-gst_median_chain (GstPad *pad, GstBuffer *buf)
+gst_median_chain (GstPad * pad, GstData * _data)
 {
+  GstBuffer *buf = GST_BUFFER (_data);
   GstMedian *median;
   guchar *data;
   gulong size;
   GstBuffer *outbuf;
+
 /*  GstMeta *meta; */
   int lumsize, chromsize;
 
-  g_return_if_fail(pad != NULL);
-  g_return_if_fail(GST_IS_PAD(pad));
-  g_return_if_fail(buf != NULL);
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
 
   median = GST_MEDIAN (GST_OBJECT_PARENT (pad));
 
   if (!median->active) {
-    gst_pad_push(median->srcpad,buf);
+    gst_pad_push (median->srcpad, GST_DATA (buf));
     return;
   }
 
-  data = GST_BUFFER_DATA(buf);
-  size = GST_BUFFER_SIZE(buf);
+  data = GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
 
-  GST_DEBUG (0,"median: have buffer of %d", GST_BUFFER_SIZE(buf));
+  GST_DEBUG ("median: have buffer of %d", GST_BUFFER_SIZE (buf));
 
-  outbuf = gst_buffer_new();
-  GST_BUFFER_DATA(outbuf) = g_malloc(GST_BUFFER_SIZE(buf));
-  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf);
+  outbuf = gst_buffer_new ();
+  GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (buf));
+  GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf);
 
   lumsize = median->width * median->height;
-  chromsize = lumsize/4;
+  chromsize = lumsize / 4;
 
   if (median->filtersize == 5) {
-    median_5(data, GST_BUFFER_DATA(outbuf), median->width, median->height);
+    median_5 (data, GST_BUFFER_DATA (outbuf), median->width, median->height);
     if (!median->lum_only) {
-      median_5(data+lumsize, GST_BUFFER_DATA(outbuf)+lumsize, median->width/2, median->height/2);
-      median_5(data+lumsize+chromsize, GST_BUFFER_DATA(outbuf)+lumsize+chromsize, median->width/2, median->height/2);
+      median_5 (data + lumsize, GST_BUFFER_DATA (outbuf) + lumsize,
+          median->width / 2, median->height / 2);
+      median_5 (data + lumsize + chromsize,
+          GST_BUFFER_DATA (outbuf) + lumsize + chromsize, median->width / 2,
+          median->height / 2);
+    } else {
+      memcpy (GST_BUFFER_DATA (outbuf) + lumsize, data + lumsize,
+          chromsize * 2);
     }
-    else {
-      memcpy (GST_BUFFER_DATA (outbuf)+lumsize, data+lumsize, chromsize*2);
-    }
-  }
-  else {
-    median_9(data, GST_BUFFER_DATA(outbuf), median->width, median->height);
+  } else {
+    median_9 (data, GST_BUFFER_DATA (outbuf), median->width, median->height);
     if (!median->lum_only) {
-      median_9(data+lumsize, GST_BUFFER_DATA(outbuf)+lumsize, median->width/2, median->height/2);
-      median_9(data+lumsize+chromsize, GST_BUFFER_DATA(outbuf)+lumsize+chromsize, median->width/2, median->height/2);
-    }
-    else {
-      memcpy (GST_BUFFER_DATA (outbuf)+lumsize, data+lumsize, chromsize*2);
+      median_9 (data + lumsize, GST_BUFFER_DATA (outbuf) + lumsize,
+          median->width / 2, median->height / 2);
+      median_9 (data + lumsize + chromsize,
+          GST_BUFFER_DATA (outbuf) + lumsize + chromsize, median->width / 2,
+          median->height / 2);
+    } else {
+      memcpy (GST_BUFFER_DATA (outbuf) + lumsize, data + lumsize,
+          chromsize * 2);
     }
   }
   GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
 
-  gst_buffer_unref(buf);
+  gst_buffer_unref (buf);
 
-  gst_pad_push(median->srcpad,outbuf);
+  gst_pad_push (median->srcpad, GST_DATA (outbuf));
 }
 
 static void
-gst_median_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+gst_median_set_property (GObject * object, guint prop_id, const GValue * value,
+    GParamSpec * pspec)
 {
   GstMedian *median;
   gint argvalue;
 
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail(GST_IS_MEDIAN(object));
-  median = GST_MEDIAN(object);
+  g_return_if_fail (GST_IS_MEDIAN (object));
+  median = GST_MEDIAN (object);
 
   switch (prop_id) {
     case ARG_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;
+        g_warning ("median: invalid filtersize (%d), must be 5 or 9\n",
+            argvalue);
+      else {
+        median->filtersize = argvalue;
       }
       break;
     case ARG_ACTIVE:
@@ -342,13 +396,13 @@ gst_median_set_property (GObject *object, guint prop_id, const GValue *value, GP
 }
 
 static void
-gst_median_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+gst_median_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
 {
   GstMedian *median;
 
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail(GST_IS_MEDIAN(object));
-  median = GST_MEDIAN(object);
+  g_return_if_fail (GST_IS_MEDIAN (object));
+  median = GST_MEDIAN (object);
 
   switch (prop_id) {
     case ARG_FILTERSIZE:
@@ -368,26 +422,14 @@ gst_median_get_property (GObject *object, guint prop_id, GValue *value, GParamSp
 
 
 static gboolean
-plugin_init (GModule *module, GstPlugin *plugin)
+plugin_init (GstPlugin * plugin)
 {
-  GstElementFactory *factory;
-
-  factory = gst_elementfactory_new("median",GST_TYPE_MEDIAN,
-                                   &median_details);
-  g_return_val_if_fail(factory != NULL, FALSE);
-
-  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (median_sink_factory));
-  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (median_src_factory));
-
-  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
-
-  return TRUE;
+  return gst_element_register (plugin, "median",
+      GST_RANK_NONE, GST_TYPE_MEDIAN);
 }
 
-GstPluginDesc plugin_desc = {
-  GST_VERSION_MAJOR,
-  GST_VERSION_MINOR,
-  "median",
-  plugin_init
-};
-
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "median",
+    "Video median filter",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)