diff options
-rw-r--r-- | subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c | 93 | ||||
-rw-r--r-- | subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c | 61 |
2 files changed, 138 insertions, 16 deletions
diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c index 4e9cd2e7f5..c235b5ac81 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c @@ -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) { @@ -2117,10 +2134,26 @@ _on_ice_transport_notify_state (GstWebRTCICETransport * transport, } 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], diff --git a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c index 617dee57c6..0b09ca0e9f 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c @@ -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); |