webrtcbin: Sync to the clock per stream and not per bundle
authorSebastian Dröge <sebastian@centricular.com>
Thu, 24 Jun 2021 10:17:09 +0000 (13:17 +0300)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 28 Jun 2021 16:38:33 +0000 (16:38 +0000)
By using the clocksync inside the dtlssrtpenc, all streams inside a
bundled are synchronized together. This will cause problems if their
buffers are not already arriving synchronized: clocksync would wait for
a buffer on one stream and then buffers from the other stream(s) with
lower timestamps would all be sent out too late.

Placing the clocksync before the rtpbin and rtpfunnel synchronizes each
stream individually and they will be send out more smoothly as a result.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2355>

ext/webrtc/gstwebrtcbin.c
gst-libs/gst/webrtc/dtlstransport.c

index 8af9707..88f956b 100644 (file)
@@ -4045,37 +4045,39 @@ _connect_input_stream (GstWebRTCBin * webrtc, GstWebRTCBinPad * pad)
 /*
  * Not-bundle case:
  *
- * ,-------------------------webrtcbin-------------------------,
- * ;                                                           ;
- * ;          ,-------rtpbin-------,   ,--transport_send_%u--, ;
- * ;          ;    send_rtp_src_%u o---o rtp_sink            ; ;
- * ;          ;                    ;   ;                     ; ;
- * ;          ;   send_rtcp_src_%u o---o rtcp_sink           ; ;
- * ; sink_%u  ;                    ;   '---------------------' ;
- * o----------o send_rtp_sink_%u   ;                           ;
- * ;          '--------------------'                           ;
- * '--------------------- -------------------------------------'
+ * ,--------------------------------------------webrtcbin-------------------------,
+ * ;                                                                              ;
+ * ;                             ,-------rtpbin-------,   ,--transport_send_%u--, ;
+ * ;                             ;    send_rtp_src_%u o---o rtp_sink            ; ;
+ * ;         ,---clocksync---,   ;                    ;   ;                     ; ;
+ * ;         ;               ;   ;   send_rtcp_src_%u o---o rtcp_sink           ; ;
+ * ; sink_%u ;               ;   ;                    ;   '---------------------' ;
+ * o---------o sink      src o---o send_rtp_sink_%u   ;                           ;
+ * ;         '---------------'   '--------------------'                           ;
+ * '------------------------------------------------------------------------------'
  */
 
 /*
  * Bundle case:
- * ,--------------------------------webrtcbin--------------------------------,
- * ;                                                                         ;
- * ;                        ,-------rtpbin-------,   ,--transport_send_%u--, ;
- * ;                        ;    send_rtp_src_%u o---o rtp_sink            ; ;
- * ;                        ;                    ;   ;                     ; ;
- * ;                        ;   send_rtcp_src_%u o---o rtcp_sink           ; ;
- * ; sink_%u ,---funnel---, ;                    ;   '---------------------' ;
- * o---------o sink_%u    ; ;                    ;                           ;
- * ; sink_%u ;        src o-o send_rtp_sink_%u   ;                           ;
- * o---------o sink_%u    ; ;                    ;                           ;
- * ;         '------------' '--------------------'                           ;
- * '-------------------------------------------------------------------------'
+ * ,-----------------------------------------------------webrtcbin--------------------------------,
+ * ;                                                                                              ;
+ * ;                                             ,-------rtpbin-------,   ,--transport_send_%u--, ;
+ * ;                                             ;    send_rtp_src_%u o---o rtp_sink            ; ;
+ * ;                                             ;                    ;   ;                     ; ;
+ * ; sink_%u  ,---clocksync---,   ,---funnel---, ;   send_rtcp_src_%u o---o rtcp_sink           ; ;
+ * o----------o sink      src o---o sink_%u    ; ;                    ;   '---------------------' ;
+ * ;          '---------------'   ;            ; ;                    ;                           ;
+ * ;                              ;        src o-o send_rtp_sink_%u   ;                           ;
+ * ; sink_%u  ,---clocksync---,   ;            ; ;                    ;                           ;
+ * o----------o sink      src o---o sink%u     ; '--------------------'                           ;
+ * ;          '---------------'   '------------'                                                  ;
+ * '----------------------------------------------------------------------------------------------'
  */
   GstPadTemplate *rtp_templ;
-  GstPad *rtp_sink;
+  GstPad *rtp_sink, *sinkpad, *srcpad;
   gchar *pad_name;
   WebRTCTransceiver *trans;
+  GstElement *clocksync;
 
   g_return_val_if_fail (pad->trans != NULL, NULL);
 
@@ -4085,6 +4087,14 @@ _connect_input_stream (GstWebRTCBin * webrtc, GstWebRTCBinPad * pad)
 
   g_assert (trans->stream);
 
+  clocksync = gst_element_factory_make ("clocksync", NULL);
+  g_object_set (clocksync, "sync", TRUE, NULL);
+  gst_bin_add (GST_BIN (webrtc), clocksync);
+  gst_element_sync_state_with_parent (clocksync);
+
+  srcpad = gst_element_get_static_pad (clocksync, "src");
+  sinkpad = gst_element_get_static_pad (clocksync, "sink");
+
   if (!webrtc->rtpfunnel) {
     rtp_templ =
         _find_pad_template (webrtc->rtpbin, GST_PAD_SINK, GST_PAD_REQUEST,
@@ -4095,9 +4105,11 @@ _connect_input_stream (GstWebRTCBin * webrtc, GstWebRTCBinPad * pad)
     rtp_sink =
         gst_element_request_pad (webrtc->rtpbin, rtp_templ, pad_name, NULL);
     g_free (pad_name);
-    gst_ghost_pad_set_target (GST_GHOST_PAD (pad), rtp_sink);
+    gst_pad_link (srcpad, rtp_sink);
     gst_object_unref (rtp_sink);
 
+    gst_ghost_pad_set_target (GST_GHOST_PAD (pad), sinkpad);
+
     pad_name = g_strdup_printf ("send_rtp_src_%u", pad->trans->mline);
     if (!gst_element_link_pads (GST_ELEMENT (webrtc->rtpbin), pad_name,
             GST_ELEMENT (trans->stream->send_bin), "rtp_sink"))
@@ -4108,12 +4120,16 @@ _connect_input_stream (GstWebRTCBin * webrtc, GstWebRTCBinPad * pad)
     GstPad *funnel_sinkpad =
         gst_element_request_pad_simple (webrtc->rtpfunnel, pad_name);
 
-    gst_ghost_pad_set_target (GST_GHOST_PAD (pad), funnel_sinkpad);
+    gst_pad_link (srcpad, funnel_sinkpad);
+    gst_ghost_pad_set_target (GST_GHOST_PAD (pad), sinkpad);
 
     g_free (pad_name);
     gst_object_unref (funnel_sinkpad);
   }
 
+  gst_object_unref (srcpad);
+  gst_object_unref (sinkpad);
+
   gst_element_sync_state_with_parent (GST_ELEMENT (trans->stream->send_bin));
 
   return GST_PAD (pad);
index e127555..c401f7f 100644 (file)
@@ -184,7 +184,7 @@ gst_webrtc_dtls_transport_constructed (GObject * object)
 
   webrtc->dtlssrtpenc = gst_element_factory_make ("dtlssrtpenc", NULL);
   g_object_set (webrtc->dtlssrtpenc, "connection-id", connection_id,
-      "is-client", webrtc->client, "rtp-sync", TRUE, NULL);
+      "is-client", webrtc->client, "rtp-sync", FALSE, NULL);
 
   webrtc->dtlssrtpdec = gst_element_factory_make ("dtlssrtpdec", NULL);
   g_object_set (webrtc->dtlssrtpdec, "connection-id", connection_id, NULL);