From e623bea6fa306db0da00159788cdd1ba4f3b5acc Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 8 May 2012 15:42:02 +0200 Subject: [PATCH] playbin2: properly reconfigure upon subsequent no-more-pads ... such as during switch in chained ogg. --- gst/playback/gstplaybin2.c | 35 ++++++++++++++++++++++++++++++++++- gst/playback/gstplaysink.c | 43 +++++++++++++++++++++++++++++++++++++++++++ gst/playback/gstplaysink.h | 1 + 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 365e138..c997104 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -2715,6 +2715,9 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) * the sink. */ changed = FALSE; sinkpad = NULL; + + /* store the selector for the pad */ + g_object_set_data (G_OBJECT (pad), "playbin2.select", select); } GST_SOURCE_GROUP_UNLOCK (group); @@ -2787,6 +2790,15 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group); GST_SOURCE_GROUP_LOCK (group); + + if ((select = g_object_get_data (G_OBJECT (pad), "playbin2.select"))) { + g_assert (select->selector == NULL); + g_assert (select->srcpad == pad); + gst_object_unref (pad); + select->srcpad = NULL; + goto exit; + } + /* get the selector sinkpad */ if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin.sinkpad"))) goto not_linked; @@ -2804,6 +2816,16 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) /* remove the pad from the array */ g_ptr_array_remove (select->channels, peer); GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer); + + if (!select->channels->len && select->selector) { + GST_DEBUG_OBJECT (playbin, "all selector sinkpads removed"); + GST_DEBUG_OBJECT (playbin, "removing selector %p", select->selector); + gst_object_unref (select->srcpad); + select->srcpad = NULL; + gst_element_set_state (select->selector, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (playbin), select->selector); + select->selector = NULL; + } } /* unlink the pad now (can fail, the pad is unlinked before it's removed) */ @@ -2823,6 +2845,7 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) gst_object_unref (peer); gst_object_unref (selector); +exit: GST_SOURCE_GROUP_UNLOCK (group); return; @@ -2877,7 +2900,17 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type); select->sinkpad = gst_play_sink_request_pad (playbin->playsink, select->type); - + } else if (select->srcpad && select->sinkpad) { + GST_DEBUG_OBJECT (playbin, "refreshing new sink pad %d", select->type); + gst_play_sink_refresh_pad (playbin->playsink, select->sinkpad, + select->type); + } else if (select->sinkpad && select->srcpad == NULL) { + GST_DEBUG_OBJECT (playbin, "releasing sink pad %d", select->type); + gst_play_sink_release_pad (playbin->playsink, select->sinkpad); + select->sinkpad = NULL; + } + if (select->sinkpad && select->srcpad && + !gst_pad_is_linked (select->srcpad)) { res = gst_pad_link (select->srcpad, select->sinkpad); GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media_list[0], res); diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index be3f5e9..e441465 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -3507,6 +3507,48 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink) } } +void +gst_play_sink_refresh_pad (GstPlaySink * playsink, GstPad * pad, + GstPlaySinkType type) +{ + GST_DEBUG_OBJECT (playsink, "refresh pad %" GST_PTR_FORMAT, pad); + + GST_PLAY_SINK_LOCK (playsink); + if (pad == playsink->video_pad) { + if (type != GST_PLAY_SINK_TYPE_VIDEO_RAW && + type != GST_PLAY_SINK_TYPE_VIDEO) + goto wrong_type; + } else if (pad == playsink->audio_pad) { + if (type != GST_PLAY_SINK_TYPE_AUDIO_RAW && + type != GST_PLAY_SINK_TYPE_AUDIO) + goto wrong_type; + } else if (pad == playsink->text_pad) { + if (type != GST_PLAY_SINK_TYPE_TEXT) + goto wrong_type; + } + + if (type != GST_PLAY_SINK_TYPE_FLUSHING) { + GstPad *blockpad = + GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (pad))); + + gst_pad_set_blocked_async (blockpad, TRUE, sinkpad_blocked_cb, playsink); + PENDING_FLAG_SET (playsink, type); + gst_object_unref (blockpad); + } + GST_PLAY_SINK_UNLOCK (playsink); + + return; + + /* ERRORS */ +wrong_type: + { + GST_WARNING_OBJECT (playsink, "wrong type %d for pad %" GST_PTR_FORMAT, + pad); + GST_PLAY_SINK_UNLOCK (playsink); + return; + } +} + /** * gst_play_sink_request_pad * @playsink: a #GstPlaySink @@ -3631,6 +3673,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) return res; } + static GstPad * gst_play_sink_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) diff --git a/gst/playback/gstplaysink.h b/gst/playback/gstplaysink.h index 51fe14b..6141c2c 100644 --- a/gst/playback/gstplaysink.h +++ b/gst/playback/gstplaysink.h @@ -70,6 +70,7 @@ GType gst_play_sink_get_type (void); GstPad * gst_play_sink_request_pad (GstPlaySink *playsink, GstPlaySinkType type); void gst_play_sink_release_pad (GstPlaySink *playsink, GstPad *pad); +void gst_play_sink_refresh_pad (GstPlaySink *playsink, GstPad *pad, GstPlaySinkType type); void gst_play_sink_set_sink (GstPlaySink * playsink, GstPlaySinkType type, GstElement * sink); GstElement * gst_play_sink_get_sink (GstPlaySink * playsink, GstPlaySinkType type); -- 2.7.4