plugins/elements/gstinputselector.*: Various cleanups.
authorWim Taymans <wim.taymans@gmail.com>
Thu, 13 Mar 2008 16:46:04 +0000 (16:46 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 31 Dec 2010 00:53:14 +0000 (00:53 +0000)
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.

plugins/elements/gstinputselector.c
plugins/elements/gstinputselector.h
plugins/elements/gstoutputselector.c
plugins/elements/gstselector-marshal.list
tests/check/elements/selector.c

index e66eed3..9cd05c5 100644 (file)
@@ -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;
index ee68346..daefced 100644 (file)
@@ -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);
 };
 
index 85c9356..ea682a8 100644 (file)
@@ -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);
index c4f6ca8..e308ac4 100644 (file)
@@ -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);