* 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
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;
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;
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);
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:
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;
+}