summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2008-03-13 16:46:04 +0000
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2010-12-31 00:53:14 +0000
commit3fcc4068158a575f841e097cf488d05735fd1249 (patch)
treecf9de73112ec12b0f83f143c537012eed9296930
parenteaff78cc08c5f0767ae5f613d21573e5ee0ec4b8 (diff)
plugins/elements/gstinputselector.*: Various cleanups.
Original commit message from CVS: * plugins/elements/gstinputselector.c: (gst_selector_pad_class_init), (gst_selector_pad_finalize), (gst_selector_pad_get_property), (gst_selector_pad_event), (gst_input_selector_class_init), (gst_input_selector_init), (gst_input_selector_set_active_pad), (gst_input_selector_set_property), (gst_input_selector_get_property), (gst_input_selector_request_new_pad), (gst_input_selector_release_pad), (gst_input_selector_push_pending_stop), (gst_input_selector_switch): * plugins/elements/gstinputselector.h: Various cleanups. Added tags to the pads. Select active pad based on the pad object instead of its name. Fix refcount in set_active_pad. Add property to get the number of pads. * plugins/elements/gstoutputselector.c: (gst_output_selector_class_init), (gst_output_selector_set_property), (gst_output_selector_get_property): Various cleanups. Select the active pad based on the pad object instead of its name. Fix locking when setting the active pad. * plugins/elements/gstselector-marshal.list: * tests/check/elements/selector.c: (cleanup_pad), (selector_set_active_pad), (run_input_selector_buffer_count): Fixes for pad instead of padname for pad selection.
-rw-r--r--plugins/elements/gstinputselector.c148
-rw-r--r--plugins/elements/gstinputselector.h5
-rw-r--r--plugins/elements/gstoutputselector.c51
-rw-r--r--plugins/elements/gstselector-marshal.list2
-rw-r--r--tests/check/elements/selector.c5
5 files changed, 135 insertions, 76 deletions
diff --git a/plugins/elements/gstinputselector.c b/plugins/elements/gstinputselector.c
index e66eed3de5..9cd05c5bdf 100644
--- a/plugins/elements/gstinputselector.c
+++ b/plugins/elements/gstinputselector.c
@@ -65,13 +65,20 @@ GST_STATIC_PAD_TEMPLATE ("src",
enum
{
- PROP_ACTIVE_PAD = 1,
- PROP_SELECT_ALL
+ PROP_0,
+ PROP_N_PADS,
+ PROP_ACTIVE_PAD,
+ PROP_SELECT_ALL,
+ PROP_LAST
};
enum
{
- PAD_PROP_RUNNING_TIME = 1
+ PROP_PAD_0,
+ PROP_PAD_RUNNING_TIME,
+ PROP_PAD_TAGS,
+ PROP_PAD_ACTIVE,
+ PROP_PAD_LAST
};
enum
@@ -112,10 +119,12 @@ struct _GstSelectorPad
{
GstPad parent;
- gboolean active;
- gboolean eos;
+ gboolean active; /* when buffer have passed the pad */
+ gboolean eos; /* when EOS has been received */
+ GstSegment segment; /* the current segment on the pad */
+ GstTagList *tags; /* last tags received on the pad */
+
gboolean segment_pending;
- GstSegment segment;
};
struct _GstSelectorPadClass
@@ -174,13 +183,21 @@ gst_selector_pad_class_init (GstSelectorPadClass * klass)
selector_pad_parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = gst_selector_pad_finalize;
+
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_selector_pad_get_property);
- g_object_class_install_property (gobject_class, PAD_PROP_RUNNING_TIME,
+
+ g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME,
g_param_spec_int64 ("running-time", "Running time",
"Running time of stream on pad", 0, G_MAXINT64, 0, G_PARAM_READABLE));
-
- gobject_class->finalize = gst_selector_pad_finalize;
+ g_object_class_install_property (gobject_class, PROP_PAD_TAGS,
+ g_param_spec_boxed ("tags", "Tags",
+ "The currently active tags on the pad", GST_TYPE_TAG_LIST,
+ G_PARAM_READABLE));
+ g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE,
+ g_param_spec_boolean ("active", "Active",
+ "If the pad is currently active", FALSE, G_PARAM_READABLE));
}
static void
@@ -196,6 +213,9 @@ gst_selector_pad_finalize (GObject * object)
pad = GST_SELECTOR_PAD_CAST (object);
+ if (pad->tags)
+ gst_tag_list_free (pad->tags);
+
G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object);
}
@@ -206,10 +226,24 @@ gst_selector_pad_get_property (GObject * object, guint prop_id,
GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object);
switch (prop_id) {
- case PAD_PROP_RUNNING_TIME:
+ case PROP_PAD_RUNNING_TIME:
g_value_set_int64 (value, gst_selector_pad_get_running_time (spad));
break;
+ case PROP_PAD_TAGS:
+ GST_OBJECT_LOCK (object);
+ g_value_set_boxed (value, spad->tags);
+ GST_OBJECT_UNLOCK (object);
+ break;
+ case PROP_PAD_ACTIVE:
+ {
+ GstInputSelector *sel;
+ sel = GST_INPUT_SELECTOR (gst_pad_get_parent (spad));
+ g_value_set_boolean (value, gst_input_selector_is_active_sinkpad (sel,
+ GST_PAD_CAST (spad)));
+ gst_object_unref (sel);
+ break;
+ }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -311,6 +345,21 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event)
selpad->segment_pending = TRUE;
break;
}
+ case GST_EVENT_TAG:
+ {
+ GstTagList *tags;
+
+ GST_OBJECT_LOCK (selpad);
+ if (selpad->tags)
+ gst_tag_list_free (selpad->tags);
+ gst_event_parse_tag (event, &tags);
+ if (tags)
+ tags = gst_tag_list_copy (tags);
+ selpad->tags = tags;
+ GST_DEBUG_OBJECT (sel, "received tags %" GST_PTR_FORMAT, selpad->tags);
+ GST_OBJECT_UNLOCK (selpad);
+ break;
+ }
case GST_EVENT_EOS:
selpad->eos = TRUE;
/* don't forward eos in select_all mode until all sink pads have eos */
@@ -489,7 +538,7 @@ static GList *gst_input_selector_get_linked_pads (GstPad * pad);
static GstCaps *gst_input_selector_getcaps (GstPad * pad);
static gint64 gst_input_selector_block (GstInputSelector * self);
static void gst_input_selector_switch (GstInputSelector * self,
- const gchar * pad_name, gint64 stop_time, gint64 start_time);
+ GstPad * pad, gint64 stop_time, gint64 start_time);
static GstElementClass *parent_class = NULL;
@@ -539,20 +588,25 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_input_selector_dispose;
+
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_input_selector_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_input_selector_get_property);
+
+ g_object_class_install_property (gobject_class, PROP_N_PADS,
+ g_param_spec_uint ("n-pads", "Number of Pads",
+ "The number of sink pads", 0, G_MAXUINT, 0, G_PARAM_READABLE));
+
g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
- g_param_spec_string ("active-pad", "Active pad",
- "Name of the currently" " active sink pad", NULL, G_PARAM_READWRITE));
+ g_param_spec_object ("active-pad", "Active pad",
+ "The currently active sink pad", GST_TYPE_PAD, G_PARAM_READWRITE));
+
g_object_class_install_property (gobject_class, PROP_SELECT_ALL,
g_param_spec_boolean ("select-all", "Select all mode",
"Forwards data from all input pads", FALSE, G_PARAM_READWRITE));
- gobject_class->dispose = gst_input_selector_dispose;
- gstelement_class->request_new_pad = gst_input_selector_request_new_pad;
- gstelement_class->release_pad = gst_input_selector_release_pad;
- gstelement_class->change_state = gst_input_selector_change_state;
/**
* GstInputSelector::block:
@@ -563,13 +617,14 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
* active pad or the current active pad never received data.
*/
gst_input_selector_signals[SIGNAL_BLOCK] =
- g_signal_new ("block", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstInputSelectorClass, block),
- NULL, NULL, gst_selector_marshal_INT64__VOID, G_TYPE_INT64, 0);
+ g_signal_new ("block", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL,
+ gst_selector_marshal_INT64__VOID, G_TYPE_INT64, 0);
/**
* GstInputSelector::switch:
* @inputselector: the #GstInputSelector
- * @pad: name of pad to switch to
+ * @pad: the pad to switch to
* @stop_time: running time at which to close the previous segment, or -1
* to use the running time of the previously active sink pad
* @start_time: running time at which to start the new segment, or -1 to
@@ -609,8 +664,12 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
gst_input_selector_signals[SIGNAL_SWITCH] =
g_signal_new ("switch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstInputSelectorClass, switch_),
- NULL, NULL, gst_selector_marshal_VOID__STRING_INT64_INT64,
- G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT64, G_TYPE_INT64);
+ NULL, NULL, gst_selector_marshal_VOID__OBJECT_INT64_INT64,
+ G_TYPE_NONE, 3, GST_TYPE_PAD, G_TYPE_INT64, G_TYPE_INT64);
+
+ gstelement_class->request_new_pad = gst_input_selector_request_new_pad;
+ gstelement_class->release_pad = gst_input_selector_release_pad;
+ gstelement_class->change_state = gst_input_selector_change_state;
klass->block = GST_DEBUG_FUNCPTR (gst_input_selector_block);
klass->switch_ = GST_DEBUG_FUNCPTR (gst_input_selector_switch);
@@ -627,7 +686,7 @@ gst_input_selector_init (GstInputSelector * sel)
gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
/* sinkpad management */
sel->active_sinkpad = NULL;
- sel->nb_sinkpads = 0;
+ sel->padcount = 0;
gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
sel->blocked_cond = g_cond_new ();
@@ -679,17 +738,11 @@ gst_segment_set_start (GstSegment * segment, gint64 running_time)
static void
gst_input_selector_set_active_pad (GstInputSelector * self,
- const gchar * pad_name, gint64 stop_time, gint64 start_time)
+ GstPad * pad, gint64 stop_time, gint64 start_time)
{
- GstPad *pad;
GstSelectorPad *old, *new;
GstPad **active_pad_p;
- if (strcmp (pad_name, "") != 0)
- pad = gst_element_get_pad (GST_ELEMENT (self), pad_name);
- else
- pad = NULL;
-
GST_OBJECT_LOCK (self);
if (pad == self->active_sinkpad)
@@ -720,12 +773,8 @@ gst_input_selector_set_active_pad (GstInputSelector * self,
done:
GST_OBJECT_UNLOCK (self);
-
- if (pad)
- gst_object_unref (pad);
}
-
static void
gst_input_selector_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@@ -735,7 +784,7 @@ gst_input_selector_set_property (GObject * object, guint prop_id,
switch (prop_id) {
case PROP_ACTIVE_PAD:
gst_input_selector_set_active_pad (sel,
- g_value_get_string (value), GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
+ g_value_get_object (value), GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
break;
case PROP_SELECT_ALL:
sel->select_all = g_value_get_boolean (value);
@@ -753,16 +802,16 @@ gst_input_selector_get_property (GObject * object, guint prop_id,
GstInputSelector *sel = GST_INPUT_SELECTOR (object);
switch (prop_id) {
- case PROP_ACTIVE_PAD:{
+ case PROP_N_PADS:
GST_OBJECT_LOCK (object);
- if (sel->active_sinkpad != NULL) {
- g_value_take_string (value, gst_pad_get_name (sel->active_sinkpad));
- } else {
- g_value_set_string (value, "");
- }
+ g_value_set_uint (value, sel->n_pads);
+ GST_OBJECT_UNLOCK (object);
+ break;
+ case PROP_ACTIVE_PAD:
+ GST_OBJECT_LOCK (object);
+ g_value_set_object (value, sel->active_sinkpad);
GST_OBJECT_UNLOCK (object);
break;
- }
case PROP_SELECT_ALL:
g_value_set_boolean (value, sel->select_all);
break;
@@ -886,12 +935,13 @@ gst_input_selector_request_new_pad (GstElement * element,
sel = GST_INPUT_SELECTOR (element);
g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
- GST_LOG_OBJECT (sel, "Creating new pad %d", sel->nb_sinkpads);
+ GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
GST_OBJECT_LOCK (sel);
- name = g_strdup_printf ("sink%d", sel->nb_sinkpads++);
+ name = g_strdup_printf ("sink%d", sel->padcount++);
sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
"name", name, "direction", templ->direction, "template", templ, NULL);
g_free (name);
+ sel->n_pads++;
GST_OBJECT_UNLOCK (sel);
gst_pad_set_event_function (sinkpad,
@@ -907,6 +957,7 @@ gst_input_selector_request_new_pad (GstElement * element,
gst_pad_set_active (sinkpad, TRUE);
gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
+
return sinkpad;
}
@@ -924,6 +975,7 @@ gst_input_selector_release_pad (GstElement * element, GstPad * pad)
GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
sel->active_sinkpad = NULL;
}
+ sel->n_pads--;
GST_OBJECT_UNLOCK (sel);
gst_pad_set_active (pad, FALSE);
@@ -983,6 +1035,8 @@ gst_input_selector_push_pending_stop (GstInputSelector * self)
if (G_UNLIKELY (self->pending_stop)) {
GstSegment *seg = &self->pending_stop_segment;
+ GST_DEBUG_OBJECT (self, "pushing pending stop");
+
event = gst_event_new_new_segment_full (TRUE, seg->rate,
seg->applied_rate, seg->format, seg->start, seg->stop, seg->stop);
@@ -997,12 +1051,12 @@ gst_input_selector_push_pending_stop (GstInputSelector * self)
/* stop_time and start_time are running times */
static void
-gst_input_selector_switch (GstInputSelector * self, const gchar * pad_name,
+gst_input_selector_switch (GstInputSelector * self, GstPad * pad,
gint64 stop_time, gint64 start_time)
{
g_return_if_fail (self->blocked == TRUE);
- gst_input_selector_set_active_pad (self, pad_name, stop_time, start_time);
+ gst_input_selector_set_active_pad (self, pad, stop_time, start_time);
GST_OBJECT_LOCK (self);
self->blocked = FALSE;
diff --git a/plugins/elements/gstinputselector.h b/plugins/elements/gstinputselector.h
index ee68346508..daefced8af 100644
--- a/plugins/elements/gstinputselector.h
+++ b/plugins/elements/gstinputselector.h
@@ -46,7 +46,8 @@ struct _GstInputSelector {
GstPad *srcpad;
GstPad *active_sinkpad;
- guint nb_sinkpads;
+ guint n_pads;
+ guint padcount;
GstSegment segment;
@@ -63,7 +64,7 @@ struct _GstInputSelectorClass {
GstElementClass parent_class;
gint64 (*block) (GstInputSelector *self);
- void (*switch_) (GstInputSelector *self, const gchar *pad_name,
+ void (*switch_) (GstInputSelector *self, GstPad *pad,
gint64 stop_time, gint64 start_time);
};
diff --git a/plugins/elements/gstoutputselector.c b/plugins/elements/gstoutputselector.c
index 85c9356415..ea682a8f83 100644
--- a/plugins/elements/gstoutputselector.c
+++ b/plugins/elements/gstoutputselector.c
@@ -56,8 +56,10 @@ GST_STATIC_PAD_TEMPLATE ("src%d",
enum
{
- PROP_ACTIVE_PAD = 1,
- PROP_RESEND_LATEST
+ PROP_0,
+ PROP_ACTIVE_PAD,
+ PROP_RESEND_LATEST,
+ PROP_LAST
};
static void gst_output_selector_dispose (GObject * object);
@@ -126,24 +128,29 @@ gst_output_selector_class_init (GstOutputSelectorClass * klass)
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->dispose = gst_output_selector_dispose;
+
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_output_selector_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_output_selector_get_property);
+
g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
- g_param_spec_string ("active-pad", "Active pad",
- "Name of the currently active src pad", NULL, G_PARAM_READWRITE));
+ g_param_spec_object ("active-pad", "Active pad",
+ "Name of the currently active src pad", GST_TYPE_PAD,
+ G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_RESEND_LATEST,
g_param_spec_boolean ("resend-latest", "Resend latest buffer",
"Resend latest buffer after a switch to a new pad", FALSE,
G_PARAM_READWRITE));
- gobject_class->dispose = gst_output_selector_dispose;
+
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_output_selector_request_new_pad);
gstelement_class->release_pad =
GST_DEBUG_FUNCPTR (gst_output_selector_release_pad);
- gstelement_class->change_state = gst_output_selector_change_state;
+ gstelement_class->change_state = gst_output_selector_change_state;
}
static void
@@ -201,22 +208,23 @@ gst_output_selector_set_property (GObject * object, guint prop_id,
GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object);
switch (prop_id) {
- case PROP_ACTIVE_PAD:{
- GstPad *next_pad =
- gst_element_get_static_pad (GST_ELEMENT (sel),
- g_value_get_string (value));
- if (!next_pad) {
- GST_WARNING ("pad %s not found, activation failed",
- g_value_get_string (value));
- break;
- }
- GST_LOG ("Activating pad %s", g_value_get_string (value));
+ case PROP_ACTIVE_PAD:
+ {
+ GstPad *next_pad;
+
+ next_pad = g_value_get_object (value);
+
+ GST_LOG ("Activating pad %s:%s", GST_DEBUG_PAD_NAME (next_pad));
+
+ GST_OBJECT_LOCK (object);
if (next_pad != sel->active_srcpad) {
/* switch to new srcpad in next chain run */
if (sel->pending_srcpad != NULL) {
GST_INFO ("replacing pending switch");
gst_object_unref (sel->pending_srcpad);
}
+ if (next_pad)
+ gst_object_ref (next_pad);
sel->pending_srcpad = next_pad;
} else {
GST_INFO ("pad already active");
@@ -224,8 +232,8 @@ gst_output_selector_set_property (GObject * object, guint prop_id,
gst_object_unref (sel->pending_srcpad);
sel->pending_srcpad = NULL;
}
- gst_object_unref (next_pad);
}
+ GST_OBJECT_UNLOCK (object);
break;
}
case PROP_RESEND_LATEST:{
@@ -245,16 +253,11 @@ gst_output_selector_get_property (GObject * object, guint prop_id,
GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object);
switch (prop_id) {
- case PROP_ACTIVE_PAD:{
+ case PROP_ACTIVE_PAD:
GST_OBJECT_LOCK (object);
- if (sel->active_srcpad != NULL) {
- g_value_take_string (value, gst_pad_get_name (sel->active_srcpad));
- } else {
- g_value_set_string (value, "");
- }
+ g_value_set_object (value, sel->active_srcpad);
GST_OBJECT_UNLOCK (object);
break;
- }
case PROP_RESEND_LATEST:{
GST_OBJECT_LOCK (object);
g_value_set_boolean (value, sel->resend_latest);
diff --git a/plugins/elements/gstselector-marshal.list b/plugins/elements/gstselector-marshal.list
index 97c741cbb3..1102f04cb7 100644
--- a/plugins/elements/gstselector-marshal.list
+++ b/plugins/elements/gstselector-marshal.list
@@ -1,2 +1,2 @@
INT64:VOID
-VOID:STRING,INT64,INT64
+VOID:OBJECT,INT64,INT64
diff --git a/tests/check/elements/selector.c b/tests/check/elements/selector.c
index c4f6ca8d97..e308ac485d 100644
--- a/tests/check/elements/selector.c
+++ b/tests/check/elements/selector.c
@@ -129,8 +129,8 @@ cleanup_pad (GstPad * pad, GstElement * element)
gst_object_unref (pad);
/* cleanup selector pad, reffed by this function (_get_peer) and creator */
- gst_object_unref (selpad);
gst_element_release_request_pad (element, selpad);
+ gst_object_unref (selpad);
}
/* Duplicate and push given buffer many times to all input_pads */
@@ -190,7 +190,7 @@ selector_set_active_pad (GstElement * elem, GstPad * selpad)
padname = gst_pad_get_name (selpad);
}
- g_object_set (G_OBJECT (elem), "active-pad", padname, NULL);
+ g_object_set (G_OBJECT (elem), "active-pad", selpad, NULL);
GST_DEBUG_OBJECT (elem, "activated selector pad: %s", padname);
if (selpad) {
g_free (padname);
@@ -333,6 +333,7 @@ run_input_selector_buffer_count (gint num_input_pads,
gst_pad_remove_data_probe (output_pad, probe_id);
gst_pad_set_active (output_pad, FALSE);
gst_check_teardown_sink_pad (sel);
+ GST_DEBUG ("setting selector pad to NULL");
selector_set_active_pad (sel, NULL); // unref input-selector active pad
g_list_foreach (input_pads, (GFunc) cleanup_pad, sel);
g_list_free (input_pads);