diff options
author | Olivier CrĂȘte <olivier.crete@collabora.com> | 2021-03-26 18:15:50 -0400 |
---|---|---|
committer | Olivier CrĂȘte <olivier.crete@collabora.com> | 2021-04-12 17:55:07 -0400 |
commit | 08dd305a205060ed50182f9c903d493d559633eb (patch) | |
tree | 931bc5e5bd073d9126ccc7784251a43de267e800 /ext/webrtc/gstwebrtcbin.c | |
parent | ed1f0f33a236a3cc83f522b628d259b14d05cc9c (diff) | |
download | gstreamer-plugins-bad-08dd305a205060ed50182f9c903d493d559633eb.tar.gz |
webrtcbin: Enforce m-line restrictions when creating offer
First fail the offer creation if the mid of an existing offer doesn't
match a forced m-mline.
Then, for all newly added mlines, first look for a transceiver that
forces this m-line, then add a "floating" one, then the data channel.
And repeat this until we're out of transceivers.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2104>
Diffstat (limited to 'ext/webrtc/gstwebrtcbin.c')
-rw-r--r-- | ext/webrtc/gstwebrtcbin.c | 119 |
1 files changed, 93 insertions, 26 deletions
diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c index a554a7bdb..ad4073c66 100644 --- a/ext/webrtc/gstwebrtcbin.c +++ b/ext/webrtc/gstwebrtcbin.c @@ -470,6 +470,9 @@ match_for_mid (GstWebRTCRTPTransceiver * trans, const gchar * mid) static gboolean transceiver_match_for_mline (GstWebRTCRTPTransceiver * trans, guint * mline) { + if (trans->stopped) + return FALSE; + return trans->mline == *mline; } @@ -2866,9 +2869,20 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options, if (trans->mid && g_strcmp0 (trans->mid, last_mid) == 0) { GstSDPMedia *media; const gchar *mid; + WebRTCTransceiver *wtrans = WEBRTC_TRANSCEIVER (trans); g_assert (!g_list_find (seen_transceivers, trans)); + if (wtrans->mline_locked && trans->mline != media_idx) { + g_set_error (error, GST_WEBRTC_BIN_ERROR, + GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION, + "Previous negotiatied transceiver %" + GST_PTR_FORMAT " with mid %s was in mline %d but transceiver" + " has locked mline %u", trans, trans->mid, media_idx, + trans->mline); + goto cancel_offer; + } + GST_LOG_OBJECT (webrtc, "using previous negotiatied transceiver %" GST_PTR_FORMAT " with mid %s into media index %u", trans, trans->mid, media_idx); @@ -2885,7 +2899,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options, g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_FAILED, "Duplicate mid %s when creating offer", mid); - goto duplicate_mid; + goto cancel_offer; } g_hash_table_insert (all_mids, g_strdup (mid), NULL); @@ -2929,27 +2943,94 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options, if (g_hash_table_contains (all_mids, trans->mid)) { g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_FAILED, "Duplicate mid %s when creating offer", trans->mid); - goto duplicate_mid; + goto cancel_offer; } g_hash_table_insert (all_mids, g_strdup (trans->mid), NULL); } } + /* add any extra streams */ - for (i = 0; i < webrtc->priv->transceivers->len; i++) { - GstWebRTCRTPTransceiver *trans; + for (;;) { + GstWebRTCRTPTransceiver *trans = NULL; GstSDPMedia media = { 0, }; - trans = g_ptr_array_index (webrtc->priv->transceivers, i); + /* First find a transceiver requesting this m-line */ + trans = _find_transceiver_for_mline (webrtc, media_idx); - /* don't add transceivers twice */ - if (g_list_find (seen_transceivers, trans)) - continue; + if (trans) { + /* We can't have seen it already, because it is locked to this line */ + g_assert (!g_list_find (seen_transceivers, trans)); + seen_transceivers = g_list_prepend (seen_transceivers, trans); + } else { + /* Otherwise find a free transceiver */ + for (i = 0; i < webrtc->priv->transceivers->len; i++) { + WebRTCTransceiver *wtrans; + + trans = g_ptr_array_index (webrtc->priv->transceivers, i); + wtrans = WEBRTC_TRANSCEIVER (trans); + + /* don't add transceivers twice */ + if (g_list_find (seen_transceivers, trans)) + continue; + + /* Ignore transceivers with a locked mline, as they would have been + * found above or will be used later */ + if (wtrans->mline_locked) + continue; + + seen_transceivers = g_list_prepend (seen_transceivers, trans); + /* don't add stopped transceivers */ + if (trans->stopped) { + continue; + } - /* don't add stopped transceivers */ - if (trans->stopped) - continue; + /* Otherwise take it */ + break; + } + + /* Stop if we got all transceivers */ + if (i == webrtc->priv->transceivers->len) { + + /* But try to add a data channel first, we do it here, because + * it can allow a locked m-line to be put after, so we need to + * do another iteration after. + */ + if (_message_get_datachannel_index (ret) == G_MAXUINT) { + GstSDPMedia media = { 0, }; + gst_sdp_media_init (&media); + if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0, + bundle_ufrag, bundle_pwd, all_mids)) { + gst_sdp_message_add_media (ret, &media); + media_idx++; + continue; + } else { + gst_sdp_media_uninit (&media); + } + } + + /* Verify that we didn't ignore any locked m-line transceivers */ + for (i = 0; i < webrtc->priv->transceivers->len; i++) { + WebRTCTransceiver *wtrans; + + trans = g_ptr_array_index (webrtc->priv->transceivers, i); + wtrans = WEBRTC_TRANSCEIVER (trans); + /* don't add transceivers twice */ + if (g_list_find (seen_transceivers, trans)) + continue; + g_assert (wtrans->mline_locked); + + g_set_error (error, GST_WEBRTC_BIN_ERROR, + GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION, + "Tranceiver %" GST_PTR_FORMAT " with mid %s has locked mline %d" + " but the whole offer only has %u sections", trans, trans->mid, + trans->mline, media_idx); + goto cancel_offer; + } + break; + } + } gst_sdp_media_init (&media); @@ -2973,7 +3054,6 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options, g_array_free (reserved_pts, TRUE); reserved_pts = NULL; } - seen_transceivers = g_list_prepend (seen_transceivers, trans); } if (webrtc->bundle_policy != GST_WEBRTC_BUNDLE_POLICY_NONE) { @@ -2981,19 +3061,6 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options, reserved_pts = NULL; } - /* add a data channel if exists and not renegotiated */ - if (_message_get_datachannel_index (ret) == G_MAXUINT) { - GstSDPMedia media = { 0, }; - gst_sdp_media_init (&media); - if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0, - bundle_ufrag, bundle_pwd, all_mids)) { - gst_sdp_message_add_media (ret, &media); - media_idx++; - } else { - gst_sdp_media_uninit (&media); - } - } - webrtc->priv->max_sink_pad_serial = MAX (webrtc->priv->max_sink_pad_serial, media_idx); @@ -3040,7 +3107,7 @@ out: return ret; -duplicate_mid: +cancel_offer: gst_sdp_message_uninit (ret); ret = NULL; goto out; |