diff --git a/ChangeLog b/ChangeLog index 1b1a2cdda3..98d487b7c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-04-26 Wim Taymans + + * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init), + (gst_rtspsrc_finalize), (gst_rtspsrc_stream_configure_transport), + (gst_rtspsrc_open), (gst_rtspsrc_close), + (gst_rtspsrc_parse_rtpinfo), (gst_rtspsrc_play), + (gst_rtspsrc_pause): + * gst/rtsp/gstrtspsrc.h: + Protect state changes with a lock. + + * gst/rtsp/rtspconnection.c: (rtsp_connection_create), + (parse_line): + * gst/rtsp/rtspconnection.h: + Remove some unused stuff. + 2007-04-26 Wim Taymans * gst/udp/gstudpsrc.c: (gst_udpsrc_create): diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index ef79b6e342..85966dbdee 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -302,6 +302,9 @@ gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class) src->extension = rtsp_ext_wms_get_context (); #endif src->extension->src = (gpointer) src; + + src->state_lock = g_mutex_new (); + src->state = RTSP_STATE_INVALID; } static void @@ -319,6 +322,7 @@ gst_rtspsrc_finalize (GObject * object) g_free (rtspsrc->content_base); rtsp_url_free (rtspsrc->url); g_free (rtspsrc->addr); + g_mutex_free (rtspsrc->state_lock); if (rtspsrc->extension) { #ifdef WITH_EXT_REAL @@ -2554,6 +2558,8 @@ gst_rtspsrc_open (GstRTSPSrc * src) GstRTSPStream *stream = NULL; gchar *respcont = NULL; + GST_RTSP_STATE_LOCK (src); + /* reset our state */ gst_segment_init (&src->segment, GST_FORMAT_TIME); @@ -2645,8 +2651,14 @@ gst_rtspsrc_open (GstRTSPSrc * src) stream = gst_rtspsrc_create_stream (src, &sdp, i); } + src->state = RTSP_STATE_INIT; + /* setup streams */ - gst_rtspsrc_setup_streams (src); + if (!gst_rtspsrc_setup_streams (src)) + goto setup_failed; + + src->state = RTSP_STATE_READY; + GST_RTSP_STATE_UNLOCK (src); /* clean up any messages */ rtsp_message_unset (&request); @@ -2705,8 +2717,14 @@ wrong_content_type: ("Server does not support SDP, got %s.", respcont)); goto cleanup_error; } +setup_failed: + { + /* error was posted */ + goto cleanup_error; + } cleanup_error: { + GST_RTSP_STATE_UNLOCK (src); rtsp_message_unset (&request); rtsp_message_unset (&response); return FALSE; @@ -2722,6 +2740,8 @@ gst_rtspsrc_close (GstRTSPSrc * src) GST_DEBUG_OBJECT (src, "TEARDOWN..."); + GST_RTSP_STATE_LOCK (src); + gst_rtspsrc_loop_send_cmd (src, CMD_STOP); /* stop task if any */ @@ -2767,17 +2787,22 @@ gst_rtspsrc_close (GstRTSPSrc * src) /* cleanup */ gst_rtspsrc_cleanup (src); + src->state = RTSP_STATE_INVALID; + GST_RTSP_STATE_UNLOCK (src); + return TRUE; /* ERRORS */ create_request_failed: { + GST_RTSP_STATE_UNLOCK (src); GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL), ("Could not create request.")); return FALSE; } send_error: { + GST_RTSP_STATE_UNLOCK (src); rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Could not send message.")); @@ -2785,6 +2810,7 @@ send_error: } close_failed: { + GST_RTSP_STATE_UNLOCK (src); GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL), ("Close failed.")); return FALSE; } @@ -2874,11 +2900,16 @@ gst_rtspsrc_play (GstRTSPSrc * src) RTSPResult res; gchar *rtpinfo; - if (!(src->methods & RTSP_PLAY)) - return TRUE; + GST_RTSP_STATE_LOCK (src); GST_DEBUG_OBJECT (src, "PLAY..."); + if (!(src->methods & RTSP_PLAY)) + goto not_supported; + + if (src->state == RTSP_STATE_PLAYING) + goto was_playing; + /* do play */ res = rtsp_message_init_request (&request, RTSP_PLAY, src->req_location); if (res < 0) @@ -2908,20 +2939,36 @@ gst_rtspsrc_play (GstRTSPSrc * src) gst_task_set_lock (src->task, src->stream_rec_lock); } src->running = TRUE; + src->state = RTSP_STATE_PLAYING; gst_rtspsrc_loop_send_cmd (src, CMD_WAIT); gst_task_start (src->task); +done: + GST_RTSP_STATE_UNLOCK (src); + return TRUE; /* ERRORS */ +not_supported: + { + GST_DEBUG_OBJECT (src, "PLAY is not supported"); + goto done; + } +was_playing: + { + GST_DEBUG_OBJECT (src, "we were already PLAYING"); + goto done; + } create_request_failed: { + GST_RTSP_STATE_UNLOCK (src); GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL), ("Could not create request.")); return FALSE; } send_error: { + GST_RTSP_STATE_UNLOCK (src); rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Could not send message.")); @@ -2936,10 +2983,16 @@ gst_rtspsrc_pause (GstRTSPSrc * src) RTSPMessage response = { 0 }; RTSPResult res; - if (!(src->methods & RTSP_PAUSE)) - return TRUE; + GST_RTSP_STATE_LOCK (src); GST_DEBUG_OBJECT (src, "PAUSE..."); + + if (!(src->methods & RTSP_PAUSE)) + goto not_supported; + + if (src->state == RTSP_STATE_READY) + goto was_paused; + /* do pause */ res = rtsp_message_init_request (&request, RTSP_PAUSE, src->req_location); if (res < 0) @@ -2951,17 +3004,34 @@ gst_rtspsrc_pause (GstRTSPSrc * src) rtsp_message_unset (&request); rtsp_message_unset (&response); + src->state = RTSP_STATE_READY; + +done: + GST_RTSP_STATE_UNLOCK (src); + return TRUE; /* ERRORS */ +not_supported: + { + GST_DEBUG_OBJECT (src, "PAUSE is not supported"); + goto done; + } +was_paused: + { + GST_DEBUG_OBJECT (src, "we were already PAUSED"); + goto done; + } create_request_failed: { + GST_RTSP_STATE_UNLOCK (src); GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL), ("Could not create request.")); return FALSE; } send_error: { + GST_RTSP_STATE_UNLOCK (src); rtsp_message_unset (&request); GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), ("Could not send message.")); diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 82582cf3a0..7d595f6998 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -67,6 +67,10 @@ G_BEGIN_DECLS typedef struct _GstRTSPSrc GstRTSPSrc; typedef struct _GstRTSPSrcClass GstRTSPSrcClass; +#define GST_RTSP_STATE_GET_LOCK(rtsp) (GST_RTSPSRC_CAST(rtsp)->state_lock) +#define GST_RTSP_STATE_LOCK(rtsp) (g_mutex_lock (GST_RTSP_STATE_GET_LOCK(rtsp))) +#define GST_RTSP_STATE_UNLOCK(rtsp) (g_mutex_unlock (GST_RTSP_STATE_GET_LOCK(rtsp))) + #define GST_RTSP_LOOP_GET_COND(rtsp) (GST_RTSPSRC_CAST(rtsp)->loop_cond) #define GST_RTSP_LOOP_WAIT(rtsp) (g_cond_wait(GST_RTSP_LOOP_GET_COND (rtsp), GST_OBJECT_GET_LOCK (rtsp))) #define GST_RTSP_LOOP_SIGNAL(rtsp) (g_cond_signal(GST_RTSP_LOOP_GET_COND (rtsp))) @@ -124,6 +128,7 @@ struct _GstRTSPSrc { /* cond to signal loop */ GCond *loop_cond; gint loop_cmd; + GMutex *state_lock; gint numstreams; GList *streams; @@ -141,6 +146,7 @@ struct _GstRTSPSrc { guint latency; /* state */ + RTSPState state; gchar *content_base; RTSPLowerTrans cur_protocols; gboolean tried_url_auth; diff --git a/gst/rtsp/rtspconnection.c b/gst/rtsp/rtspconnection.c index e921a346a3..448dccd3d9 100644 --- a/gst/rtsp/rtspconnection.c +++ b/gst/rtsp/rtspconnection.c @@ -142,7 +142,6 @@ rtsp_connection_create (RTSPUrl * url, RTSPConnection ** conn) newconn->fd = -1; newconn->cseq = 0; newconn->session_id[0] = 0; - newconn->state = RTSP_STATE_INIT; newconn->auth_method = RTSP_AUTH_NONE; newconn->username = NULL; @@ -524,7 +523,7 @@ parse_line (gchar * buffer, RTSPMessage * msg) /* read key */ read_key (key, sizeof (key), &bptr); if (*bptr != ':') - return RTSP_EINVAL; + goto no_column; bptr++; @@ -536,6 +535,11 @@ parse_line (gchar * buffer, RTSPMessage * msg) } return RTSP_OK; + +no_column: + { + return RTSP_EINVAL; + } } RTSPResult diff --git a/gst/rtsp/rtspconnection.h b/gst/rtsp/rtspconnection.h index 2076950b89..fc3b28cfd2 100644 --- a/gst/rtsp/rtspconnection.h +++ b/gst/rtsp/rtspconnection.h @@ -61,7 +61,6 @@ typedef struct _RTSPConnection gint control_sock[2]; /* Session state */ - RTSPState state; gint cseq; /* sequence number */ gchar session_id[512]; /* session id */