gst/playback/gstplaybin2.c: Fix some comments and docs.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 7 Jan 2009 13:52:14 +0000 (13:52 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 7 Jan 2009 13:52:14 +0000 (13:52 +0000)
Original commit message from CVS:
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(gst_play_bin_set_uri), (gst_play_bin_set_suburi),
(no_more_pads_cb), (drained_cb), (group_set_locked_state_unlocked),
(activate_group), (deactivate_group), (groups_set_locked_state),
(gst_play_bin_change_state):
Fix some comments and docs.
Post an error message when we fail to link the selector to the sink.
Remove pushing of EOS, this seems unneeded.
Lock the state of deactivated groups so that they don't accidentally
reactivate when the playbin2 state changes.
Reuse uridecodebins.
Unlock and relock state of groups when playbin goes to NULL.
Fixes #566654.
Fixes #566341.
* gst/playback/gsturidecodebin.c: (pad_removed_cb), (type_found):
Only do something in the pad removed callback when we are dealing with
our sourcepads because the sinkpads don't have a ghostpad.

ChangeLog
gst/playback/gstplaybin2.c
gst/playback/gsturidecodebin.c

index 0f81c46..d44bdb6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2009-01-07  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
+       (gst_play_bin_set_uri), (gst_play_bin_set_suburi),
+       (no_more_pads_cb), (drained_cb), (group_set_locked_state_unlocked),
+       (activate_group), (deactivate_group), (groups_set_locked_state),
+       (gst_play_bin_change_state):
+       Fix some comments and docs.
+       Post an error message when we fail to link the selector to the sink.
+       Remove pushing of EOS, this seems unneeded. 
+       Lock the state of deactivated groups so that they don't accidentally
+       reactivate when the playbin2 state changes.
+       Reuse uridecodebins.
+       Unlock and relock state of groups when playbin goes to NULL.
+       Fixes #566654.
+       Fixes #566341.
+
+       * gst/playback/gsturidecodebin.c: (pad_removed_cb), (type_found):
+       Only do something in the pad removed callback when we are dealing with
+       our sourcepads because the sinkpads don't have a ghostpad.
+
 2009-01-07  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
 
        * gst-libs/gst/cdda/gstcddabasesrc.c:
index efa2a65..8fa8d5c 100644 (file)
@@ -732,7 +732,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
    * @playbin: a #GstPlayBin2
    *
    * This signal is emitted when the current uri is about to finish. You can
-   * set the next-uri and next-suburi to make sure that playback continues.
+   * set the uri and suburi to make sure that playback continues.
    */
   gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
@@ -1022,14 +1022,13 @@ gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri)
   group = playbin->next_group;
 
   GST_SOURCE_GROUP_LOCK (group);
-  /* if we have no previous uri, or the new uri is different from the
-   * old one, replug */
+  /* store the uri in the next group we will play */
   g_free (group->uri);
   group->uri = g_strdup (uri);
   group->valid = TRUE;
   GST_SOURCE_GROUP_UNLOCK (group);
 
-  GST_DEBUG ("setting new uri to %s", uri);
+  GST_DEBUG ("set new uri to %s", uri);
   GST_PLAY_BIN_UNLOCK (playbin);
 }
 
@@ -1042,17 +1041,12 @@ gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
   group = playbin->next_group;
 
   GST_SOURCE_GROUP_LOCK (group);
-  if ((!suburi && !group->suburi) ||
-      (suburi && group->suburi && !strcmp (group->suburi, suburi)))
-    goto done;
-
   g_free (group->suburi);
   group->suburi = g_strdup (suburi);
+  GST_SOURCE_GROUP_UNLOCK (group);
 
   GST_DEBUG ("setting new .sub uri to %s", suburi);
 
-done:
-  GST_SOURCE_GROUP_UNLOCK (group);
   GST_PLAY_BIN_UNLOCK (playbin);
 }
 
@@ -1894,6 +1888,11 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
       res = gst_pad_link (select->srcpad, select->sinkpad);
       GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media,
           res);
+      if (res != GST_PAD_LINK_OK) {
+        GST_ELEMENT_ERROR (playbin, CORE, PAD,
+            ("Internal playbin error."),
+            ("Failed to link selector to sink. Error %d", res));
+      }
     }
   }
   GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
@@ -1944,41 +1943,6 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
   }
 }
 
-/* send an EOS event to all of the selectors */
-static void
-perform_eos (GstPlayBin * playbin, GstSourceGroup * group)
-{
-  gboolean res;
-  GstEvent *event;
-  gint i;
-
-  GST_DEBUG_OBJECT (playbin, "doing EOS in group %p", group);
-
-  event = gst_event_new_eos ();
-
-  res = FALSE;
-
-  GST_SOURCE_GROUP_LOCK (group);
-  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
-    GstSourceSelect *select = &group->selector[i];
-
-    if (select->selector) {
-      GST_DEBUG_OBJECT (playbin, "send EOS in selector %s", select->media);
-      gst_event_ref (event);
-      res |= gst_pad_push_event (select->srcpad, event);
-    }
-  }
-  GST_SOURCE_GROUP_UNLOCK (group);
-
-  gst_event_unref (event);
-
-  if (!res) {
-    /* we cannot post an error because we don't know if the EOS failed because
-     * of a fatal error or simply a pipeline shutdown */
-    GST_ERROR_OBJECT (playbin, "failed to send EOS");
-  }
-}
-
 static void
 drained_cb (GstElement * decodebin, GstSourceGroup * group)
 {
@@ -2000,9 +1964,7 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group)
 
   /* now activate the next group. If the app did not set a next-uri, this will
    * fail and we can do EOS */
-  if (!setup_next_source (playbin)) {
-    perform_eos (playbin, group);
-  }
+  setup_next_source (playbin);
 }
 
 /* Called when we must provide a list of factories to plug to @pad with @caps.
@@ -2124,6 +2086,20 @@ notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec,
   g_object_notify (G_OBJECT (playbin), "source");
 }
 
+static gboolean
+group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group,
+    gboolean locked)
+{
+  GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group);
+
+  if (group->uridecodebin)
+    gst_element_set_locked_state (group->uridecodebin, locked);
+  if (group->suburidecodebin)
+    gst_element_set_locked_state (group->suburidecodebin, locked);
+
+  return TRUE;
+}
+
 #define REMOVE_SIGNAL(obj,id)            \
 if (id) {                                \
   g_signal_handler_disconnect (obj, id); \
@@ -2142,6 +2118,7 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
 
   GST_SOURCE_GROUP_LOCK (group);
   if (group->uridecodebin) {
+    GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
     REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id);
     REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id);
     REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id);
@@ -2150,14 +2127,16 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
     gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
-    gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
-    group->uridecodebin = NULL;
+    uridecodebin = group->uridecodebin;
+  } else {
+    GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
+    uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
+    if (!uridecodebin)
+      goto no_decodebin;
+    gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
+    group->uridecodebin = uridecodebin;
   }
 
-  uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
-  if (!uridecodebin)
-    goto no_decodebin;
-
   /* configure connection speed */
   g_object_set (uridecodebin, "connection-speed", playbin->connection_speed,
       NULL);
@@ -2195,25 +2174,25 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
   group->autoplug_select_id = g_signal_connect (uridecodebin, "autoplug-select",
       G_CALLBACK (autoplug_select_cb), group);
 
-  /*  */
-  gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
-  group->uridecodebin = uridecodebin;
-
   if (group->suburi) {
     /* subtitles */
     if (group->suburidecodebin) {
+      GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
       REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
       gst_element_set_state (group->suburidecodebin, GST_STATE_NULL);
-      gst_bin_remove (GST_BIN_CAST (playbin), group->suburidecodebin);
-      group->suburidecodebin = NULL;
+      suburidecodebin = group->suburidecodebin;
+    } else {
+      GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
+      suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
+      if (!suburidecodebin)
+        goto no_decodebin;
+
+      gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
+      group->suburidecodebin = suburidecodebin;
     }
 
-    suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
-    if (!suburidecodebin)
-      goto no_decodebin;
-
     /* configure connection speed */
     g_object_set (suburidecodebin, "connection-speed",
         playbin->connection_speed, NULL);
@@ -2223,10 +2202,6 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
     /* configure uri */
     g_object_set (suburidecodebin, "uri", group->suburi, NULL);
 
-    /*  */
-    gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
-    group->suburidecodebin = suburidecodebin;
-
     /* connect pads and other things */
     group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added",
         G_CALLBACK (pad_added_cb), group);
@@ -2246,6 +2221,8 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group)
           GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE)
     goto uridecodebin_failure;
 
+  /* alow state changes of the playbin2 affect the group elements now */
+  group_set_locked_state_unlocked (playbin, group, FALSE);
   group->active = TRUE;
   GST_SOURCE_GROUP_UNLOCK (group);
 
@@ -2294,9 +2271,11 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
     GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
 
     if (select->sinkpad) {
+      GST_LOG_OBJECT (playbin, "unlinking from sink");
       gst_pad_unlink (select->srcpad, select->sinkpad);
 
       /* release back */
+      GST_LOG_OBJECT (playbin, "release sink pad");
       gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
       select->sinkpad = NULL;
     }
@@ -2308,6 +2287,11 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
     gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
     select->selector = NULL;
   }
+  /* we still have the decodebins added to the playbin2 but we can't remove them
+   * yet or change their state because this function might be called from the
+   * streaming threads, instead block the state so that state changes on the
+   * playbin2 don't affect us anymore */
+  group_set_locked_state_unlocked (playbin, group, TRUE);
   GST_SOURCE_GROUP_UNLOCK (group);
 
   return TRUE;
@@ -2364,7 +2348,7 @@ activate_failed:
 }
 
 /* The group that is currently playing is copied again to the
- * next_group.
+ * next_group so that it will start playing the next time.
  */
 static gboolean
 save_current_group (GstPlayBin * playbin)
@@ -2388,6 +2372,25 @@ save_current_group (GstPlayBin * playbin)
   return TRUE;
 }
 
+/* clear the locked state from all groups. This function is called before a
+ * state change to NULL is performed on them. */
+static gboolean
+groups_set_locked_state (GstPlayBin * playbin, gboolean locked)
+{
+  GST_DEBUG_OBJECT (playbin, "setting locked state to %d on groups groups");
+
+  GST_PLAY_BIN_LOCK (playbin);
+  GST_SOURCE_GROUP_LOCK (playbin->curr_group);
+  group_set_locked_state_unlocked (playbin, playbin->curr_group, locked);
+  GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
+  GST_SOURCE_GROUP_LOCK (playbin->next_group);
+  group_set_locked_state_unlocked (playbin, playbin->next_group, locked);
+  GST_SOURCE_GROUP_UNLOCK (playbin->next_group);
+  GST_PLAY_BIN_UNLOCK (playbin);
+
+  return TRUE;
+}
+
 static GstStateChangeReturn
 gst_play_bin_change_state (GstElement * element, GstStateChange transition)
 {
@@ -2404,6 +2407,10 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       /* FIXME unlock our waiting groups */
       break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      /* unlock so that all groups go to NULL */
+      groups_set_locked_state (playbin, FALSE);
+      break;
     default:
       break;
   }
@@ -2421,6 +2428,9 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       save_current_group (playbin);
       break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      groups_set_locked_state (playbin, TRUE);
+      break;
     default:
       break;
   }
index 034d728..9f917ae 100644 (file)
@@ -693,6 +693,10 @@ pad_removed_cb (GstElement * element, GstPad * pad, GstURIDecodeBin * decoder)
   GST_DEBUG_OBJECT (element, "pad removed name: <%s:%s>",
       GST_DEBUG_PAD_NAME (pad));
 
+  /* we only care about srcpads */
+  if (!GST_PAD_IS_SRC (pad))
+    return;
+
   if (!(ghost = g_object_get_data (G_OBJECT (pad), "uridecodebin.ghostpad")))
     goto no_ghost;
 
@@ -1141,7 +1145,7 @@ type_found (GstElement * typefind, guint probability,
     goto no_queue2;
 
   g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
-//  g_object_set (G_OBJECT (queue), "temp-location", "temp", NULL);
+  /* g_object_set (G_OBJECT (queue), "temp-location", "temp", NULL); */
 
   /* Disable max-size-buffers */
   g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL);