playsink: Reconfigure when pads are added later

Instead of just assuming all pads are created at the same time,
remember which ones are actually new (via ->pending_blocked_pads).

This allows the following use-case to properly work:
* Upstream starts with audio-only
* Only that pad gets data, blocks and a real audio sink is created
* Upstream laters adds a video stream
* A new pad is requested, blocks and reconfiguration kicks in in
  order to add a new real video sink
This commit is contained in:
Edward Hervey 2011-07-27 11:05:31 +00:00 committed by Sebastian Dröge
parent 1dadc5eac1
commit 2ee31ccac9

View file

@ -127,6 +127,19 @@ typedef struct
g_static_rec_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)); \
} G_STMT_END
#define PENDING_FLAG_SET(playsink, flagtype) \
((playsink->pending_blocked_pads) |= (1 << flagtype))
#define PENDING_FLAG_UNSET(playsink, flagtype) \
((playsink->pending_blocked_pads) &= ~(1 << flagtype))
#define PENDING_FLAG_IS_SET(playsink, flagtype) \
((playsink->pending_blocked_pads) & (1 << flagtype))
#define PENDING_VIDEO_BLOCK(playsink) \
((playsink->pending_blocked_pads) & (1 << GST_PLAY_SINK_TYPE_VIDEO_RAW | 1 << GST_PLAY_SINK_TYPE_VIDEO))
#define PENDING_AUDIO_BLOCK(playsink) \
((playsink->pending_blocked_pads) & (1 << GST_PLAY_SINK_TYPE_AUDIO_RAW | 1 << GST_PLAY_SINK_TYPE_AUDIO))
#define PENDING_TEXT_BLOCK(playsink) \
PENDING_FLAG_IS_SET(playsink, GST_PLAY_SINK_TYPE_TEXT)
struct _GstPlaySink
{
GstBin bin;
@ -170,6 +183,8 @@ struct _GstPlaySink
GstPad *text_srcpad_stream_synchronizer;
GstPad *text_sinkpad_stream_synchronizer;
guint32 pending_blocked_pads;
/* properties */
GstElement *audio_sink;
GstElement *video_sink;
@ -2868,12 +2883,22 @@ sinkpad_blocked_cb (GstPad * blockedpad, gboolean blocked, gpointer user_data)
if (pad == playsink->video_pad) {
playsink->video_pad_blocked = blocked;
GST_DEBUG_OBJECT (pad, "Video pad blocked: %d", blocked);
if (!blocked) {
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW);
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO);
}
} else if (pad == playsink->audio_pad) {
playsink->audio_pad_blocked = blocked;
GST_DEBUG_OBJECT (pad, "Audio pad blocked: %d", blocked);
if (!blocked) {
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW);
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO);
}
} else if (pad == playsink->text_pad) {
playsink->text_pad_blocked = blocked;
GST_DEBUG_OBJECT (pad, "Text pad blocked: %d", blocked);
if (!blocked)
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT);
}
if (!blocked) {
@ -2882,9 +2907,17 @@ sinkpad_blocked_cb (GstPad * blockedpad, gboolean blocked, gpointer user_data)
return;
}
if ((!playsink->video_pad || playsink->video_pad_blocked) &&
(!playsink->audio_pad || playsink->audio_pad_blocked) &&
(!playsink->text_pad || playsink->text_pad_blocked)) {
/* We reconfigure when for ALL streams:
* * there isn't a pad
* * OR the pad is blocked
* * OR there are no pending blocks on that pad
*/
if ((!playsink->video_pad || playsink->video_pad_blocked
|| !PENDING_VIDEO_BLOCK (playsink)) && (!playsink->audio_pad
|| playsink->audio_pad_blocked || !PENDING_AUDIO_BLOCK (playsink))
&& (!playsink->text_pad || playsink->text_pad_blocked
|| !PENDING_TEXT_BLOCK (playsink))) {
GST_DEBUG_OBJECT (playsink, "All pads blocked -- reconfiguring");
if (playsink->video_pad) {
@ -3104,6 +3137,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
gst_pad_set_blocked_async_full (blockpad, TRUE, sinkpad_blocked_cb,
gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
PENDING_FLAG_SET (playsink, type);
gst_object_unref (blockpad);
}
if (!activate)