summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/rtsp-server/rtsp-media.c16
-rw-r--r--gst/rtsp-server/rtsp-stream.c74
-rw-r--r--gst/rtsp-server/rtsp-stream.h3
-rw-r--r--gst/rtsp-sink/gstrtspclientsink.c5
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);