rtspsrc: send keep alive when paused

When we are paused, send keep alive messages to the server so that our session
doesn't time out when we go back to playing later.
This commit is contained in:
Wim Taymans 2010-02-26 17:13:49 +01:00
parent 8599aff951
commit 38f2b4735d

View file

@ -241,7 +241,7 @@ static GstRTSPResult gst_rtspsrc_send_cb (GstRTSPExtension * ext,
static gboolean gst_rtspsrc_open (GstRTSPSrc * src); static gboolean gst_rtspsrc_open (GstRTSPSrc * src);
static gboolean gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment); static gboolean gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment);
static gboolean gst_rtspsrc_pause (GstRTSPSrc * src); static gboolean gst_rtspsrc_pause (GstRTSPSrc * src, gboolean idle);
static gboolean gst_rtspsrc_close (GstRTSPSrc * src); static gboolean gst_rtspsrc_close (GstRTSPSrc * src);
static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler, static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler,
@ -1590,7 +1590,7 @@ gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
/* if we were playing, pause first */ /* if we were playing, pause first */
if (playing) if (playing)
gst_rtspsrc_pause (src); gst_rtspsrc_pause (src, FALSE);
gst_rtspsrc_do_seek (src, &seeksegment); gst_rtspsrc_do_seek (src, &seeksegment);
@ -2947,30 +2947,12 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
/* get the next timeout interval */ /* get the next timeout interval */
gst_rtsp_connection_next_timeout (src->connection, &tv_timeout); gst_rtsp_connection_next_timeout (src->connection, &tv_timeout);
/* see if the timeout period expired */ GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
if ((tv_timeout.tv_sec | tv_timeout.tv_usec) == 0) { (gint) tv_timeout.tv_sec);
GST_DEBUG_OBJECT (src, "timout, sending keep-alive");
/* send keep-alive, ignore the result, a warning will be posted. */
gst_rtspsrc_send_keep_alive (src);
}
GST_DEBUG_OBJECT (src, "doing receive");
/* We need to check if playback has been paused while we have been
* doing something else in our own GstTask (e.g. pushing buffer). There
* is a slight chance that we have just received data buffer when PAUSE
* state change happens (in another thread). In this case we well be
* totally ignorant of that unless we explicitly check it here. */
GST_RTSP_STATE_LOCK (src);
if (src->state == GST_RTSP_STATE_READY) {
/* We are looping in a paused mode */
GST_RTSP_STATE_UNLOCK (src);
goto already_paused;
}
/* protect the connection with the connection lock so that we can see when /* protect the connection with the connection lock so that we can see when
* we are finished doing server communication */ * we are finished doing server communication */
res = gst_rtspsrc_connection_receive (src, &message, src->ptcp_timeout); res = gst_rtspsrc_connection_receive (src, &message, src->ptcp_timeout);
GST_RTSP_STATE_UNLOCK (src);
switch (res) { switch (res) {
case GST_RTSP_OK: case GST_RTSP_OK:
@ -2980,8 +2962,10 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
/* we got interrupted this means we need to stop */ /* we got interrupted this means we need to stop */
goto interrupt; goto interrupt;
case GST_RTSP_ETIMEOUT: case GST_RTSP_ETIMEOUT:
/* no reply, go EOS */ /* no reply, send keep alive */
goto timeout; GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
gst_rtspsrc_send_keep_alive (src);
continue;
case GST_RTSP_EEOF: case GST_RTSP_EEOF:
/* go EOS when the server closed the connection */ /* go EOS when the server closed the connection */
goto server_eof; goto server_eof;
@ -3131,14 +3115,6 @@ unknown_stream:
gst_rtsp_message_unset (&message); gst_rtsp_message_unset (&message);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
timeout:
{
GST_DEBUG_OBJECT (src, "we got a timeout");
GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
("Timeout while waiting for server message."));
gst_rtsp_message_unset (&message);
return GST_FLOW_UNEXPECTED;
}
server_eof: server_eof:
{ {
GST_DEBUG_OBJECT (src, "we got an eof from the server"); GST_DEBUG_OBJECT (src, "we got an eof from the server");
@ -3156,11 +3132,6 @@ interrupt:
gst_rtsp_connection_flush (src->connection, FALSE); gst_rtsp_connection_flush (src->connection, FALSE);
return GST_FLOW_WRONG_STATE; return GST_FLOW_WRONG_STATE;
} }
already_paused:
{
GST_DEBUG_OBJECT (src, "got interrupted: playback already paused");
return GST_FLOW_WRONG_STATE;
}
receive_error: receive_error:
{ {
gchar *str = gst_rtsp_strresult (res); gchar *str = gst_rtsp_strresult (res);
@ -3305,7 +3276,7 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
src->cur_protocols = GST_RTSP_LOWER_TRANS_TCP; src->cur_protocols = GST_RTSP_LOWER_TRANS_TCP;
/* pause to prepare for a restart */ /* pause to prepare for a restart */
gst_rtspsrc_pause (src); gst_rtspsrc_pause (src, FALSE);
if (src->task) { if (src->task) {
/* stop task, we cannot join as this would deadlock, the task will stop when /* stop task, we cannot join as this would deadlock, the task will stop when
@ -5176,6 +5147,19 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment)
if (src->state == GST_RTSP_STATE_PLAYING) if (src->state == GST_RTSP_STATE_PLAYING)
goto was_playing; goto was_playing;
if (!src->connection || !src->connected)
goto done;
/* waiting for connection idle, we were flushing so any attempt at doing data
* transfer will result in pausing the tasks. */
GST_DEBUG_OBJECT (src, "wait for connection idle");
GST_RTSP_CONN_LOCK (src);
GST_DEBUG_OBJECT (src, "connection is idle now");
GST_RTSP_CONN_UNLOCK (src);
GST_DEBUG_OBJECT (src, "stop connection flush");
gst_rtsp_connection_flush (src->connection, FALSE);
/* do play */ /* do play */
res = res =
gst_rtsp_message_init_request (&request, GST_RTSP_PLAY, gst_rtsp_message_init_request (&request, GST_RTSP_PLAY,
@ -5286,7 +5270,7 @@ send_error:
} }
static gboolean static gboolean
gst_rtspsrc_pause (GstRTSPSrc * src) gst_rtspsrc_pause (GstRTSPSrc * src, gboolean idle)
{ {
GstRTSPMessage request = { 0 }; GstRTSPMessage request = { 0 };
GstRTSPMessage response = { 0 }; GstRTSPMessage response = { 0 };
@ -5325,6 +5309,13 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
gst_rtsp_message_unset (&request); gst_rtsp_message_unset (&request);
gst_rtsp_message_unset (&response); gst_rtsp_message_unset (&response);
if (idle && src->task) {
GST_DEBUG_OBJECT (src, "starting idle task again");
src->base_time = -1;
gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, FALSE);
gst_task_start (src->task);
}
no_connection: no_connection:
src->state = GST_RTSP_STATE_READY; src->state = GST_RTSP_STATE_READY;
@ -5461,14 +5452,14 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
GST_DEBUG_OBJECT (rtspsrc, "PAUSED->PLAYING: stop connection flush"); GST_DEBUG_OBJECT (rtspsrc, "PAUSED->PLAYING: stop connection flush");
gst_rtsp_connection_flush (rtspsrc->connection, FALSE); gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_STOP, TRUE);
/* send some dummy packets before we chain up to the parent to activate /* send some dummy packets before we chain up to the parent to activate
* the receive in the udp sources */ * the receive in the udp sources */
gst_rtspsrc_send_dummy_packets (rtspsrc); gst_rtspsrc_send_dummy_packets (rtspsrc);
break; break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_DEBUG_OBJECT (rtspsrc, "shutdown: sending stop command"); GST_DEBUG_OBJECT (rtspsrc, "state change: sending stop command");
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_STOP, TRUE); gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_STOP, TRUE);
break; break;
default: default:
@ -5485,7 +5476,8 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
gst_rtspsrc_play (rtspsrc, &rtspsrc->segment); gst_rtspsrc_play (rtspsrc, &rtspsrc->segment);
break; break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
gst_rtspsrc_pause (rtspsrc); /* send pause request and keep the idle task around */
gst_rtspsrc_pause (rtspsrc, TRUE);
ret = GST_STATE_CHANGE_NO_PREROLL; ret = GST_STATE_CHANGE_NO_PREROLL;
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED: