gst/rtsp/gstrtspsrc.*: Setup UDP sources correctly, receives raw data from RTSP compliant servers now.

Original commit message from CVS:
* gst/rtsp/gstrtspsrc.c: (gst_rtsp_proto_get_type),
(gst_rtspsrc_class_init), (gst_rtspsrc_init),
(gst_rtspsrc_create_stream), (gst_rtspsrc_add_element),
(gst_rtspsrc_set_state), (gst_rtspsrc_stream_setup_rtp),
(gst_rtspsrc_stream_configure_transport), (find_stream),
(gst_rtspsrc_loop), (gst_rtspsrc_open), (gst_rtspsrc_close),
(gst_rtspsrc_play), (gst_rtspsrc_change_state):
* gst/rtsp/gstrtspsrc.h:
Setup UDP sources correctly, receives raw data from RTSP
compliant servers now.
This commit is contained in:
Wim Taymans 2005-05-11 09:18:25 +00:00
parent 6f0ea35883
commit 91ce2b294e
3 changed files with 120 additions and 80 deletions

View file

@ -1,3 +1,16 @@
2005-05-11 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtsp_proto_get_type),
(gst_rtspsrc_class_init), (gst_rtspsrc_init),
(gst_rtspsrc_create_stream), (gst_rtspsrc_add_element),
(gst_rtspsrc_set_state), (gst_rtspsrc_stream_setup_rtp),
(gst_rtspsrc_stream_configure_transport), (find_stream),
(gst_rtspsrc_loop), (gst_rtspsrc_open), (gst_rtspsrc_close),
(gst_rtspsrc_play), (gst_rtspsrc_change_state):
* gst/rtsp/gstrtspsrc.h:
Setup UDP sources correctly, receives raw data from RTSP
compliant servers now.
2005-05-11 Wim Taymans <wim@fluendo.com> 2005-05-11 Wim Taymans <wim@fluendo.com>
* gst/rtsp/.cvsignore: * gst/rtsp/.cvsignore:

View file

@ -89,7 +89,6 @@ static void gst_rtspsrc_class_init (GstRTSPSrc * klass);
static void gst_rtspsrc_init (GstRTSPSrc * rtspsrc); static void gst_rtspsrc_init (GstRTSPSrc * rtspsrc);
static GstElementStateReturn gst_rtspsrc_change_state (GstElement * element); static GstElementStateReturn gst_rtspsrc_change_state (GstElement * element);
static gboolean gst_rtspsrc_activate (GstPad * pad, GstActivateMode mode);
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);
@ -167,7 +166,7 @@ gst_rtspsrc_class_init (GstRTSPSrc * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEBUG, g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEBUG,
g_param_spec_boolean ("debug", "Debug", g_param_spec_boolean ("debug", "Debug",
"Dump request qnd response messages to stdout", "Dump request and response messages to stdout",
DEFAULT_DEBUG, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); DEFAULT_DEBUG, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
gstelement_class->change_state = gst_rtspsrc_change_state; gstelement_class->change_state = gst_rtspsrc_change_state;
@ -176,14 +175,6 @@ gst_rtspsrc_class_init (GstRTSPSrc * klass)
static void static void
gst_rtspsrc_init (GstRTSPSrc * src) gst_rtspsrc_init (GstRTSPSrc * src)
{ {
/*
src->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
"src");
gst_pad_set_loop_function (src->srcpad, gst_rtspsrc_loop);
gst_pad_set_activate_function (src->srcpad, gst_rtspsrc_activate);
gst_element_add_pad (GST_ELEMENT (src), src->srcpad);
*/
} }
static void static void
@ -242,6 +233,7 @@ gst_rtspsrc_create_stream (GstRTSPSrc * src)
s = g_new0 (GstRTSPStream, 1); s = g_new0 (GstRTSPStream, 1);
s->parent = src; s->parent = src;
s->id = src->numstreams++;
src->streams = g_list_append (src->streams, s); src->streams = g_list_append (src->streams, s);
@ -249,7 +241,7 @@ gst_rtspsrc_create_stream (GstRTSPSrc * src)
} }
static gboolean static gboolean
rtspsrc_add_element (GstRTSPSrc * src, GstElement * element) gst_rtspsrc_add_element (GstRTSPSrc * src, GstElement * element)
{ {
gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (src)); gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (src));
gst_element_set_manager (element, GST_ELEMENT_MANAGER (src)); gst_element_set_manager (element, GST_ELEMENT_MANAGER (src));
@ -258,6 +250,42 @@ rtspsrc_add_element (GstRTSPSrc * src, GstElement * element)
return TRUE; return TRUE;
} }
static GstElementStateReturn
gst_rtspsrc_set_state (GstRTSPSrc * src, GstElementState state)
{
GstElementStateReturn ret;
GList *streams;
/* for all streams */
for (streams = src->streams; streams; streams = g_list_next (streams)) {
GstRTSPStream *stream;
stream = (GstRTSPStream *) streams->data;
/* first our rtp session manager */
if ((ret =
gst_element_set_state (stream->rtpdec, state)) != GST_STATE_SUCCESS)
goto done;
/* then our sources */
if (stream->rtpsrc) {
if ((ret =
gst_element_set_state (stream->rtpsrc,
state)) != GST_STATE_SUCCESS)
goto done;
}
if (stream->rtcpsrc) {
if ((ret =
gst_element_set_state (stream->rtcpsrc,
state)) != GST_STATE_SUCCESS)
goto done;
}
}
done:
return ret;
}
static gboolean static gboolean
gst_rtspsrc_stream_setup_rtp (GstRTSPStream * stream, gint * rtpport, gst_rtspsrc_stream_setup_rtp (GstRTSPStream * stream, gint * rtpport,
gint * rtcpport) gint * rtcpport)
@ -273,7 +301,7 @@ gst_rtspsrc_stream_setup_rtp (GstRTSPStream * stream, gint * rtpport,
goto no_udp_rtp_protocol; goto no_udp_rtp_protocol;
/* we manage this element */ /* we manage this element */
rtspsrc_add_element (src, stream->rtpsrc); gst_rtspsrc_add_element (src, stream->rtpsrc);
if ((ret = if ((ret =
gst_element_set_state (stream->rtpsrc, gst_element_set_state (stream->rtpsrc,
@ -285,7 +313,7 @@ gst_rtspsrc_stream_setup_rtp (GstRTSPStream * stream, gint * rtpport,
goto no_udp_rtcp_protocol; goto no_udp_rtcp_protocol;
/* we manage this element */ /* we manage this element */
rtspsrc_add_element (src, stream->rtcpsrc); gst_rtspsrc_add_element (src, stream->rtcpsrc);
if ((ret = if ((ret =
gst_element_set_state (stream->rtcpsrc, gst_element_set_state (stream->rtcpsrc,
@ -325,27 +353,47 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
RTSPTransport * transport) RTSPTransport * transport)
{ {
GstRTSPSrc *src; GstRTSPSrc *src;
GstPad *pad;
GstElementStateReturn ret;
gchar *name;
src = stream->parent; src = stream->parent;
if (transport->lower_transport == RTSP_LOWER_TRANS_TCP) {
GstPad *pad;
/* configure for interleaved delivery */
if (!(stream->rtpdec = gst_element_factory_make ("rtpdec", NULL))) if (!(stream->rtpdec = gst_element_factory_make ("rtpdec", NULL)))
goto no_element; goto no_element;
/* we manage this element */ /* we manage this element */
rtspsrc_add_element (src, stream->rtpdec); gst_rtspsrc_add_element (src, stream->rtpdec);
if ((ret =
gst_element_set_state (stream->rtpdec,
GST_STATE_PAUSED)) != GST_STATE_SUCCESS)
goto start_rtpdec_failure;
stream->rtpdecrtp = gst_element_get_pad (stream->rtpdec, "sinkrtp"); stream->rtpdecrtp = gst_element_get_pad (stream->rtpdec, "sinkrtp");
stream->rtpdecrtcp = gst_element_get_pad (stream->rtpdec, "sinkrtcp"); stream->rtpdecrtcp = gst_element_get_pad (stream->rtpdec, "sinkrtcp");
/* FIXME, make sure it outputs the caps */ /* FIXME, make sure it outputs the caps */
pad = gst_element_get_pad (stream->rtpdec, "srcrtp"); pad = gst_element_get_pad (stream->rtpdec, "srcrtp");
gst_element_add_ghost_pad (GST_ELEMENT (src), pad, "srcrtp"); name = g_strdup_printf ("rtp_stream%d", stream->id);
gst_element_add_ghost_pad (GST_ELEMENT (src), pad, name);
g_free (name);
gst_object_unref (GST_OBJECT (pad)); gst_object_unref (GST_OBJECT (pad));
if (transport->lower_transport == RTSP_LOWER_TRANS_TCP) {
/* configure for interleaved delivery, nothing needs to be done
* here, the loop function will call the chain functions of the
* rtp session manager. */
} else { } else {
/* configure for UDP delivery, FIXME */ /* configure for UDP delivery, we need to connect the udp pads to
* the rtp session plugin. */
pad = gst_element_get_pad (stream->rtpsrc, "src");
gst_pad_link (pad, stream->rtpdecrtp);
gst_object_unref (GST_OBJECT (pad));
pad = gst_element_get_pad (stream->rtcpsrc, "src");
gst_pad_link (pad, stream->rtpdecrtcp);
gst_object_unref (GST_OBJECT (pad));
} }
return TRUE; return TRUE;
@ -354,6 +402,11 @@ no_element:
GST_DEBUG ("no rtpdec element found"); GST_DEBUG ("no rtpdec element found");
return FALSE; return FALSE;
} }
start_rtpdec_failure:
{
GST_DEBUG ("could not start RTP session");
return FALSE;
}
} }
static gint static gint
@ -602,8 +655,6 @@ gst_rtspsrc_open (GstRTSPSrc * src)
rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports); rtsp_message_add_header (&request, RTSP_HDR_TRANSPORT, transports);
g_free (transports); g_free (transports);
rtsp_message_dump (&request);
if (!gst_rtspsrc_send (src, &request, &response)) if (!gst_rtspsrc_send (src, &request, &response))
goto send_error; goto send_error;
@ -614,8 +665,9 @@ gst_rtspsrc_open (GstRTSPSrc * src)
rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans); rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans);
/* update allowed transports for other streams */ /* parse transport */
rtsp_transport_parse (resptrans, &transport); rtsp_transport_parse (resptrans, &transport);
/* update allowed transports for other streams */
if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) { if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) {
protocols = GST_RTSP_PROTO_TCP; protocols = GST_RTSP_PROTO_TCP;
src->interleaved = TRUE; src->interleaved = TRUE;
@ -628,7 +680,11 @@ gst_rtspsrc_open (GstRTSPSrc * src)
protocols = GST_RTSP_PROTO_UDP_UNICAST; protocols = GST_RTSP_PROTO_UDP_UNICAST;
} }
} }
gst_rtspsrc_stream_configure_transport (stream, &transport); /* now configure the stream with the transport */
if (!gst_rtspsrc_stream_configure_transport (stream, &transport)) {
GST_DEBUG ("could not configure stream transport, skipping stream");
}
/* clean up our transport struct */
rtsp_transport_init (&transport); rtsp_transport_init (&transport);
} }
} }
@ -670,6 +726,14 @@ gst_rtspsrc_close (GstRTSPSrc * src)
RTSPResult res; RTSPResult res;
GST_DEBUG ("TEARDOWN..."); GST_DEBUG ("TEARDOWN...");
/* stop task if any */
if (src->task) {
gst_task_stop (src->task);
gst_object_unref (GST_OBJECT (src->task));
src->task = NULL;
}
/* do TEARDOWN */ /* do TEARDOWN */
if ((res = if ((res =
rtsp_message_init_request (RTSP_TEARDOWN, src->location, rtsp_message_init_request (RTSP_TEARDOWN, src->location,
@ -713,6 +777,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
RTSPResult res; RTSPResult res;
GST_DEBUG ("PLAY..."); GST_DEBUG ("PLAY...");
/* do play */ /* do play */
if ((res = if ((res =
rtsp_message_init_request (RTSP_PLAY, src->location, &request)) < 0) rtsp_message_init_request (RTSP_PLAY, src->location, &request)) < 0)
@ -777,52 +842,6 @@ send_error:
} }
} }
static gboolean
gst_rtspsrc_activate (GstPad * pad, GstActivateMode mode)
{
gboolean result;
GstRTSPSrc *rtspsrc;
rtspsrc = GST_RTSPSRC (GST_OBJECT_PARENT (pad));
switch (mode) {
case GST_ACTIVATE_PUSH:
/* if we have a scheduler we can start the task */
if (GST_ELEMENT_SCHEDULER (rtspsrc) && rtspsrc->interleaved) {
GST_STREAM_LOCK (pad);
GST_RPAD_TASK (pad) =
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (rtspsrc),
(GstTaskFunction) gst_rtspsrc_loop, pad);
gst_task_start (GST_RPAD_TASK (pad));
GST_STREAM_UNLOCK (pad);
result = TRUE;
}
break;
case GST_ACTIVATE_PULL:
result = FALSE;
break;
case GST_ACTIVATE_NONE:
/* step 1, unblock clock sync (if any) */
/* step 2, make sure streaming finishes */
GST_STREAM_LOCK (pad);
gst_rtspsrc_close (rtspsrc);
/* step 3, stop the task */
if (GST_RPAD_TASK (pad)) {
gst_task_stop (GST_RPAD_TASK (pad));
gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad)));
GST_RPAD_TASK (pad) = NULL;
}
GST_STREAM_UNLOCK (pad);
result = TRUE;
break;
}
return result;
}
static GstElementStateReturn static GstElementStateReturn
gst_rtspsrc_change_state (GstElement * element) gst_rtspsrc_change_state (GstElement * element)
{ {
@ -845,18 +864,22 @@ gst_rtspsrc_change_state (GstElement * element)
gst_rtspsrc_play (rtspsrc); gst_rtspsrc_play (rtspsrc);
break; break;
case GST_STATE_PAUSED_TO_PLAYING: case GST_STATE_PAUSED_TO_PLAYING:
gst_rtspsrc_play (rtspsrc);
break; break;
default: default:
break; break;
} }
ret = gst_rtspsrc_set_state (rtspsrc, GST_STATE_PENDING (rtspsrc));
if (ret != GST_STATE_SUCCESS)
goto error;
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
switch (transition) { switch (transition) {
case GST_STATE_PLAYING_TO_PAUSED: case GST_STATE_PLAYING_TO_PAUSED:
gst_rtspsrc_pause (rtspsrc);
break; break;
case GST_STATE_PAUSED_TO_READY: case GST_STATE_PAUSED_TO_READY:
gst_rtspsrc_pause (rtspsrc);
break; break;
case GST_STATE_READY_TO_NULL: case GST_STATE_READY_TO_NULL:
break; break;
@ -864,5 +887,6 @@ gst_rtspsrc_change_state (GstElement * element)
break; break;
} }
error:
return ret; return ret;
} }

View file

@ -55,6 +55,8 @@ typedef enum
typedef struct _GstRTSPStream GstRTSPStream; typedef struct _GstRTSPStream GstRTSPStream;
struct _GstRTSPStream { struct _GstRTSPStream {
gint id;
gint rtpchannel; gint rtpchannel;
gint rtcpchannel; gint rtcpchannel;
@ -79,6 +81,7 @@ struct _GstRTSPSrc {
gboolean interleaved; gboolean interleaved;
GstTask *task; GstTask *task;
gint numstreams;
GList *streams; GList *streams;
gchar *location; gchar *location;