various: fix pad template leaks
[platform/upstream/gstreamer.git] / gst / effectv / gstvertigo.c
index 6faa8cb..51b1f90 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/**
+ * SECTION:element-vertigotv
+ *
+ * VertigoTV is a loopback alpha blending effector with rotating and scaling.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc ! vertigotv ! ffmpegcolorspace ! autovideosink
+ * ]| This pipeline shows the effect of vertigotv on a test stream.
+ * </refsect2>
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
 #include <math.h>
 #include <string.h>
-#include <gst/gst.h>
-#include <gstvideofilter.h>
-
-#define GST_TYPE_VERTIGOTV \
-  (gst_vertigotv_get_type())
-#define GST_VERTIGOTV(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VERTIGOTV,GstVertigoTV))
-#define GST_VERTIGOTV_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VERTIGOTV,GstVertigoTVClass))
-#define GST_IS_VERTIGOTV(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VERTIGOTV))
-#define GST_IS_VERTIGOTV_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VERTIGOTV))
-
-typedef struct _GstVertigoTV GstVertigoTV;
-typedef struct _GstVertigoTVClass GstVertigoTVClass;
-
-struct _GstVertigoTV
-{
-  GstVideofilter videofilter;
-
-  gint width, height;
-  guint32 *buffer;
-  guint32 *current_buffer, *alt_buffer;
-  gint dx, dy;
-  gint sx, sy;
-  gdouble phase;
-  gdouble phase_increment;
-  gdouble zoomrate;
-};
 
-struct _GstVertigoTVClass
-{
-  GstVideofilterClass parent_class;
+#include "gstvertigo.h"
 
-  void (*reset) (GstElement * element);
-};
+#include <gst/video/video.h>
+#include <gst/controller/gstcontroller.h>
 
-/* Filter signals and args */
-enum
-{
-  /* FILL ME */
-  RESET_SIGNAL,
-  LAST_SIGNAL
-};
+GST_BOILERPLATE (GstVertigoTV, gst_vertigotv, GstVideoFilter,
+    GST_TYPE_VIDEO_FILTER);
 
+/* Filter signals and args */
 enum
 {
-  ARG_0,
-  ARG_SPEED,
-  ARG_ZOOM_SPEED,
+  PROP_0,
+  PROP_SPEED,
+  PROP_ZOOM_SPEED
 };
 
-static void gst_vertigotv_base_init (gpointer g_class);
-static void gst_vertigotv_class_init (GstVertigoTVClass * klass,
-    gpointer class_data);
-static void gst_vertigotv_init (GTypeInstance * instance, gpointer g_class);
-static void gst_vertigotv_setup (GstVideofilter * videofilter);
-
-static void gst_vertigotv_reset_handler (GstElement * element);
-
-static void gst_vertigotv_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_vertigotv_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_vertigotv_rgb32 (GstVideofilter * videofilter, void *d,
-    void *s);
-
-static guint gst_vertigotv_signals[LAST_SIGNAL] = { 0 };
-
-GType
-gst_vertigotv_get_type (void)
-{
-  static GType vertigotv_type = 0;
-
-  if (!vertigotv_type) {
-    static const GTypeInfo vertigotv_info = {
-      sizeof (GstVertigoTVClass),
-      gst_vertigotv_base_init,
-      NULL,
-      (GClassInitFunc) gst_vertigotv_class_init,
-      NULL,
-      NULL,
-      sizeof (GstVertigoTV),
-      0,
-      (GInstanceInitFunc) gst_vertigotv_init,
-    };
-
-    vertigotv_type =
-       g_type_register_static (GST_TYPE_VIDEOFILTER, "GstVertigoTV",
-       &vertigotv_info, 0);
-  }
-  return vertigotv_type;
-}
-
-static GstVideofilterFormat gst_vertigotv_formats[] = {
-  {"RGB ", 32, gst_vertigotv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000,
-      0xff000000}
-};
-
-static void
-gst_vertigotv_base_init (gpointer g_class)
-{
-  /* elementfactory information */
-  static GstElementDetails vertigotv_details = GST_ELEMENT_DETAILS ("VertigoTV",
-      "Filter/Effect/Video",
-      "A loopback alpha blending effector with rotating and scaling",
-      "Wim Taymans <wim.taymans@chello.be>");
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
-  int i;
-
-  gst_element_class_set_details (element_class, &vertigotv_details);
-
-  for (i = 0; i < G_N_ELEMENTS (gst_vertigotv_formats); i++) {
-    gst_videofilter_class_add_format (videofilter_class,
-       gst_vertigotv_formats + i);
-  }
-
-  gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
-}
-
-static void
-gst_vertigotv_class_init (GstVertigoTVClass * klass, gpointer class_data)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstVideofilterClass *videofilter_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  videofilter_class = GST_VIDEOFILTER_CLASS (klass);
-
-  gst_vertigotv_signals[RESET_SIGNAL] =
-      g_signal_new ("reset-parms",
-      G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-      G_STRUCT_OFFSET (GstVertigoTVClass, reset),
-      NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
-  klass->reset = gst_vertigotv_reset_handler;
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SPEED,
-      g_param_spec_float ("speed", "Speed", "Control the speed of movement",
-         0.01, 100.0, 0.02, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ZOOM_SPEED,
-      g_param_spec_float ("zoom_speed", "Zoom Speed",
-         "Control the rate of zooming", 1.01, 1.1, 1.01, G_PARAM_READWRITE));
-
-  gobject_class->set_property = gst_vertigotv_set_property;
-  gobject_class->get_property = gst_vertigotv_get_property;
-
-  videofilter_class->setup = gst_vertigotv_setup;
-}
-
-static void
-gst_vertigotv_reset_handler (GstElement * element)
-{
-  GstVertigoTV *filter = GST_VERTIGOTV (element);
-
-  filter->phase = 0.0;
-  filter->phase_increment = 0.02;
-  filter->zoomrate = 1.01;
-}
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define CAPS_STR GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx
+#else
+#define CAPS_STR GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR
+#endif
 
-static void
-gst_vertigotv_setup (GstVideofilter * videofilter)
+static GstStaticPadTemplate gst_vertigotv_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (CAPS_STR)
+    );
+
+static GstStaticPadTemplate gst_vertigotv_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (CAPS_STR)
+    );
+
+static gboolean
+gst_vertigotv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
+    GstCaps * outcaps)
 {
-  GstVertigoTV *filter;
-  gint area;
-  int width = gst_videofilter_get_input_width (videofilter);
-  int height = gst_videofilter_get_input_height (videofilter);
+  GstVertigoTV *filter = GST_VERTIGOTV (btrans);
+  GstStructure *structure;
+  gboolean ret = FALSE;
 
-  g_return_if_fail (GST_IS_VERTIGOTV (videofilter));
-  filter = GST_VERTIGOTV (videofilter);
+  structure = gst_caps_get_structure (incaps, 0);
 
-  filter->width = width;
-  filter->height = height;
+  GST_OBJECT_LOCK (filter);
+  if (gst_structure_get_int (structure, "width", &filter->width) &&
+      gst_structure_get_int (structure, "height", &filter->height)) {
+    gint area = filter->width * filter->height;
 
-  area = width * height;
-
-  g_free (filter->buffer);
-  filter->buffer = (guint32 *) g_malloc (area * 2 * sizeof (guint32));
+    g_free (filter->buffer);
+    filter->buffer = (guint32 *) g_malloc0 (area * 2 * sizeof (guint32));
 
-  memset (filter->buffer, 0, area * 2 * sizeof (guint32));
-  filter->current_buffer = filter->buffer;
-  filter->alt_buffer = filter->buffer + area;
-  filter->phase = 0;
-}
+    filter->current_buffer = filter->buffer;
+    filter->alt_buffer = filter->buffer + area;
+    filter->phase = 0;
 
-static void
-gst_vertigotv_init (GTypeInstance * instance, gpointer g_class)
-{
-  GstVertigoTV *filter = GST_VERTIGOTV (instance);
+    ret = TRUE;
+  }
+  GST_OBJECT_UNLOCK (filter);
 
-  filter->buffer = NULL;
-  filter->phase = 0.0;
-  filter->phase_increment = 0.02;
-  filter->zoomrate = 1.01;
+  return ret;
 }
 
 static void
@@ -246,22 +124,22 @@ gst_vertigotv_set_parms (GstVertigoTV * filter)
   if (filter->width > filter->height) {
     if (dizz >= 0) {
       if (dizz > x)
-       dizz = x;
+        dizz = x;
       vx = (x * (x - dizz) + y * y) / t;
     } else {
       if (dizz < -x)
-       dizz = -x;
+        dizz = -x;
       vx = (x * (x + dizz) + y * y) / t;
     }
     vy = (dizz * y) / t;
   } else {
     if (dizz >= 0) {
       if (dizz > y)
-       dizz = y;
+        dizz = y;
       vx = (x * x + y * (y - dizz)) / t;
     } else {
       if (dizz < -y)
-       dizz = -y;
+        dizz = -y;
       vx = (x * x + y * (y + dizz)) / t;
     }
     vy = (dizz * x) / t;
@@ -276,22 +154,31 @@ gst_vertigotv_set_parms (GstVertigoTV * filter)
     filter->phase = 0;
 }
 
-static void
-gst_vertigotv_rgb32 (GstVideofilter * videofilter, void *d, void *s)
+static GstFlowReturn
+gst_vertigotv_transform (GstBaseTransform * trans, GstBuffer * in,
+    GstBuffer * out)
 {
-  GstVertigoTV *filter;
-  guint32 *src, *dest;
-  guint32 *p;
+  GstVertigoTV *filter = GST_VERTIGOTV (trans);
+  guint32 *src, *dest, *p;
   guint32 v;
-  gint x, y;
-  gint ox, oy;
-  gint i;
-  gint width, height, area;
+  gint x, y, ox, oy, i, width, height, area;
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstClockTime timestamp, stream_time;
+
+  timestamp = GST_BUFFER_TIMESTAMP (in);
+  stream_time =
+      gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, timestamp);
+
+  GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (timestamp));
 
-  filter = GST_VERTIGOTV (videofilter);
+  if (GST_CLOCK_TIME_IS_VALID (stream_time))
+    gst_object_sync_values (G_OBJECT (filter), stream_time);
 
-  src = (guint32 *) s;
-  dest = (guint32 *) d;
+  src = (guint32 *) GST_BUFFER_DATA (in);
+  dest = (guint32 *) GST_BUFFER_DATA (out);
+
+  GST_OBJECT_LOCK (filter);
 
   width = filter->width;
   height = filter->height;
@@ -307,9 +194,9 @@ gst_vertigotv_rgb32 (GstVideofilter * videofilter, void *d, void *s)
     for (x = width; x > 0; x--) {
       i = (oy >> 16) * width + (ox >> 16);
       if (i < 0)
-       i = 0;
+        i = 0;
       if (i >= area)
-       i = area;
+        i = area;
 
       v = filter->current_buffer[i] & 0xfcfcff;
       v = (v * 3) + ((*src++) & 0xfcfcff);
@@ -327,47 +214,52 @@ gst_vertigotv_rgb32 (GstVideofilter * videofilter, void *d, void *s)
   p = filter->current_buffer;
   filter->current_buffer = filter->alt_buffer;
   filter->alt_buffer = p;
+  GST_OBJECT_UNLOCK (filter);
+
+  return ret;
+}
+
+static gboolean
+gst_vertigotv_start (GstBaseTransform * trans)
+{
+  GstVertigoTV *filter = GST_VERTIGOTV (trans);
+
+  filter->phase = 0.0;
+
+  return TRUE;
 }
 
 static void
 gst_vertigotv_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstVertigoTV *filter;
-
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_VERTIGOTV (object));
-
-  filter = GST_VERTIGOTV (object);
+  GstVertigoTV *filter = GST_VERTIGOTV (object);
 
+  GST_OBJECT_LOCK (filter);
   switch (prop_id) {
-    case ARG_SPEED:
+    case PROP_SPEED:
       filter->phase_increment = g_value_get_float (value);
       break;
-    case ARG_ZOOM_SPEED:
+    case PROP_ZOOM_SPEED:
       filter->zoomrate = g_value_get_float (value);
       break;
     default:
       break;
   }
+  GST_OBJECT_UNLOCK (filter);
 }
 
 static void
 gst_vertigotv_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
 {
-  GstVertigoTV *filter;
-
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_VERTIGOTV (object));
-
-  filter = GST_VERTIGOTV (object);
+  GstVertigoTV *filter = GST_VERTIGOTV (object);
 
   switch (prop_id) {
-    case ARG_SPEED:
+    case PROP_SPEED:
       g_value_set_float (value, filter->phase_increment);
       break;
-    case ARG_ZOOM_SPEED:
+    case PROP_ZOOM_SPEED:
       g_value_set_float (value, filter->zoomrate);
       break;
     default:
@@ -375,3 +267,62 @@ gst_vertigotv_get_property (GObject * object, guint prop_id, GValue * value,
       break;
   }
 }
+
+static void
+gst_vertigotv_finalize (GObject * object)
+{
+  GstVertigoTV *filter = GST_VERTIGOTV (object);
+
+  g_free (filter->buffer);
+  filter->buffer = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_vertigotv_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class, "VertigoTV effect",
+      "Filter/Effect/Video",
+      "A loopback alpha blending effector with rotating and scaling",
+      "Wim Taymans <wim.taymans@chello.be>");
+
+  gst_element_class_add_static_pad_template (element_class,
+      &gst_vertigotv_sink_template);
+  gst_element_class_add_static_pad_template (element_class,
+      &gst_vertigotv_src_template);
+}
+
+static void
+gst_vertigotv_class_init (GstVertigoTVClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+
+  gobject_class->set_property = gst_vertigotv_set_property;
+  gobject_class->get_property = gst_vertigotv_get_property;
+  gobject_class->finalize = gst_vertigotv_finalize;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SPEED,
+      g_param_spec_float ("speed", "Speed", "Control the speed of movement",
+          0.01, 100.0, 0.02, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ZOOM_SPEED,
+      g_param_spec_float ("zoom-speed", "Zoom Speed",
+          "Control the rate of zooming", 1.01, 1.1, 1.01,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  trans_class->start = GST_DEBUG_FUNCPTR (gst_vertigotv_start);
+  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_vertigotv_set_caps);
+  trans_class->transform = GST_DEBUG_FUNCPTR (gst_vertigotv_transform);
+}
+
+static void
+gst_vertigotv_init (GstVertigoTV * filter, GstVertigoTVClass * klass)
+{
+  filter->buffer = NULL;
+  filter->phase = 0.0;
+  filter->phase_increment = 0.02;
+  filter->zoomrate = 1.01;
+}