summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c93
-rw-r--r--subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c61
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);