diff --git a/ChangeLog b/ChangeLog index d0e175d3cc..4730050de0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-01-25 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (group_commit), + (gen_preroll_element), (probe_triggered), (gen_source_element), + (setup_source), (gst_play_base_bin_change_state), + (gst_play_base_bin_add_element): + Don't block for streams. + * gst/playback/gststreaminfo.c: (stream_info_change_state), + (gst_stream_info_set_mute): + Use gst_pad_set_active_recursive. + 2005-01-25 Andy Wingo * sys/v4l/gstv4lelement.c (gst_v4l_iface_supported): Fix compile diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c index 05e88ee6b9..eff94ae5ec 100644 --- a/gst/playback/gstplaybasebin.c +++ b/gst/playback/gstplaybasebin.c @@ -373,6 +373,7 @@ static void group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal) { GstPlayBaseGroup *group = play_base_bin->building_group; + gboolean had_active_group = (get_active_group (play_base_bin) != NULL); /* if an element signalled a no-more-pads after we stopped due * to preroll, the group is NULL. This is not an error */ @@ -414,6 +415,14 @@ group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal) g_cond_signal (play_base_bin->group_cond); GST_DEBUG ("signaled group done"); g_mutex_unlock (play_base_bin->group_lock); + + if (!had_active_group && GST_STATE (play_base_bin) > GST_STATE_READY) { + setup_substreams (play_base_bin); + GST_DEBUG ("Emitting signal"); + g_signal_emit (play_base_bin, + gst_play_base_bin_signals[SETUP_OUTPUT_PADS_SIGNAL], 0); + GST_DEBUG ("done"); + } } /* check if there are streams in the group that are not muted */ @@ -504,7 +513,12 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, gst_bin_add (GST_BIN (play_base_bin->thread), preroll); gst_element_set_state (selector, GST_STATE_PLAYING); } - gst_element_set_state (preroll, GST_STATE_PAUSED); + if (GST_STATE (play_base_bin) == GST_STATE_PLAYING && + !get_active_group (play_base_bin)) { + gst_element_set_state (preroll, GST_STATE_PLAYING); + } else { + gst_element_set_state (preroll, GST_STATE_PAUSED); + } play_base_bin->threaded = TRUE; } @@ -648,15 +662,6 @@ probe_triggered (GstProbe * probe, GstData ** data, gpointer user_data) } if (have_left) { - g_mutex_lock (play_base_bin->group_lock); - while (g_list_length (play_base_bin->queued_groups) < 2 && - GST_STATE (play_base_bin->thread) == GST_STATE_PLAYING) { - GST_DEBUG ("Waiting for new groups"); - g_cond_wait (play_base_bin->group_cond, play_base_bin->group_lock); - GST_DEBUG ("done"); - } - g_mutex_unlock (play_base_bin->group_lock); - /* error? */ if (GST_STATE (play_base_bin->thread) != GST_STATE_PLAYING) return TRUE; @@ -671,14 +676,16 @@ probe_triggered (GstProbe * probe, GstData ** data, gpointer user_data) * active */ play_base_bin->queued_groups = g_list_remove (play_base_bin->queued_groups, group); - setup_substreams (play_base_bin); - GST_DEBUG ("switching to next group %p", - play_base_bin->queued_groups->data); - /* and signal the new group */ - GST_DEBUG ("emit signal"); - g_signal_emit (play_base_bin, - gst_play_base_bin_signals[SETUP_OUTPUT_PADS_SIGNAL], 0); - + if (play_base_bin->queued_groups) { + setup_substreams (play_base_bin); + GST_DEBUG ("switching to next group %p", + play_base_bin->queued_groups->data); + /* and signal the new group */ + GST_DEBUG ("emit signal"); + g_signal_emit (play_base_bin, + gst_play_base_bin_signals[SETUP_OUTPUT_PADS_SIGNAL], 0); + } + /* else, it'll be handled in commit_group */ GST_DEBUG ("Syncing state from %d", GST_STATE (play_base_bin->thread)); gst_element_set_state (play_base_bin->thread, GST_STATE_PLAYING); GST_DEBUG ("done"); @@ -988,7 +995,8 @@ setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri) */ static GstElement * -gen_source_element (GstPlayBaseBin * play_base_bin, GstElement ** subbin) +gen_source_element (GstPlayBaseBin * play_base_bin, + GstElement ** subbin, gboolean * _is_stream) { GstElement *source, *queue, *bin; GstProbe *probe; @@ -1011,7 +1019,7 @@ gen_source_element (GstPlayBaseBin * play_base_bin, GstElement ** subbin) return NULL; /* lame - FIXME, maybe we can use seek_types/mask here? */ - is_stream = !strncmp (play_base_bin->uri, "http://", 7) || + *_is_stream = is_stream = !strncmp (play_base_bin->uri, "http://", 7) || !strncmp (play_base_bin->uri, "mms://", 6); if (!is_stream) return source; @@ -1089,12 +1097,14 @@ setup_substreams (GstPlayBaseBin * play_base_bin) * all the streams or until a preroll queue has been filled. */ static gboolean -setup_source (GstPlayBaseBin * play_base_bin, GError ** error) +setup_source (GstPlayBaseBin * play_base_bin, + gboolean * _stream, GError ** error) { GstElement *old_src; GstElement *old_dec; GstPad *srcpad = NULL; GstElement *subbin; + gboolean stream; if (!play_base_bin->need_rebuild) return TRUE; @@ -1105,7 +1115,8 @@ setup_source (GstPlayBaseBin * play_base_bin, GError ** error) old_src = play_base_bin->source; /* create and configure an element that can handle the uri */ - play_base_bin->source = gen_source_element (play_base_bin, &subbin); + play_base_bin->source = gen_source_element (play_base_bin, &subbin, &stream); + *_stream = stream; if (!play_base_bin->source) { /* whoops, could not create the source element */ @@ -1243,33 +1254,39 @@ setup_source (GstPlayBaseBin * play_base_bin, GError ** error) "removed-decoded-pad", G_CALLBACK (removed_decoded_pad), play_base_bin); sig3 = g_signal_connect (G_OBJECT (play_base_bin->decoder), "no-more-pads", G_CALLBACK (no_more_pads), play_base_bin); - sig4 = g_signal_connect (G_OBJECT (play_base_bin->decoder), "unknown-type", - G_CALLBACK (unknown_type), play_base_bin); - sig5 = g_signal_connect (G_OBJECT (play_base_bin->thread), "error", - G_CALLBACK (thread_error), error); - /* either when the queues are filled or when the decoder element has no more - * dynamic streams, the cond is unlocked. We can remove the signal handlers then - */ - g_mutex_lock (play_base_bin->group_lock); - if (gst_element_set_state (play_base_bin->thread, GST_STATE_PLAYING) == - GST_STATE_SUCCESS) { - GST_DEBUG ("waiting for first group..."); - sig6 = g_signal_connect (G_OBJECT (play_base_bin->thread), - "state-change", G_CALLBACK (state_change), play_base_bin); - g_cond_wait (play_base_bin->group_cond, play_base_bin->group_lock); - GST_DEBUG ("group done !"); + if (!stream) { + sig4 = g_signal_connect (G_OBJECT (play_base_bin->decoder), + "unknown-type", G_CALLBACK (unknown_type), play_base_bin); + sig5 = g_signal_connect (G_OBJECT (play_base_bin->thread), "error", + G_CALLBACK (thread_error), error); + + /* either when the queues are filled or when the decoder element + * has no more dynamic streams, the cond is unlocked. We can remove + * the signal handlers then + */ + g_mutex_lock (play_base_bin->group_lock); + if (gst_element_set_state (play_base_bin->thread, GST_STATE_PLAYING) == + GST_STATE_SUCCESS) { + GST_DEBUG ("waiting for first group..."); + sig6 = g_signal_connect (G_OBJECT (play_base_bin->thread), + "state-change", G_CALLBACK (state_change), play_base_bin); + g_cond_wait (play_base_bin->group_cond, play_base_bin->group_lock); + GST_DEBUG ("group done !"); + } else { + GST_DEBUG ("state change failed, media cannot be loaded"); + sig6 = 0; + } + g_mutex_unlock (play_base_bin->group_lock); + + if (sig6 != 0) + g_signal_handler_disconnect (G_OBJECT (play_base_bin->thread), sig6); + + g_signal_handler_disconnect (G_OBJECT (play_base_bin->thread), sig5); + g_signal_handler_disconnect (G_OBJECT (play_base_bin->decoder), sig4); } else { - GST_DEBUG ("state change failed, media cannot be loaded"); - sig6 = 0; + GST_DEBUG ("Source is a stream, delaying stream initialization"); } - g_mutex_unlock (play_base_bin->group_lock); - - if (sig6 != 0) - g_signal_handler_disconnect (G_OBJECT (play_base_bin->thread), sig6); - - g_signal_handler_disconnect (G_OBJECT (play_base_bin->thread), sig5); - g_signal_handler_disconnect (G_OBJECT (play_base_bin->decoder), sig4); play_base_bin->need_rebuild = FALSE; } @@ -1279,7 +1296,9 @@ setup_source (GstPlayBaseBin * play_base_bin, GError ** error) /* make subs iterate from now on */ gst_bin_add (GST_BIN (play_base_bin->thread), play_base_bin->subtitle); } - setup_substreams (play_base_bin); + if (!stream) { + setup_substreams (play_base_bin); + } } return TRUE; @@ -1564,8 +1583,9 @@ gst_play_base_bin_change_state (GstElement * element) case GST_STATE_READY_TO_PAUSED: { GError *error = NULL; + gboolean stream; - if (!setup_source (play_base_bin, &error) || error != NULL) { + if (!setup_source (play_base_bin, &stream, &error) || error != NULL) { if (!error) { /* opening failed but no error - hellup */ GST_ELEMENT_ERROR (GST_ELEMENT (play_base_bin), STREAM, @@ -1578,6 +1598,8 @@ gst_play_base_bin_change_state (GstElement * element) g_error_free (error); } ret = GST_STATE_FAILURE; + } else if (stream) { + ret = gst_element_set_state (play_base_bin->thread, GST_STATE_PAUSED); } else { const GList *item; gboolean stream_found = FALSE, no_media = FALSE; @@ -1640,10 +1662,12 @@ gst_play_base_bin_change_state (GstElement * element) G_CALLBACK (gst_play_base_bin_error), play_base_bin); g_signal_connect (G_OBJECT (play_base_bin->thread), "eos", G_CALLBACK (play_base_eos), play_base_bin); - GST_DEBUG ("emit signal"); - g_signal_emit (play_base_bin, - gst_play_base_bin_signals[SETUP_OUTPUT_PADS_SIGNAL], 0); - GST_DEBUG ("done"); + if (!stream) { + GST_DEBUG ("emit signal"); + g_signal_emit (play_base_bin, + gst_play_base_bin_signals[SETUP_OUTPUT_PADS_SIGNAL], 0); + GST_DEBUG ("done"); + } } else { /* clean up leftover groups */ remove_groups (play_base_bin); @@ -1708,6 +1732,9 @@ gst_play_base_bin_add_element (GstBin * bin, GstElement * element) element = thread; } gst_bin_add (GST_BIN (play_base_bin->thread), element); + if (GST_STATE (play_base_bin) > GST_STATE_READY) { + gst_element_set_state (element, GST_STATE (play_base_bin)); + } /* hack, the clock is not correctly distributed in the core */ sched = gst_element_get_scheduler (GST_ELEMENT (play_base_bin->thread)); diff --git a/gst/playback/gststreaminfo.c b/gst/playback/gststreaminfo.c index 08fcb742e5..160738cf7c 100644 --- a/gst/playback/gststreaminfo.c +++ b/gst/playback/gststreaminfo.c @@ -215,42 +215,6 @@ gst_stream_info_dispose (GObject * object) } } -static void -stream_info_mute_pad (GstStreamInfo * stream_info, GstPad * pad, gboolean mute) -{ - GList *int_links; - gboolean activate = !mute; - gchar *debug_str = (activate ? "activate" : "inactivate"); - - GST_DEBUG_OBJECT (stream_info, "%s %s:%s", debug_str, - GST_DEBUG_PAD_NAME (pad)); - gst_pad_set_active (pad, activate); - if (gst_pad_get_parent (pad)->numsrcpads > 1) - return; - - for (int_links = gst_pad_get_internal_links (pad); - int_links; int_links = g_list_next (int_links)) { - GstPad *pad = GST_PAD (int_links->data); - GstPad *peer = gst_pad_get_peer (pad); - GstElement *peer_elem = peer ? gst_pad_get_parent (peer) : NULL; - - GST_DEBUG_OBJECT (stream_info, "%s internal pad %s:%s", - debug_str, GST_DEBUG_PAD_NAME (pad)); - - gst_pad_set_active (pad, activate); - - if (peer_elem && peer_elem->numsrcpads == 1) { - GST_DEBUG_OBJECT (stream_info, "recursing element %s on pad %s:%s", - gst_element_get_name (peer_elem), GST_DEBUG_PAD_NAME (peer)); - stream_info_mute_pad (stream_info, peer, mute); - } else if (peer) { - GST_DEBUG_OBJECT (stream_info, "%s final pad %s:%s", - debug_str, GST_DEBUG_PAD_NAME (peer)); - gst_pad_set_active (peer, activate); - } - } -} - static void stream_info_change_state (GstElement * element, gint old_state, gint new_state, gpointer data) @@ -261,7 +225,7 @@ stream_info_change_state (GstElement * element, /* state change will annoy us */ g_return_if_fail (stream_info->mute == TRUE); GST_DEBUG_OBJECT (stream_info, "Re-muting pads after state-change"); - stream_info_mute_pad (stream_info, GST_PAD (stream_info->object), TRUE); + gst_pad_set_active_recursive (GST_PAD (stream_info->object), FALSE); } } @@ -277,8 +241,8 @@ gst_stream_info_set_mute (GstStreamInfo * stream_info, gboolean mute) if (mute != stream_info->mute) { stream_info->mute = mute; - stream_info_mute_pad (stream_info, - (GstPad *) GST_PAD_REALIZE (stream_info->object), mute); + gst_pad_set_active_recursive ((GstPad *) + GST_PAD_REALIZE (stream_info->object), !mute); if (mute) { g_signal_connect (gst_pad_get_parent ((GstPad *)