diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.c | 85 | ||||
-rw-r--r-- | gst/rtsp/gstrtspsrc.h | 2 |
3 files changed, 81 insertions, 19 deletions
@@ -1,5 +1,18 @@ 2006-09-18 Wim Taymans <wim@fluendo.com> + * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_base_init), + (gst_rtspsrc_stream_configure_transport), (gst_rtspsrc_push_event), + (gst_rtspsrc_loop), (gst_rtspsrc_uri_set_uri): + * gst/rtsp/gstrtspsrc.h: + Export sometimes source pad with correct caps on the template, create + the ghostpad from the template. + Remove RTCP template as we never expose RTCP. + Protect against invalid body size. + Avoid memcpy when creating the output buffer. + Properly post an error and send EOS when the loop function is shut down. + +2006-09-18 Wim Taymans <wim@fluendo.com> + Based on patch by: Lutz Mueller <lutz at topfrose dot de> * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_class_init), diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 3d29815c..1353852c 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -86,13 +86,7 @@ static GstStaticPadTemplate rtptemplate = GST_STATIC_PAD_TEMPLATE ("rtp_stream%d", GST_PAD_SRC, GST_PAD_SOMETIMES, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate rtcptemplate = -GST_STATIC_PAD_TEMPLATE ("rtcp_stream%d", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS_ANY); + GST_STATIC_CAPS ("application/x-rtp")); enum { @@ -178,8 +172,6 @@ gst_rtspsrc_base_init (gpointer g_class) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&rtptemplate)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&rtcptemplate)); gst_element_class_set_details (element_class, &gst_rtspsrc_details); } @@ -649,7 +641,8 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream, SDPMedia * media, RTSPTransport * transport) { GstRTSPSrc *src; - GstPad *pad; + GstPad *pad, *gpad; + GstPadTemplate *template; GstStateChangeReturn ret; gchar *name; @@ -736,11 +729,18 @@ gst_rtspsrc_stream_configure_transport (GstRTSPStream * stream, gst_pad_use_fixed_caps (pad); gst_pad_set_caps (pad, stream->caps); } + + /* create ghostpad */ name = g_strdup_printf ("rtp_stream%d", stream->id); - gst_element_add_pad (GST_ELEMENT_CAST (src), gst_ghost_pad_new (name, pad)); + template = gst_static_pad_template_get (&rtptemplate); + gpad = gst_ghost_pad_new_from_template (name, pad, template); + gst_object_unref (template); g_free (name); + gst_object_unref (pad); + gst_element_add_pad (GST_ELEMENT_CAST (src), gpad); + return TRUE; /* ERRORS */ @@ -802,6 +802,22 @@ done: } static void +gst_rtspsrc_push_event (GstRTSPSrc * src, GstEvent * event) +{ + GList *streams; + + for (streams = src->streams; streams; streams = g_list_next (streams)) { + GstRTSPStream *ostream = (GstRTSPStream *) streams->data; + + gst_event_ref (event); + gst_pad_push_event (ostream->rtpdecrtp, event); + gst_event_ref (event); + gst_pad_push_event (ostream->rtpdecrtcp, event); + } + gst_event_unref (event); +} + +static void gst_rtspsrc_loop (GstRTSPSrc * src) { RTSPMessage response = { 0 }; @@ -838,7 +854,10 @@ gst_rtspsrc_loop (GstRTSPSrc * src) outpad = stream->rtpdecrtcp; } + /* take a look at the body to figure out what we have */ rtsp_message_get_body (&response, &data, &size); + if (size < 2) + goto invalid_length; /* channels are not correct on some servers, do extra check */ if (data[1] >= 200 && data[1] <= 204) { @@ -854,11 +873,15 @@ gst_rtspsrc_loop (GstRTSPSrc * src) { GstBuffer *buf; + rtsp_message_steal_body (&response, &data, &size); + /* strip the trailing \0 */ size -= 1; buf = gst_buffer_new_and_alloc (size); - memcpy (GST_BUFFER_DATA (buf), data, size); + GST_BUFFER_DATA (buf) = data; + GST_BUFFER_MALLOCDATA (buf) = data; + GST_BUFFER_SIZE (buf) = size; if (caps) gst_buffer_set_caps (buf, caps); @@ -869,7 +892,7 @@ gst_rtspsrc_loop (GstRTSPSrc * src) /* chain to the peer pad */ ret = gst_pad_chain (outpad, buf); - /* combine all streams */ + /* combine all stream flows */ ret = gst_rtspsrc_combine_flows (src, stream, ret); if (ret != GST_FLOW_OK) goto need_pause; @@ -884,19 +907,43 @@ unknown_stream: } receive_error: { - GST_ELEMENT_ERROR (src, RESOURCE, WRITE, + GST_ELEMENT_ERROR (src, RESOURCE, READ, ("Could not receive message."), (NULL)); ret = GST_FLOW_UNEXPECTED; - /* - gst_pad_push_event (src->srcpad, gst_event_new (GST_EVENT_EOS)); - */ goto need_pause; } +invalid_length: + { + GST_ELEMENT_WARNING (src, RESOURCE, READ, + ("Short message received."), (NULL)); + return; + } need_pause: { - GST_DEBUG_OBJECT (src, "pausing task, reason %d (%s)", ret, - gst_flow_get_name (ret)); + const gchar *reason = gst_flow_get_name (ret); + + GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason); + src->running = FALSE; gst_task_pause (src->task); + if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { + if (ret == GST_FLOW_UNEXPECTED) { + /* perform EOS logic */ + if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) { + gst_element_post_message (GST_ELEMENT_CAST (src), + gst_message_new_segment_done (GST_OBJECT_CAST (src), + src->segment.format, src->segment.last_stop)); + } else { + gst_rtspsrc_push_event (src, gst_event_new_eos ()); + } + } else { + /* for fatal errors we post an error message, post the error + * first so the app knows about the error first. */ + GST_ELEMENT_ERROR (src, STREAM, FAILED, + ("Internal data flow error."), + ("streaming task paused, reason %s (%d)", reason, ret)); + gst_rtspsrc_push_event (src, gst_event_new_eos ()); + } + } return; } } diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h index 2731e080..73267edd 100644 --- a/gst/rtsp/gstrtspsrc.h +++ b/gst/rtsp/gstrtspsrc.h @@ -91,6 +91,8 @@ struct _GstRTSPSrc { gboolean interleaved; GstTask *task; GStaticRecMutex *stream_rec_lock; + GstSegment segment; + gboolean running; gint numstreams; GList *streams; |