From 9c0d244072ec8c459a1cd9358d3ae754fd861b21 Mon Sep 17 00:00:00 2001 From: Amarnath Valluri Date: Mon, 26 Nov 2012 11:08:17 +0200 Subject: [PATCH] Policy element integration --- configure.ac | 5 + gst-libs/gst/Makefile.am | 5 +- gst-libs/gst/policy/Makefile.am | 72 +++++++ gst-libs/gst/policy/gstpolicy.c | 284 +++++++++++++++++++++++++++ gst-libs/gst/policy/gstpolicy.h | 70 +++++++ gst-plugins-base.spec.in | 2 + gst/playback/gstplaybin2.c | 20 ++ gst/playback/gstplaysink.c | 261 ++++++++++++++---------- gst/policy/Makefile.am | 37 ++++ gst/policy/gstautopolicy.c | 237 ++++++++++++++++++++++ gst/policy/gstautopolicy.h | 59 ++++++ gst/policy/gstdefaultpolicy.c | 69 +++++++ gst/policy/gstdefaultpolicy.h | 58 ++++++ gst/policy/gstpolicyplugin.c | 48 +++++ gst/policy/gstpolicyplugin.h | 24 +++ packaging/gst-plugins-base.spec | 5 + pkgconfig/Makefile.am | 3 + pkgconfig/gstreamer-policy-uninstalled.pc.in | 16 ++ pkgconfig/gstreamer-policy.pc.in | 16 ++ tests/check/Makefile.am | 4 + tests/check/elements/policy.c | 113 +++++++++++ 21 files changed, 1302 insertions(+), 106 deletions(-) create mode 100644 gst-libs/gst/policy/Makefile.am create mode 100644 gst-libs/gst/policy/gstpolicy.c create mode 100644 gst-libs/gst/policy/gstpolicy.h create mode 100644 gst/policy/Makefile.am create mode 100644 gst/policy/gstautopolicy.c create mode 100644 gst/policy/gstautopolicy.h create mode 100644 gst/policy/gstdefaultpolicy.c create mode 100644 gst/policy/gstdefaultpolicy.h create mode 100644 gst/policy/gstpolicyplugin.c create mode 100644 gst/policy/gstpolicyplugin.h create mode 100644 pkgconfig/gstreamer-policy-uninstalled.pc.in create mode 100644 pkgconfig/gstreamer-policy.pc.in create mode 100644 tests/check/elements/policy.c diff --git a/configure.ac b/configure.ac index 1901bcf..a7bfabb 100644 --- a/configure.ac +++ b/configure.ac @@ -423,6 +423,7 @@ AG_GST_CHECK_PLUGIN(encoding) AG_GST_CHECK_PLUGIN(ffmpegcolorspace) AG_GST_CHECK_PLUGIN(gdp) AG_GST_CHECK_PLUGIN(playback) +AG_GST_CHECK_PLUGIN(policy) AG_GST_CHECK_PLUGIN(audioresample) AG_GST_CHECK_PLUGIN(subparse) AG_GST_CHECK_PLUGIN(tcp) @@ -938,6 +939,7 @@ gst/encoding/Makefile gst/ffmpegcolorspace/Makefile gst/gdp/Makefile gst/playback/Makefile +gst/policy/Makefile gst/audioresample/Makefile gst/subparse/Makefile gst/tcp/Makefile @@ -969,6 +971,7 @@ gst-libs/gst/fft/Makefile gst-libs/gst/floatcast/Makefile gst-libs/gst/interfaces/Makefile gst-libs/gst/netbuffer/Makefile +gst-libs/gst/policy/Makefile gst-libs/gst/riff/Makefile gst-libs/gst/rtp/Makefile gst-libs/gst/rtsp/Makefile @@ -995,6 +998,8 @@ pkgconfig/gstreamer-netbuffer.pc pkgconfig/gstreamer-netbuffer-uninstalled.pc pkgconfig/gstreamer-pbutils.pc pkgconfig/gstreamer-pbutils-uninstalled.pc +pkgconfig/gstreamer-policy.pc +pkgconfig/gstreamer-policy-uninstalled.pc pkgconfig/gstreamer-riff.pc pkgconfig/gstreamer-riff-uninstalled.pc pkgconfig/gstreamer-rtp.pc diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index 0984251..f300fa8 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -16,7 +16,8 @@ SUBDIRS = \ pbutils \ audio \ riff \ - app + app \ + policy noinst_HEADERS = gettext.h gst-i18n-plugin.h glib-compat-private.h @@ -30,7 +31,7 @@ riff: tag audio rtsp: sdp INDEPENDENT_SUBDIRS = \ - interfaces tag fft floatcast netbuffer pbutils rtp sdp video app + interfaces tag fft floatcast netbuffer pbutils rtp sdp video app policy .PHONY: independent-subdirs $(INDEPENDENT_SUBDIRS) diff --git a/gst-libs/gst/policy/Makefile.am b/gst-libs/gst/policy/Makefile.am new file mode 100644 index 0000000..c1037e8 --- /dev/null +++ b/gst-libs/gst/policy/Makefile.am @@ -0,0 +1,72 @@ +libgstpolicyincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/policy + +libgstpolicyinclude_HEADERS = gstpolicy.h + +lib_LTLIBRARIES = libgstpolicy-@GST_MAJORMINOR@.la + +libgstpolicy_@GST_MAJORMINOR@_la_SOURCES = gstpolicy.c + +libgstpolicy_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) +libgstpolicy_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(GIO_LIBS) +libgstpolicy_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstPolicy-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstpolicyinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstpolicy_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/policy/%',$(libgstpolicyinclude_HEADERS)) + +GstPolicy-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstpolicy-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstPolicy \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + --warn-all \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + --add-include-path=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstpolicy-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-policy-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" $(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstpolicy -:SHARED libgstpolicy-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstpolicy_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstpolicy_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstpolicy_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstpolicy_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/policy \ + -:HEADERS $(libgstpolicyinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-libs/gst/policy/gstpolicy.c b/gst-libs/gst/policy/gstpolicy.c new file mode 100644 index 0000000..3b2d786 --- /dev/null +++ b/gst-libs/gst/policy/gstpolicy.c @@ -0,0 +1,284 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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:gstpolicy + * @short_description: Simple base class for platform-specific policy implementations + * @see_also: autopolicy + * + * Any platform-specific policy element should be implemented by subclassing + * #GstPolicy. Applications should be using #autopolicy element that finds and + * and wraps an appropriate policy element, or just #playbin element which + * encapsulates autopolicy element. + * + * #GstPolicy provides an unlimited number of request sink pads. You can obtain + * the corresponding source pad by listening to a "pad-added" signal while + * requesting the sink pad. + * + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "gstpolicy.h" + +GST_DEBUG_CATEGORY_STATIC (gst_policy_debug); +#define GST_CAT_DEFAULT gst_policy_debug + +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_ROLE +}; + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("ANY") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src_%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("ANY") + ); + +GST_BOILERPLATE(GstPolicy, gst_policy, GstElement, GST_TYPE_ELEMENT); + +static void gst_policy_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_policy_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_policy_finalize (GObject * object); + +static GstPad *gst_policy_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_policy_release_pad (GstElement * element, GstPad * pad); + +static gboolean gst_policy_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_policy_src_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_policy_chain (GstPad * pad, GstBuffer * buf); + +static GstIterator *gst_policy_iterate_internal_links (GstPad * + pad, GstObject * parent); + +static void +gst_policy_class_init (GstPolicyClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + GST_DEBUG_CATEGORY_INIT (gst_policy_debug, "policy", 0, "Policy debugging"); + + gobject_class->set_property = gst_policy_set_property; + gobject_class->get_property = gst_policy_get_property; + gobject_class->finalize = gst_policy_finalize; + + /** + * GstPolicy:role + * + * Set the role of the stream. This property can be used by the platform policy subsystem + * to make policy decisions that affect the stream (for example routing and enforced + * pause/playback). + */ + g_object_class_install_property (gobject_class, PROP_ROLE, + g_param_spec_string ("role", "Stream role", + "Stream role for the platform policy sybsystem", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + // element class methods + gstelement_class->request_new_pad = gst_policy_request_new_pad; + gstelement_class->release_pad = gst_policy_release_pad; +} + +static void +gst_policy_init (GstPolicy * policy, GstPolicyClass *klass) +{ + GST_DEBUG_CATEGORY_INIT (gst_policy_debug, "policy", 0, "Policy"); + + policy->role = NULL; +} + +static void +gst_policy_base_init (gpointer klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_factory)); + +} + +static void +gst_policy_finalize (GObject * object) +{ + GstPolicy *policy; + + policy = GST_POLICY (object); + + g_free (policy->role); + policy->role = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_policy_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPolicy *policy = GST_POLICY (object); + + switch (prop_id) { + case PROP_ROLE: + g_free (policy->role); + policy->role = g_strdup (g_value_get_string (value)); + GST_DEBUG_OBJECT (policy, "Setting stream role to %s", policy->role); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_policy_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstPolicy *policy = GST_POLICY (object); + + switch (prop_id) { + case PROP_ROLE: + GST_DEBUG_OBJECT (policy, "Getting stream role: %s", policy->role); + g_value_set_string (value, policy->role); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} +static void +gst_policy_release_pad (GstElement * element, GstPad * pad) +{ + GstPolicy *self = GST_POLICY (element); + GstPad *srcpad = gst_pad_get_element_private (pad); + + gst_pad_set_element_private (pad, NULL); + gst_pad_set_element_private (srcpad, NULL); + + gst_element_remove_pad (GST_ELEMENT_CAST (self), srcpad); + gst_element_remove_pad (GST_ELEMENT_CAST (self), pad); +} + +static GstIterator * +gst_policy_iterate_internal_links (GstPad * pad, GstObject * parent) +{ + GstIterator *it = NULL; + GstPad *opad; + + opad = gst_pad_get_element_private (pad); + if (opad) { + it = gst_iterator_new_single (GST_TYPE_PAD, (gpointer)opad, + (GstCopyFunction)gst_object_ref, + (GFreeFunc)gst_object_unref); + } + + return it; +} + +static gboolean +gst_policy_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret; + + switch (GST_EVENT_TYPE (event)) { + default: + ret = gst_pad_event_default (pad, event); + break; + } + return ret; +} + +static gboolean +gst_policy_src_event (GstPad * pad, GstEvent * event) +{ + gboolean ret; + + switch (GST_EVENT_TYPE (event)) { + default: + ret = gst_pad_event_default (pad, event); + break; + } + return ret; +} + +static GstFlowReturn +gst_policy_chain (GstPad * pad, GstBuffer * buf) +{ + /* just push out the incoming buffer without touching it */ + return gst_pad_push (gst_pad_get_element_private (pad), buf); +} + +static GstPad * +gst_policy_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name) +{ + GstPad *srcpad; + GstPad *sinkpad; + GstPolicy *self = GST_POLICY (element); + + sinkpad = gst_pad_new_from_template (templ, name); + srcpad = gst_pad_new_from_static_template (&src_factory, NULL); + + gst_pad_set_element_private (sinkpad, srcpad); + gst_pad_set_element_private (srcpad, sinkpad); + + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_policy_chain)); + gst_pad_set_iterate_internal_links_function (sinkpad, + (GstPadIterIntLinkFunction)gst_policy_iterate_internal_links); + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_policy_sink_event)); + + gst_pad_set_iterate_internal_links_function (srcpad, + (GstPadIterIntLinkFunction)gst_policy_iterate_internal_links); + gst_pad_set_event_function (srcpad, + GST_DEBUG_FUNCPTR (gst_policy_src_event)); + + gst_pad_set_active (srcpad, TRUE); + gst_pad_set_active (sinkpad, TRUE); + + gst_element_add_pad (GST_ELEMENT (self), sinkpad); + gst_element_add_pad (GST_ELEMENT (self), srcpad); + + return sinkpad; +} + diff --git a/gst-libs/gst/policy/gstpolicy.h b/gst-libs/gst/policy/gstpolicy.h new file mode 100644 index 0000000..fd9defc --- /dev/null +++ b/gst-libs/gst/policy/gstpolicy.h @@ -0,0 +1,70 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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_POLICY_H__ +#define __GST_POLICY_H__ + +#include + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_POLICY \ + (gst_policy_get_type()) +#define GST_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_POLICY,GstPolicy)) +#define GST_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_POLICY,GstPolicyClass)) +#define GST_IS_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_POLICY)) +#define GST_IS_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_POLICY)) + +typedef struct _GstPolicy GstPolicy; +typedef struct _GstPolicyClass GstPolicyClass; + +/** + * GstPolicy: + * + * Opaque #GstPolicy. + */ +struct _GstPolicy +{ + GstElement element; + + gchar* role; +}; + +/** + * GstPolicyClass: + * @parent_class: the parent class structure. + * + * #GstPolicy class. + */ +struct _GstPolicyClass +{ + GstElementClass parent_class; +}; + +GType gst_policy_get_type (void); + +G_END_DECLS + +#endif /* __GST_POLICY_H__ */ diff --git a/gst-plugins-base.spec.in b/gst-plugins-base.spec.in index 5f741ac..994e485 100644 --- a/gst-plugins-base.spec.in +++ b/gst-plugins-base.spec.in @@ -98,6 +98,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/libgstrtsp-%{majorminor}.so.* %{_libdir}/libgstsdp-%{majorminor}.so.* %{_libdir}/libgstapp-%{majorminor}.so.* +%{_libdir}/libgstpolicy-%{majorminor}.so.* # base plugins without external dependencies %{_libdir}/gstreamer-%{majorminor}/libgstadder.so @@ -106,6 +107,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstdecodebin.so %{_libdir}/gstreamer-%{majorminor}/libgstdecodebin2.so %{_libdir}/gstreamer-%{majorminor}/libgstplaybin.so +%{_libdir}/gstreamer-%{majorminor}/libgstpolicy.so %{_libdir}/gstreamer-%{majorminor}/libgsttypefindfunctions.so %{_libdir}/gstreamer-%{majorminor}/libgstvideotestsrc.so %{_libdir}/gstreamer-%{majorminor}/libgstaudiorate.so diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index e01ff6c..5956544 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -504,6 +504,7 @@ enum PROP_BUFFER_DURATION, PROP_AV_OFFSET, PROP_RING_BUFFER_MAX_SIZE, + PROP_ROLE, PROP_LAST }; @@ -824,6 +825,17 @@ gst_play_bin_class_init (GstPlayBinClass * klass) "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)", 0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin:role + * + * Set the role of the stream. This property is used by the platform policy subsystem + * to make policy decisions that affect the stream (for example routing and enforced + * pause/playback). + */ + g_object_class_install_property (gobject_klass, PROP_ROLE, + g_param_spec_string ("role", "Stream role", + "Stream role for the platform policy sybsystem", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstPlayBin2::about-to-finish @@ -1959,6 +1971,10 @@ gst_play_bin_set_property (GObject * object, guint prop_id, case PROP_RING_BUFFER_MAX_SIZE: playbin->ring_buffer_max_size = g_value_get_uint64 (value); break; + case PROP_ROLE: + gst_child_proxy_set_property (GST_OBJECT_CAST(playbin->playsink), + "policy::actual-policy::role", value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2134,6 +2150,10 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, case PROP_RING_BUFFER_MAX_SIZE: g_value_set_uint64 (value, playbin->ring_buffer_max_size); break; + case PROP_ROLE: + gst_child_proxy_get_property (GST_OBJECT_CAST (playbin->playsink), + "policy::actual-policy::role", value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index d02ec60..011d5cd 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -156,6 +156,7 @@ struct _GstPlaySink GstPlayFlags flags; GstStreamSynchronizer *stream_synchronizer; + GstElement *policy; /* chains */ GstPlayAudioChain *audiochain; @@ -170,6 +171,8 @@ struct _GstPlaySink gboolean audio_pad_blocked; GstPad *audio_srcpad_stream_synchronizer; GstPad *audio_sinkpad_stream_synchronizer; + GstPad *audio_srcpad_policy; + GstPad *audio_sinkpad_policy; /* audio tee */ GstElement *audio_tee; GstPad *audio_tee_sink; @@ -181,11 +184,15 @@ struct _GstPlaySink gboolean video_pad_blocked; GstPad *video_srcpad_stream_synchronizer; GstPad *video_sinkpad_stream_synchronizer; + GstPad *video_srcpad_policy; + GstPad *video_sinkpad_policy; /* text */ GstPad *text_pad; gboolean text_pad_blocked; GstPad *text_srcpad_stream_synchronizer; GstPad *text_sinkpad_stream_synchronizer; + GstPad *text_srcpad_policy; + GstPad *text_sinkpad_policy; guint32 pending_blocked_pads; @@ -525,6 +532,10 @@ gst_play_sink_init (GstPlaySink * playsink) gst_bin_add (GST_BIN_CAST (playsink), GST_ELEMENT_CAST (playsink->stream_synchronizer)); + playsink->policy = + gst_element_factory_make ("autopolicy", "policy"); + gst_bin_add (GST_BIN_CAST (playsink), playsink->policy); + g_static_rec_mutex_init (&playsink->lock); GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_IS_SINK); } @@ -617,6 +628,7 @@ gst_play_sink_dispose (GObject * object) playsink->subtitle_encoding = NULL; playsink->stream_synchronizer = NULL; + playsink->policy = NULL; G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object); } @@ -2146,6 +2158,85 @@ link_failed: } } +static void +policy_pad_added_cb (GstElement * gstelement, + GstPad * new_pad, gpointer user_data) +{ + GstPad **ppad; + ppad = user_data; + if (gst_pad_get_direction (new_pad) == GST_PAD_SRC) { + gst_object_ref (new_pad); + *ppad = new_pad; + } +} + +static void +_add_policy_and_synchronizer_pads (GstPlaySink * playsink, + GstPad ** sinkpad_stream_synchronizer, + GstPad ** srcpad_stream_synchronizer, + GstPad ** sinkpad_policy, + GstPad ** srcpad_policy) +{ + if (!*sinkpad_stream_synchronizer) { + GstIterator *it; + + /* request stream synchronizer pads */ + *sinkpad_stream_synchronizer = + gst_element_get_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), "sink_%d"); + it = gst_pad_iterate_internal_links (*sinkpad_stream_synchronizer); + g_assert (it); + gst_iterator_next (it, (gpointer *)srcpad_stream_synchronizer); + gst_iterator_free (it); + + /* request policy pads */ + g_signal_connect (G_OBJECT (playsink->policy), "pad-added", + G_CALLBACK (policy_pad_added_cb), srcpad_policy); + *sinkpad_policy = gst_element_get_request_pad (playsink->policy, "sink_%d"); + g_assert (*sinkpad_policy); + g_signal_handlers_disconnect_by_func (playsink->policy, + G_CALLBACK (policy_pad_added_cb), srcpad_policy); + + /* link pads */ + if (gst_pad_link (*srcpad_stream_synchronizer, + *sinkpad_policy) != GST_PAD_LINK_OK) { + GST_WARNING_OBJECT (playsink, "pad linking failed : (%s, %s)", + GST_DEBUG_PAD_NAME (*srcpad_stream_synchronizer), + GST_DEBUG_PAD_NAME (*sinkpad_policy)); + } + } +} + +static void +_remove_policy_and_synchronizer_pads (GstPlaySink * playsink, + GstPad ** sinkpad_stream_synchronizer, + GstPad ** srcpad_stream_synchronizer, + GstPad ** sinkpad_policy, + GstPad ** srcpad_policy) +{ + if (*sinkpad_stream_synchronizer) { + gst_pad_unlink (*srcpad_stream_synchronizer, *sinkpad_policy); + + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + *sinkpad_stream_synchronizer); + + gst_object_unref (*sinkpad_stream_synchronizer); + *sinkpad_stream_synchronizer = NULL; + + gst_object_unref (*srcpad_stream_synchronizer); + *srcpad_stream_synchronizer = NULL; + + gst_element_release_request_pad (playsink->policy, *sinkpad_policy); + + gst_object_unref (*sinkpad_policy); + *sinkpad_policy = NULL; + + gst_object_unref (*srcpad_policy); + *srcpad_policy = NULL; + } +} + /* this function is called when all the request pads are requested and when we * have to construct the final pipeline. Based on the flags we construct the * final output pipelines. @@ -2238,13 +2329,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) /* try to reactivate the chain */ if (!setup_video_chain (playsink, raw, async)) { if (playsink->video_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->video_sinkpad_stream_synchronizer); - gst_object_unref (playsink->video_sinkpad_stream_synchronizer); - playsink->video_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->video_srcpad_stream_synchronizer); - playsink->video_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->video_sinkpad_stream_synchronizer, + &playsink->video_srcpad_stream_synchronizer, + &playsink->video_sinkpad_policy, + &playsink->video_srcpad_policy); } add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); @@ -2267,18 +2356,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) goto no_chain; if (!playsink->video_sinkpad_stream_synchronizer) { - GstIterator *it; - - playsink->video_sinkpad_stream_synchronizer = - gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); - it = gst_pad_iterate_internal_links - (playsink->video_sinkpad_stream_synchronizer); - g_assert (it); - gst_iterator_next (it, - (gpointer *) & playsink->video_srcpad_stream_synchronizer); - g_assert (playsink->video_srcpad_stream_synchronizer); - gst_iterator_free (it); + _add_policy_and_synchronizer_pads (playsink, + &playsink->video_sinkpad_stream_synchronizer, + &playsink->video_srcpad_stream_synchronizer, + &playsink->video_sinkpad_policy, + &playsink->video_srcpad_policy); } if (playsink->video_pad) @@ -2299,7 +2381,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) add_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), TRUE); activate_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), TRUE); - gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->video_srcpad_policy, playsink->videodeinterlacechain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); } else { if (playsink->videodeinterlacechain) { @@ -2320,7 +2402,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) gst_pad_link_full (playsink->videodeinterlacechain->srcpad, playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); else - gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->video_srcpad_policy, playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); } } else { @@ -2346,13 +2428,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } if (playsink->video_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->video_sinkpad_stream_synchronizer); - gst_object_unref (playsink->video_sinkpad_stream_synchronizer); - playsink->video_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->video_srcpad_stream_synchronizer); - playsink->video_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->video_sinkpad_stream_synchronizer, + &playsink->video_srcpad_stream_synchronizer, + &playsink->video_sinkpad_policy, + &playsink->video_srcpad_policy); } add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); @@ -2391,13 +2471,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } if (playsink->audio_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->audio_sinkpad_stream_synchronizer); - gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); - playsink->audio_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->audio_srcpad_stream_synchronizer); - playsink->audio_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->audio_sinkpad_stream_synchronizer, + &playsink->audio_srcpad_stream_synchronizer, + &playsink->audio_sinkpad_policy, + &playsink->audio_srcpad_policy); } add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); @@ -2427,18 +2505,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } if (!playsink->audio_sinkpad_stream_synchronizer) { - GstIterator *it; - - playsink->audio_sinkpad_stream_synchronizer = - gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); - it = gst_pad_iterate_internal_links - (playsink->audio_sinkpad_stream_synchronizer); - g_assert (it); - gst_iterator_next (it, - (gpointer *) & playsink->audio_srcpad_stream_synchronizer); - g_assert (playsink->audio_srcpad_stream_synchronizer); - gst_iterator_free (it); + _add_policy_and_synchronizer_pads (playsink, + &playsink->audio_sinkpad_stream_synchronizer, + &playsink->audio_srcpad_stream_synchronizer, + &playsink->audio_sinkpad_policy, + &playsink->audio_srcpad_policy); } if (playsink->audiochain) { @@ -2452,7 +2523,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) gst_pad_link_full (playsink->audio_tee_asrc, playsink->audio_sinkpad_stream_synchronizer, GST_PAD_LINK_CHECK_NOTHING); - gst_pad_link_full (playsink->audio_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->audio_srcpad_policy, playsink->audiochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); } } else { @@ -2469,13 +2540,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } if (playsink->audio_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->audio_sinkpad_stream_synchronizer); - gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); - playsink->audio_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->audio_srcpad_stream_synchronizer); - playsink->audio_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->audio_sinkpad_stream_synchronizer, + &playsink->audio_srcpad_stream_synchronizer, + &playsink->audio_sinkpad_policy, + &playsink->audio_srcpad_policy); } if (playsink->audiochain->sink_volume) { @@ -2513,7 +2582,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) playsink->vischain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); gst_pad_link_full (srcpad, playsink->video_sinkpad_stream_synchronizer, GST_PAD_LINK_CHECK_NOTHING); - gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->video_srcpad_policy, playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref (srcpad); } @@ -2539,7 +2608,6 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) playsink->textchain = gen_text_chain (playsink); } if (playsink->textchain) { - GstIterator *it; GST_DEBUG_OBJECT (playsink, "adding text chain"); if (playsink->textchain->overlay) @@ -2548,20 +2616,15 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) add_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE); if (!playsink->text_sinkpad_stream_synchronizer) { - playsink->text_sinkpad_stream_synchronizer = - gst_element_get_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), "sink_%d"); - it = gst_pad_iterate_internal_links - (playsink->text_sinkpad_stream_synchronizer); - g_assert (it); - gst_iterator_next (it, - (gpointer *) & playsink->text_srcpad_stream_synchronizer); - g_assert (playsink->text_srcpad_stream_synchronizer); - gst_iterator_free (it); + _add_policy_and_synchronizer_pads (playsink, + &playsink->text_sinkpad_stream_synchronizer, + &playsink->text_srcpad_stream_synchronizer, + &playsink->text_sinkpad_policy, + &playsink->text_srcpad_policy); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->text_pad), playsink->text_sinkpad_stream_synchronizer); - gst_pad_link_full (playsink->text_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->text_srcpad_policy, playsink->textchain->textsinkpad, GST_PAD_LINK_CHECK_NOTHING); } @@ -2579,7 +2642,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) gst_pad_link_full (playsink->videodeinterlacechain->srcpad, playsink->textchain->videosinkpad, GST_PAD_LINK_CHECK_NOTHING); else - gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + gst_pad_link_full (playsink->video_srcpad_policy, playsink->textchain->videosinkpad, GST_PAD_LINK_CHECK_NOTHING); } gst_pad_link_full (playsink->textchain->srcpad, @@ -2592,13 +2655,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) /* we have no subtitles/text or we are requested to not show them */ if (playsink->text_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->text_sinkpad_stream_synchronizer); - gst_object_unref (playsink->text_sinkpad_stream_synchronizer); - playsink->text_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->text_srcpad_stream_synchronizer); - playsink->text_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->text_sinkpad_stream_synchronizer, + &playsink->text_srcpad_stream_synchronizer, + &playsink->text_sinkpad_policy, + &playsink->text_srcpad_policy); } if (playsink->textchain) { @@ -2617,13 +2678,11 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } if (!need_video && playsink->video_pad) { if (playsink->video_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->video_sinkpad_stream_synchronizer); - gst_object_unref (playsink->video_sinkpad_stream_synchronizer); - playsink->video_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->video_srcpad_stream_synchronizer); - playsink->video_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->video_sinkpad_stream_synchronizer, + &playsink->video_srcpad_stream_synchronizer, + &playsink->video_sinkpad_policy, + &playsink->video_srcpad_policy); } gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL); @@ -3544,31 +3603,25 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition) break; case GST_STATE_CHANGE_PAUSED_TO_READY:{ if (playsink->video_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->video_sinkpad_stream_synchronizer); - gst_object_unref (playsink->video_sinkpad_stream_synchronizer); - playsink->video_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->video_srcpad_stream_synchronizer); - playsink->video_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->video_sinkpad_stream_synchronizer, + &playsink->video_srcpad_stream_synchronizer, + &playsink->video_sinkpad_policy, + &playsink->video_srcpad_policy); } if (playsink->audio_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->audio_sinkpad_stream_synchronizer); - gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); - playsink->audio_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->audio_srcpad_stream_synchronizer); - playsink->audio_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->audio_sinkpad_stream_synchronizer, + &playsink->audio_srcpad_stream_synchronizer, + &playsink->audio_sinkpad_policy, + &playsink->audio_srcpad_policy); } if (playsink->text_sinkpad_stream_synchronizer) { - gst_element_release_request_pad (GST_ELEMENT_CAST - (playsink->stream_synchronizer), - playsink->text_sinkpad_stream_synchronizer); - gst_object_unref (playsink->text_sinkpad_stream_synchronizer); - playsink->text_sinkpad_stream_synchronizer = NULL; - gst_object_unref (playsink->text_srcpad_stream_synchronizer); - playsink->text_srcpad_stream_synchronizer = NULL; + _remove_policy_and_synchronizer_pads (playsink, + &playsink->text_sinkpad_stream_synchronizer, + &playsink->text_srcpad_stream_synchronizer, + &playsink->text_sinkpad_policy, + &playsink->text_srcpad_policy); } } /* fall through */ diff --git a/gst/policy/Makefile.am b/gst/policy/Makefile.am new file mode 100644 index 0000000..56b377e --- /dev/null +++ b/gst/policy/Makefile.am @@ -0,0 +1,37 @@ +plugin_LTLIBRARIES = libgstpolicy.la + +libgstpolicy_la_SOURCES = \ + gstpolicyplugin.c \ + gstautopolicy.c \ + gstdefaultpolicy.c + +nodist_libgstpolicy_la_SOURCES = $(built_sources) +libgstpolicy_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstpolicy_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstpolicy_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/policy/libgstpolicy-$(GST_MAJORMINOR).la \ + $(GST_LIBS) +libgstpolicy_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstautopolicy.h \ + gstdefaultpolicy.h + +BUILT_SOURCES = $(built_headers) $(built_sources) + +CLEANFILES = $(BUILT_SOURCES) + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstpolicy -:SHARED libgstpolicy \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstpolicy_la_SOURCES) \ + $(nodist_libgstpolicy_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstpolicy_la_CFLAGS) $(csp_cflags) \ + -:LDFLAGS $(libgstpolicy_la_LDFLAGS) \ + $(libgstpolicy_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst/policy/gstautopolicy.c b/gst/policy/gstautopolicy.c new file mode 100644 index 0000000..c46062f --- /dev/null +++ b/gst/policy/gstautopolicy.c @@ -0,0 +1,237 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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-autopolicy + * @see_also: defaultpolicy + * + * Autopolicy is a wrapper element for platform-specific policy elements. + * It automatically detects an appropriate policy element to use by scanning + * the registry for all elements that have Policy in the class + * field of their element information. The list is sorted by rank and only + * elements with a non-zero autoplugging rank are included. + * + * + * Example launch line (with policy-specific debugging) + * |[ + * gst-launch -v -m --gst-debug=policy:5 fakesrc ! autopolicy actual-policy::role=testrole ! fakesink silent=TRUE + * ]| + * + * + * Usage + * Autopolicy provides an unlimited number of request sink pads. You can obtain + * the corresponding source pad by listening to a "pad-added" signal while + * requesting the sink pad. + * + * You can also get and set the stream role property #GstPolicy:role by using + * #GstChildProxy interface that autopolicy implements. The name of the role + * property is "actual-policy::role". + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "gstautopolicy.h" +#include "gstpolicyplugin.h" + +GST_DEBUG_CATEGORY_EXTERN (gst_policy_debug); +#define GST_CAT_DEFAULT gst_policy_debug + +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0 +}; + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("ANY") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src_%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("ANY") + ); + +#define gst_auto_policy_parent_class parent_class +G_DEFINE_TYPE (GstAutoPolicy, gst_auto_policy, GST_TYPE_BIN); + +static GstPad * +gst_auto_policy_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name/*, const GstCaps * caps*/) +{ + GstPad *srcpad = NULL; + GstPad *sinkpad = NULL; + GstPad *kid_sink_pad = NULL; + GstPad *kid_src_pad = NULL; + GstIterator *it = NULL; + GstAutoPolicy *self = GST_AUTO_POLICY (element); + + kid_sink_pad = gst_element_get_request_pad (self->kid, "sink_%d"); + it = gst_pad_iterate_internal_links (kid_sink_pad); + if (!it) { + gst_object_unref(kid_sink_pad); + return NULL; + } + gst_iterator_next (it, (gpointer *)&kid_src_pad); + gst_iterator_free (it); + + sinkpad = gst_ghost_pad_new (name, kid_sink_pad); + srcpad = gst_ghost_pad_new (NULL, kid_src_pad); + + gst_pad_set_element_private (sinkpad, srcpad); + gst_pad_set_element_private (srcpad, sinkpad); + + gst_pad_set_active (srcpad, TRUE); + gst_pad_set_active (sinkpad, TRUE); + + gst_element_add_pad (GST_ELEMENT (self), sinkpad); + gst_element_add_pad (GST_ELEMENT (self), srcpad); + + gst_object_unref (kid_sink_pad); + gst_object_unref (kid_src_pad); + + return sinkpad; +} + +static void +gst_auto_policy_release_pad (GstElement * element, GstPad * pad) +{ + GstAutoPolicy *self = GST_AUTO_POLICY (element); + GstPad *srcpad = gst_pad_get_element_private (pad); + + gst_pad_set_element_private (pad, NULL); + gst_pad_set_element_private (srcpad, NULL); + + gst_element_remove_pad (GST_ELEMENT_CAST (self), srcpad); + gst_element_remove_pad (GST_ELEMENT_CAST (self), pad); +} + +static void +gst_auto_policy_dispose (GstAutoPolicy * auto_policy) +{ + gst_element_set_state (auto_policy->kid, GST_STATE_NULL); + gst_bin_remove (GST_BIN (auto_policy), auto_policy->kid); + auto_policy->kid = NULL; + + G_OBJECT_CLASS (parent_class)->dispose ((GObject *) auto_policy); +} + +/* initialize the policy's class */ +static void +gst_auto_policy_class_init (GstAutoPolicyClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + const GstElementDetails details = { + (gchar *)"Auto policy", (gchar *)"Policy", + (gchar *)"Wrapper element for automatically detected policy element", + (gchar *)"Alexander Kanavin " + }; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->dispose = (GObjectFinalizeFunc) gst_auto_policy_dispose; + + gst_element_class_set_details(gstelement_class, &details); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_factory)); + + gstelement_class->request_new_pad = gst_auto_policy_request_new_pad; + gstelement_class->release_pad = gst_auto_policy_release_pad; +} + +static gboolean +gst_auto_policy_factory_filter (GstPluginFeature * feature, gpointer data) +{ + guint rank; + const gchar *klass; + + /* we only care about element factories */ + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + + /* policy elements */ + klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature)); + if (strstr (klass, "Policy") == NULL) + return FALSE; + + /* only select elements with autoplugging rank */ + rank = gst_plugin_feature_get_rank (feature); + if (rank < GST_RANK_MARGINAL) + return FALSE; + + return TRUE; +} + +static gint +gst_auto_policy_compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2) +{ + return gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); +} + +static GstElement * +gst_auto_policy_discover_actual_policy (GstAutoPolicy * auto_policy) +{ + GList *list, *item; + GstElement *choice = NULL; + + list = gst_registry_feature_filter (gst_registry_get_default (), + (GstPluginFeatureFilter) gst_auto_policy_factory_filter, FALSE, + auto_policy); + list = g_list_sort (list, (GCompareFunc) gst_auto_policy_compare_ranks); + + for (item = list; item != NULL; item = item->next) { + GstElementFactory *f = GST_ELEMENT_FACTORY (item->data); + GST_DEBUG_OBJECT (auto_policy, "Testing %s", GST_OBJECT_NAME (f)); + choice = gst_element_factory_create (f, "actual-policy"); + if (choice) { + GST_DEBUG_OBJECT (auto_policy, "Selected %s", GST_OBJECT_NAME (f)); + break; + } + } + gst_plugin_feature_list_free (list); + return choice; +} + +static void +gst_auto_policy_init (GstAutoPolicy * auto_policy) +{ + auto_policy->kid = gst_auto_policy_discover_actual_policy (auto_policy); + //At least default policy should always be available + g_assert (auto_policy->kid); + gst_bin_add (GST_BIN (auto_policy), auto_policy->kid); + +} diff --git a/gst/policy/gstautopolicy.h b/gst/policy/gstautopolicy.h new file mode 100644 index 0000000..216b153 --- /dev/null +++ b/gst/policy/gstautopolicy.h @@ -0,0 +1,59 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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_AUTO_POLICY_H__ +#define __GST_AUTO_POLICY_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_AUTO_POLICY \ + (gst_auto_policy_get_type()) +#define GST_AUTO_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUTO_POLICY,GstAutoPolicy)) +#define GST_AUTO_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUTO_POLICY,GstAutoPolicyClass)) +#define GST_IS_AUTO_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUTO_POLICY)) +#define GST_IS_AUTO_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUTO_POLICY)) + +typedef struct _GstAutoPolicy GstAutoPolicy; +typedef struct _GstAutoPolicyClass GstAutoPolicyClass; + +struct _GstAutoPolicy +{ + GstBin parent; + + GstElement *kid; +}; + +struct _GstAutoPolicyClass +{ + GstBinClass parent_class; +}; + +GType gst_auto_policy_get_type (void); + +G_END_DECLS + +#endif /* __GST_POLICY_H__ */ diff --git a/gst/policy/gstdefaultpolicy.c b/gst/policy/gstdefaultpolicy.c new file mode 100644 index 0000000..4f1a13a --- /dev/null +++ b/gst/policy/gstdefaultpolicy.c @@ -0,0 +1,69 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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-defaultpolicy + * @see_also: autopolicy + * + * Defaultpolicy implements a default policy, which does nothing at all with the + * stream. It's the element that autopolicy element selects in the absence of any + * other policy element. + * + * + * Example launch line (with policy-specific debugging) + * |[ + * gst-launch -v -m --gst-debug=policy:5 fakesrc ! defaultpolicy role=testrole ! fakesink silent=TRUE + * ]| + * + * + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "gstdefaultpolicy.h" + +#define gst_default_policy_parent_class parent_class +G_DEFINE_TYPE (GstDefaultPolicy, gst_default_policy, GST_TYPE_POLICY); + +static void +gst_default_policy_class_init (GstDefaultPolicyClass * klass) +{ + GstElementClass *gstelement_class; + const GstElementDetails details = { + (gchar *)"Default policy", + (gchar *)"Policy", + (gchar *)"Default policy element that does nothing", + (gchar *)"Alexander Kanavin " + }; + + gstelement_class = (GstElementClass *) klass; + + gst_element_class_set_details (gstelement_class, &details); +} + +static void +gst_default_policy_init (GstDefaultPolicy * policy) +{ +} diff --git a/gst/policy/gstdefaultpolicy.h b/gst/policy/gstdefaultpolicy.h new file mode 100644 index 0000000..fa6f7cb --- /dev/null +++ b/gst/policy/gstdefaultpolicy.h @@ -0,0 +1,58 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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_DEFAULT_POLICY_H__ +#define __GST_DEFAULT_POLICY_H__ + +#include +#include "gst/policy/gstpolicy.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DEFAULT_POLICY \ + (gst_default_policy_get_type()) +#define GST_DEFAULT_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEFAULT_POLICY,GstDefaultPolicy)) +#define GST_DEFAULT_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEFAULT_POLICY,GstDefaultPolicyClass)) +#define GST_IS_DEFAULT_POLICY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEFAULT_POLICY)) +#define GST_IS_DEFAULT_POLICY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEFAULT_POLICY)) + +typedef struct _GstDefaultPolicy GstDefaultPolicy; +typedef struct _GstDefaultPolicyClass GstDefaultPolicyClass; + +struct _GstDefaultPolicy +{ + GstPolicy policy; + +}; + +struct _GstDefaultPolicyClass +{ + GstPolicyClass parent_class; +}; + +GType gst_default_policy_get_type (void); + +G_END_DECLS + +#endif /* __GST_DEFAULT_POLICY_H__ */ diff --git a/gst/policy/gstpolicyplugin.c b/gst/policy/gstpolicyplugin.c new file mode 100644 index 0000000..fe10554 --- /dev/null +++ b/gst/policy/gstpolicyplugin.c @@ -0,0 +1,48 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gstdefaultpolicy.h" +#include "gstautopolicy.h" +#include "gstpolicyplugin.h" + +GST_DEBUG_CATEGORY (gst_policy_debug); +#define GST_CAT_DEFAULT gst_policy_debug + +static gboolean +policy_init (GstPlugin * policy) +{ + GST_DEBUG_CATEGORY_INIT (gst_policy_debug, "policy", 0, "Policy debugging"); + + return gst_element_register (policy, "defaultpolicy", GST_RANK_MARGINAL, + GST_TYPE_DEFAULT_POLICY) && + gst_element_register (policy, "autopolicy", GST_RANK_NONE, + GST_TYPE_AUTO_POLICY); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "policy", + "various policy elements", policy_init, VERSION, GST_LICENSE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/policy/gstpolicyplugin.h b/gst/policy/gstpolicyplugin.h new file mode 100644 index 0000000..cc2ae6d --- /dev/null +++ b/gst/policy/gstpolicyplugin.h @@ -0,0 +1,24 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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_POLICYPLUGIN_H__ +#define __GST_POLICYPLUGIN_H__ + + +#endif /* __GST_POLICYPLUGIN_H__ */ diff --git a/packaging/gst-plugins-base.spec b/packaging/gst-plugins-base.spec index 588b782..867eec8 100644 --- a/packaging/gst-plugins-base.spec +++ b/packaging/gst-plugins-base.spec @@ -102,6 +102,7 @@ rm -rf %{buildroot}/tmp/dump %{_libdir}/libgstrtsp-0.10.so.* %{_libdir}/libgstsdp-0.10.so.* %{_libdir}/libgstapp-0.10.so.* +%{_libdir}/libgstpolicy-0.10.so.* # base plugins without external dependencies %{_libdir}/gstreamer-0.10/libgstadder.so %{_libdir}/gstreamer-0.10/libgstaudioconvert.so @@ -109,6 +110,7 @@ rm -rf %{buildroot}/tmp/dump %{_libdir}/gstreamer-0.10/libgstffmpegcolorspace.so %{_libdir}/gstreamer-0.10/libgstdecodebin.so %{_libdir}/gstreamer-0.10/libgstdecodebin2.so +%{_libdir}/gstreamer-0.10/libgstpolicy.so %{_libdir}/gstreamer-0.10/libgstplaybin.so %{_libdir}/gstreamer-0.10/libgsttypefindfunctions.so %{_libdir}/gstreamer-0.10/libgstvideotestsrc.so @@ -224,6 +226,8 @@ rm -rf %{buildroot}/tmp/dump %{_includedir}/gstreamer-0.10/gst/video/video.h %{_includedir}/gstreamer-0.10/gst/video/video-enumtypes.h %{_includedir}/gstreamer-0.10/gst/video/video-overlay-composition.h +%dir %{_includedir}/gstreamer-0.10/gst/policy/ +%{_includedir}/gstreamer-0.10/gst/policy/gstpolicy.h %{_libdir}/libgstaudio-0.10.so %{_libdir}/libgstinterfaces-0.10.so %{_libdir}/libgstnetbuffer-0.10.so @@ -237,6 +241,7 @@ rm -rf %{buildroot}/tmp/dump %{_libdir}/libgstsdp-0.10.so %{_libdir}/libgstfft-0.10.so %{_libdir}/libgstapp-0.10.so +%{_libdir}/libgstpolicy-0.10.so # pkg-config files %{_libdir}/pkgconfig/*.pc # documentation diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 8fb2529..86b2b12 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am @@ -8,6 +8,7 @@ pcverfiles = \ gstreamer-interfaces-@GST_MAJORMINOR@.pc \ gstreamer-netbuffer-@GST_MAJORMINOR@.pc \ gstreamer-pbutils-@GST_MAJORMINOR@.pc \ + gstreamer-policy-@GST_MAJORMINOR@.pc \ gstreamer-riff-@GST_MAJORMINOR@.pc \ gstreamer-rtp-@GST_MAJORMINOR@.pc \ gstreamer-rtsp-@GST_MAJORMINOR@.pc \ @@ -24,6 +25,7 @@ pcverfiles_uninstalled = \ gstreamer-interfaces-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-netbuffer-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-pbutils-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-policy-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-riff-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-rtp-@GST_MAJORMINOR@-uninstalled.pc \ gstreamer-rtsp-@GST_MAJORMINOR@-uninstalled.pc \ @@ -57,6 +59,7 @@ pcinfiles = \ gstreamer-interfaces.pc.in gstreamer-interfaces-uninstalled.pc.in \ gstreamer-netbuffer.pc.in gstreamer-netbuffer-uninstalled.pc.in \ gstreamer-pbutils.pc.in gstreamer-pbutils-uninstalled.pc.in \ + gstreamer-policy.pc.in gstreamer-policy-uninstalled.pc.in \ gstreamer-riff.pc.in gstreamer-riff-uninstalled.pc.in \ gstreamer-rtp.pc.in gstreamer-rtp-uninstalled.pc.in \ gstreamer-rtsp.pc.in gstreamer-rtsp-uninstalled.pc.in \ diff --git a/pkgconfig/gstreamer-policy-uninstalled.pc.in b/pkgconfig/gstreamer-policy-uninstalled.pc.in new file mode 100644 index 0000000..ef07ea2 --- /dev/null +++ b/pkgconfig/gstreamer-policy-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/policy +typelibdir=@abs_top_builddir@/gst-libs/gst/policy + +Name: GStreamer Policy Library, Uninstalled +Description: Helper functions and base classes for policy integration, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/policy/libgstpolicy-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/pkgconfig/gstreamer-policy.pc.in b/pkgconfig/gstreamer-policy.pc.in new file mode 100644 index 0000000..9ede774 --- /dev/null +++ b/pkgconfig/gstreamer-policy.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Policy Library +Description: Helper functions and base classes for policy integration +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstpolicy-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 3280ba3..f3d9bb9 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -131,6 +131,7 @@ check_PROGRAMS = \ elements/playbin \ elements/playbin2 \ elements/playbin2-compressed \ + elements/policy \ $(check_subparse) \ elements/videorate \ elements/videoscale \ @@ -376,6 +377,9 @@ elements_gdppay_LDADD = $(GST_GDP_LIBS) $(LDADD) elements_playbin_LDADD = $(GST_BASE_LIBS) $(LDADD) elements_playbin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) +elements_policy_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_policy_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + elements_playbin2_LDADD = $(GST_BASE_LIBS) $(LDADD) elements_playbin2_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) diff --git a/tests/check/elements/policy.c b/tests/check/elements/policy.c new file mode 100644 index 0000000..f444b79 --- /dev/null +++ b/tests/check/elements/policy.c @@ -0,0 +1,113 @@ +/* GStreamer + * Copyright (C) <2012> Intel Corporation + * + * 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 +#include + + +static void +test_pads (GstElement * policy) +{ + GstPad *sinkpad1; + GstPad *sinkpad2; + + sinkpad1 = gst_element_get_request_pad (policy, "sink_%d"); + + assert_equals_int (policy->numpads, 2); + assert_equals_int (policy->numsinkpads, 1); + assert_equals_int (policy->numsrcpads, 1); + + sinkpad2 = gst_element_get_request_pad (policy, "sink_%d"); + + assert_equals_int (policy->numpads, 4); + assert_equals_int (policy->numsinkpads, 2); + assert_equals_int (policy->numsrcpads, 2); + + gst_element_release_request_pad (policy, sinkpad2); + g_object_unref (sinkpad2); + assert_equals_int (policy->numpads, 2); + assert_equals_int (policy->numsinkpads, 1); + assert_equals_int (policy->numsrcpads, 1); + + gst_element_release_request_pad (policy, sinkpad1); + g_object_unref (sinkpad1); + assert_equals_int (policy->numpads, 0); + assert_equals_int (policy->numsinkpads, 0); + assert_equals_int (policy->numsrcpads, 0); +} + +GST_START_TEST (test_autopolicy) +{ + GstElement *policy; + const gchar *role1; + gchar *role2; + + policy = gst_check_setup_element ("autopolicy"); + + test_pads (policy); + + role1 = "megarole"; + gst_child_proxy_set (GST_OBJECT (policy), "actual-policy::role", role1, + NULL); + gst_child_proxy_get (GST_OBJECT (policy), "actual-policy::role", &role2, + NULL); + assert_equals_string (role1, role2); + g_free (role2); + + gst_check_teardown_element (policy); +} + +GST_END_TEST; + + +GST_START_TEST (test_defaultpolicy) +{ + GstElement *policy; + const gchar *role1; + gchar *role2; + + policy = gst_check_setup_element ("defaultpolicy"); + + test_pads (policy); + + role1 = "megarole"; + g_object_set (policy, "role", role1, NULL); + g_object_get (policy, "role", &role2, NULL); + assert_equals_string (role1, role2); + g_free (role2); + + gst_check_teardown_element (policy); +} + +GST_END_TEST; + +static Suite * +policy_suite (void) +{ + Suite *s = suite_create ("policy"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_defaultpolicy); + tcase_add_test (tc_chain, test_autopolicy); + + return s; +} + +GST_CHECK_MAIN (policy); -- 2.7.4