media: start live streams in blocked state

Start live streams in the blocked state and make them preroll using the
messages. This ensure that no data is played by the sink until we explicitly
unblock the stream right before going to PLAYING.

See https://bugzilla.gnome.org/show_bug.cgi?id=711257
This commit is contained in:
Wim Taymans 2013-11-28 14:06:53 +01:00
parent 6ce48c51a2
commit db771c5167

View file

@ -86,6 +86,7 @@ struct _GstRTSPMediaPrivate
gboolean eos_shutdown;
guint buffer_size;
GstRTSPAddressPool *pool;
gboolean blocked;
GstElement *element;
GRecMutex state_lock; /* locking order: state lock, lock */
@ -1265,6 +1266,22 @@ conversion_failed:
}
}
static void
stream_update_blocked (GstRTSPStream * stream, GstRTSPMedia * media)
{
gst_rtsp_stream_set_blocked (stream, media->priv->blocked);
}
static void
media_streams_set_blocked (GstRTSPMedia * media, gboolean blocked)
{
GstRTSPMediaPrivate *priv = media->priv;
GST_DEBUG ("media %p set blocked %d", media, blocked);
priv->blocked = blocked;
g_ptr_array_foreach (priv->streams, (GFunc) stream_update_blocked, media);
}
/**
* gst_rtsp_media_seek:
* @media: a #GstRTSPMedia
@ -1342,6 +1359,10 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
GST_INFO ("seeking to %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
priv->status = GST_RTSP_MEDIA_STATUS_PREPARING;
if (priv->blocked)
media_streams_set_blocked (media, TRUE);
res = gst_element_seek (priv->pipeline, 1.0, GST_FORMAT_TIME,
flags, start_type, start, stop_type, stop);
@ -1435,6 +1456,23 @@ gst_rtsp_media_get_status (GstRTSPMedia * media)
return result;
}
static void
stream_collect_blocking (GstRTSPStream * stream, gboolean * blocked)
{
*blocked &= gst_rtsp_stream_is_blocking (stream);
}
static gboolean
media_streams_blocking (GstRTSPMedia * media)
{
gboolean blocking = TRUE;
g_ptr_array_foreach (media->priv->streams, (GFunc) stream_collect_blocking,
&blocking);
return blocking;
}
/* called with state-lock */
static gboolean
default_handle_message (GstRTSPMedia * media, GstMessage * message)
@ -1512,7 +1550,22 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
break;
}
case GST_MESSAGE_ELEMENT:
{
const GstStructure *s;
s = gst_message_get_structure (message);
if (gst_structure_has_name (s, "GstRTSPStreamBlocking")) {
GST_DEBUG ("media received blocking message");
if (priv->blocked && media_streams_blocking (media)) {
GST_DEBUG ("media is blocking");
collect_media_stats (media);
if (priv->status == GST_RTSP_MEDIA_STATUS_PREPARING)
gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
}
}
break;
}
case GST_MESSAGE_STREAM_STATUS:
break;
case GST_MESSAGE_ASYNC_DONE:
@ -1721,6 +1774,8 @@ start_preroll (GstRTSPMedia * media)
* seeking query in preroll instead */
priv->seekable = FALSE;
priv->is_live = TRUE;
/* start blocked to make sure nothing goes to the sink */
media_streams_set_blocked (media, TRUE);
ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE)
goto state_failed;
@ -2231,6 +2286,10 @@ media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state)
if (priv->buffering) {
GST_INFO ("Buffering busy, delay state change");
} else {
if (state == GST_STATE_PLAYING)
/* make sure pads are not blocking anymore when going to PLAYING */
media_streams_set_blocked (media, FALSE);
gst_element_set_state (priv->pipeline, state);
}
}