summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--gst/playback/gstplaybin2.c148
-rw-r--r--gst/playback/gsturidecodebin.c6
3 files changed, 105 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 0f81c46e..d44bdb61 100644
--- 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:
diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c
index efa2a657..8fa8d5cb 100644
--- a/gst/playback/gstplaybin2.c
+++ b/gst/playback/gstplaybin2.c
@@ -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;
}
diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c
index 034d7288..9f917ae9 100644
--- a/gst/playback/gsturidecodebin.c
+++ b/gst/playback/gsturidecodebin.c
@@ -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);