summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2019-03-15 16:47:35 +0100
committerMathieu Duponchelle <mathieu@centricular.com>2019-03-15 18:37:51 +0100
commita2779ef36607c3f28e6903b5ed509e3db431b59b (patch)
treeb47d41e6c0b7ebcb1e9a7aea70bac7c6f2fc5aeb
parent2f907b7e2de4d4a623a666abfe356b5654a3b754 (diff)
downloadgstreamer-plugins-bad-a2779ef36607c3f28e6903b5ed509e3db431b59b.tar.gz
webrtcbin: fix pt selection for FEC and RTX when BUNDLE
When we offer bundled media, payload types must be unique across all bundled media, as they will be multiplexed in the same session.
-rw-r--r--ext/webrtc/gstwebrtcbin.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c
index 76c99edf0..9236753d1 100644
--- a/ext/webrtc/gstwebrtcbin.c
+++ b/ext/webrtc/gstwebrtcbin.c
@@ -1946,7 +1946,8 @@ _add_fingerprint_to_media (GstWebRTCDTLSTransport * transport,
static gboolean
sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
GstWebRTCRTPTransceiver * trans, GstWebRTCSDPType type, guint media_idx,
- GString * bundled_mids, guint bundle_idx, gboolean bundle_only)
+ GString * bundled_mids, guint bundle_idx, gboolean bundle_only,
+ GArray * reserved_pts)
{
/* TODO:
* rtp header extensions
@@ -2028,14 +2029,14 @@ sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
}
if (type == GST_WEBRTC_SDP_TYPE_OFFER) {
- GArray *reserved_pts = g_array_new (FALSE, FALSE, sizeof (guint));
const GstStructure *s = gst_caps_get_structure (caps, 0);
gint clockrate = -1;
gint rtx_target_pt;
gint original_rtx_target_pt; /* Workaround chrome bug: https://bugs.chromium.org/p/webrtc/issues/detail?id=6196 */
guint rtx_target_ssrc = -1;
- if (gst_structure_get_int (s, "payload", &rtx_target_pt))
+ if (gst_structure_get_int (s, "payload", &rtx_target_pt) &&
+ webrtc->bundle_policy == GST_WEBRTC_BUNDLE_POLICY_NONE)
g_array_append_val (reserved_pts, rtx_target_pt);
original_rtx_target_pt = rtx_target_pt;
@@ -2054,7 +2055,6 @@ sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
if (original_rtx_target_pt != rtx_target_pt)
_pick_rtx_payload_types (webrtc, WEBRTC_TRANSCEIVER (trans), reserved_pts,
clockrate, original_rtx_target_pt, rtx_target_ssrc, media);
- g_array_free (reserved_pts, TRUE);
}
_media_add_ssrcs (media, caps, webrtc, WEBRTC_TRANSCEIVER (trans));
@@ -2084,6 +2084,34 @@ sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
return TRUE;
}
+static void
+gather_pad_pt (GstWebRTCBinPad * pad, GArray * reserved_pts)
+{
+ if (pad->received_caps) {
+ GstStructure *s = gst_caps_get_structure (pad->received_caps, 0);
+ gint pt;
+
+ if (gst_structure_get_int (s, "payload", &pt)) {
+ g_array_append_val (reserved_pts, pt);
+ }
+ }
+}
+
+static GArray *
+gather_reserved_pts (GstWebRTCBin * webrtc)
+{
+ GstElement *element = GST_ELEMENT (webrtc);
+ GArray *reserved_pts = g_array_new (FALSE, FALSE, sizeof (guint));
+
+ GST_OBJECT_LOCK (webrtc);
+ g_list_foreach (element->sinkpads, (GFunc) gather_pad_pt, reserved_pts);
+ g_list_foreach (webrtc->priv->pending_pads, (GFunc) gather_pad_pt,
+ reserved_pts);
+ GST_OBJECT_UNLOCK (webrtc);
+
+ return reserved_pts;
+}
+
/* TODO: use the options argument */
static GstSDPMessage *
_create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
@@ -2093,6 +2121,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
GString *bundled_mids = NULL;
gchar *bundle_ufrag = NULL;
gchar *bundle_pwd = NULL;
+ GArray *reserved_pts = NULL;
gst_sdp_message_new (&ret);
@@ -2115,6 +2144,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
if (webrtc->bundle_policy != GST_WEBRTC_BUNDLE_POLICY_NONE) {
_generate_ice_credentials (&bundle_ufrag, &bundle_pwd);
+ reserved_pts = gather_reserved_pts (webrtc);
}
/* for each rtp transceiver */
@@ -2136,6 +2166,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
/* FIXME: only needed when restarting ICE */
if (webrtc->bundle_policy == GST_WEBRTC_BUNDLE_POLICY_NONE) {
+ reserved_pts = g_array_new (FALSE, FALSE, sizeof (guint));
_generate_ice_credentials (&ufrag, &pwd);
} else {
ufrag = g_strdup (bundle_ufrag);
@@ -2147,8 +2178,11 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
g_free (ufrag);
g_free (pwd);
+ g_assert (reserved_pts != NULL);
+
if (sdp_media_from_transceiver (webrtc, &media, trans,
- GST_WEBRTC_SDP_TYPE_OFFER, i, bundled_mids, 0, bundle_only)) {
+ GST_WEBRTC_SDP_TYPE_OFFER, i, bundled_mids, 0, bundle_only,
+ reserved_pts)) {
if (bundled_mids) {
const gchar *mid = gst_sdp_media_get_attribute_val (&media, "mid");
@@ -2159,6 +2193,14 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options)
} else {
gst_sdp_media_uninit (&media);
}
+
+ if (webrtc->bundle_policy == GST_WEBRTC_BUNDLE_POLICY_NONE) {
+ g_array_free (reserved_pts, TRUE);
+ }
+ }
+
+ if (webrtc->bundle_policy != GST_WEBRTC_BUNDLE_POLICY_NONE) {
+ g_array_free (reserved_pts, TRUE);
}
/* add data channel support */