gst/rtsp/URLS: Added some other URL.

Original commit message from CVS:
* 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.
This commit is contained in:
Wim Taymans 2006-10-11 16:21:53 +00:00
parent 7cb2c5f8a0
commit 7accf76da8
7 changed files with 156 additions and 14 deletions

View file

@ -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):

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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
};

View file

@ -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;

View file

@ -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;