diff options
-rw-r--r-- | gst/rtsp-server/rtsp-media.c | 16 | ||||
-rw-r--r-- | gst/rtsp-server/rtsp-stream.c | 74 | ||||
-rw-r--r-- | gst/rtsp-server/rtsp-stream.h | 3 | ||||
-rw-r--r-- | gst/rtsp-sink/gstrtspclientsink.c | 5 |
4 files changed, 98 insertions, 0 deletions
diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 63f43bc..f2d498a 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -4683,6 +4683,21 @@ preroll_failed: } } +static void +gst_rtsp_media_unblock_rtcp (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv; + guint i; + + priv = media->priv; + g_mutex_lock (&priv->lock); + for (i = 0; i < priv->streams->len; i++) { + GstRTSPStream *stream = g_ptr_array_index (priv->streams, i); + gst_rtsp_stream_unblock_rtcp (stream); + } + g_mutex_unlock (&priv->lock); +} + /** * gst_rtsp_media_unsuspend: * @media: a #GstRTSPMedia @@ -4711,6 +4726,7 @@ gst_rtsp_media_unsuspend (GstRTSPMedia * media) } done: + gst_rtsp_media_unblock_rtcp (media); g_rec_mutex_unlock (&priv->state_lock); return TRUE; diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 1495b73..92ef358 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -224,6 +224,12 @@ struct _GstRTSPStreamPrivate /* Whether we should send and receive RTCP */ gboolean enable_rtcp; + + /* blocking early rtcp packets */ + GstPad *block_early_rtcp_pad; + gulong block_early_rtcp_probe; + GstPad *block_early_rtcp_pad_ipv6; + gulong block_early_rtcp_probe_ipv6; }; #define DEFAULT_CONTROL NULL @@ -347,6 +353,10 @@ gst_rtsp_stream_init (GstRTSPStream * stream) priv->ptmap = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) gst_caps_unref); priv->send_pool = NULL; + priv->block_early_rtcp_pad = NULL; + priv->block_early_rtcp_probe = 0; + priv->block_early_rtcp_pad_ipv6 = NULL; + priv->block_early_rtcp_probe_ipv6 = 0; } typedef struct _UdpClientAddrInfo UdpClientAddrInfo; @@ -431,6 +441,18 @@ gst_rtsp_stream_finalize (GObject * obj) g_mutex_clear (&priv->send_lock); g_cond_clear (&priv->send_cond); + if (priv->block_early_rtcp_probe != 0) { + gst_pad_remove_probe + (priv->block_early_rtcp_pad, priv->block_early_rtcp_probe); + gst_object_unref (priv->block_early_rtcp_pad); + } + + if (priv->block_early_rtcp_probe_ipv6 != 0) { + gst_pad_remove_probe + (priv->block_early_rtcp_pad_ipv6, priv->block_early_rtcp_probe_ipv6); + gst_object_unref (priv->block_early_rtcp_pad_ipv6); + } + G_OBJECT_CLASS (gst_rtsp_stream_parent_class)->finalize (obj); } @@ -3755,6 +3777,15 @@ create_receiver_part (GstRTSPStream * stream, const GstRTSPTransport * g_object_set (priv->udpsrc_v4[i], "caps", rtp_caps, NULL); } else { g_object_set (priv->udpsrc_v4[i], "caps", rtcp_caps, NULL); + + /* block early rtcp packets, pipeline not ready */ + g_assert (priv->block_early_rtcp_pad == NULL); + priv->block_early_rtcp_pad = gst_element_get_static_pad + (priv->udpsrc_v4[i], "src"); + priv->block_early_rtcp_probe = gst_pad_add_probe + (priv->block_early_rtcp_pad, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, NULL, NULL, + NULL); } plug_src (stream, bin, priv->udpsrc_v4[i], priv->funnel[i]); @@ -3770,6 +3801,15 @@ create_receiver_part (GstRTSPStream * stream, const GstRTSPTransport * g_object_set (priv->udpsrc_v6[i], "caps", rtp_caps, NULL); } else { g_object_set (priv->udpsrc_v6[i], "caps", rtcp_caps, NULL); + + /* block early rtcp packets, pipeline not ready */ + g_assert (priv->block_early_rtcp_pad_ipv6 == NULL); + priv->block_early_rtcp_pad_ipv6 = gst_element_get_static_pad + (priv->udpsrc_v6[i], "src"); + priv->block_early_rtcp_probe_ipv6 = gst_pad_add_probe + (priv->block_early_rtcp_pad_ipv6, + GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER, NULL, NULL, + NULL); } plug_src (stream, bin, priv->udpsrc_v6[i], priv->funnel[i]); @@ -6290,3 +6330,37 @@ gst_rtsp_stream_get_rate_control (GstRTSPStream * stream) return ret; } + +/** + * gst_rtsp_stream_unblock_rtcp: + * + * Remove blocking probe from the RTCP source. When creating an UDP source for + * RTCP it is initially blocked until this function is called. + * This functions should be called once the pipeline is ready for handling RTCP + * packets. + * + * Since: 1.20 + */ +void +gst_rtsp_stream_unblock_rtcp (GstRTSPStream * stream) +{ + GstRTSPStreamPrivate *priv; + + priv = stream->priv; + g_mutex_lock (&priv->lock); + if (priv->block_early_rtcp_probe != 0) { + gst_pad_remove_probe + (priv->block_early_rtcp_pad, priv->block_early_rtcp_probe); + priv->block_early_rtcp_probe = 0; + gst_object_unref (priv->block_early_rtcp_pad); + priv->block_early_rtcp_pad = NULL; + } + if (priv->block_early_rtcp_probe_ipv6 != 0) { + gst_pad_remove_probe + (priv->block_early_rtcp_pad_ipv6, priv->block_early_rtcp_probe_ipv6); + priv->block_early_rtcp_probe_ipv6 = 0; + gst_object_unref (priv->block_early_rtcp_pad_ipv6); + priv->block_early_rtcp_pad_ipv6 = NULL; + } + g_mutex_unlock (&priv->lock); +} diff --git a/gst/rtsp-server/rtsp-stream.h b/gst/rtsp-server/rtsp-stream.h index dcb5d7a..5e6ff21 100644 --- a/gst/rtsp-server/rtsp-stream.h +++ b/gst/rtsp-server/rtsp-stream.h @@ -365,6 +365,9 @@ void gst_rtsp_stream_set_rate_control (GstRTSPStream * stream, gbo GST_RTSP_SERVER_API gboolean gst_rtsp_stream_get_rate_control (GstRTSPStream * stream); +GST_RTSP_SERVER_API +void gst_rtsp_stream_unblock_rtcp (GstRTSPStream * stream); + /** * GstRTSPStreamTransportFilterFunc: * @stream: a #GstRTSPStream object diff --git a/gst/rtsp-sink/gstrtspclientsink.c b/gst/rtsp-sink/gstrtspclientsink.c index 96b6044..3573e20 100644 --- a/gst/rtsp-sink/gstrtspclientsink.c +++ b/gst/rtsp-sink/gstrtspclientsink.c @@ -4580,6 +4580,11 @@ gst_rtsp_client_sink_record (GstRTSPClientSink * sink, gboolean async) gst_rtsp_client_sink_set_state (sink, GST_STATE_PLAYING); sink->state = GST_RTSP_STATE_PLAYING; + for (walk = sink->contexts; walk; walk = g_list_next (walk)) { + GstRTSPStreamContext *context = (GstRTSPStreamContext *) walk->data; + + gst_rtsp_stream_unblock_rtcp (context->stream); + } /* clean up any messages */ gst_rtsp_message_unset (&request); |