mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-12 11:26:39 +00:00
gst/rtsp/URLS: Add some more URLs.
Original commit message from CVS: * gst/rtsp/URLS: Add some more URLs. * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_class_init), (gst_rtspsrc_init), (gst_rtspsrc_finalize), (gst_rtspsrc_set_property), (gst_rtspsrc_get_property), (gst_rtspsrc_stream_setup_rtp), (gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp), (gst_rtspsrc_loop_send_cmd), (gst_rtspsrc_loop), (gst_rtspsrc_send), (gst_rtspsrc_parse_methods), (gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play), (gst_rtspsrc_pause), (gst_rtspsrc_handle_message), (gst_rtspsrc_change_state): * gst/rtsp/gstrtspsrc.h: Add timeout property to control UDP timeouts. Fix error messages. Also start a loop function when operating in UDP mode so that we can do some more stuff async. Handle element messages from udpsrc to detect timeouts. If a timeout happens we currently generate an error. API: rtspsrc::timeout property. * gst/udp/gstudpsrc.c: (gst_udpsrc_class_init), (gst_udpsrc_create): Really implement the timeout in microseconds and not milliseconds.
This commit is contained in:
parent
fcd901a5bf
commit
6e08550345
5 changed files with 221 additions and 74 deletions
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
||||||
|
2006-09-29 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/rtsp/URLS:
|
||||||
|
Add some more URLs.
|
||||||
|
|
||||||
|
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_class_init),
|
||||||
|
(gst_rtspsrc_init), (gst_rtspsrc_finalize),
|
||||||
|
(gst_rtspsrc_set_property), (gst_rtspsrc_get_property),
|
||||||
|
(gst_rtspsrc_stream_setup_rtp), (gst_rtspsrc_loop_interleaved),
|
||||||
|
(gst_rtspsrc_loop_udp), (gst_rtspsrc_loop_send_cmd),
|
||||||
|
(gst_rtspsrc_loop), (gst_rtspsrc_send),
|
||||||
|
(gst_rtspsrc_parse_methods), (gst_rtspsrc_open),
|
||||||
|
(gst_rtspsrc_close), (gst_rtspsrc_play), (gst_rtspsrc_pause),
|
||||||
|
(gst_rtspsrc_handle_message), (gst_rtspsrc_change_state):
|
||||||
|
* gst/rtsp/gstrtspsrc.h:
|
||||||
|
Add timeout property to control UDP timeouts.
|
||||||
|
Fix error messages.
|
||||||
|
Also start a loop function when operating in UDP mode so that we can
|
||||||
|
do some more stuff async.
|
||||||
|
Handle element messages from udpsrc to detect timeouts. If a timeout
|
||||||
|
happens we currently generate an error.
|
||||||
|
API: rtspsrc::timeout property.
|
||||||
|
|
||||||
|
* gst/udp/gstudpsrc.c: (gst_udpsrc_class_init),
|
||||||
|
(gst_udpsrc_create):
|
||||||
|
Really implement the timeout in microseconds and not milliseconds.
|
||||||
|
|
||||||
2006-09-29 Wim Taymans <wim@fluendo.com>
|
2006-09-29 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/udp/gstudpsrc.c: (gst_udpsrc_class_init), (gst_udpsrc_init),
|
* gst/udp/gstudpsrc.c: (gst_udpsrc_class_init), (gst_udpsrc_init),
|
||||||
|
|
|
@ -2,6 +2,7 @@ Some test URLS:
|
||||||
|
|
||||||
SVQ3 video:
|
SVQ3 video:
|
||||||
rtsp://cumulus.creative.auckland.ac.nz/~shado/nelson_iv_512k.mov
|
rtsp://cumulus.creative.auckland.ac.nz/~shado/nelson_iv_512k.mov
|
||||||
|
rtsp://streamr.hitpops.jp/ngc/mov/m0609.mov
|
||||||
|
|
||||||
ASF (audio/video):
|
ASF (audio/video):
|
||||||
rtsp://aod.mylisten.com/aod/8/03/069803_0903135.wma
|
rtsp://aod.mylisten.com/aod/8/03/069803_0903135.wma
|
||||||
|
@ -11,3 +12,7 @@ ASF (audio/video):
|
||||||
|
|
||||||
MP4V-ES/mpeg4-generic(ACC):
|
MP4V-ES/mpeg4-generic(ACC):
|
||||||
rtsp://vod.nwec.jp/quicktime/505.mov
|
rtsp://vod.nwec.jp/quicktime/505.mov
|
||||||
|
rtsp://203.140.68.241:554/hirakataeizou9.mp4
|
||||||
|
|
||||||
|
REAL:
|
||||||
|
rtsp://213.254.239.61/farm/*/encoder/tagesschau/live1high.rm
|
||||||
|
|
|
@ -123,6 +123,7 @@ enum
|
||||||
#define DEFAULT_PROTOCOLS GST_RTSP_PROTO_UDP_UNICAST | GST_RTSP_PROTO_UDP_MULTICAST | GST_RTSP_PROTO_TCP
|
#define DEFAULT_PROTOCOLS GST_RTSP_PROTO_UDP_UNICAST | GST_RTSP_PROTO_UDP_MULTICAST | GST_RTSP_PROTO_TCP
|
||||||
#define DEFAULT_DEBUG FALSE
|
#define DEFAULT_DEBUG FALSE
|
||||||
#define DEFAULT_RETRY 20
|
#define DEFAULT_RETRY 20
|
||||||
|
#define DEFAULT_TIMEOUT 5000000
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -131,7 +132,7 @@ enum
|
||||||
PROP_PROTOCOLS,
|
PROP_PROTOCOLS,
|
||||||
PROP_DEBUG,
|
PROP_DEBUG,
|
||||||
PROP_RETRY,
|
PROP_RETRY,
|
||||||
/* FILL ME */
|
PROP_TIMEOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GST_TYPE_RTSP_PROTO (gst_rtsp_proto_get_type())
|
#define GST_TYPE_RTSP_PROTO (gst_rtsp_proto_get_type())
|
||||||
|
@ -161,6 +162,7 @@ static GstCaps *gst_rtspsrc_media_to_caps (gint pt, SDPMedia * media);
|
||||||
|
|
||||||
static GstStateChangeReturn gst_rtspsrc_change_state (GstElement * element,
|
static GstStateChangeReturn gst_rtspsrc_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
static void gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message);
|
||||||
|
|
||||||
static void gst_rtspsrc_set_property (GObject * object, guint prop_id,
|
static void gst_rtspsrc_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -172,6 +174,11 @@ static gboolean gst_rtspsrc_uri_set_uri (GstURIHandler * handler,
|
||||||
|
|
||||||
static void gst_rtspsrc_loop (GstRTSPSrc * src);
|
static void gst_rtspsrc_loop (GstRTSPSrc * src);
|
||||||
|
|
||||||
|
/* commands we send to out loop to notify it of events */
|
||||||
|
#define CMD_WAIT 0
|
||||||
|
#define CMD_RECONNECT 1
|
||||||
|
#define CMD_STOP 2
|
||||||
|
|
||||||
/*static guint gst_rtspsrc_signals[LAST_SIGNAL] = { 0 }; */
|
/*static guint gst_rtspsrc_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -239,7 +246,15 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
|
||||||
0, G_MAXUINT16, DEFAULT_RETRY,
|
0, G_MAXUINT16, DEFAULT_RETRY,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_TIMEOUT,
|
||||||
|
g_param_spec_uint64 ("timeout", "Timeout",
|
||||||
|
"Retry TCP transport after timeout microseconds (0 = disabled)",
|
||||||
|
0, G_MAXUINT64, DEFAULT_TIMEOUT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||||
|
|
||||||
gstelement_class->change_state = gst_rtspsrc_change_state;
|
gstelement_class->change_state = gst_rtspsrc_change_state;
|
||||||
|
|
||||||
|
gstbin_class->handle_message = gst_rtspsrc_handle_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -248,6 +263,8 @@ gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
|
||||||
src->stream_rec_lock = g_new (GStaticRecMutex, 1);
|
src->stream_rec_lock = g_new (GStaticRecMutex, 1);
|
||||||
g_static_rec_mutex_init (src->stream_rec_lock);
|
g_static_rec_mutex_init (src->stream_rec_lock);
|
||||||
|
|
||||||
|
src->loop_cond = g_cond_new ();
|
||||||
|
|
||||||
src->location = DEFAULT_LOCATION;
|
src->location = DEFAULT_LOCATION;
|
||||||
src->url = NULL;
|
src->url = NULL;
|
||||||
}
|
}
|
||||||
|
@ -261,6 +278,7 @@ gst_rtspsrc_finalize (GObject * object)
|
||||||
|
|
||||||
g_static_rec_mutex_free (rtspsrc->stream_rec_lock);
|
g_static_rec_mutex_free (rtspsrc->stream_rec_lock);
|
||||||
g_free (rtspsrc->stream_rec_lock);
|
g_free (rtspsrc->stream_rec_lock);
|
||||||
|
g_cond_free (rtspsrc->loop_cond);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -287,6 +305,9 @@ gst_rtspsrc_set_property (GObject * object, guint prop_id, const GValue * value,
|
||||||
case PROP_RETRY:
|
case PROP_RETRY:
|
||||||
rtspsrc->retry = g_value_get_uint (value);
|
rtspsrc->retry = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TIMEOUT:
|
||||||
|
rtspsrc->timeout = g_value_get_uint64 (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -314,6 +335,9 @@ gst_rtspsrc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_RETRY:
|
case PROP_RETRY:
|
||||||
g_value_set_uint (value, rtspsrc->retry);
|
g_value_set_uint (value, rtspsrc->retry);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TIMEOUT:
|
||||||
|
g_value_set_uint64 (value, rtspsrc->timeout);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -666,6 +690,9 @@ again:
|
||||||
if (*rtpport != tmp_rtp || *rtcpport != tmp_rtcp)
|
if (*rtpport != tmp_rtp || *rtcpport != tmp_rtcp)
|
||||||
goto port_error;
|
goto port_error;
|
||||||
|
|
||||||
|
/* configure a timeout */
|
||||||
|
g_object_set (G_OBJECT (rtpsrc), "timeout", src->timeout, NULL);
|
||||||
|
|
||||||
/* we manage these elements, we set the caps in configure_transport */
|
/* we manage these elements, we set the caps in configure_transport */
|
||||||
stream->rtpsrc = rtpsrc;
|
stream->rtpsrc = rtpsrc;
|
||||||
stream->rtcpsrc = rtcpsrc;
|
stream->rtcpsrc = rtcpsrc;
|
||||||
|
@ -910,7 +937,7 @@ gst_rtspsrc_push_event (GstRTSPSrc * src, GstEvent * event)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtspsrc_loop (GstRTSPSrc * src)
|
gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
RTSPMessage response = { 0 };
|
RTSPMessage response = { 0 };
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
@ -928,6 +955,7 @@ gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
GST_DEBUG_OBJECT (src, "doing receive");
|
GST_DEBUG_OBJECT (src, "doing receive");
|
||||||
if ((res = rtsp_connection_receive (src->connection, &response)) < 0)
|
if ((res = rtsp_connection_receive (src->connection, &response)) < 0)
|
||||||
goto receive_error;
|
goto receive_error;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "got packet type %d", response.type);
|
GST_DEBUG_OBJECT (src, "got packet type %d", response.type);
|
||||||
}
|
}
|
||||||
while (response.type != RTSP_MESSAGE_DATA);
|
while (response.type != RTSP_MESSAGE_DATA);
|
||||||
|
@ -1003,8 +1031,8 @@ receive_error:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, READ,
|
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||||
("Could not receive message. (%s)", str), (NULL));
|
("Could not receive message. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
if (src->debug)
|
if (src->debug)
|
||||||
rtsp_message_dump (&response);
|
rtsp_message_dump (&response);
|
||||||
|
@ -1014,8 +1042,8 @@ receive_error:
|
||||||
}
|
}
|
||||||
invalid_length:
|
invalid_length:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_WARNING (src, RESOURCE, READ,
|
GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
|
||||||
("Short message received."), (NULL));
|
("Short message received."));
|
||||||
rtsp_message_unset (&response);
|
rtsp_message_unset (&response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1049,6 +1077,55 @@ need_pause:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_loop_udp (GstRTSPSrc * src)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
GST_DEBUG_OBJECT (src, "waiting done");
|
||||||
|
if (src->loop_cmd == CMD_STOP)
|
||||||
|
goto stopping;
|
||||||
|
}
|
||||||
|
if (src->loop_cmd == CMD_RECONNECT) {
|
||||||
|
/* FIXME, when we get here we have to reconnect using tcp */
|
||||||
|
src->loop_cmd = CMD_WAIT;
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
stopping:
|
||||||
|
{
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
src->running = FALSE;
|
||||||
|
gst_task_pause (src->task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd)
|
||||||
|
{
|
||||||
|
GST_OBJECT_LOCK (src);
|
||||||
|
src->loop_cmd = cmd;
|
||||||
|
GST_RTSP_LOOP_SIGNAL (src);
|
||||||
|
GST_OBJECT_UNLOCK (src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
|
{
|
||||||
|
if (src->interleaved)
|
||||||
|
gst_rtspsrc_loop_interleaved (src);
|
||||||
|
else
|
||||||
|
gst_rtspsrc_loop_udp (src);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_rtspsrc_send:
|
* gst_rtspsrc_send:
|
||||||
* @src: the rtsp source
|
* @src: the rtsp source
|
||||||
|
@ -1100,8 +1177,8 @@ send_error:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
|
||||||
("Could not send message. (%s)", res), (NULL));
|
("Could not send message. (%s)", res));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1109,8 +1186,8 @@ receive_error:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, READ,
|
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||||
("Could not receive message. (%s)", str), (NULL));
|
("Could not receive message. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1118,13 +1195,13 @@ error_response:
|
||||||
{
|
{
|
||||||
switch (response->type_data.response.code) {
|
switch (response->type_data.response.code) {
|
||||||
case RTSP_STS_NOT_FOUND:
|
case RTSP_STS_NOT_FOUND:
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s",
|
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), ("%s",
|
||||||
response->type_data.response.reason), (NULL));
|
response->type_data.response.reason));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, READ, ("Got error response: %d (%s).",
|
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
|
||||||
response->type_data.response.code,
|
("Got error response: %d (%s).", response->type_data.response.code,
|
||||||
response->type_data.response.reason), (NULL));
|
response->type_data.response.reason));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* we return FALSE so we should unset the response ourselves */
|
/* we return FALSE so we should unset the response ourselves */
|
||||||
|
@ -1192,14 +1269,14 @@ done:
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_describe:
|
no_describe:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||||
("Server does not support DESCRIBE."), (NULL));
|
("Server does not support DESCRIBE."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
no_setup:
|
no_setup:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
|
||||||
("Server does not support SETUP."), (NULL));
|
("Server does not support SETUP."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1293,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
SDPMessage sdp = { 0 };
|
SDPMessage sdp = { 0 };
|
||||||
GstRTSPProto protocols;
|
GstRTSPProto protocols;
|
||||||
GstRTSPStream *stream = NULL;
|
GstRTSPStream *stream = NULL;
|
||||||
|
gchar *respcont = NULL;
|
||||||
|
|
||||||
/* can't continue without a valid url */
|
/* can't continue without a valid url */
|
||||||
if (G_UNLIKELY (src->url == NULL))
|
if (G_UNLIKELY (src->url == NULL))
|
||||||
|
@ -1261,22 +1339,18 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
/* check if reply is SDP */
|
/* check if reply is SDP */
|
||||||
{
|
rtsp_message_get_header (&response, RTSP_HDR_CONTENT_TYPE, &respcont);
|
||||||
gchar *respcont = NULL;
|
/* could not be set but since the request returned OK, we assume it
|
||||||
|
* was SDP, else check it. */
|
||||||
rtsp_message_get_header (&response, RTSP_HDR_CONTENT_TYPE, &respcont);
|
if (respcont) {
|
||||||
/* could not be set but since the request returned OK, we assume it
|
if (!g_ascii_strcasecmp (respcont, "application/sdp") == 0)
|
||||||
* was SDP, else check it. */
|
goto wrong_content_type;
|
||||||
if (respcont) {
|
|
||||||
if (!g_ascii_strcasecmp (respcont, "application/sdp") == 0)
|
|
||||||
goto wrong_content_type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get message body and parse as SDP */
|
/* get message body and parse as SDP */
|
||||||
rtsp_message_get_body (&response, &data, &size);
|
rtsp_message_get_body (&response, &data, &size);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "parse sdp...");
|
GST_DEBUG_OBJECT (src, "parse SDP...");
|
||||||
sdp_message_init (&sdp);
|
sdp_message_init (&sdp);
|
||||||
sdp_message_parse_buffer (data, size, &sdp);
|
sdp_message_parse_buffer (data, size, &sdp);
|
||||||
|
|
||||||
|
@ -1462,16 +1536,16 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_url:
|
no_url:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
|
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
|
||||||
("No valid RTSP url was provided"), (NULL));
|
("No valid RTSP URL was provided"));
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
could_not_create:
|
could_not_create:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
|
||||||
("Could not create connection. (%s)", str), (NULL));
|
("Could not create connection. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
|
@ -1479,8 +1553,8 @@ could_not_connect:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
|
||||||
("Could not connect to server. (%s)", str), (NULL));
|
("Could not connect to server. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
|
@ -1488,8 +1562,8 @@ create_request_failed:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
|
||||||
("Could not create request. (%s)", str), (NULL));
|
("Could not create request. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
|
@ -1497,8 +1571,8 @@ send_error:
|
||||||
{
|
{
|
||||||
gchar *str = rtsp_strresult (res);
|
gchar *str = rtsp_strresult (res);
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
|
||||||
("Could not send message. (%s)", str), (NULL));
|
("Could not send message. (%s)", str));
|
||||||
g_free (str);
|
g_free (str);
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
|
@ -1509,20 +1583,20 @@ methods_error:
|
||||||
}
|
}
|
||||||
wrong_content_type:
|
wrong_content_type:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
|
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
|
||||||
("Server does not support SDP."), (NULL));
|
("Server does not support SDP, got %s.", respcont));
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
setup_rtp_failed:
|
setup_rtp_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Could not setup rtp."),
|
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
|
||||||
(NULL));
|
("Could not setup rtp."));
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
no_transport:
|
no_transport:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
|
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
|
||||||
("Server did not select transport."), (NULL));
|
("Server did not select transport."));
|
||||||
goto cleanup_error;
|
goto cleanup_error;
|
||||||
}
|
}
|
||||||
cleanup_error:
|
cleanup_error:
|
||||||
|
@ -1542,6 +1616,8 @@ gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "TEARDOWN...");
|
GST_DEBUG_OBJECT (src, "TEARDOWN...");
|
||||||
|
|
||||||
|
gst_rtspsrc_loop_send_cmd (src, CMD_STOP);
|
||||||
|
|
||||||
/* stop task if any */
|
/* stop task if any */
|
||||||
if (src->task) {
|
if (src->task) {
|
||||||
gst_task_stop (src->task);
|
gst_task_stop (src->task);
|
||||||
|
@ -1582,20 +1658,20 @@ gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
create_request_failed:
|
create_request_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
|
||||||
("Could not create request."), (NULL));
|
("Could not create request."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
send_error:
|
send_error:
|
||||||
{
|
{
|
||||||
rtsp_message_unset (&request);
|
rtsp_message_unset (&request);
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
|
||||||
("Could not send message."), (NULL));
|
("Could not send message."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
close_failed:
|
close_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, ("Close failed."), (NULL));
|
GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL), ("Close failed."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1660,29 +1736,28 @@ gst_rtspsrc_play (GstRTSPSrc * src)
|
||||||
|
|
||||||
/* for interleaved transport, we receive the data on the RTSP connection
|
/* for interleaved transport, we receive the data on the RTSP connection
|
||||||
* instead of UDP. We start a task to select and read from that connection. */
|
* instead of UDP. We start a task to select and read from that connection. */
|
||||||
if (src->interleaved) {
|
if (src->task == NULL) {
|
||||||
if (src->task == NULL) {
|
src->task = gst_task_create ((GstTaskFunction) gst_rtspsrc_loop, src);
|
||||||
src->task = gst_task_create ((GstTaskFunction) gst_rtspsrc_loop, src);
|
gst_task_set_lock (src->task, src->stream_rec_lock);
|
||||||
gst_task_set_lock (src->task, src->stream_rec_lock);
|
|
||||||
}
|
|
||||||
src->running = TRUE;
|
|
||||||
gst_task_start (src->task);
|
|
||||||
}
|
}
|
||||||
|
src->running = TRUE;
|
||||||
|
gst_rtspsrc_loop_send_cmd (src, CMD_WAIT);
|
||||||
|
gst_task_start (src->task);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
create_request_failed:
|
create_request_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
|
||||||
("Could not create request."), (NULL));
|
("Could not create request."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
send_error:
|
send_error:
|
||||||
{
|
{
|
||||||
rtsp_message_unset (&request);
|
rtsp_message_unset (&request);
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
|
||||||
("Could not send message."), (NULL));
|
("Could not send message."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1714,19 +1789,49 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
create_request_failed:
|
create_request_failed:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
|
||||||
("Could not create request."), (NULL));
|
("Could not create request."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
send_error:
|
send_error:
|
||||||
{
|
{
|
||||||
rtsp_message_unset (&request);
|
rtsp_message_unset (&request);
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE, (NULL),
|
||||||
("Could not send message."), (NULL));
|
("Could not send message."));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message)
|
||||||
|
{
|
||||||
|
switch (GST_MESSAGE_TYPE (message)) {
|
||||||
|
case GST_MESSAGE_ELEMENT:
|
||||||
|
{
|
||||||
|
GstRTSPSrc *rtspsrc;
|
||||||
|
const GstStructure *s = gst_message_get_structure (message);
|
||||||
|
|
||||||
|
rtspsrc = GST_RTSPSRC (bin);
|
||||||
|
|
||||||
|
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. */
|
||||||
|
GST_ELEMENT_ERROR (rtspsrc, RESOURCE, READ, (NULL),
|
||||||
|
("Could not receive any UDP packets for %" G_GUINT64_FORMAT
|
||||||
|
".%d seconds, maybe your firewall is blocking it.",
|
||||||
|
rtspsrc->timeout / 1000000, rtspsrc->timeout % 1000000));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Fallthrough */
|
||||||
|
default:
|
||||||
|
GST_BIN_CLASS (parent_class)->handle_message (bin, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
|
gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -1735,7 +1840,6 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
rtspsrc = GST_RTSPSRC (element);
|
rtspsrc = GST_RTSPSRC (element);
|
||||||
|
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -61,10 +61,16 @@ G_BEGIN_DECLS
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTSPSRC))
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTSPSRC))
|
||||||
#define GST_IS_RTSPSRC_CLASS(klass) \
|
#define GST_IS_RTSPSRC_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTSPSRC))
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTSPSRC))
|
||||||
|
#define GST_RTSPSRC_CAST(obj) \
|
||||||
|
((GstRTSPSrc *)(obj))
|
||||||
|
|
||||||
typedef struct _GstRTSPSrc GstRTSPSrc;
|
typedef struct _GstRTSPSrc GstRTSPSrc;
|
||||||
typedef struct _GstRTSPSrcClass GstRTSPSrcClass;
|
typedef struct _GstRTSPSrcClass GstRTSPSrcClass;
|
||||||
|
|
||||||
|
#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)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstRTSPProto:
|
* GstRTSPProto:
|
||||||
* @GST_RTSP_PROTO_UDP_UNICAST: Use unicast UDP transfer.
|
* @GST_RTSP_PROTO_UDP_UNICAST: Use unicast UDP transfer.
|
||||||
|
@ -126,16 +132,21 @@ struct _GstRTSPSrc {
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
||||||
|
/* cond to signal loop */
|
||||||
|
GCond *loop_cond;
|
||||||
|
gint loop_cmd;
|
||||||
|
|
||||||
gint numstreams;
|
gint numstreams;
|
||||||
GList *streams;
|
GList *streams;
|
||||||
GstStructure *props;
|
GstStructure *props;
|
||||||
|
|
||||||
gchar *location;
|
gchar *location;
|
||||||
RTSPUrl *url;
|
RTSPUrl *url;
|
||||||
|
GstRTSPProto protocols;
|
||||||
gboolean debug;
|
gboolean debug;
|
||||||
guint retry;
|
guint retry;
|
||||||
|
guint64 timeout;
|
||||||
|
|
||||||
GstRTSPProto protocols;
|
|
||||||
/* supported methods */
|
/* supported methods */
|
||||||
gint methods;
|
gint methods;
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,8 @@
|
||||||
* <listitem>
|
* <listitem>
|
||||||
* <para>
|
* <para>
|
||||||
* #guint64
|
* #guint64
|
||||||
* <classname>"timeout"</classname>: the timeout that expired when
|
* <classname>"timeout"</classname>: the timeout in microseconds that
|
||||||
* waiting for data.
|
* expired when waiting for data.
|
||||||
* </para>
|
* </para>
|
||||||
* </listitem>
|
* </listitem>
|
||||||
* </itemizedlist>
|
* </itemizedlist>
|
||||||
|
@ -250,8 +250,8 @@ gst_udpsrc_class_init (GstUDPSrcClass * klass)
|
||||||
UDP_DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE));
|
UDP_DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE));
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMEOUT,
|
||||||
g_param_spec_uint64 ("timeout", "Timeout",
|
g_param_spec_uint64 ("timeout", "Timeout",
|
||||||
"Post a message after this timeout (in microseconds) (0 = disabled)",
|
"Post a message after timeout microseconds (0 = disabled)", 0,
|
||||||
0, G_MAXUINT64, UDP_DEFAULT_TIMEOUT, G_PARAM_READWRITE));
|
G_MAXUINT64, UDP_DEFAULT_TIMEOUT, G_PARAM_READWRITE));
|
||||||
|
|
||||||
gstbasesrc_class->start = gst_udpsrc_start;
|
gstbasesrc_class->start = gst_udpsrc_start;
|
||||||
gstbasesrc_class->stop = gst_udpsrc_stop;
|
gstbasesrc_class->stop = gst_udpsrc_stop;
|
||||||
|
@ -331,8 +331,8 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
|
||||||
udpsrc->timeout);
|
udpsrc->timeout);
|
||||||
|
|
||||||
if (udpsrc->timeout > 0) {
|
if (udpsrc->timeout > 0) {
|
||||||
timeval.tv_sec = udpsrc->timeout / 1000;
|
timeval.tv_sec = udpsrc->timeout / 1000000;
|
||||||
timeval.tv_usec = (udpsrc->timeout % 1000) * 1000;
|
timeval.tv_usec = udpsrc->timeout % 1000000;
|
||||||
timeout = &timeval;
|
timeout = &timeval;
|
||||||
} else {
|
} else {
|
||||||
timeout = NULL;
|
timeout = NULL;
|
||||||
|
|
Loading…
Reference in a new issue