diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2010-02-12 11:21:23 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2010-02-12 11:35:17 +0100 |
commit | f79842e308c50f7e95d24ebb7f9214ba8a9c8804 (patch) | |
tree | 09967dd901250e6afab46f9abfc62c20985597f4 | |
parent | 68b644a43703d0b80d615895838e3047eb0bf15a (diff) | |
download | gstreamer-plugins-bad-f79842e308c50f7e95d24ebb7f9214ba8a9c8804.tar.gz |
Moved 'shapewipe' from -bad to -good
Fixes bug #584536.
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | docs/plugins/Makefile.am | 1 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-docs.sgml | 2 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-sections.txt | 15 | ||||
-rw-r--r-- | docs/plugins/inspect/plugin-shapewipe.xml | 40 | ||||
-rw-r--r-- | gst/shapewipe/Makefile.am | 11 | ||||
-rw-r--r-- | gst/shapewipe/gstshapewipe.c | 1181 | ||||
-rw-r--r-- | gst/shapewipe/gstshapewipe.h | 81 | ||||
-rw-r--r-- | tests/check/Makefile.am | 1 | ||||
-rw-r--r-- | tests/check/elements/shapewipe.c | 307 | ||||
-rw-r--r-- | tests/examples/Makefile.am | 4 | ||||
-rw-r--r-- | tests/examples/shapewipe/Makefile.am | 8 | ||||
-rw-r--r-- | tests/examples/shapewipe/shapewipe-example.c | 140 |
14 files changed, 6 insertions, 1794 deletions
diff --git a/Makefile.am b/Makefile.am index 18593b09b..3800f86b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,12 +43,14 @@ include $(top_srcdir)/common/coverage/lcov.mak CRUFT_FILES = \ $(top_builddir)/gst/aacparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \ - $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} + $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} CRUFT_DIRS = \ $(top_srcdir)/gst/aacparse \ $(top_srcdir)/gst/amrparse \ - $(top_srcdir)/gst/flacparse + $(top_srcdir)/gst/flacparse \ + $(top_srcdir)/gst/shapewipe include $(top_srcdir)/common/cruft.mak diff --git a/configure.ac b/configure.ac index 142492a64..6f8883278 100644 --- a/configure.ac +++ b/configure.ac @@ -290,7 +290,6 @@ AG_GST_CHECK_PLUGIN(rtpmux) AG_GST_CHECK_PLUGIN(scaletempo) AG_GST_CHECK_PLUGIN(sdp) AG_GST_CHECK_PLUGIN(selector) -AG_GST_CHECK_PLUGIN(shapewipe) AG_GST_CHECK_PLUGIN(siren) AG_GST_CHECK_PLUGIN(speed) AG_GST_CHECK_PLUGIN(subenc) @@ -1681,7 +1680,6 @@ gst/rtpmux/Makefile gst/scaletempo/Makefile gst/sdp/Makefile gst/selector/Makefile -gst/shapewipe/Makefile gst/siren/Makefile gst/speed/Makefile gst/subenc/Makefile @@ -1722,7 +1720,6 @@ tests/examples/camerabin/Makefile tests/examples/directfb/Makefile tests/examples/mxf/Makefile tests/examples/scaletempo/Makefile -tests/examples/shapewipe/Makefile tests/examples/switch/Makefile tests/icles/Makefile ext/alsaspdif/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index b9e3456ae..e184fc2c4 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -159,7 +159,6 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/sdp/gstsdpdemux.h \ $(top_srcdir)/gst/selector/gstinputselector.h \ $(top_srcdir)/gst/selector/gstoutputselector.h \ - $(top_srcdir)/gst/shapewipe/gstshapewipe.h \ $(top_srcdir)/gst/speed/gstspeed.h \ $(top_srcdir)/gst/stereo/gststereo.h \ $(top_srcdir)/gst/videosignal/gstvideoanalyse.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index 4cbe7b330..d87ffdcf7 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -80,7 +80,6 @@ <xi:include href="xml/element-sdlaudiosink.xml" /> <xi:include href="xml/element-sdlvideosink.xml" /> <xi:include href="xml/element-sdpdemux.xml" /> - <xi:include href="xml/element-shapewipe.xml" /> <xi:include href="xml/element-speed.xml" /> <xi:include href="xml/element-stereo.xml" /> <!--xi:include href="xml/element-theoradecexp.xml" /--> @@ -163,7 +162,6 @@ <xi:include href="xml/plugin-sdl.xml" /> <xi:include href="xml/plugin-sdp.xml" /> <xi:include href="xml/plugin-selector.xml" /> - <xi:include href="xml/plugin-shapewipe.xml" /> <xi:include href="xml/plugin-sndfile.xml" /> <xi:include href="xml/plugin-soundtouch.xml" /> <xi:include href="xml/plugin-spcdec.xml" /> diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 4cf934a62..508ef718c 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -1032,21 +1032,6 @@ gst_speed_get_type </SECTION> <SECTION> -<FILE>element-shapewipe</FILE> -<TITLE>shapewipe</TITLE> -GstShapeWipe -<SUBSECTION Standard> -GstShapeWipeClass -GST_SHAPE_WIPE -GST_SHAPE_WIPE_CLASS -GST_IS_SHAPE_WIPE -GST_IS_SHAPE_WIPE_CLASS -GST_TYPE_SHAPE_WIPE -gst_shape_wipe_get_type -</SECTION> - - -<SECTION> <FILE>element-stereo</FILE> <TITLE>stereo</TITLE> GstStereo diff --git a/docs/plugins/inspect/plugin-shapewipe.xml b/docs/plugins/inspect/plugin-shapewipe.xml deleted file mode 100644 index 590d36347..000000000 --- a/docs/plugins/inspect/plugin-shapewipe.xml +++ /dev/null @@ -1,40 +0,0 @@ -<plugin> - <name>shapewipe</name> - <description>Shape Wipe transition filter</description> - <filename>../../gst/shapewipe/.libs/libgstshapewipe.so</filename> - <basename>libgstshapewipe.so</basename> - <version>0.10.17.1</version> - <license>LGPL</license> - <source>gst-plugins-bad</source> - <package>GStreamer Bad Plug-ins git</package> - <origin>Unknown package origin</origin> - <elements> - <element> - <name>shapewipe</name> - <longname>Shape Wipe transition filter</longname> - <class>Filter/Editor/Video</class> - <description>Adds a shape wipe transition to a video stream</description> - <author>Sebastian Dröge <sebastian.droege@collabora.co.uk></author> - <pads> - <caps> - <name>src</name> - <direction>source</direction> - <presence>always</presence> - <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details> - </caps> - <caps> - <name>mask_sink</name> - <direction>sink</direction> - <presence>always</presence> - <details>video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)0/1; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)0/1</details> - </caps> - <caps> - <name>video_sink</name> - <direction>sink</direction> - <presence>always</presence> - <details>video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details> - </caps> - </pads> - </element> - </elements> -</plugin>
\ No newline at end of file diff --git a/gst/shapewipe/Makefile.am b/gst/shapewipe/Makefile.am deleted file mode 100644 index 7f6df3726..000000000 --- a/gst/shapewipe/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -plugin_LTLIBRARIES = libgstshapewipe.la - -libgstshapewipe_la_SOURCES = gstshapewipe.c - -libgstshapewipe_la_CFLAGS = $(GIO_CFLAGS) $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -libgstshapewipe_la_LIBADD = $(GIO_LIBS) $(GST_LIBS) $(GST_CONTROLLER_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstvideo-@GST_MAJORMINOR@ -libgstshapewipe_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstshapewipe_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = gstshapewipe.h - diff --git a/gst/shapewipe/gstshapewipe.c b/gst/shapewipe/gstshapewipe.c deleted file mode 100644 index 11f24c7f3..000000000 --- a/gst/shapewipe/gstshapewipe.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* GStreamer - * Copyright (C) 2009,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * 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. - */ - -/** - * SECTION:element-shapewipe - * - * The shapewipe element provides custom transitions on video streams - * based on a grayscale bitmap. The state of the transition can be - * controlled by the position property and an optional blended border - * can be added by the border property. - * - * Transition bitmaps can be downloaded from the - * <ulink url="http://cinelerra.org/transitions.php">Cinelerra transition</ulink> - * page. - * - * <refsect2> - * <title>Example launch line</title> - * |[ - * gst-launch -v videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe position=0.5 name=shape ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink filesrc location=mask.png ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer. - * ]| This pipeline adds the transition from mask.png with position 0.5 to an SMPTE test screen and snow. - * </refsect2> - */ - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <string.h> - -#include <gst/gst.h> -#include <gst/controller/gstcontroller.h> - -#include "gstshapewipe.h" - -static void gst_shape_wipe_finalize (GObject * object); -static void gst_shape_wipe_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_shape_wipe_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); - -static void gst_shape_wipe_reset (GstShapeWipe * self); -static void gst_shape_wipe_update_qos (GstShapeWipe * self, gdouble proportion, - GstClockTimeDiff diff, GstClockTime time); -static void gst_shape_wipe_reset_qos (GstShapeWipe * self); -static void gst_shape_wipe_read_qos (GstShapeWipe * self, gdouble * proportion, - GstClockTime * time); - -static GstStateChangeReturn gst_shape_wipe_change_state (GstElement * element, - GstStateChange transition); - -static GstFlowReturn gst_shape_wipe_video_sink_chain (GstPad * pad, - GstBuffer * buffer); -static gboolean gst_shape_wipe_video_sink_event (GstPad * pad, - GstEvent * event); -static gboolean gst_shape_wipe_video_sink_setcaps (GstPad * pad, - GstCaps * caps); -static GstCaps *gst_shape_wipe_video_sink_getcaps (GstPad * pad); -static GstFlowReturn gst_shape_wipe_video_sink_bufferalloc (GstPad * pad, - guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); -static gboolean gst_shape_wipe_video_sink_query (GstPad * pad, - GstQuery * query); -static GstFlowReturn gst_shape_wipe_mask_sink_chain (GstPad * pad, - GstBuffer * buffer); -static gboolean gst_shape_wipe_mask_sink_event (GstPad * pad, GstEvent * event); -static gboolean gst_shape_wipe_mask_sink_setcaps (GstPad * pad, GstCaps * caps); -static GstCaps *gst_shape_wipe_mask_sink_getcaps (GstPad * pad); -static gboolean gst_shape_wipe_src_event (GstPad * pad, GstEvent * event); -static GstCaps *gst_shape_wipe_src_getcaps (GstPad * pad); -static gboolean gst_shape_wipe_src_query (GstPad * pad, GstQuery * query); - -enum -{ - PROP_0, - PROP_POSITION, - PROP_BORDER -}; - -#define DEFAULT_POSITION 0.0 -#define DEFAULT_BORDER 0.0 - -static GstStaticPadTemplate video_sink_pad_template = - GST_STATIC_PAD_TEMPLATE ("video_sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB " ; " - GST_VIDEO_CAPS_BGRA)); - -static GstStaticPadTemplate mask_sink_pad_template = - GST_STATIC_PAD_TEMPLATE ("mask_sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-gray, " - "bpp = 8, " - "depth = 8, " - "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = 0/1 ; " - "video/x-raw-gray, " "bpp = 16, " "depth = 16, " - "endianness = BYTE_ORDER, " "width = " GST_VIDEO_SIZE_RANGE ", " - "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = 0/1")); - -static GstStaticPadTemplate src_pad_template = - GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB " ; " - GST_VIDEO_CAPS_BGRA)); - -GST_DEBUG_CATEGORY_STATIC (gst_shape_wipe_debug); -#define GST_CAT_DEFAULT gst_shape_wipe_debug - -GST_BOILERPLATE (GstShapeWipe, gst_shape_wipe, GstElement, GST_TYPE_ELEMENT); - -static void -gst_shape_wipe_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (gstelement_class, - "Shape Wipe transition filter", - "Filter/Editor/Video", - "Adds a shape wipe transition to a video stream", - "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&video_sink_pad_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&mask_sink_pad_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&src_pad_template)); -} - -static void -gst_shape_wipe_class_init (GstShapeWipeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = gst_shape_wipe_finalize; - gobject_class->set_property = gst_shape_wipe_set_property; - gobject_class->get_property = gst_shape_wipe_get_property; - - g_object_class_install_property (gobject_class, PROP_POSITION, - g_param_spec_float ("position", "Position", "Position of the mask", - 0.0, 1.0, DEFAULT_POSITION, - G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - g_object_class_install_property (gobject_class, PROP_BORDER, - g_param_spec_float ("border", "Border", "Border of the mask", - 0.0, 1.0, DEFAULT_BORDER, - G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_shape_wipe_change_state); -} - -static void -gst_shape_wipe_init (GstShapeWipe * self, GstShapeWipeClass * g_class) -{ - self->video_sinkpad = - gst_pad_new_from_static_template (&video_sink_pad_template, "video_sink"); - gst_pad_set_chain_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_chain)); - gst_pad_set_event_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_event)); - gst_pad_set_setcaps_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_setcaps)); - gst_pad_set_getcaps_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_getcaps)); - gst_pad_set_bufferalloc_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_bufferalloc)); - gst_pad_set_query_function (self->video_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_video_sink_query)); - gst_element_add_pad (GST_ELEMENT (self), self->video_sinkpad); - - self->mask_sinkpad = - gst_pad_new_from_static_template (&mask_sink_pad_template, "mask_sink"); - gst_pad_set_chain_function (self->mask_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_mask_sink_chain)); - gst_pad_set_event_function (self->mask_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_mask_sink_event)); - gst_pad_set_setcaps_function (self->mask_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_mask_sink_setcaps)); - gst_pad_set_getcaps_function (self->mask_sinkpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_mask_sink_getcaps)); - gst_element_add_pad (GST_ELEMENT (self), self->mask_sinkpad); - - self->srcpad = gst_pad_new_from_static_template (&src_pad_template, "src"); - gst_pad_set_event_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_src_event)); - gst_pad_set_getcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_src_getcaps)); - gst_pad_set_query_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_shape_wipe_src_query)); - gst_element_add_pad (GST_ELEMENT (self), self->srcpad); - - self->mask_mutex = g_mutex_new (); - self->mask_cond = g_cond_new (); - - gst_shape_wipe_reset (self); -} - -static void -gst_shape_wipe_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (object); - - switch (prop_id) { - case PROP_POSITION: - g_value_set_float (value, self->mask_position); - break; - case PROP_BORDER: - g_value_set_float (value, self->mask_border); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_shape_wipe_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (object); - - switch (prop_id) { - case PROP_POSITION:{ - gfloat f = g_value_get_float (value); - - GST_LOG_OBJECT (self, "Setting mask position: %f", f); - self->mask_position = f; - break; - } - case PROP_BORDER:{ - gfloat f = g_value_get_float (value); - - GST_LOG_OBJECT (self, "Setting mask border: %f", f); - self->mask_border = f; - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_shape_wipe_finalize (GObject * object) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (object); - - gst_shape_wipe_reset (self); - - if (self->mask_cond) - g_cond_free (self->mask_cond); - self->mask_cond = NULL; - - if (self->mask_mutex) - g_mutex_free (self->mask_mutex); - self->mask_mutex = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_shape_wipe_reset (GstShapeWipe * self) -{ - GST_DEBUG_OBJECT (self, "Resetting internal state"); - - if (self->mask) - gst_buffer_unref (self->mask); - self->mask = NULL; - - g_mutex_lock (self->mask_mutex); - g_cond_signal (self->mask_cond); - g_mutex_unlock (self->mask_mutex); - - self->fmt = GST_VIDEO_FORMAT_UNKNOWN; - self->width = self->height = 0; - self->mask_bpp = 0; - - gst_segment_init (&self->segment, GST_FORMAT_TIME); - - gst_shape_wipe_reset_qos (self); - self->frame_duration = 0; -} - -static GstFlowReturn -gst_shape_wipe_video_sink_bufferalloc (GstPad * pad, guint64 offset, guint size, - GstCaps * caps, GstBuffer ** buf) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - GstFlowReturn ret = GST_FLOW_OK; - - GST_LOG_OBJECT (pad, "Allocating buffer with offset 0x%" G_GINT64_MODIFIER - "x and size %u with caps: %" GST_PTR_FORMAT, offset, size, caps); - - *buf = NULL; - - ret = gst_pad_alloc_buffer (self->srcpad, offset, size, caps, buf); - if (G_UNLIKELY (ret != GST_FLOW_OK)) - GST_ERROR_OBJECT (pad, "Allocating buffer failed: %s", - gst_flow_get_name (ret)); - - gst_object_unref (self); - - return ret; -} - -static gboolean -gst_shape_wipe_video_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret = TRUE; - GstStructure *s; - GstVideoFormat fmt; - gint width, height; - gint fps_n, fps_d; - - GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps); - - s = gst_caps_get_structure (caps, 0); - - if (!gst_video_format_parse_caps (caps, &fmt, &width, &height) || - !gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) { - GST_ERROR_OBJECT (pad, "Invalid caps"); - ret = FALSE; - goto done; - } - - self->fmt = fmt; - if (self->width != width || self->height != height) { - g_mutex_lock (self->mask_mutex); - self->width = width; - self->height = height; - - if (self->mask) - gst_buffer_unref (self->mask); - self->mask = NULL; - g_mutex_unlock (self->mask_mutex); - } - - if (fps_n != 0) - self->frame_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); - else - self->frame_duration = 0; - - ret = gst_pad_set_caps (self->srcpad, caps); - -done: - gst_object_unref (self); - - return ret; -} - -static GstCaps * -gst_shape_wipe_video_sink_getcaps (GstPad * pad) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - GstCaps *ret, *tmp; - - if (GST_PAD_CAPS (pad)) - return gst_caps_copy (GST_PAD_CAPS (pad)); - - tmp = gst_pad_peer_get_caps (self->srcpad); - if (tmp) { - ret = gst_caps_intersect (tmp, gst_pad_get_pad_template_caps (pad)); - gst_caps_unref (tmp); - } else { - ret = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - } - - tmp = gst_pad_peer_get_caps (pad); - if (tmp) { - GstCaps *intersection; - - intersection = gst_caps_intersect (tmp, ret); - gst_caps_unref (tmp); - gst_caps_unref (ret); - ret = intersection; - } - - if (self->height && self->width) { - guint i, n; - - n = gst_caps_get_size (ret); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (ret, i); - - gst_structure_set (s, "width", G_TYPE_INT, self->width, "height", - G_TYPE_INT, self->height, NULL); - } - } - - tmp = gst_pad_peer_get_caps (self->mask_sinkpad); - if (tmp) { - GstCaps *intersection, *tmp2; - guint i, n; - - tmp = gst_caps_make_writable (tmp); - - tmp2 = gst_caps_copy (gst_pad_get_pad_template_caps (self->mask_sinkpad)); - - intersection = gst_caps_intersect (tmp, tmp2); - gst_caps_unref (tmp); - gst_caps_unref (tmp2); - tmp = intersection; - - n = gst_caps_get_size (tmp); - - tmp2 = gst_caps_new_empty (); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (tmp, i); - GstStructure *c; - - gst_structure_remove_fields (s, "format", "bpp", "depth", "endianness", - "framerate", "red_mask", "green_mask", "blue_mask", "alpha_mask", - NULL); - gst_structure_set_name (s, "video/x-raw-yuv"); - c = gst_structure_copy (s); - gst_structure_set_name (c, "video/x-raw-rgb"); - gst_caps_append_structure (tmp2, c); - } - gst_caps_append (tmp, tmp2); - - intersection = gst_caps_intersect (tmp, ret); - gst_caps_unref (tmp); - gst_caps_unref (ret); - ret = intersection; - } - - gst_object_unref (self); - - GST_LOG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, ret); - - return ret; -} - -static gboolean -gst_shape_wipe_mask_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret = TRUE; - GstStructure *s; - gint width, height, bpp; - - GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps); - - s = gst_caps_get_structure (caps, 0); - - if (!gst_structure_get_int (s, "width", &width) || - !gst_structure_get_int (s, "height", &height) || - !gst_structure_get_int (s, "bpp", &bpp)) { - ret = FALSE; - goto done; - } - - if ((self->width != width || self->height != height) && - self->width > 0 && self->height > 0) { - GST_ERROR_OBJECT (pad, "Mask caps must have the same width/height " - "as the video caps"); - ret = FALSE; - goto done; - } else { - self->width = width; - self->height = height; - } - - self->mask_bpp = bpp; - -done: - gst_object_unref (self); - - return ret; -} - -static GstCaps * -gst_shape_wipe_mask_sink_getcaps (GstPad * pad) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - GstCaps *ret, *tmp; - guint i, n; - - if (GST_PAD_CAPS (pad)) - return gst_caps_copy (GST_PAD_CAPS (pad)); - - tmp = gst_pad_peer_get_caps (self->video_sinkpad); - if (tmp) { - ret = - gst_caps_intersect (tmp, - gst_pad_get_pad_template_caps (self->video_sinkpad)); - gst_caps_unref (tmp); - } else { - ret = gst_caps_copy (gst_pad_get_pad_template_caps (self->video_sinkpad)); - } - - tmp = gst_pad_peer_get_caps (self->srcpad); - if (tmp) { - GstCaps *intersection; - - intersection = gst_caps_intersect (ret, tmp); - gst_caps_unref (ret); - gst_caps_unref (tmp); - ret = intersection; - } - - n = gst_caps_get_size (ret); - tmp = gst_caps_new_empty (); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (ret, i); - GstStructure *t; - - gst_structure_set_name (s, "video/x-raw-gray"); - gst_structure_remove_fields (s, "format", "framerate", "bpp", "depth", - "endianness", "framerate", "red_mask", "green_mask", "blue_mask", - "alpha_mask", NULL); - - if (self->width && self->height) - gst_structure_set (s, "width", G_TYPE_INT, self->width, "height", - G_TYPE_INT, self->height, NULL); - - gst_structure_set (s, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); - - t = gst_structure_copy (s); - - gst_structure_set (s, "bpp", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); - gst_structure_set (t, "bpp", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, NULL); - - gst_caps_append_structure (tmp, t); - } - gst_caps_append (ret, tmp); - - tmp = gst_pad_peer_get_caps (pad); - if (tmp) { - GstCaps *intersection; - - intersection = gst_caps_intersect (tmp, ret); - gst_caps_unref (tmp); - gst_caps_unref (ret); - ret = intersection; - } - - gst_object_unref (self); - - GST_LOG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, ret); - - return ret; -} - -static GstCaps * -gst_shape_wipe_src_getcaps (GstPad * pad) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - GstCaps *ret, *tmp; - - if (GST_PAD_CAPS (pad)) - return gst_caps_copy (GST_PAD_CAPS (pad)); - else if (GST_PAD_CAPS (self->video_sinkpad)) - return gst_caps_copy (GST_PAD_CAPS (self->video_sinkpad)); - - tmp = gst_pad_peer_get_caps (self->video_sinkpad); - if (tmp) { - ret = - gst_caps_intersect (tmp, - gst_pad_get_pad_template_caps (self->video_sinkpad)); - gst_caps_unref (tmp); - } else { - ret = gst_caps_copy (gst_pad_get_pad_template_caps (self->video_sinkpad)); - } - - tmp = gst_pad_peer_get_caps (pad); - if (tmp) { - GstCaps *intersection; - - intersection = gst_caps_intersect (tmp, ret); - gst_caps_unref (tmp); - gst_caps_unref (ret); - ret = intersection; - } - - if (self->height && self->width) { - guint i, n; - - n = gst_caps_get_size (ret); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (ret, i); - - gst_structure_set (s, "width", G_TYPE_INT, self->width, "height", - G_TYPE_INT, self->height, NULL); - } - } - - tmp = gst_pad_peer_get_caps (self->mask_sinkpad); - if (tmp) { - GstCaps *intersection, *tmp2; - guint i, n; - - tmp = gst_caps_make_writable (tmp); - tmp2 = gst_caps_copy (gst_pad_get_pad_template_caps (self->mask_sinkpad)); - - intersection = gst_caps_intersect (tmp, tmp2); - gst_caps_unref (tmp); - gst_caps_unref (tmp2); - - tmp = intersection; - n = gst_caps_get_size (tmp); - - tmp2 = gst_caps_new_empty (); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (tmp, i); - GstStructure *c; - - gst_structure_remove_fields (s, "format", "bpp", "depth", "endianness", - "framerate", "red_mask", "green_mask", "blue_mask", "alpha_mask", - NULL); - gst_structure_set_name (s, "video/x-raw-yuv"); - c = gst_structure_copy (s); - - gst_caps_append_structure (tmp2, c); - } - gst_caps_append (tmp, tmp2); - - intersection = gst_caps_intersect (tmp, ret); - gst_caps_unref (tmp); - gst_caps_unref (ret); - ret = intersection; - } - - gst_object_unref (self); - - GST_LOG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, ret); - - return ret; -} - -static gboolean -gst_shape_wipe_video_sink_query (GstPad * pad, GstQuery * query) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret; - GstPad *peer = gst_pad_get_peer (self->srcpad); - - GST_LOG_OBJECT (pad, "Handling query of type '%s'", - gst_query_type_get_name (GST_QUERY_TYPE (query))); - - if (!peer) { - GST_INFO_OBJECT (pad, "No peer yet, dropping query"); - ret = FALSE; - } else { - ret = gst_pad_query (peer, query); - gst_object_unref (peer); - } - - gst_object_unref (self); - return ret; -} - -static gboolean -gst_shape_wipe_src_query (GstPad * pad, GstQuery * query) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret; - GstPad *peer = gst_pad_get_peer (self->video_sinkpad); - - GST_LOG_OBJECT (pad, "Handling query of type '%s'", - gst_query_type_get_name (GST_QUERY_TYPE (query))); - - if (!peer) { - GST_INFO_OBJECT (pad, "No peer yet, dropping query"); - ret = FALSE; - } else { - ret = gst_pad_query (peer, query); - gst_object_unref (peer); - } - - gst_object_unref (self); - return ret; -} - -static void -gst_shape_wipe_update_qos (GstShapeWipe * self, gdouble proportion, - GstClockTimeDiff diff, GstClockTime timestamp) -{ - GST_OBJECT_LOCK (self); - self->proportion = proportion; - if (G_LIKELY (timestamp != GST_CLOCK_TIME_NONE)) { - if (G_UNLIKELY (diff > 0)) - self->earliest_time = timestamp + 2 * diff + self->frame_duration; - else - self->earliest_time = timestamp + diff; - } else { - self->earliest_time = GST_CLOCK_TIME_NONE; - } - GST_OBJECT_UNLOCK (self); -} - -static void -gst_shape_wipe_reset_qos (GstShapeWipe * self) -{ - gst_shape_wipe_update_qos (self, 0.5, 0, GST_CLOCK_TIME_NONE); -} - -static void -gst_shape_wipe_read_qos (GstShapeWipe * self, gdouble * proportion, - GstClockTime * time) -{ - GST_OBJECT_LOCK (self); - *proportion = self->proportion; - *time = self->earliest_time; - GST_OBJECT_UNLOCK (self); -} - -/* Perform qos calculations before processing the next frame. Returns TRUE if - * the frame should be processed, FALSE if the frame can be dropped entirely */ -static gboolean -gst_shape_wipe_do_qos (GstShapeWipe * self, GstClockTime timestamp) -{ - GstClockTime qostime, earliest_time; - gdouble proportion; - - /* no timestamp, can't do QoS => process frame */ - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp))) { - GST_LOG_OBJECT (self, "invalid timestamp, can't do QoS, process frame"); - return TRUE; - } - - /* get latest QoS observation values */ - gst_shape_wipe_read_qos (self, &proportion, &earliest_time); - - /* skip qos if we have no observation (yet) => process frame */ - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) { - GST_LOG_OBJECT (self, "no observation yet, process frame"); - return TRUE; - } - - /* qos is done on running time */ - qostime = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME, - timestamp); - - /* see how our next timestamp relates to the latest qos timestamp */ - GST_LOG_OBJECT (self, "qostime %" GST_TIME_FORMAT ", earliest %" - GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (earliest_time)); - - if (qostime != GST_CLOCK_TIME_NONE && qostime <= earliest_time) { - GST_DEBUG_OBJECT (self, "we are late, drop frame"); - return FALSE; - } - - GST_LOG_OBJECT (self, "process frame"); - return TRUE; -} - -#define CREATE_AYUV_FUNCTIONS(depth, shift) \ -static void \ -gst_shape_wipe_blend_ayuv_##depth (GstShapeWipe * self, GstBuffer * inbuf, \ - GstBuffer * maskbuf, GstBuffer * outbuf) \ -{ \ - const guint##depth *mask = (const guint##depth *) GST_BUFFER_DATA (maskbuf); \ - const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf); \ - guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf); \ - guint i, j; \ - guint mask_increment = ((depth == 16) ? GST_ROUND_UP_2 (self->width) : \ - GST_ROUND_UP_4 (self->width)) - self->width; \ - gfloat position = self->mask_position; \ - gfloat low = position - (self->mask_border / 2.0f); \ - gfloat high = position + (self->mask_border / 2.0f); \ - guint32 low_i, high_i, position_i, round_i; \ - gint width = self->width, height = self->height; \ - \ - if (low < 0.0f) { \ - high = 0.0f; \ - low = 0.0f; \ - } \ - \ - if (high > 1.0f) { \ - low = 1.0f; \ - high = 1.0f; \ - } \ - \ - position_i = position * 65536; \ - low_i = low * 65536; \ - high_i = high * 65536; \ - round_i = (high_i - low_i) >> 1; \ - \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < width; j++) { \ - guint32 in = *mask << shift; \ - \ - if (in < low_i) { \ - output[0] = 0x00; /* A */ \ - output[1] = input[1]; /* Y */ \ - output[2] = input[2]; /* U */ \ - output[3] = input[3]; /* V */ \ - } else if (in >= high_i) { \ - output[0] = input[0]; /* A */ \ - output[1] = input[1]; /* Y */ \ - output[2] = input[2]; /* U */ \ - output[3] = input[3]; /* V */ \ - } else { \ - guint32 val; \ - /* Note: This will never overflow or be larger than 255! */ \ - val = (((in - low_i) << 16) + round_i) / (high_i - low_i); \ - val = (val * input[0] + 32768) >> 16; \ - \ - output[0] = val; /* A */ \ - output[1] = input[1]; /* Y */ \ - output[2] = input[2]; /* U */ \ - output[3] = input[3]; /* V */ \ - } \ - \ - mask++; \ - input += 4; \ - output += 4; \ - } \ - mask += mask_increment; \ - } \ -} - -CREATE_AYUV_FUNCTIONS (16, 0); -CREATE_AYUV_FUNCTIONS (8, 8); - -#define CREATE_ARGB_FUNCTIONS(depth, name, shift, a, r, g, b) \ -static void \ -gst_shape_wipe_blend_##name##_##depth (GstShapeWipe * self, GstBuffer * inbuf, \ - GstBuffer * maskbuf, GstBuffer * outbuf) \ -{ \ - const guint##depth *mask = (const guint##depth *) GST_BUFFER_DATA (maskbuf); \ - const guint8 *input = (const guint8 *) GST_BUFFER_DATA (inbuf); \ - guint8 *output = (guint8 *) GST_BUFFER_DATA (outbuf); \ - guint i, j; \ - guint mask_increment = ((depth == 16) ? GST_ROUND_UP_2 (self->width) : \ - GST_ROUND_UP_4 (self->width)) - self->width; \ - gfloat position = self->mask_position; \ - gfloat low = position - (self->mask_border / 2.0f); \ - gfloat high = position + (self->mask_border / 2.0f); \ - guint32 low_i, high_i, position_i, round_i; \ - gint width = self->width, height = self->height; \ - \ - if (low < 0.0f) { \ - high = 0.0f; \ - low = 0.0f; \ - } \ - \ - if (high > 1.0f) { \ - low = 1.0f; \ - high = 1.0f; \ - } \ - \ - position_i = position * 65536; \ - low_i = low * 65536; \ - high_i = high * 65536; \ - round_i = (high_i - low_i) >> 1; \ - \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < width; j++) { \ - guint32 in = *mask << shift; \ - \ - if (in < low_i) { \ - output[a] = 0x00; /* A */ \ - output[r] = input[r]; /* R */ \ - output[g] = input[g]; /* G */ \ - output[b] = input[b]; /* B */ \ - } else if (in >= high_i) { \ - output[a] = input[a]; /* A */ \ - output[r] = input[r]; /* R */ \ - output[g] = input[g]; /* G */ \ - output[b] = input[b]; /* B */ \ - } else { \ - guint32 val; \ - /* Note: This will never overflow or be larger than 255! */ \ - val = (((in - low_i) << 16) + round_i) / (high_i - low_i); \ - val = (val * input[a] + 32768) >> 16; \ - \ - output[a] = val; /* A */ \ - output[r] = input[r]; /* R */ \ - output[g] = input[g]; /* G */ \ - output[b] = input[b]; /* B */ \ - } \ - \ - mask++; \ - input += 4; \ - output += 4; \ - } \ - mask += mask_increment; \ - } \ -} - -CREATE_ARGB_FUNCTIONS (16, argb, 0, 0, 1, 2, 3); -CREATE_ARGB_FUNCTIONS (8, argb, 8, 0, 1, 2, 3); - -CREATE_ARGB_FUNCTIONS (16, bgra, 0, 3, 2, 1, 0); -CREATE_ARGB_FUNCTIONS (8, bgra, 8, 3, 2, 1, 0); - -static GstFlowReturn -gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (GST_PAD_PARENT (pad)); - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *mask = NULL, *outbuf = NULL; - GstClockTime timestamp; - gboolean new_outbuf = FALSE; - - if (G_UNLIKELY (self->fmt == GST_VIDEO_FORMAT_UNKNOWN)) - goto not_negotiated; - - timestamp = GST_BUFFER_TIMESTAMP (buffer); - timestamp = - gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME, timestamp); - - if (GST_CLOCK_TIME_IS_VALID (timestamp)) - gst_object_sync_values (G_OBJECT (self), timestamp); - - GST_LOG_OBJECT (self, - "Blending buffer with timestamp %" GST_TIME_FORMAT " at position %f", - GST_TIME_ARGS (timestamp), self->mask_position); - - g_mutex_lock (self->mask_mutex); - if (self->shutdown) - goto shutdown; - - if (!self->mask) - g_cond_wait (self->mask_cond, self->mask_mutex); - - if (self->mask == NULL || self->shutdown) { - goto shutdown; - } else { - mask = gst_buffer_ref (self->mask); - } - g_mutex_unlock (self->mask_mutex); - - if (!gst_shape_wipe_do_qos (self, GST_BUFFER_TIMESTAMP (buffer))) - goto qos; - - /* Try to blend inplace, if it's not possible - * get a new buffer from downstream. */ - if (!gst_buffer_is_writable (buffer)) { - ret = - gst_pad_alloc_buffer_and_set_caps (self->srcpad, GST_BUFFER_OFFSET_NONE, - GST_BUFFER_SIZE (buffer), GST_PAD_CAPS (self->srcpad), &outbuf); - if (G_UNLIKELY (ret != GST_FLOW_OK)) - goto alloc_failed; - - gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_ALL); - new_outbuf = TRUE; - } else { - outbuf = buffer; - } - - if (self->fmt == GST_VIDEO_FORMAT_AYUV && self->mask_bpp == 16) - gst_shape_wipe_blend_ayuv_16 (self, buffer, mask, outbuf); - else if (self->fmt == GST_VIDEO_FORMAT_AYUV) - gst_shape_wipe_blend_ayuv_8 (self, buffer, mask, outbuf); - else if (self->fmt == GST_VIDEO_FORMAT_ARGB && self->mask_bpp == 16) - gst_shape_wipe_blend_argb_16 (self, buffer, mask, outbuf); - else if (self->fmt == GST_VIDEO_FORMAT_ARGB) - gst_shape_wipe_blend_argb_8 (self, buffer, mask, outbuf); - else if (self->fmt == GST_VIDEO_FORMAT_BGRA && self->mask_bpp == 16) - gst_shape_wipe_blend_bgra_16 (self, buffer, mask, outbuf); - else if (self->fmt == GST_VIDEO_FORMAT_BGRA) - gst_shape_wipe_blend_bgra_8 (self, buffer, mask, outbuf); - else - g_assert_not_reached (); - - gst_buffer_unref (mask); - if (new_outbuf) - gst_buffer_unref (buffer); - - ret = gst_pad_push (self->srcpad, outbuf); - if (G_UNLIKELY (ret != GST_FLOW_OK)) - goto push_failed; - - return ret; - - /* Errors */ -not_negotiated: - GST_ERROR_OBJECT (self, "No valid caps yet"); - gst_buffer_unref (buffer); - return GST_FLOW_NOT_NEGOTIATED; -shutdown: - GST_DEBUG_OBJECT (self, "Shutting down"); - gst_buffer_unref (buffer); - return GST_FLOW_WRONG_STATE; -qos: - GST_DEBUG_OBJECT (self, "Dropping buffer because of QoS"); - gst_buffer_unref (buffer); - gst_buffer_unref (mask); - return GST_FLOW_OK; -alloc_failed: - GST_ERROR_OBJECT (self, "Buffer allocation from downstream failed: %s", - gst_flow_get_name (ret)); - gst_buffer_unref (buffer); - gst_buffer_unref (mask); - return ret; -push_failed: - GST_ERROR_OBJECT (self, "Pushing buffer downstream failed: %s", - gst_flow_get_name (ret)); - return ret; -} - -static GstFlowReturn -gst_shape_wipe_mask_sink_chain (GstPad * pad, GstBuffer * buffer) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (GST_PAD_PARENT (pad)); - GstFlowReturn ret = GST_FLOW_OK; - - g_mutex_lock (self->mask_mutex); - GST_DEBUG_OBJECT (self, "Setting new mask buffer: %" GST_PTR_FORMAT, buffer); - - gst_buffer_replace (&self->mask, buffer); - g_cond_signal (self->mask_cond); - g_mutex_unlock (self->mask_mutex); - - gst_buffer_unref (buffer); - - return ret; -} - -static GstStateChangeReturn -gst_shape_wipe_change_state (GstElement * element, GstStateChange transition) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (element); - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - self->shutdown = FALSE; - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - /* Unblock video sink chain function */ - g_mutex_lock (self->mask_mutex); - self->shutdown = TRUE; - g_cond_signal (self->mask_cond); - g_mutex_unlock (self->mask_mutex); - break; - default: - break; - } - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_shape_wipe_reset (self); - break; - default: - break; - } - - return ret; -} - -static gboolean -gst_shape_wipe_video_sink_event (GstPad * pad, GstEvent * event) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret; - - GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT:{ - GstFormat fmt; - gboolean is_update; - gint64 start, end, base; - gdouble rate; - - gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start, - &end, &base); - if (fmt == GST_FORMAT_TIME) { - GST_DEBUG_OBJECT (pad, - "Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%" - GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start), - GST_TIME_ARGS (end)); - gst_segment_set_newsegment (&self->segment, is_update, rate, fmt, start, - end, base); - } else { - gst_segment_init (&self->segment, GST_FORMAT_TIME); - } - } - /* fall through */ - case GST_EVENT_FLUSH_STOP: - gst_shape_wipe_reset_qos (self); - /* fall through */ - default: - ret = gst_pad_push_event (self->srcpad, event); - break; - } - - gst_object_unref (self); - return ret; -} - -static gboolean -gst_shape_wipe_mask_sink_event (GstPad * pad, GstEvent * event) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - - GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - g_mutex_lock (self->mask_mutex); - gst_buffer_replace (&self->mask, NULL); - g_mutex_unlock (self->mask_mutex); - break; - default: - break; - } - - /* Dropping all events here */ - gst_event_unref (event); - - gst_object_unref (self); - return TRUE; -} - -static gboolean -gst_shape_wipe_src_event (GstPad * pad, GstEvent * event) -{ - GstShapeWipe *self = GST_SHAPE_WIPE (gst_pad_get_parent (pad)); - gboolean ret; - - GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_QOS:{ - GstClockTimeDiff diff; - GstClockTime timestamp; - gdouble proportion; - - gst_event_parse_qos (event, &proportion, &diff, ×tamp); - - gst_shape_wipe_update_qos (self, proportion, diff, timestamp); - } - /* fall through */ - default: - ret = gst_pad_push_event (self->video_sinkpad, event); - break; - } - - gst_object_unref (self); - return ret; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (gst_shape_wipe_debug, "shapewipe", 0, - "shapewipe element"); - - gst_controller_init (NULL, NULL); - - if (!gst_element_register (plugin, "shapewipe", GST_RANK_NONE, - GST_TYPE_SHAPE_WIPE)) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "shapewipe", - "Shape Wipe transition filter", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/shapewipe/gstshapewipe.h b/gst/shapewipe/gstshapewipe.h deleted file mode 100644 index 36b4fc552..000000000 --- a/gst/shapewipe/gstshapewipe.h +++ /dev/null @@ -1,81 +0,0 @@ -/* GStreamer - * Copyright (C) 2009,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * 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_SHAPE_WIPE_H__ -#define __GST_SHAPE_WIPE_H__ - -#include <gst/gst.h> -#include <gst/video/video.h> - -G_BEGIN_DECLS - -#define GST_TYPE_SHAPE_WIPE \ - (gst_shape_wipe_get_type()) -#define GST_SHAPE_WIPE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SHAPE_WIPE,GstShapeWipe)) -#define GST_SHAPE_WIPE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SHAPE_WIPE,GstShapeWipeClass)) -#define GST_SHAPE_WIPE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_SHAPE_WIPE,GstShapeWipeClass)) -#define GST_IS_SHAPE_WIPE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SHAPE_WIPE)) -#define GST_IS_SHAPE_WIPE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SHAPE_WIPE)) - -typedef struct _GstShapeWipe GstShapeWipe; -typedef struct _GstShapeWipeClass GstShapeWipeClass; - -struct _GstShapeWipe -{ - GstElement parent; - - /* private */ - GstPad *video_sinkpad; - GstPad *mask_sinkpad; - - GstPad *srcpad; - - GstSegment segment; - - GstBuffer *mask; - gfloat mask_position; - gfloat mask_border; - GMutex *mask_mutex; - GCond *mask_cond; - gint mask_bpp; - - GstVideoFormat fmt; - gint width, height; - - gboolean shutdown; - - gdouble proportion; - GstClockTime earliest_time; - GstClockTime frame_duration; -}; - -struct _GstShapeWipeClass -{ - GstElementClass parent_class; -}; - -GType gst_shape_wipe_get_type (void); - -G_END_DECLS - -#endif /* __GST_SHAPE_WIPE_H__ */ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index eca2ff189..eeb62fc1a 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -123,7 +123,6 @@ check_PROGRAMS = \ elements/jpegparse \ elements/qtmux \ elements/selector \ - elements/shapewipe \ elements/mxfdemux \ elements/mxfmux \ pipelines/mxf \ diff --git a/tests/check/elements/shapewipe.c b/tests/check/elements/shapewipe.c deleted file mode 100644 index d0ec63f9a..000000000 --- a/tests/check/elements/shapewipe.c +++ /dev/null @@ -1,307 +0,0 @@ -/* GStreamer - * - * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * 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. - */ - -#include <unistd.h> - -#include <gst/check/gstcheck.h> - -gboolean have_eos = FALSE; - -/* For ease of programming we use globals to keep refs for our floating - * src and sink pads we create; otherwise we always have to do get_pad, - * get_peer, and then remove references in every test function */ -GstPad *myvideosrcpad, *mymasksrcpad, *mysinkpad; - - -#define SHAPEWIPE_VIDEO_CAPS_STRING \ - "video/x-raw-yuv, " \ - "format = (GstFourcc)AYUV, " \ - "width = 400, " \ - "height = 400, " \ - "framerate = 0/1" - -#define SHAPEWIPE_MASK_CAPS_STRING \ - "video/x-raw-gray, " \ - "bpp = 8, " \ - "depth = 8, " \ - "width = 400, " \ - "height = 400, " \ - "framerate = 0/1" - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (SHAPEWIPE_VIDEO_CAPS_STRING) - ); -static GstStaticPadTemplate videosrctemplate = -GST_STATIC_PAD_TEMPLATE ("videosrc", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (SHAPEWIPE_VIDEO_CAPS_STRING) - ); -static GstStaticPadTemplate masksrctemplate = -GST_STATIC_PAD_TEMPLATE ("masksrc", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (SHAPEWIPE_MASK_CAPS_STRING) - ); - - -static GstBuffer *output = NULL; - -static GstFlowReturn -on_chain (GstPad * pad, GstBuffer * buffer) -{ - g_return_val_if_fail (output == NULL, GST_FLOW_ERROR); - - output = buffer; - return GST_FLOW_OK; -} - -GST_START_TEST (test_general) -{ - GstElement *shapewipe; - GstPad *p; - GstCaps *caps; - GstBuffer *mask, *input; - guint i, j; - guint8 *data; - - myvideosrcpad = - gst_pad_new_from_static_template (&videosrctemplate, "videosrc"); - gst_pad_set_active (myvideosrcpad, TRUE); - caps = gst_caps_from_string (SHAPEWIPE_VIDEO_CAPS_STRING); - gst_pad_set_caps (myvideosrcpad, caps); - gst_caps_unref (caps); - - mymasksrcpad = gst_pad_new_from_static_template (&masksrctemplate, "masksrc"); - gst_pad_set_active (mymasksrcpad, TRUE); - caps = gst_caps_from_string (SHAPEWIPE_MASK_CAPS_STRING); - gst_pad_set_caps (mymasksrcpad, caps); - gst_caps_unref (caps); - - mysinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); - gst_pad_set_chain_function (mysinkpad, on_chain); - gst_pad_set_active (mysinkpad, TRUE); - caps = gst_caps_from_string (SHAPEWIPE_VIDEO_CAPS_STRING); - gst_pad_set_caps (mysinkpad, caps); - gst_caps_unref (caps); - - shapewipe = gst_element_factory_make ("shapewipe", NULL); - fail_unless (shapewipe != NULL); - - p = gst_element_get_static_pad (shapewipe, "video_sink"); - fail_unless (gst_pad_link (myvideosrcpad, p) == GST_PAD_LINK_OK); - gst_object_unref (p); - p = gst_element_get_static_pad (shapewipe, "mask_sink"); - fail_unless (gst_pad_link (mymasksrcpad, p) == GST_PAD_LINK_OK); - gst_object_unref (p); - p = gst_element_get_static_pad (shapewipe, "src"); - fail_unless (gst_pad_link (p, mysinkpad) == GST_PAD_LINK_OK); - gst_object_unref (p); - - fail_unless (gst_element_set_state (shapewipe, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); - - mask = gst_buffer_new_and_alloc (400 * 400); - caps = gst_caps_from_string (SHAPEWIPE_MASK_CAPS_STRING); - gst_buffer_set_caps (mask, caps); - gst_caps_unref (caps); - data = GST_BUFFER_DATA (mask); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - if (i < 100 && j < 100) - data[0] = 0; - else if (i < 200 && j < 200) - data[0] = 85; - else if (i < 300 && j < 300) - data[0] = 170; - else - data[0] = 254; - data++; - } - } - - fail_unless (gst_pad_push (mymasksrcpad, mask) == GST_FLOW_OK); - - input = gst_buffer_new_and_alloc (400 * 400 * 4); - caps = gst_caps_from_string (SHAPEWIPE_VIDEO_CAPS_STRING); - gst_buffer_set_caps (input, caps); - gst_caps_unref (caps); - data = GST_BUFFER_DATA (input); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - /* This is green */ - data[0] = 0; /* A */ - data[1] = 173; /* Y */ - data[2] = 42; /* U */ - data[3] = 26; /* V */ - data += 4; - } - } - - g_object_set (G_OBJECT (shapewipe), "position", 0.0, NULL); - output = NULL; - fail_unless (gst_pad_push (myvideosrcpad, - gst_buffer_ref (input)) == GST_FLOW_OK); - fail_unless (output != NULL); - data = GST_BUFFER_DATA (output); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - fail_unless (data[0] == 255); /* A */ - fail_unless (data[1] == 173); /* Y */ - fail_unless (data[2] == 42); /* U */ - fail_unless (data[3] == 26); /* V */ - data += 4; - } - } - gst_buffer_unref (output); - output = NULL; - - g_object_set (G_OBJECT (shapewipe), "position", 0.1, NULL); - output = NULL; - fail_unless (gst_pad_push (myvideosrcpad, - gst_buffer_ref (input)) == GST_FLOW_OK); - fail_unless (output != NULL); - data = GST_BUFFER_DATA (output); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - if (i < 100 && j < 100) { - fail_unless (data[0] == 0); /* A */ - fail_unless (data[1] == 0); /* Y */ - fail_unless (data[2] == 128); /* U */ - fail_unless (data[3] == 128); /* V */ - } else { - fail_unless (data[0] == 255); /* A */ - fail_unless (data[1] == 173); /* Y */ - fail_unless (data[2] == 42); /* U */ - fail_unless (data[3] == 26); /* V */ - } - data += 4; - } - } - gst_buffer_unref (output); - output = NULL; - - g_object_set (G_OBJECT (shapewipe), "position", 0.34, NULL); - output = NULL; - fail_unless (gst_pad_push (myvideosrcpad, - gst_buffer_ref (input)) == GST_FLOW_OK); - fail_unless (output != NULL); - data = GST_BUFFER_DATA (output); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - if (i < 200 && j < 200) { - fail_unless (data[0] == 0); /* A */ - fail_unless (data[1] == 0); /* Y */ - fail_unless (data[2] == 128); /* U */ - fail_unless (data[3] == 128); /* V */ - } else { - fail_unless (data[0] == 255); /* A */ - fail_unless (data[1] == 173); /* Y */ - fail_unless (data[2] == 42); /* U */ - fail_unless (data[3] == 26); /* V */ - } - data += 4; - } - } - gst_buffer_unref (output); - output = NULL; - - g_object_set (G_OBJECT (shapewipe), "position", 0.67, NULL); - output = NULL; - fail_unless (gst_pad_push (myvideosrcpad, - gst_buffer_ref (input)) == GST_FLOW_OK); - fail_unless (output != NULL); - data = GST_BUFFER_DATA (output); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - if (i < 300 && j < 300) { - fail_unless (data[0] == 0); /* A */ - fail_unless (data[1] == 0); /* Y */ - fail_unless (data[2] == 128); /* U */ - fail_unless (data[3] == 128); /* V */ - } else { - fail_unless (data[0] == 255); /* A */ - fail_unless (data[1] == 173); /* Y */ - fail_unless (data[2] == 42); /* U */ - fail_unless (data[3] == 26); /* V */ - } - data += 4; - } - } - gst_buffer_unref (output); - output = NULL; - - g_object_set (G_OBJECT (shapewipe), "position", 1.0, NULL); - output = NULL; - fail_unless (gst_pad_push (myvideosrcpad, - gst_buffer_ref (input)) == GST_FLOW_OK); - fail_unless (output != NULL); - data = GST_BUFFER_DATA (output); - for (i = 0; i < 400; i++) { - for (j = 0; j < 400; j++) { - fail_unless (data[0] == 0); /* A */ - fail_unless (data[1] == 0); /* Y */ - fail_unless (data[2] == 128); /* U */ - fail_unless (data[3] == 128); /* V */ - data += 4; - } - } - gst_buffer_unref (output); - output = NULL; - - gst_buffer_unref (input); - - fail_unless (gst_element_set_state (shapewipe, - GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); - - p = gst_element_get_static_pad (shapewipe, "video_sink"); - fail_unless (gst_pad_unlink (myvideosrcpad, p)); - gst_object_unref (p); - p = gst_element_get_static_pad (shapewipe, "mask_sink"); - fail_unless (gst_pad_unlink (mymasksrcpad, p)); - gst_object_unref (p); - p = gst_element_get_static_pad (shapewipe, "src"); - fail_unless (gst_pad_unlink (p, mysinkpad)); - gst_object_unref (p); - - gst_object_unref (myvideosrcpad); - gst_object_unref (mymasksrcpad); - gst_object_unref (mysinkpad); - gst_object_unref (shapewipe); -} - -GST_END_TEST; - -Suite * -shapewipe_suite (void) -{ - Suite *s = suite_create ("shapewipe"); - TCase *tc_chain = tcase_create ("general"); - - suite_add_tcase (s, tc_chain); - tcase_set_timeout (tc_chain, 180); - tcase_add_test (tc_chain, test_general); - - return s; -} - -GST_CHECK_MAIN (shapewipe); diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 42ffa4812..562b36118 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -10,5 +10,5 @@ else DIRECTFB_DIR= endif -SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) shapewipe switch -DIST_SUBDIRS= camerabin directfb mxf scaletempo shapewipe switch +SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) switch +DIST_SUBDIRS= camerabin directfb mxf scaletempo switch diff --git a/tests/examples/shapewipe/Makefile.am b/tests/examples/shapewipe/Makefile.am deleted file mode 100644 index 0a5eecf1a..000000000 --- a/tests/examples/shapewipe/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -noinst_PROGRAMS = shapewipe-example - -shapewipe_example_SOURCES = shapewipe-example.c -shapewipe_example_CFLAGS = $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS) -shapewipe_example_LDFLAGS = $(GST_LIBS) $(GST_CONTROLLER_LIBS) - -noinst_HEADERS = - diff --git a/tests/examples/shapewipe/shapewipe-example.c b/tests/examples/shapewipe/shapewipe-example.c deleted file mode 100644 index 14df6dd3b..000000000 --- a/tests/examples/shapewipe/shapewipe-example.c +++ /dev/null @@ -1,140 +0,0 @@ -/* GStreamer - * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * 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. - */ - -#include <gst/gst.h> -#include <gst/controller/gstcontroller.h> -#include <gst/controller/gstlfocontrolsource.h> - -static gboolean -on_message (GstBus * bus, GstMessage * message, gpointer user_data) -{ - GMainLoop *loop = (GMainLoop *) user_data; - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR:{ - GError *err = NULL; - gchar *debug = NULL; - - g_warning ("Got ERROR"); - gst_message_parse_error (message, &err, &debug); - g_warning ("%s: %s", err->message, debug); - g_main_loop_quit (loop); - break; - } - case GST_MESSAGE_WARNING:{ - GError *err = NULL; - gchar *debug = NULL; - - g_warning ("Got WARNING"); - gst_message_parse_error (message, &err, &debug); - g_warning ("%s: %s", err->message, debug); - g_main_loop_quit (loop); - break; - } - case GST_MESSAGE_EOS: - g_main_loop_quit (loop); - break; - default: - break; - } - - return TRUE; -} - -gint -main (gint argc, gchar ** argv) -{ - GstElement *pipeline; - GstElement *shapewipe; - GstController *ctrl; - GstLFOControlSource *csource; - GValue val = { 0, }; - GMainLoop *loop; - GstBus *bus; - gchar *pipeline_string; - - if (argc != 2) { - g_print ("Usage: shapewipe mask.png\n"); - return -1; - } - - gst_init (&argc, &argv); - gst_controller_init (&argc, &argv); - - pipeline_string = - g_strdup_printf - ("videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe name=shape border=0.05 ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink filesrc location=%s ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.", - argv[1]); - - pipeline = gst_parse_launch (pipeline_string, NULL); - g_free (pipeline_string); - - if (pipeline == NULL) { - g_print ("Failed to create pipeline\n"); - return -2; - } - - shapewipe = gst_bin_get_by_name (GST_BIN (pipeline), "shape"); - - if (!(ctrl = gst_controller_new (G_OBJECT (shapewipe), "position", NULL))) { - g_print ("can't control shapewipe element\n"); - return -3; - } - - csource = gst_lfo_control_source_new (); - - gst_controller_set_control_source (ctrl, "position", - GST_CONTROL_SOURCE (csource)); - - g_value_init (&val, G_TYPE_FLOAT); - g_value_set_float (&val, 0.5); - g_object_set (G_OBJECT (csource), "amplitude", &val, NULL); - g_value_set_float (&val, 0.5); - g_object_set (G_OBJECT (csource), "offset", &val, NULL); - g_value_unset (&val); - - g_object_set (G_OBJECT (csource), "frequency", 0.5, NULL); - g_object_set (G_OBJECT (csource), "timeshift", 500 * GST_MSECOND, NULL); - - g_object_unref (csource); - - loop = g_main_loop_new (NULL, FALSE); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_signal_watch (bus); - g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (on_message), loop); - gst_object_unref (GST_OBJECT (bus)); - - if (gst_element_set_state (pipeline, - GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { - g_error ("Failed to go into PLAYING state"); - return -4; - } - - g_main_loop_run (loop); - - gst_element_set_state (pipeline, GST_STATE_NULL); - - g_main_loop_unref (loop); - - g_object_unref (G_OBJECT (ctrl)); - gst_object_unref (G_OBJECT (pipeline)); - - return 0; -} |