mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-08 16:35:40 +00:00
webrtc: advertise end-of-candidate with an empty candidate string
Just like what is done in the browsers. When this is sent to the peer, they will be able to know that no more candidates are coming and can complete ICE. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4598>
This commit is contained in:
parent
5e45a1b1bd
commit
b10ec569d7
2 changed files with 138 additions and 16 deletions
|
@ -821,6 +821,30 @@ _find_transport_for_session (GstWebRTCBin * webrtc, guint session_id)
|
|||
return stream;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
match_stream_for_ice_transport (TransportStream * trans,
|
||||
GstWebRTCICETransport * transport)
|
||||
{
|
||||
return trans->transport && trans->transport->transport == transport;
|
||||
}
|
||||
|
||||
static TransportStream *
|
||||
_find_transport_for_ice_transport (GstWebRTCBin * webrtc,
|
||||
GstWebRTCICETransport * transport)
|
||||
{
|
||||
TransportStream *stream;
|
||||
|
||||
stream = _find_transport (webrtc, transport,
|
||||
(FindTransportFunc) match_stream_for_ice_transport);
|
||||
|
||||
GST_TRACE_OBJECT (webrtc,
|
||||
"Found transport %" GST_PTR_FORMAT " for ice transport %" GST_PTR_FORMAT,
|
||||
stream, transport);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
typedef gboolean (*FindPadFunc) (GstWebRTCBinPad * p1, gconstpointer data);
|
||||
|
||||
static GstWebRTCBinPad *
|
||||
|
@ -1601,13 +1625,6 @@ _update_ice_gathering_state_task (GstWebRTCBin * webrtc, gpointer data)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_ice_gathering_state (GstWebRTCBin * webrtc)
|
||||
{
|
||||
gst_webrtc_bin_enqueue_task (webrtc, _update_ice_gathering_state_task, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static GstStructure *
|
||||
_update_ice_connection_state_task (GstWebRTCBin * webrtc, gpointer data)
|
||||
{
|
||||
|
@ -2116,11 +2133,27 @@ _on_ice_transport_notify_state (GstWebRTCICETransport * transport,
|
|||
_update_peer_connection_state (webrtc);
|
||||
}
|
||||
|
||||
static void
|
||||
_on_local_ice_candidate_cb (GstWebRTCICE * ice, guint session_id,
|
||||
gchar * candidate, GstWebRTCBin * webrtc);
|
||||
|
||||
static void
|
||||
_on_ice_transport_notify_gathering_state (GstWebRTCICETransport * transport,
|
||||
GParamSpec * pspec, GstWebRTCBin * webrtc)
|
||||
{
|
||||
_update_ice_gathering_state (webrtc);
|
||||
GstWebRTCICEGatheringState ice_state;
|
||||
|
||||
g_object_get (transport, "gathering-state", &ice_state, NULL);
|
||||
if (ice_state == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
|
||||
TransportStream *stream =
|
||||
_find_transport_for_ice_transport (webrtc, transport);
|
||||
/* signal end-of-candidates */
|
||||
_on_local_ice_candidate_cb (webrtc->priv->ice, stream->session_id,
|
||||
(char *) "", webrtc);
|
||||
}
|
||||
|
||||
gst_webrtc_bin_enqueue_task (webrtc, _update_ice_gathering_state_task, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5411,6 +5444,24 @@ _add_ice_candidate_to_sdp (GstWebRTCBin * webrtc,
|
|||
gst_sdp_media_add_attribute (media, "candidate", candidate + 10);
|
||||
}
|
||||
|
||||
static void
|
||||
_add_end_of_candidate_to_sdp (GstWebRTCBin * webrtc,
|
||||
GstSDPMessage * sdp, gint mline_index)
|
||||
{
|
||||
GstSDPMedia *media = NULL;
|
||||
|
||||
if (mline_index < sdp->medias->len) {
|
||||
media = &g_array_index (sdp->medias, GstSDPMedia, mline_index);
|
||||
}
|
||||
|
||||
if (media == NULL) {
|
||||
GST_WARNING_OBJECT (webrtc, "Couldn't find mline %d to merge ICE candidate",
|
||||
mline_index);
|
||||
return;
|
||||
}
|
||||
gst_sdp_media_add_attribute (media, "end-of-candidates", "");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_filter_sdp_fields (GQuark field_id, const GValue * value,
|
||||
GstStructure * new_structure)
|
||||
|
@ -6861,7 +6912,7 @@ _on_local_ice_candidate_task (GstWebRTCBin * webrtc)
|
|||
IceCandidateItem *item = &g_array_index (items, IceCandidateItem, i);
|
||||
const gchar *cand = item->candidate;
|
||||
|
||||
if (!g_ascii_strncasecmp (cand, "a=candidate:", 12)) {
|
||||
if (cand && !g_ascii_strncasecmp (cand, "a=candidate:", 12)) {
|
||||
/* stripping away "a=" */
|
||||
cand += 2;
|
||||
}
|
||||
|
@ -6876,12 +6927,24 @@ _on_local_ice_candidate_task (GstWebRTCBin * webrtc)
|
|||
* FIXME: This ICE candidate should be stored somewhere with
|
||||
* the associated mid and also merged back into any subsequent
|
||||
* local descriptions on renegotiation */
|
||||
if (webrtc->current_local_description)
|
||||
_add_ice_candidate_to_sdp (webrtc, webrtc->current_local_description->sdp,
|
||||
item->mlineindex, cand);
|
||||
if (webrtc->pending_local_description)
|
||||
_add_ice_candidate_to_sdp (webrtc, webrtc->pending_local_description->sdp,
|
||||
item->mlineindex, cand);
|
||||
if (webrtc->current_local_description) {
|
||||
if (cand && cand[0] != '\0') {
|
||||
_add_ice_candidate_to_sdp (webrtc,
|
||||
webrtc->current_local_description->sdp, item->mlineindex, cand);
|
||||
} else {
|
||||
_add_end_of_candidate_to_sdp (webrtc,
|
||||
webrtc->current_local_description->sdp, item->mlineindex);
|
||||
}
|
||||
}
|
||||
if (webrtc->pending_local_description) {
|
||||
if (cand && cand[0] != '\0') {
|
||||
_add_ice_candidate_to_sdp (webrtc,
|
||||
webrtc->pending_local_description->sdp, item->mlineindex, cand);
|
||||
} else {
|
||||
_add_end_of_candidate_to_sdp (webrtc,
|
||||
webrtc->pending_local_description->sdp, item->mlineindex);
|
||||
}
|
||||
}
|
||||
|
||||
PC_UNLOCK (webrtc);
|
||||
g_signal_emit (webrtc, gst_webrtc_bin_signals[ON_ICE_CANDIDATE_SIGNAL],
|
||||
|
|
|
@ -845,7 +845,7 @@ test_webrtc_wait_for_ice_gathering_complete (struct test_webrtc *t)
|
|||
g_mutex_lock (&t->lock);
|
||||
g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
|
||||
g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
|
||||
while (ice_state1 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE &&
|
||||
while (ice_state1 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE ||
|
||||
ice_state2 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
|
||||
g_cond_wait (&t->cond, &t->lock);
|
||||
g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
|
||||
|
@ -1211,6 +1211,9 @@ _check_ice_port_restriction (struct test_webrtc *t, GstElement * element,
|
|||
guint port_as_int;
|
||||
guint peer_number;
|
||||
|
||||
if (!candidate || candidate[0] == '\0')
|
||||
return;
|
||||
|
||||
regex =
|
||||
g_regex_new ("candidate:(\\d+) (1) (UDP|TCP) (\\d+) ([0-9.]+|[0-9a-f:]+)"
|
||||
" (\\d+) typ ([a-z]+)", 0, 0, NULL);
|
||||
|
@ -5708,6 +5711,61 @@ GST_START_TEST (test_msid)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
_check_ice_end_of_candidates (struct test_webrtc *t, GstElement * element,
|
||||
guint mlineindex, gchar * candidate, GstElement * other, gpointer user_data)
|
||||
{
|
||||
gint *end_count = user_data;
|
||||
|
||||
if (!candidate || candidate[0] == '\0') {
|
||||
g_atomic_int_inc (end_count);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sdp_media_has_end_of_candidates (struct test_webrtc *t, GstElement * element,
|
||||
GstWebRTCSessionDescription * desc, gpointer user_data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
|
||||
const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
|
||||
|
||||
fail_unless_equals_string (gst_sdp_media_get_attribute_val_n (media,
|
||||
"end-of-candidates", 0), "");
|
||||
|
||||
fail_unless (gst_sdp_media_get_attribute_val_n (media, "end-of-candidates",
|
||||
1) == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
GST_START_TEST (test_ice_end_of_candidates)
|
||||
{
|
||||
struct test_webrtc *t = create_audio_test ();
|
||||
GstWebRTCSessionDescription *local_desc;
|
||||
gint end_candidate_count = 0;
|
||||
|
||||
VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
|
||||
VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
|
||||
|
||||
|
||||
t->on_ice_candidate = _check_ice_end_of_candidates;
|
||||
t->ice_candidate_data = &end_candidate_count;
|
||||
test_validate_sdp (t, &offer, &answer);
|
||||
|
||||
test_webrtc_wait_for_ice_gathering_complete (t);
|
||||
|
||||
fail_unless_equals_int (end_candidate_count, 2);
|
||||
|
||||
g_object_get (t->webrtc1, "current-local-description", &local_desc, NULL);
|
||||
sdp_media_has_end_of_candidates (t, t->webrtc1, local_desc, NULL);
|
||||
gst_webrtc_session_description_free (local_desc);
|
||||
|
||||
test_webrtc_free (t);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
webrtcbin_suite (void)
|
||||
{
|
||||
|
@ -5773,6 +5831,7 @@ webrtcbin_suite (void)
|
|||
tcase_add_test (tc, test_invalid_add_media_in_answer);
|
||||
tcase_add_test (tc, test_add_turn_server);
|
||||
tcase_add_test (tc, test_msid);
|
||||
tcase_add_test (tc, test_ice_end_of_candidates);
|
||||
if (sctpenc && sctpdec) {
|
||||
tcase_add_test (tc, test_data_channel_create);
|
||||
tcase_add_test (tc, test_data_channel_remote_notify);
|
||||
|
|
Loading…
Reference in a new issue