diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | gst/rtsp/URLS | 1 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.c | 118 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.h | 6 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.c | 9 | ||||
-rw-r--r-- | gst/rtsp/rtspdefs.h | 10 | ||||
-rw-r--r-- | gst/rtsp/rtspurl.c | 5 |
7 files changed, 156 insertions, 14 deletions
@@ -1,3 +1,24 @@ +2006-10-11 Wim Taymans <wim@fluendo.com> + + * gst/rtsp/URLS: + Added some other URL. + + * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_loop_udp), + (gst_rtspsrc_handle_request), (gst_rtspsrc_send), + (gst_rtspsrc_open), (gst_rtspsrc_play), + (gst_rtspsrc_handle_message), (gst_rtspsrc_change_state): + * gst/rtsp/gstrtspsrc.h: + Work on fallback to TCP connection when the UDP socket times out. + Handler server requests, just reply with OK for now. + + * gst/rtsp/rtspdefs.c: (rtsp_strresult): + * gst/rtsp/rtspdefs.h: + Added some more Real extension headers. + + * gst/rtsp/rtspurl.c: (rtsp_url_parse): + Fix parsing of urls with a ':' that is not part of the hostname:port + part of the url. + 2006-10-11 Tim-Philipp Müller <tim at centricular dot net> * gst/apetag/gsttagdemux.c: (gst_tag_demux_add_srcpad): diff --git a/gst/rtsp/URLS b/gst/rtsp/URLS index 16d5d5a4..4c08f804 100644 --- a/gst/rtsp/URLS +++ b/gst/rtsp/URLS @@ -16,3 +16,4 @@ MP4V-ES/mpeg4-generic(ACC): REAL: rtsp://213.254.239.61/farm/*/encoder/tagesschau/live1high.rm + rtsp://64.192.137.105:554/real.amazon-de.eu2/phononet/B/0/0/0/H/W/Y/4/K/S/01.01.rm?cloakport=80,554,7070 diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index f67ac46b..47917535 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -95,6 +95,10 @@ #include "gstrtspsrc.h" #include "sdp.h" +#if 0 +#define WITH_EXT_REAL +#endif + #include "rtspextwms.h" #ifdef WITH_EXT_REAL #include "rtspextreal.h" @@ -173,6 +177,11 @@ static void gst_rtspsrc_set_property (GObject * object, guint prop_id, static void gst_rtspsrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static gboolean gst_rtspsrc_open (GstRTSPSrc * src); +static gboolean gst_rtspsrc_play (GstRTSPSrc * src); +static gboolean gst_rtspsrc_pause (GstRTSPSrc * src); +static gboolean gst_rtspsrc_close (GstRTSPSrc * src); + static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri); @@ -1207,9 +1216,12 @@ need_pause: static void gst_rtspsrc_loop_udp (GstRTSPSrc * src) { + gboolean restart = FALSE; + GST_OBJECT_LOCK (src); if (src->loop_cmd == CMD_STOP) goto stopping; + while (src->loop_cmd == CMD_WAIT) { GST_DEBUG_OBJECT (src, "waiting"); GST_RTSP_LOOP_WAIT (src); @@ -1220,9 +1232,42 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src) if (src->loop_cmd == CMD_RECONNECT) { /* FIXME, when we get here we have to reconnect using tcp */ src->loop_cmd = CMD_WAIT; + restart = TRUE; } GST_OBJECT_UNLOCK (src); + if (restart) { + gst_rtspsrc_pause (src); + + if (src->task) { + /* stop task, we cannot join as this would deadlock */ + gst_task_stop (src->task); + /* and free the task so that _close will not stop/join it again. */ + gst_object_unref (GST_OBJECT (src->task)); + src->task = NULL; + } + gst_rtspsrc_close (src); + + /* see if we have TCP left to try */ + if (src->cur_protocols & RTSP_LOWER_TRANS_TCP) { + /* We post a warning message now to inform the user + * that nothing happened. It's most likely a firewall thing. */ + GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL), + ("Could not receive any UDP packets for %.4f seconds, maybe your " + "firewall is blocking it. Retrying using a TCP connection.", + (gdouble) src->timeout / 1000000)); + /* we can try only TCP now */ + src->cur_protocols = RTSP_LOWER_TRANS_TCP; + gst_rtspsrc_open (src); + gst_rtspsrc_play (src); + } else { + src->cur_protocols = 0; + /* no transport possible, post an error */ + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Could not receive any UDP packets for %.4f seconds, maybe your " + "firewall is blocking it.", (gdouble) src->timeout / 1000000)); + } + } return; /* ERRORS */ @@ -1253,6 +1298,36 @@ gst_rtspsrc_loop (GstRTSPSrc * src) gst_rtspsrc_loop_udp (src); } +static RTSPResult +gst_rtspsrc_handle_request (GstRTSPSrc * src, RTSPMessage * request) +{ + RTSPMessage response = { 0 }; + RTSPResult res; + + res = rtsp_message_init_response (&response, RTSP_STS_OK, "OK", request); + if (res < 0) + goto send_error; + + if (src->debug) + rtsp_message_dump (&response); + + if ((res = rtsp_connection_send (src->connection, &response)) < 0) + goto send_error; + + return RTSP_OK; + + /* ERRORS */ +send_error: + { + gchar *str = rtsp_strresult (res); + + GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL), + ("Could not send message. (%s)", str)); + g_free (str); + return res; + } +} + /** * gst_rtspsrc_send: * @src: the rtsp source @@ -1287,12 +1362,28 @@ gst_rtspsrc_send (GstRTSPSrc * src, RTSPMessage * request, if ((res = rtsp_connection_send (src->connection, request)) < 0) goto send_error; +next: if ((res = rtsp_connection_receive (src->connection, response)) < 0) goto receive_error; if (src->debug) rtsp_message_dump (response); + switch (response->type) { + case RTSP_MESSAGE_REQUEST: + /* FIXME, handle server request, reply with OK, for now */ + if ((res = gst_rtspsrc_handle_request (src, response)) < 0) + goto handle_request_failed; + goto next; + case RTSP_MESSAGE_RESPONSE: + /* ok, a response is good */ + break; + default: + case RTSP_MESSAGE_DATA: + /* get next response */ + goto next; + } + thecode = response->type_data.response.code; /* if the caller wanted the result code, we store it. Else we check if it's * OK. */ @@ -1332,6 +1423,11 @@ receive_error: g_free (str); return FALSE; } +handle_request_failed: + { + /* ERROR was posted */ + return FALSE; + } error_response: { switch (response->type_data.response.code) { @@ -1566,6 +1662,11 @@ gst_rtspsrc_open (GstRTSPSrc * src) GstRTSPStream *stream = NULL; gchar *respcont = NULL; + /* reset our state */ + src->free_channel = 0; + src->interleaved = FALSE; + gst_segment_init (&src->segment, GST_FORMAT_TIME); + /* can't continue without a valid url */ if (G_UNLIKELY (src->url == NULL)) goto no_url; @@ -1639,7 +1740,7 @@ gst_rtspsrc_open (GstRTSPSrc * src) /* we initially allow all configured lower transports. based on the * replies from the server we narrow them down. */ - protocols = src->protocols; + protocols = src->cur_protocols; /* setup streams */ n_streams = sdp_message_medias_len (&sdp); @@ -1952,7 +2053,7 @@ gst_rtspsrc_play (GstRTSPSrc * src) if (res < 0) goto create_request_failed; - rtsp_message_add_header (&request, RTSP_HDR_RANGE, "npt=0.000-"); + rtsp_message_add_header (&request, RTSP_HDR_RANGE, "npt=0-"); if (!gst_rtspsrc_send (src, &request, &response, NULL)) goto send_error; @@ -2051,13 +2152,6 @@ gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message) if (gst_structure_has_name (s, "GstUDPSrcTimeout")) { GST_DEBUG_OBJECT (bin, "timeout on UDP port"); gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_RECONNECT); - /* FIXME, we post an error message now to inform the user - * that nothing happened. It's most likely a firewall thing. Ideally we - * notify the thread and redo the setup with only TCP. */ - GST_ELEMENT_ERROR (rtspsrc, RESOURCE, READ, (NULL), - ("Could not receive any UDP packets for %.4f seconds, maybe your " - "firewall is blocking it.", - (gdouble) rtspsrc->timeout / 1000000)); return; } } @@ -2080,15 +2174,13 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: - /* the first free channel for interleaved mode */ - rtspsrc->free_channel = 0; - rtspsrc->interleaved = FALSE; - gst_segment_init (&rtspsrc->segment, GST_FORMAT_TIME); + rtspsrc->cur_protocols = rtspsrc->protocols; if (!gst_rtspsrc_open (rtspsrc)) goto open_failed; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: rtsp_connection_flush (rtspsrc->connection, FALSE); + /* copy configuerd protocols */ gst_rtspsrc_play (rtspsrc); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 94b9ed3d..d7ea7e59 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -124,14 +124,18 @@ struct _GstRTSPSrc { GList *streams; GstStructure *props; + /* properties */ gchar *location; RTSPUrl *url; - gchar *content_base; RTSPLowerTrans protocols; gboolean debug; guint retry; guint64 timeout; + /* state */ + gchar *content_base; + RTSPLowerTrans cur_protocols; + /* supported methods */ gint methods; diff --git a/gst/rtsp/rtspdefs.c b/gst/rtsp/rtspdefs.c index 0138d792..63b68a3f 100644 --- a/gst/rtsp/rtspdefs.c +++ b/gst/rtsp/rtspdefs.c @@ -128,7 +128,16 @@ static const gchar *rtsp_headers[] = { "ClientChallenge", /* ClientChallenge */ "RealChallenge1", /* RealChallenge1 */ "RealChallenge2", /* RealChallenge2 */ + "RealChallenge3", /* RealChallenge3 */ "Subscribe", /* Subscribe */ + "Alert", /* Alert */ + "ClientID", /* ClientID */ + "CompanyID", /* CompanyID */ + "GUID", /* GUID */ + "RegionData", /* RegionData */ + "SupportsMaximumASMBandwidth", /* SupportsMaximumASMBandwidth */ + "Language", /* Language */ + "PlayerStarttime", /* PlayerStarttime */ NULL }; diff --git a/gst/rtsp/rtspdefs.h b/gst/rtsp/rtspdefs.h index 229fc42a..7afece94 100644 --- a/gst/rtsp/rtspdefs.h +++ b/gst/rtsp/rtspdefs.h @@ -155,7 +155,17 @@ typedef enum { RTSP_HDR_CLIENT_CHALLENGE, /* ClientChallenge */ RTSP_HDR_REAL_CHALLENGE1, /* RealChallenge1 */ RTSP_HDR_REAL_CHALLENGE2, /* RealChallenge2 */ + RTSP_HDR_REAL_CHALLENGE3, /* RealChallenge3 */ RTSP_HDR_SUBSCRIBE, /* Subscribe */ + RTSP_HDR_ALERT, /* Alert */ + RTSP_HDR_CLIENT_ID, /* ClientID */ + RTSP_HDR_COMPANY_ID, /* CompanyID */ + RTSP_HDR_GUID, /* GUID */ + RTSP_HDR_REGION_DATA, /* RegionData */ + RTSP_HDR_MAX_ASM_WIDTH, /* SupportsMaximumASMBandwidth */ + RTSP_HDR_LANGUAGE, /* Language */ + RTSP_HDR_PLAYER_START_TIME, /* PlayerStarttime */ + } RTSPHeaderField; diff --git a/gst/rtsp/rtspurl.c b/gst/rtsp/rtspurl.c index 04b455ac..cc11e91f 100644 --- a/gst/rtsp/rtspurl.c +++ b/gst/rtsp/rtspurl.c @@ -95,6 +95,11 @@ rtsp_url_parse (const gchar * urlstr, RTSPUrl ** url) } col = strstr (p, ":"); + /* we have a ':' and a slash but the ':' is after the slash, it's not really + * part of the hostname */ + if (col && slash && col >= slash) + col = NULL; + if (col) { res->host = g_strndup (p, col - p); p = col + 1; |