From 0e3a07aabf95708085a2e2fec4942dba632de08e Mon Sep 17 00:00:00 2001 From: Evangelos Ribeiro Tzaras Date: Mon, 28 Feb 2022 22:04:23 +0100 Subject: [PATCH] sip: media-pipeline: Setup socket reuse for RTP and RTCP during initialization Now that initialization is split per pipeline and that the OS handles port allocation we can move setting up socket reuse into the pipeline initialization step instead of setting it up when starting the media pipelines. This makes the calls_sip_media_pipeline_start() method a bit simpler. We're also now reusing sockets for RTCP. Closes #315 --- plugins/sip/calls-sip-media-pipeline.c | 78 ++++++++++++++++++++------ 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/plugins/sip/calls-sip-media-pipeline.c b/plugins/sip/calls-sip-media-pipeline.c index 9c740b8..78dc4cb 100644 --- a/plugins/sip/calls-sip-media-pipeline.c +++ b/plugins/sip/calls-sip-media-pipeline.c @@ -457,6 +457,8 @@ static gboolean send_pipeline_init (CallsSipMediaPipeline *self, GError **error) { + g_autoptr (GSocket) rtp_sock = NULL; + g_autoptr (GSocket) rtcp_sock = NULL; const char *env_var; g_assert (CALLS_SIP_MEDIA_PIPELINE (self)); @@ -518,7 +520,36 @@ send_pipeline_init (CallsSipMediaPipeline *self, self->rtcp_send_sink, "host", G_BINDING_BIDIRECTIONAL); - /* TODO bind sockets */ + /* bind sockets for hole punching scheme */ + g_object_get (self->rtp_src, "used-socket", &rtp_sock, NULL); + if (!rtp_sock) { + if (error) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Could not retrieve used socket from RTP udpsrc element"); + return FALSE; + } + + g_object_set (self->rtp_sink, + "socket", rtp_sock, + "close-socket", FALSE, + NULL); + + + g_object_get (self->rtcp_recv_src, "used-socket", &rtcp_sock, NULL); + if (!rtcp_sock) { + if (error) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Could not retrieve used socket from RTCP udpsrc element"); + return FALSE; + } + g_object_set (self->rtcp_send_sink, + "socket", rtcp_sock, + "close-socket", FALSE, + NULL); + g_object_set (self->rtcp_send_src, + "socket", rtcp_sock, + "close-socket", FALSE, + NULL); gst_bin_add (GST_BIN (self->send_pipeline), self->send_rtpbin); gst_bin_add_many (GST_BIN (self->send_pipeline), self->rtp_sink, @@ -645,6 +676,7 @@ static gboolean recv_pipeline_init (CallsSipMediaPipeline *self, GError **error) { + g_autoptr (GSocket) rtcp_sock = NULL; const char *env_var; g_assert (CALLS_SIP_MEDIA_PIPELINE (self)); @@ -712,9 +744,32 @@ recv_pipeline_init (CallsSipMediaPipeline *self, self->bus_recv = gst_pipeline_get_bus (GST_PIPELINE (self->recv_pipeline)); self->bus_watch_recv = gst_bus_add_watch (self->bus_recv, on_bus_message, self); + g_object_set (self->rtp_src, + "close-socket", FALSE, + "reuse", TRUE, + NULL); + g_object_set (self->rtcp_recv_src, + "close-socket", FALSE, + "reuse", TRUE, + NULL); + /* Set pipeline to ready to get ports allocated */ gst_element_set_state (self->recv_pipeline, GST_STATE_READY); + g_object_get (self->rtcp_recv_src, "used-socket", &rtcp_sock, NULL); + if (!rtcp_sock) { + if (error) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Could not retrieve used socket from RTCP udpsrc element"); + return FALSE; + } + + /* Ports are allocated. Let's reuse the socket for rtcp source in the sink for NAT traversal*/ + g_object_set (self->rtcp_recv_sink, + "socket", rtcp_sock, + "close-socket", FALSE, + NULL); + return TRUE; } @@ -1036,7 +1091,6 @@ diagnose_ports_in_use (CallsSipMediaPipeline *self) void calls_sip_media_pipeline_start (CallsSipMediaPipeline *self) { - GSocket *socket; g_return_if_fail (CALLS_IS_SIP_MEDIA_PIPELINE (self)); if (self->state != CALLS_MEDIA_PIPELINE_STATE_READY) { @@ -1046,25 +1100,13 @@ calls_sip_media_pipeline_start (CallsSipMediaPipeline *self) g_debug ("Starting media pipeline"); - /* First start the receiver pipeline so that - we may reuse the socket in the sender pipeline */ - /* TODO can we do something similar for RTCP? */ gst_element_set_state (self->recv_pipeline, GST_STATE_PLAYING); - - g_object_get (self->rtp_src, "used-socket", &socket, NULL); - - if (socket) { - g_object_set (self->rtp_sink, - "close-socket", FALSE, - "socket", socket, - NULL); - } - else - g_warning ("Could not get used socket of udpsrc element"); - - /* Now start the sender pipeline */ gst_element_set_state (self->send_pipeline, GST_STATE_PLAYING); + g_debug ("RTP/RTCP port after starting pipeline: %d/%d", + calls_sip_media_pipeline_get_rtp_port (self), + calls_sip_media_pipeline_get_rtcp_port (self)); + set_state (self, CALLS_MEDIA_PIPELINE_STATE_PLAY_PENDING); if (self->debug)