mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
gst/rtsp/gstrtpdec.c: Add pads after setting them up.
Original commit message from CVS: * gst/rtsp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps): Add pads after setting them up. * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_class_init), (gst_rtspsrc_init), (gst_rtspsrc_finalize), (gst_rtspsrc_free_stream), (gst_rtspsrc_media_to_caps), (gst_rtspsrc_stream_setup_rtp), (gst_rtspsrc_stream_configure_transport), (gst_rtspsrc_combine_flows), (gst_rtspsrc_loop), (gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play), (gst_rtspsrc_pause): * gst/rtsp/gstrtspsrc.h: Fix interleaved mode. - Protect streaming with lock. - Combine flows - set caps on outgoing buffers. - strip trailing \0 from data packets. - Configure RTP/RTCP in stream. Use DEBUG_OBJECT more.
This commit is contained in:
parent
64faced49c
commit
6eedcfbc8c
4 changed files with 227 additions and 69 deletions
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
||||||
|
2006-08-16 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* gst/rtsp/gstrtpdec.c: (gst_rtpdec_init), (gst_rtpdec_getcaps):
|
||||||
|
Add pads after setting them up.
|
||||||
|
|
||||||
|
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_class_init),
|
||||||
|
(gst_rtspsrc_init), (gst_rtspsrc_finalize),
|
||||||
|
(gst_rtspsrc_free_stream), (gst_rtspsrc_media_to_caps),
|
||||||
|
(gst_rtspsrc_stream_setup_rtp),
|
||||||
|
(gst_rtspsrc_stream_configure_transport),
|
||||||
|
(gst_rtspsrc_combine_flows), (gst_rtspsrc_loop),
|
||||||
|
(gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play),
|
||||||
|
(gst_rtspsrc_pause):
|
||||||
|
* gst/rtsp/gstrtspsrc.h:
|
||||||
|
Fix interleaved mode.
|
||||||
|
- Protect streaming with lock.
|
||||||
|
- Combine flows
|
||||||
|
- set caps on outgoing buffers.
|
||||||
|
- strip trailing \0 from data packets.
|
||||||
|
- Configure RTP/RTCP in stream.
|
||||||
|
Use DEBUG_OBJECT more.
|
||||||
|
|
||||||
2006-08-16 Wim Taymans <wim@fluendo.com>
|
2006-08-16 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_add):
|
* gst/udp/gstmultiudpsink.c: (gst_multiudpsink_add):
|
||||||
|
|
|
@ -170,16 +170,16 @@ gst_rtpdec_init (GstRTPDec * rtpdec)
|
||||||
rtpdec->sink_rtp =
|
rtpdec->sink_rtp =
|
||||||
gst_pad_new_from_static_template (&gst_rtpdec_sink_rtp_template,
|
gst_pad_new_from_static_template (&gst_rtpdec_sink_rtp_template,
|
||||||
"sinkrtp");
|
"sinkrtp");
|
||||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
|
|
||||||
gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
|
gst_pad_set_getcaps_function (rtpdec->sink_rtp, gst_rtpdec_getcaps);
|
||||||
gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
|
gst_pad_set_chain_function (rtpdec->sink_rtp, gst_rtpdec_chain_rtp);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtp);
|
||||||
|
|
||||||
/* the input rtcp pad */
|
/* the input rtcp pad */
|
||||||
rtpdec->sink_rtcp =
|
rtpdec->sink_rtcp =
|
||||||
gst_pad_new_from_static_template (&gst_rtpdec_sink_rtcp_template,
|
gst_pad_new_from_static_template (&gst_rtpdec_sink_rtcp_template,
|
||||||
"sinkrtcp");
|
"sinkrtcp");
|
||||||
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtcp);
|
|
||||||
gst_pad_set_chain_function (rtpdec->sink_rtcp, gst_rtpdec_chain_rtcp);
|
gst_pad_set_chain_function (rtpdec->sink_rtcp, gst_rtpdec_chain_rtcp);
|
||||||
|
gst_element_add_pad (GST_ELEMENT (rtpdec), rtpdec->sink_rtcp);
|
||||||
|
|
||||||
/* the output rtp pad */
|
/* the output rtp pad */
|
||||||
rtpdec->src_rtp =
|
rtpdec->src_rtp =
|
||||||
|
@ -203,7 +203,7 @@ gst_rtpdec_getcaps (GstPad * pad)
|
||||||
|
|
||||||
src = GST_RTPDEC (GST_PAD_PARENT (pad));
|
src = GST_RTPDEC (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
other = pad == src->src_rtp ? src->sink_rtp : src->src_rtp;
|
other = (pad == src->src_rtp ? src->sink_rtp : src->src_rtp);
|
||||||
|
|
||||||
caps = gst_pad_peer_get_caps (other);
|
caps = gst_pad_peer_get_caps (other);
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ gst_rtsp_proto_get_type (void)
|
||||||
static void gst_rtspsrc_base_init (gpointer g_class);
|
static void gst_rtspsrc_base_init (gpointer g_class);
|
||||||
static void gst_rtspsrc_class_init (GstRTSPSrc * klass);
|
static void gst_rtspsrc_class_init (GstRTSPSrc * klass);
|
||||||
static void gst_rtspsrc_init (GstRTSPSrc * rtspsrc);
|
static void gst_rtspsrc_init (GstRTSPSrc * rtspsrc);
|
||||||
|
static void gst_rtspsrc_finalize (GObject * object);
|
||||||
|
|
||||||
static void gst_rtspsrc_uri_handler_init (gpointer g_iface,
|
static void gst_rtspsrc_uri_handler_init (gpointer g_iface,
|
||||||
gpointer iface_data);
|
gpointer iface_data);
|
||||||
|
@ -216,6 +217,8 @@ gst_rtspsrc_class_init (GstRTSPSrc * klass)
|
||||||
gobject_class->set_property = gst_rtspsrc_set_property;
|
gobject_class->set_property = gst_rtspsrc_set_property;
|
||||||
gobject_class->get_property = gst_rtspsrc_get_property;
|
gobject_class->get_property = gst_rtspsrc_get_property;
|
||||||
|
|
||||||
|
gobject_class->finalize = gst_rtspsrc_finalize;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LOCATION,
|
g_object_class_install_property (gobject_class, PROP_LOCATION,
|
||||||
g_param_spec_string ("location", "RTSP Location",
|
g_param_spec_string ("location", "RTSP Location",
|
||||||
"Location of the RTSP url to read",
|
"Location of the RTSP url to read",
|
||||||
|
@ -243,6 +246,21 @@ gst_rtspsrc_class_init (GstRTSPSrc * klass)
|
||||||
static void
|
static void
|
||||||
gst_rtspsrc_init (GstRTSPSrc * src)
|
gst_rtspsrc_init (GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
|
src->stream_rec_lock = g_new (GStaticRecMutex, 1);
|
||||||
|
g_static_rec_mutex_init (src->stream_rec_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstRTSPSrc *rtspsrc;
|
||||||
|
|
||||||
|
rtspsrc = GST_RTSPSRC (object);
|
||||||
|
|
||||||
|
g_static_rec_mutex_free (rtspsrc->stream_rec_lock);
|
||||||
|
g_free (rtspsrc->stream_rec_lock);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -314,6 +332,22 @@ gst_rtspsrc_create_stream (GstRTSPSrc * src)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
gst_rtspsrc_free_stream (GstRTSPSrc * src, GstRTSPStream * stream)
|
||||||
|
{
|
||||||
|
if (stream->caps) {
|
||||||
|
gst_caps_unref (stream->caps);
|
||||||
|
stream->caps = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
src->streams = g_list_remove (src->streams, stream);
|
||||||
|
src->numstreams--;
|
||||||
|
|
||||||
|
g_free (stream);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtspsrc_add_element (GstRTSPSrc * src, GstElement * element)
|
gst_rtspsrc_add_element (GstRTSPSrc * src, GstElement * element)
|
||||||
{
|
{
|
||||||
|
@ -437,7 +471,7 @@ gst_rtspsrc_parse_rtpmap (gchar * rtpmap, gint * payload, gchar ** name,
|
||||||
*
|
*
|
||||||
* m=<media> <udp port> RTP/AVP <payload>
|
* m=<media> <udp port> RTP/AVP <payload>
|
||||||
* a=rtpmap:<payload> <encoding_name>/<clock_rate>[/<encoding_params>]
|
* a=rtpmap:<payload> <encoding_name>/<clock_rate>[/<encoding_params>]
|
||||||
* a=fmtp:<payload> <param>=<value>;...
|
* a=fmtp:<payload> <param>[=<value>];...
|
||||||
*/
|
*/
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_rtspsrc_media_to_caps (SDPMedia * media)
|
gst_rtspsrc_media_to_caps (SDPMedia * media)
|
||||||
|
@ -502,34 +536,37 @@ gst_rtspsrc_media_to_caps (SDPMedia * media)
|
||||||
|
|
||||||
p = fmtp;
|
p = fmtp;
|
||||||
|
|
||||||
|
/* p is now of the format <payload> <param>[=<value>];... */
|
||||||
PARSE_INT (p, " ", payload);
|
PARSE_INT (p, " ", payload);
|
||||||
if (payload != -1 && payload == pt) {
|
if (payload != -1 && payload == pt) {
|
||||||
gchar **pairs;
|
gchar **pairs;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
/* <param>[=<value>] are separated with ';' */
|
||||||
pairs = g_strsplit (p, ";", 0);
|
pairs = g_strsplit (p, ";", 0);
|
||||||
for (i = 0; pairs[i]; i++) {
|
for (i = 0; pairs[i]; i++) {
|
||||||
gchar **keyval;
|
gchar *valpos;
|
||||||
|
gchar *val, *key;
|
||||||
|
|
||||||
keyval = g_strsplit (pairs[i], "=", 0);
|
/* the key may not have a '=', the value can have other '='s */
|
||||||
if (keyval[0]) {
|
valpos = strstr (pairs[i], "=");
|
||||||
gchar *val, *key;
|
if (valpos) {
|
||||||
|
/* we have a '=' and thus a value, remove the '=' with \0 */
|
||||||
if (keyval[1])
|
*valpos = '\0';
|
||||||
val = g_strstrip (keyval[1]);
|
/* value is everything between '=' and ';' */
|
||||||
else
|
val = g_strstrip (valpos + 1);
|
||||||
val = "1";
|
} else {
|
||||||
|
/* simple <param>;.. is translated into <param>=1;... */
|
||||||
key = g_strstrip (keyval[0]);
|
val = "1";
|
||||||
|
|
||||||
gst_structure_set (s, key, G_TYPE_STRING, val, NULL);
|
|
||||||
}
|
}
|
||||||
g_strfreev (keyval);
|
/* strip the key of spaces */
|
||||||
|
key = g_strstrip (pairs[i]);
|
||||||
|
|
||||||
|
gst_structure_set (s, key, G_TYPE_STRING, val, NULL);
|
||||||
}
|
}
|
||||||
g_strfreev (pairs);
|
g_strfreev (pairs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,32 +667,33 @@ again:
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_udp_rtp_protocol:
|
no_udp_rtp_protocol:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not get UDP source for RTP");
|
GST_DEBUG_OBJECT (src, "could not get UDP source for RTP");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
start_rtp_failure:
|
start_rtp_failure:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not start UDP source for RTP");
|
GST_DEBUG_OBJECT (src, "could not start UDP source for RTP");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
no_ports:
|
no_ports:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not allocate UDP port pair after %d retries", count);
|
GST_DEBUG_OBJECT (src, "could not allocate UDP port pair after %d retries",
|
||||||
|
count);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
no_udp_rtcp_protocol:
|
no_udp_rtcp_protocol:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not get UDP source for RTCP");
|
GST_DEBUG_OBJECT (src, "could not get UDP source for RTCP");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
start_rtcp_failure:
|
start_rtcp_failure:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not start UDP source for RTCP");
|
GST_DEBUG_OBJECT (src, "could not start UDP source for RTCP");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
port_error:
|
port_error:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("ports don't match rtp: %d<->%d, rtcp: %d<->%d",
|
GST_DEBUG_OBJECT (src, "ports don't match rtp: %d<->%d, rtcp: %d<->%d",
|
||||||
tmp_rtp, *rtpport, tmp_rtcp, *rtcpport);
|
tmp_rtp, *rtpport, tmp_rtcp, *rtcpport);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -679,7 +717,7 @@ cleanup:
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
||||||
RTSPTransport * transport)
|
SDPMedia * media, RTSPTransport * transport)
|
||||||
{
|
{
|
||||||
GstRTSPSrc *src;
|
GstRTSPSrc *src;
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
@ -688,6 +726,8 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
||||||
|
|
||||||
src = stream->parent;
|
src = stream->parent;
|
||||||
|
|
||||||
|
GST_DEBUG ("configuring RTP transport for stream %p", stream);
|
||||||
|
|
||||||
if (!(stream->rtpdec = gst_element_factory_make ("rtpdec", NULL)))
|
if (!(stream->rtpdec = gst_element_factory_make ("rtpdec", NULL)))
|
||||||
goto no_element;
|
goto no_element;
|
||||||
|
|
||||||
|
@ -706,6 +746,13 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
||||||
/* configure for interleaved delivery, nothing needs to be done
|
/* configure for interleaved delivery, nothing needs to be done
|
||||||
* here, the loop function will call the chain functions of the
|
* here, the loop function will call the chain functions of the
|
||||||
* rtp session manager. */
|
* rtp session manager. */
|
||||||
|
stream->rtpchannel = transport->interleaved.min;
|
||||||
|
stream->rtcpchannel = transport->interleaved.max;
|
||||||
|
GST_DEBUG ("stream %p on channels %d-%d", stream,
|
||||||
|
stream->rtpchannel, stream->rtcpchannel);
|
||||||
|
|
||||||
|
/* also store the caps in the stream */
|
||||||
|
stream->caps = gst_rtspsrc_media_to_caps (media);
|
||||||
} else {
|
} else {
|
||||||
/* configure for UDP delivery, we need to connect the udp pads to
|
/* configure for UDP delivery, we need to connect the udp pads to
|
||||||
* the rtp session plugin. */
|
* the rtp session plugin. */
|
||||||
|
@ -719,6 +766,10 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
pad = gst_element_get_pad (stream->rtpdec, "srcrtp");
|
pad = gst_element_get_pad (stream->rtpdec, "srcrtp");
|
||||||
|
if (stream->caps) {
|
||||||
|
gst_pad_use_fixed_caps (pad);
|
||||||
|
gst_pad_set_caps (pad, stream->caps);
|
||||||
|
}
|
||||||
name = g_strdup_printf ("rtp_stream%d", stream->id);
|
name = g_strdup_printf ("rtp_stream%d", stream->id);
|
||||||
gst_element_add_pad (GST_ELEMENT_CAST (src), gst_ghost_pad_new (name, pad));
|
gst_element_add_pad (GST_ELEMENT_CAST (src), gst_ghost_pad_new (name, pad));
|
||||||
g_free (name);
|
g_free (name);
|
||||||
|
@ -726,14 +777,15 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream,
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
no_element:
|
no_element:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("no rtpdec element found");
|
GST_DEBUG_OBJECT (src, "no rtpdec element found");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
start_rtpdec_failure:
|
start_rtpdec_failure:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("could not start RTP session");
|
GST_DEBUG_OBJECT (src, "could not start RTP session");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,6 +801,40 @@ find_stream (GstRTSPStream * stream, gconstpointer a)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_rtspsrc_combine_flows (GstRTSPSrc * src, GstRTSPStream * stream,
|
||||||
|
GstFlowReturn ret)
|
||||||
|
{
|
||||||
|
GList *streams;
|
||||||
|
|
||||||
|
/* store the value */
|
||||||
|
stream->last_ret = ret;
|
||||||
|
|
||||||
|
/* if it's success we can return the value right away */
|
||||||
|
if (GST_FLOW_IS_SUCCESS (ret))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* any other error that is not-linked can be returned right
|
||||||
|
* away */
|
||||||
|
if (ret != GST_FLOW_NOT_LINKED)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* only return NOT_LINKED if all other pads returned NOT_LINKED */
|
||||||
|
for (streams = src->streams; streams; streams = g_list_next (streams)) {
|
||||||
|
GstRTSPStream *ostream = (GstRTSPStream *) streams->data;
|
||||||
|
|
||||||
|
ret = ostream->last_ret;
|
||||||
|
/* some other return value (must be SUCCESS but we can return
|
||||||
|
* other values as well) */
|
||||||
|
if (ret != GST_FLOW_NOT_LINKED)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* if we get here, all other pads were unlinked and we return
|
||||||
|
* NOT_LINKED then */
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_rtspsrc_loop (GstRTSPSrc * src)
|
gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
|
@ -760,12 +846,14 @@ gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
GstPad *outpad = NULL;
|
GstPad *outpad = NULL;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
guint size;
|
guint size;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
GST_DEBUG ("doing reveive");
|
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 ("got packet");
|
GST_DEBUG_OBJECT (src, "got packet type %d", response.type);
|
||||||
}
|
}
|
||||||
while (response.type != RTSP_MESSAGE_DATA);
|
while (response.type != RTSP_MESSAGE_DATA);
|
||||||
|
|
||||||
|
@ -777,10 +865,12 @@ gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
goto unknown_stream;
|
goto unknown_stream;
|
||||||
|
|
||||||
stream = (GstRTSPStream *) lstream->data;
|
stream = (GstRTSPStream *) lstream->data;
|
||||||
if (channel == stream->rtpchannel)
|
if (channel == stream->rtpchannel) {
|
||||||
outpad = stream->rtpdecrtp;
|
outpad = stream->rtpdecrtp;
|
||||||
else if (channel == stream->rtcpchannel)
|
caps = stream->caps;
|
||||||
|
} else if (channel == stream->rtcpchannel) {
|
||||||
outpad = stream->rtpdecrtcp;
|
outpad = stream->rtpdecrtcp;
|
||||||
|
}
|
||||||
|
|
||||||
rtsp_message_get_body (&response, &data, &size);
|
rtsp_message_get_body (&response, &data, &size);
|
||||||
|
|
||||||
|
@ -798,21 +888,39 @@ gst_rtspsrc_loop (GstRTSPSrc * src)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
/* strip the trailing \0 */
|
||||||
|
size -= 1;
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (size);
|
buf = gst_buffer_new_and_alloc (size);
|
||||||
memcpy (GST_BUFFER_DATA (buf), data, size);
|
memcpy (GST_BUFFER_DATA (buf), data, size);
|
||||||
|
|
||||||
if (gst_pad_chain (outpad, buf) != GST_FLOW_OK)
|
if (caps)
|
||||||
|
gst_buffer_set_caps (buf, caps);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "pushing data of size %d on channel %d", size,
|
||||||
|
channel);
|
||||||
|
|
||||||
|
/* chain to the peer pad */
|
||||||
|
ret = gst_pad_chain (outpad, buf);
|
||||||
|
|
||||||
|
/* combine all streams */
|
||||||
|
ret = gst_rtspsrc_combine_flows (src, stream, ret);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
goto need_pause;
|
goto need_pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
unknown_stream:
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
unknown_stream:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (src, "unknown stream on channel %d, ignored", channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
receive_error:
|
receive_error:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (src, RESOURCE, WRITE,
|
||||||
("Could not receive message."), (NULL));
|
("Could not receive message."), (NULL));
|
||||||
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
/*
|
/*
|
||||||
gst_pad_push_event (src->srcpad, gst_event_new (GST_EVENT_EOS));
|
gst_pad_push_event (src->srcpad, gst_event_new (GST_EVENT_EOS));
|
||||||
*/
|
*/
|
||||||
|
@ -820,6 +928,8 @@ receive_error:
|
||||||
}
|
}
|
||||||
need_pause:
|
need_pause:
|
||||||
{
|
{
|
||||||
|
GST_DEBUG_OBJECT (src, "pausing task, reason %d (%s)", ret,
|
||||||
|
gst_flow_get_name (ret));
|
||||||
gst_task_pause (src->task);
|
gst_task_pause (src->task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -886,24 +996,24 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
GstRTSPProto protocols;
|
GstRTSPProto protocols;
|
||||||
|
|
||||||
/* parse url */
|
/* parse url */
|
||||||
GST_DEBUG ("parsing url...");
|
GST_DEBUG_OBJECT (src, "parsing url...");
|
||||||
if ((res = rtsp_url_parse (src->location, &url)) < 0)
|
if ((res = rtsp_url_parse (src->location, &url)) < 0)
|
||||||
goto invalid_url;
|
goto invalid_url;
|
||||||
|
|
||||||
/* open connection */
|
/* open connection */
|
||||||
GST_DEBUG ("opening connection...");
|
GST_DEBUG_OBJECT (src, "opening connection...");
|
||||||
if ((res = rtsp_connection_open (url, &src->connection)) < 0)
|
if ((res = rtsp_connection_open (url, &src->connection)) < 0)
|
||||||
goto could_not_open;
|
goto could_not_open;
|
||||||
|
|
||||||
/* create OPTIONS */
|
/* create OPTIONS */
|
||||||
GST_DEBUG ("create options...");
|
GST_DEBUG_OBJECT (src, "create options...");
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_OPTIONS, src->location,
|
rtsp_message_init_request (RTSP_OPTIONS, src->location,
|
||||||
&request)) < 0)
|
&request)) < 0)
|
||||||
goto create_request_failed;
|
goto create_request_failed;
|
||||||
|
|
||||||
/* send OPTIONS */
|
/* send OPTIONS */
|
||||||
GST_DEBUG ("send options...");
|
GST_DEBUG_OBJECT (src, "send options...");
|
||||||
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
|
@ -955,7 +1065,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create DESCRIBE */
|
/* create DESCRIBE */
|
||||||
GST_DEBUG ("create describe...");
|
GST_DEBUG_OBJECT (src, "create describe...");
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_DESCRIBE, src->location,
|
rtsp_message_init_request (RTSP_DESCRIBE, src->location,
|
||||||
&request)) < 0)
|
&request)) < 0)
|
||||||
|
@ -964,7 +1074,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
rtsp_message_add_header (&request, RTSP_HDR_ACCEPT, "application/sdp");
|
rtsp_message_add_header (&request, RTSP_HDR_ACCEPT, "application/sdp");
|
||||||
|
|
||||||
/* send DESCRIBE */
|
/* send DESCRIBE */
|
||||||
GST_DEBUG ("send describe...");
|
GST_DEBUG_OBJECT (src, "send describe...");
|
||||||
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
if (!gst_rtspsrc_send (src, &request, &response, NULL))
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
|
||||||
|
@ -984,7 +1094,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
/* parse SDP */
|
/* parse SDP */
|
||||||
rtsp_message_get_body (&response, &data, &size);
|
rtsp_message_get_body (&response, &data, &size);
|
||||||
|
|
||||||
GST_DEBUG ("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);
|
||||||
|
|
||||||
|
@ -1008,10 +1118,10 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
|
|
||||||
stream = gst_rtspsrc_create_stream (src);
|
stream = gst_rtspsrc_create_stream (src);
|
||||||
|
|
||||||
GST_DEBUG ("setup media %d", i);
|
GST_DEBUG_OBJECT (src, "setup media %d", i);
|
||||||
control_url = sdp_media_get_attribute_val (media, "control");
|
control_url = sdp_media_get_attribute_val (media, "control");
|
||||||
if (control_url == NULL) {
|
if (control_url == NULL) {
|
||||||
GST_DEBUG ("no control url found, skipping stream");
|
GST_DEBUG_OBJECT (src, "no control url found, skipping stream");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,7 +1133,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
setup_url = g_strdup_printf ("%s/%s", src->location, control_url);
|
setup_url = g_strdup_printf ("%s/%s", src->location, control_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("setup %s", setup_url);
|
GST_DEBUG_OBJECT (src, "setup %s", setup_url);
|
||||||
/* create SETUP request */
|
/* create SETUP request */
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_SETUP, setup_url,
|
rtsp_message_init_request (RTSP_SETUP, setup_url,
|
||||||
|
@ -1043,6 +1153,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
if (!gst_rtspsrc_stream_setup_rtp (stream, media, &rtpport, &rtcpport))
|
if (!gst_rtspsrc_stream_setup_rtp (stream, media, &rtpport, &rtcpport))
|
||||||
goto setup_rtp_failed;
|
goto setup_rtp_failed;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "setting up RTP ports %d-%d", rtpport, rtcpport);
|
||||||
|
|
||||||
trxparams = g_strdup_printf ("client_port=%d-%d", rtpport, rtcpport);
|
trxparams = g_strdup_printf ("client_port=%d-%d", rtpport, rtcpport);
|
||||||
new = g_strconcat (transports, "RTP/AVP/UDP;unicast;", trxparams, NULL);
|
new = g_strconcat (transports, "RTP/AVP/UDP;unicast;", trxparams, NULL);
|
||||||
g_free (trxparams);
|
g_free (trxparams);
|
||||||
|
@ -1052,6 +1164,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
if (protocols & GST_RTSP_PROTO_UDP_MULTICAST) {
|
if (protocols & GST_RTSP_PROTO_UDP_MULTICAST) {
|
||||||
gchar *new;
|
gchar *new;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "setting up MULTICAST");
|
||||||
|
|
||||||
new =
|
new =
|
||||||
g_strconcat (transports, transports[0] ? "," : "",
|
g_strconcat (transports, transports[0] ? "," : "",
|
||||||
"RTP/AVP/UDP;multicast", NULL);
|
"RTP/AVP/UDP;multicast", NULL);
|
||||||
|
@ -1061,6 +1175,8 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
if (protocols & GST_RTSP_PROTO_TCP) {
|
if (protocols & GST_RTSP_PROTO_TCP) {
|
||||||
gchar *new;
|
gchar *new;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "setting up TCP");
|
||||||
|
|
||||||
new =
|
new =
|
||||||
g_strconcat (transports, transports[0] ? "," : "", "RTP/AVP/TCP",
|
g_strconcat (transports, transports[0] ? "," : "", "RTP/AVP/TCP",
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -1088,20 +1204,24 @@ gst_rtspsrc_open (GstRTSPSrc * src)
|
||||||
rtsp_transport_parse (resptrans, &transport);
|
rtsp_transport_parse (resptrans, &transport);
|
||||||
/* update allowed transports for other streams */
|
/* update allowed transports for other streams */
|
||||||
if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) {
|
if (transport.lower_transport == RTSP_LOWER_TRANS_TCP) {
|
||||||
|
GST_DEBUG_OBJECT (src, "stream %d as TCP", i);
|
||||||
protocols = GST_RTSP_PROTO_TCP;
|
protocols = GST_RTSP_PROTO_TCP;
|
||||||
src->interleaved = TRUE;
|
src->interleaved = TRUE;
|
||||||
} else {
|
} else {
|
||||||
if (transport.multicast) {
|
if (transport.multicast) {
|
||||||
/* disable unicast */
|
/* disable unicast */
|
||||||
|
GST_DEBUG_OBJECT (src, "stream %d as MULTICAST", i);
|
||||||
protocols = GST_RTSP_PROTO_UDP_MULTICAST;
|
protocols = GST_RTSP_PROTO_UDP_MULTICAST;
|
||||||
} else {
|
} else {
|
||||||
/* disable multicast */
|
/* disable multicast */
|
||||||
|
GST_DEBUG_OBJECT (src, "stream %d as UNICAST", i);
|
||||||
protocols = GST_RTSP_PROTO_UDP_UNICAST;
|
protocols = GST_RTSP_PROTO_UDP_UNICAST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* now configure the stream with the transport */
|
/* now configure the stream with the transport */
|
||||||
if (!gst_rtspsrc_stream_configure_transport (stream, &transport)) {
|
if (!gst_rtspsrc_stream_configure_transport (stream, media, &transport)) {
|
||||||
GST_DEBUG ("could not configure stream transport, skipping stream");
|
GST_DEBUG_OBJECT (src,
|
||||||
|
"could not configure stream transport, skipping stream");
|
||||||
}
|
}
|
||||||
/* clean up our transport struct */
|
/* clean up our transport struct */
|
||||||
rtsp_transport_init (&transport);
|
rtsp_transport_init (&transport);
|
||||||
|
@ -1173,11 +1293,20 @@ gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
RTSPMessage response = { 0 };
|
RTSPMessage response = { 0 };
|
||||||
RTSPResult res;
|
RTSPResult res;
|
||||||
|
|
||||||
GST_DEBUG ("TEARDOWN...");
|
GST_DEBUG_OBJECT (src, "TEARDOWN...");
|
||||||
|
|
||||||
/* stop task if any */
|
/* stop task if any */
|
||||||
if (src->task) {
|
if (src->task) {
|
||||||
gst_task_stop (src->task);
|
gst_task_stop (src->task);
|
||||||
|
|
||||||
|
/* make sure it is not running */
|
||||||
|
g_static_rec_mutex_lock (src->stream_rec_lock);
|
||||||
|
g_static_rec_mutex_unlock (src->stream_rec_lock);
|
||||||
|
|
||||||
|
/* no wait for the task to finish */
|
||||||
|
gst_task_join (src->task);
|
||||||
|
|
||||||
|
/* and free the task */
|
||||||
gst_object_unref (GST_OBJECT (src->task));
|
gst_object_unref (GST_OBJECT (src->task));
|
||||||
src->task = NULL;
|
src->task = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1194,7 +1323,7 @@ gst_rtspsrc_close (GstRTSPSrc * src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close connection */
|
/* close connection */
|
||||||
GST_DEBUG ("closing connection...");
|
GST_DEBUG_OBJECT (src, "closing connection...");
|
||||||
if ((res = rtsp_connection_close (src->connection)) < 0)
|
if ((res = rtsp_connection_close (src->connection)) < 0)
|
||||||
goto close_failed;
|
goto close_failed;
|
||||||
|
|
||||||
|
@ -1229,7 +1358,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
|
||||||
if (!(src->options & RTSP_PLAY))
|
if (!(src->options & RTSP_PLAY))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG ("PLAY...");
|
GST_DEBUG_OBJECT (src, "PLAY...");
|
||||||
|
|
||||||
/* do play */
|
/* do play */
|
||||||
if ((res =
|
if ((res =
|
||||||
|
@ -1242,6 +1371,7 @@ gst_rtspsrc_play (GstRTSPSrc * src)
|
||||||
if (src->interleaved) {
|
if (src->interleaved) {
|
||||||
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_start (src->task);
|
gst_task_start (src->task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,7 +1401,7 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
|
||||||
if (!(src->options & RTSP_PAUSE))
|
if (!(src->options & RTSP_PAUSE))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG ("PAUSE...");
|
GST_DEBUG_OBJECT (src, "PAUSE...");
|
||||||
/* do pause */
|
/* do pause */
|
||||||
if ((res =
|
if ((res =
|
||||||
rtsp_message_init_request (RTSP_PAUSE, src->location, &request)) < 0)
|
rtsp_message_init_request (RTSP_PAUSE, src->location, &request)) < 0)
|
||||||
|
|
|
@ -55,19 +55,23 @@ typedef struct _GstRTSPStream GstRTSPStream;
|
||||||
struct _GstRTSPStream {
|
struct _GstRTSPStream {
|
||||||
gint id;
|
gint id;
|
||||||
|
|
||||||
gint rtpchannel;
|
|
||||||
gint rtcpchannel;
|
|
||||||
|
|
||||||
GstRTSPSrc *parent;
|
GstRTSPSrc *parent;
|
||||||
|
|
||||||
/* our udp sources */
|
GstFlowReturn last_ret;
|
||||||
|
|
||||||
|
/* for interleaved mode */
|
||||||
|
gint rtpchannel;
|
||||||
|
gint rtcpchannel;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
/* our udp sources for RTP */
|
||||||
GstElement *rtpsrc;
|
GstElement *rtpsrc;
|
||||||
GstElement *rtcpsrc;
|
GstElement *rtcpsrc;
|
||||||
|
|
||||||
/* our udp sink back to the server */
|
/* our udp sink back to the server */
|
||||||
GstElement *rtcpsink;
|
GstElement *rtcpsink;
|
||||||
|
|
||||||
/* the rtp decoder */
|
/* the RTP decoder */
|
||||||
GstElement *rtpdec;
|
GstElement *rtpdec;
|
||||||
GstPad *rtpdecrtp;
|
GstPad *rtpdecrtp;
|
||||||
GstPad *rtpdecrtcp;
|
GstPad *rtpdecrtcp;
|
||||||
|
@ -76,23 +80,25 @@ struct _GstRTSPStream {
|
||||||
struct _GstRTSPSrc {
|
struct _GstRTSPSrc {
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
gboolean interleaved;
|
/* task and mutex for interleaved mode */
|
||||||
GstTask *task;
|
gboolean interleaved;
|
||||||
|
GstTask *task;
|
||||||
|
GStaticRecMutex *stream_rec_lock;
|
||||||
|
|
||||||
gint numstreams;
|
gint numstreams;
|
||||||
GList *streams;
|
GList *streams;
|
||||||
|
|
||||||
gchar *location;
|
gchar *location;
|
||||||
gboolean debug;
|
gboolean debug;
|
||||||
guint retry;
|
guint retry;
|
||||||
|
|
||||||
GstRTSPProto protocols;
|
GstRTSPProto protocols;
|
||||||
/* supported options */
|
/* supported options */
|
||||||
gint options;
|
gint options;
|
||||||
|
|
||||||
RTSPConnection *connection;
|
RTSPConnection *connection;
|
||||||
RTSPMessage *request;
|
RTSPMessage *request;
|
||||||
RTSPMessage *response;
|
RTSPMessage *response;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstRTSPSrcClass {
|
struct _GstRTSPSrcClass {
|
||||||
|
|
Loading…
Reference in a new issue