3 * Unit tests for webrtcbin
5 * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include <gst/check/gstcheck.h>
30 #include <gst/check/gstharness.h>
31 #include <gst/webrtc/webrtc.h>
32 #include "../../../ext/webrtc/webrtcsdp.h"
33 #include "../../../ext/webrtc/webrtcsdp.c"
34 #include "../../../ext/webrtc/utils.h"
35 #include "../../../ext/webrtc/utils.c"
37 #define OPUS_RTP_CAPS(pt) "application/x-rtp,payload=" G_STRINGIFY(pt) ",encoding-name=OPUS,media=audio,clock-rate=48000,ssrc=(uint)3384078950"
38 #define VP8_RTP_CAPS(pt) "application/x-rtp,payload=" G_STRINGIFY(pt) ",encoding-name=VP8,media=video,clock-rate=90000,ssrc=(uint)3484078950"
40 #define TEST_IS_OFFER_ELEMENT(t, e) ((((t)->offerror == 1 && (e) == (t)->webrtc1) || ((t)->offerror == 2 && (e) == (t)->webrtc2)) ? TRUE : FALSE)
41 #define TEST_GET_OFFEROR(t) (TEST_IS_OFFER_ELEMENT(t, t->webrtc1) ? (t)->webrtc1 : t->webrtc2)
42 #define TEST_GET_ANSWERER(t) (TEST_IS_OFFER_ELEMENT(t, t->webrtc1) ? (t)->webrtc2 : t->webrtc1)
44 #define TEST_SDP_IS_LOCAL(t, e, d) ((TEST_IS_OFFER_ELEMENT (t, e) ^ ((d)->type == GST_WEBRTC_SDP_TYPE_OFFER)) == 0)
49 STATE_NEGOTIATION_NEEDED,
59 /* basic premise of this is that webrtc1 and webrtc2 are attempting to connect
60 * to each other in various configurations */
76 GDestroyNotify data_notify;
78 void (*on_negotiation_needed) (struct test_webrtc * t,
81 gpointer negotiation_data;
82 GDestroyNotify negotiation_notify;
83 void (*on_ice_candidate) (struct test_webrtc * t,
89 gpointer ice_candidate_data;
90 GDestroyNotify ice_candidate_notify;
91 void (*on_offer_created) (struct test_webrtc * t,
95 GstWebRTCSessionDescription *offer_desc;
96 guint offer_set_count;
98 GDestroyNotify offer_notify;
99 void (*on_offer_set) (struct test_webrtc * t,
100 GstElement * element,
101 GstPromise * promise,
103 gpointer offer_set_data;
104 GDestroyNotify offer_set_notify;
105 void (*on_answer_created) (struct test_webrtc * t,
106 GstElement * element,
107 GstPromise * promise,
109 GstWebRTCSessionDescription *answer_desc;
110 guint answer_set_count;
111 gpointer answer_data;
112 GDestroyNotify answer_notify;
113 void (*on_answer_set) (struct test_webrtc * t,
114 GstElement * element,
115 GstPromise * promise,
117 gpointer answer_set_data;
118 GDestroyNotify answer_set_notify;
119 void (*on_data_channel) (struct test_webrtc * t,
120 GstElement * element,
121 GObject *data_channel,
123 gpointer data_channel_data;
124 GDestroyNotify data_channel_notify;
125 void (*on_pad_added) (struct test_webrtc * t,
126 GstElement * element,
129 gpointer pad_added_data;
130 GDestroyNotify pad_added_notify;
131 void (*bus_message) (struct test_webrtc * t,
136 GDestroyNotify bus_notify;
141 test_webrtc_signal_state_unlocked (struct test_webrtc *t, TestState state)
144 g_cond_broadcast (&t->cond);
148 test_webrtc_signal_state (struct test_webrtc *t, TestState state)
150 g_mutex_lock (&t->lock);
151 test_webrtc_signal_state_unlocked (t, state);
152 g_mutex_unlock (&t->lock);
156 _on_answer_set (GstPromise * promise, gpointer user_data)
158 struct test_webrtc *t = user_data;
159 GstElement *answerer = TEST_GET_ANSWERER (t);
161 g_mutex_lock (&t->lock);
162 if (++t->answer_set_count >= 2 && t->on_answer_set) {
163 t->on_answer_set (t, answerer, promise, t->answer_set_data);
165 if (t->state == STATE_ANSWER_CREATED)
166 t->state = STATE_ANSWER_SET;
167 g_cond_broadcast (&t->cond);
168 gst_promise_unref (promise);
169 g_mutex_unlock (&t->lock);
173 _on_answer_received (GstPromise * promise, gpointer user_data)
175 struct test_webrtc *t = user_data;
176 GstElement *offeror = TEST_GET_OFFEROR (t);
177 GstElement *answerer = TEST_GET_ANSWERER (t);
178 const GstStructure *reply;
179 GstWebRTCSessionDescription *answer = NULL;
180 GError *error = NULL;
182 reply = gst_promise_get_reply (promise);
183 if (gst_structure_get (reply, "answer",
184 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &answer, NULL)) {
185 gchar *desc = gst_sdp_message_as_text (answer->sdp);
186 GST_INFO ("Created Answer: %s", desc);
188 } else if (gst_structure_get (reply, "error", G_TYPE_ERROR, &error, NULL)) {
189 GST_INFO ("Creating answer resulted in error: %s", error->message);
191 g_assert_not_reached ();
194 g_mutex_lock (&t->lock);
196 g_assert (t->answer_desc == NULL);
197 t->answer_desc = answer;
199 if (t->on_answer_created) {
200 t->on_answer_created (t, answerer, promise, t->answer_data);
202 gst_promise_unref (promise);
207 if (t->answer_desc) {
208 promise = gst_promise_new_with_change_func (_on_answer_set, t, NULL);
209 g_signal_emit_by_name (answerer, "set-local-description", t->answer_desc,
211 promise = gst_promise_new_with_change_func (_on_answer_set, t, NULL);
212 g_signal_emit_by_name (offeror, "set-remote-description", t->answer_desc,
216 test_webrtc_signal_state_unlocked (t, STATE_ANSWER_CREATED);
217 g_mutex_unlock (&t->lock);
221 g_clear_error (&error);
222 if (t->state < STATE_ERROR)
223 test_webrtc_signal_state_unlocked (t, STATE_ERROR);
224 g_mutex_unlock (&t->lock);
229 _on_offer_set (GstPromise * promise, gpointer user_data)
231 struct test_webrtc *t = user_data;
232 GstElement *offeror = TEST_GET_OFFEROR (t);
234 g_mutex_lock (&t->lock);
235 if (++t->offer_set_count >= 2 && t->on_offer_set) {
236 t->on_offer_set (t, offeror, promise, t->offer_set_data);
238 if (t->state == STATE_OFFER_CREATED)
239 t->state = STATE_OFFER_SET;
240 g_cond_broadcast (&t->cond);
241 gst_promise_unref (promise);
242 g_mutex_unlock (&t->lock);
246 _on_offer_received (GstPromise * promise, gpointer user_data)
248 struct test_webrtc *t = user_data;
249 GstElement *offeror = TEST_GET_OFFEROR (t);
250 GstElement *answerer = TEST_GET_ANSWERER (t);
251 const GstStructure *reply;
252 GstWebRTCSessionDescription *offer = NULL;
253 GError *error = NULL;
255 reply = gst_promise_get_reply (promise);
256 if (gst_structure_get (reply, "offer",
257 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL)) {
258 gchar *desc = gst_sdp_message_as_text (offer->sdp);
259 GST_INFO ("Created offer: %s", desc);
261 } else if (gst_structure_get (reply, "error", G_TYPE_ERROR, &error, NULL)) {
262 GST_INFO ("Creating offer resulted in error: %s", error->message);
264 g_assert_not_reached ();
267 g_mutex_lock (&t->lock);
269 g_assert (t->offer_desc == NULL);
270 t->offer_desc = offer;
272 if (t->on_offer_created) {
273 t->on_offer_created (t, offeror, promise, t->offer_data);
275 gst_promise_unref (promise);
281 promise = gst_promise_new_with_change_func (_on_offer_set, t, NULL);
282 g_signal_emit_by_name (offeror, "set-local-description", t->offer_desc,
284 promise = gst_promise_new_with_change_func (_on_offer_set, t, NULL);
285 g_signal_emit_by_name (answerer, "set-remote-description", t->offer_desc,
288 promise = gst_promise_new_with_change_func (_on_answer_received, t, NULL);
289 g_signal_emit_by_name (answerer, "create-answer", NULL, promise);
292 test_webrtc_signal_state_unlocked (t, STATE_OFFER_CREATED);
293 g_mutex_unlock (&t->lock);
297 g_clear_error (&error);
298 if (t->state < STATE_ERROR)
299 test_webrtc_signal_state_unlocked (t, STATE_ERROR);
300 g_mutex_unlock (&t->lock);
305 _bus_watch (GstBus * bus, GstMessage * msg, struct test_webrtc *t)
307 g_mutex_lock (&t->lock);
308 switch (GST_MESSAGE_TYPE (msg)) {
309 case GST_MESSAGE_STATE_CHANGED:
310 if (GST_ELEMENT (msg->src) == t->webrtc1
311 || GST_ELEMENT (msg->src) == t->webrtc2) {
312 GstState old, new, pending;
314 gst_message_parse_state_changed (msg, &old, &new, &pending);
317 gchar *dump_name = g_strconcat ("%s-state_changed-",
318 GST_OBJECT_NAME (msg->src), gst_element_state_get_name (old), "_",
319 gst_element_state_get_name (new), NULL);
320 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (msg->src),
321 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
326 case GST_MESSAGE_ERROR:{
328 gchar *dbg_info = NULL;
333 g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc1), NULL);
334 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
335 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
338 g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc2), NULL);
339 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
340 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
344 gst_message_parse_error (msg, &err, &dbg_info);
345 GST_WARNING ("ERROR from element %s: %s",
346 GST_OBJECT_NAME (msg->src), err->message);
347 GST_WARNING ("Debugging info: %s", (dbg_info) ? dbg_info : "none");
350 test_webrtc_signal_state_unlocked (t, STATE_ERROR);
353 case GST_MESSAGE_EOS:{
356 dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc1), NULL);
357 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
358 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
360 dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc2), NULL);
361 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
362 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
365 GST_INFO ("EOS received");
366 test_webrtc_signal_state_unlocked (t, STATE_EOS);
374 t->bus_message (t, bus, msg, t->bus_data);
375 g_mutex_unlock (&t->lock);
381 _on_negotiation_needed (GstElement * webrtc, struct test_webrtc *t)
383 g_mutex_lock (&t->lock);
384 if (t->on_negotiation_needed)
385 t->on_negotiation_needed (t, webrtc, t->negotiation_data);
386 if (t->state == STATE_NEW)
387 t->state = STATE_NEGOTIATION_NEEDED;
388 g_cond_broadcast (&t->cond);
389 g_mutex_unlock (&t->lock);
393 _on_ice_candidate (GstElement * webrtc, guint mlineindex, gchar * candidate,
394 struct test_webrtc *t)
398 g_mutex_lock (&t->lock);
399 other = webrtc == t->webrtc1 ? t->webrtc2 : t->webrtc1;
401 if (t->on_ice_candidate)
402 t->on_ice_candidate (t, webrtc, mlineindex, candidate, other,
403 t->ice_candidate_data);
405 g_signal_emit_by_name (other, "add-ice-candidate", mlineindex, candidate);
406 g_mutex_unlock (&t->lock);
410 _on_pad_added (GstElement * webrtc, GstPad * new_pad, struct test_webrtc *t)
412 g_mutex_lock (&t->lock);
414 t->on_pad_added (t, webrtc, new_pad, t->pad_added_data);
415 g_mutex_unlock (&t->lock);
419 _on_data_channel (GstElement * webrtc, GObject * data_channel,
420 struct test_webrtc *t)
422 g_mutex_lock (&t->lock);
423 if (t->on_data_channel)
424 t->on_data_channel (t, webrtc, data_channel, t->data_channel_data);
425 g_mutex_unlock (&t->lock);
429 _pad_added_not_reached (struct test_webrtc *t, GstElement * element,
430 GstPad * pad, gpointer user_data)
432 g_assert_not_reached ();
436 _ice_candidate_not_reached (struct test_webrtc *t, GstElement * element,
437 guint mlineindex, gchar * candidate, GstElement * other, gpointer user_data)
439 g_assert_not_reached ();
443 _negotiation_not_reached (struct test_webrtc *t, GstElement * element,
446 g_assert_not_reached ();
450 _bus_no_errors (struct test_webrtc *t, GstBus * bus, GstMessage * msg,
453 switch (GST_MESSAGE_TYPE (msg)) {
454 case GST_MESSAGE_ERROR:{
455 g_assert_not_reached ();
464 _offer_answer_not_reached (struct test_webrtc *t, GstElement * element,
465 GstPromise * promise, gpointer user_data)
467 g_assert_not_reached ();
471 _on_data_channel_not_reached (struct test_webrtc *t, GstElement * element,
472 GObject * data_channel, gpointer user_data)
474 g_assert_not_reached ();
478 _broadcast (struct test_webrtc *t)
480 g_mutex_lock (&t->lock);
481 g_cond_broadcast (&t->cond);
482 g_mutex_unlock (&t->lock);
486 _unlock_create_thread (GMutex * lock)
488 g_mutex_unlock (lock);
489 return G_SOURCE_REMOVE;
493 _bus_thread (struct test_webrtc *t)
495 g_mutex_lock (&t->lock);
496 t->loop = g_main_loop_new (NULL, FALSE);
497 g_idle_add ((GSourceFunc) _unlock_create_thread, &t->lock);
498 g_cond_broadcast (&t->cond);
500 g_main_loop_run (t->loop);
502 g_mutex_lock (&t->lock);
503 g_main_loop_unref (t->loop);
505 g_cond_broadcast (&t->cond);
506 g_mutex_unlock (&t->lock);
512 element_added_disable_sync (GstBin * bin, GstBin * sub_bin,
513 GstElement * element, gpointer user_data)
515 GObjectClass *class = G_OBJECT_GET_CLASS (element);
516 if (g_object_class_find_property (class, "async"))
517 g_object_set (element, "async", FALSE, NULL);
518 if (g_object_class_find_property (class, "sync"))
519 g_object_set (element, "sync", FALSE, NULL);
522 static struct test_webrtc *
523 test_webrtc_new (void)
525 struct test_webrtc *ret = g_new0 (struct test_webrtc, 1);
527 ret->on_negotiation_needed = _negotiation_not_reached;
528 ret->on_ice_candidate = _ice_candidate_not_reached;
529 ret->on_pad_added = _pad_added_not_reached;
530 ret->on_offer_created = _offer_answer_not_reached;
531 ret->on_answer_created = _offer_answer_not_reached;
532 ret->on_data_channel = _on_data_channel_not_reached;
533 ret->bus_message = _bus_no_errors;
536 g_mutex_init (&ret->lock);
537 g_cond_init (&ret->cond);
539 ret->thread = g_thread_new ("test-webrtc", (GThreadFunc) _bus_thread, ret);
541 g_mutex_lock (&ret->lock);
543 g_cond_wait (&ret->cond, &ret->lock);
544 g_mutex_unlock (&ret->lock);
546 ret->bus1 = gst_bus_new ();
547 ret->bus2 = gst_bus_new ();
548 gst_bus_add_watch (ret->bus1, (GstBusFunc) _bus_watch, ret);
549 gst_bus_add_watch (ret->bus2, (GstBusFunc) _bus_watch, ret);
550 ret->webrtc1 = gst_element_factory_make ("webrtcbin", NULL);
551 ret->webrtc2 = gst_element_factory_make ("webrtcbin", NULL);
552 fail_unless (ret->webrtc1 != NULL && ret->webrtc2 != NULL);
554 gst_element_set_bus (ret->webrtc1, ret->bus1);
555 gst_element_set_bus (ret->webrtc2, ret->bus2);
557 g_signal_connect (ret->webrtc1, "deep-element-added",
558 G_CALLBACK (element_added_disable_sync), NULL);
559 g_signal_connect (ret->webrtc2, "deep-element-added",
560 G_CALLBACK (element_added_disable_sync), NULL);
561 g_signal_connect (ret->webrtc1, "on-negotiation-needed",
562 G_CALLBACK (_on_negotiation_needed), ret);
563 g_signal_connect (ret->webrtc2, "on-negotiation-needed",
564 G_CALLBACK (_on_negotiation_needed), ret);
565 g_signal_connect (ret->webrtc1, "on-ice-candidate",
566 G_CALLBACK (_on_ice_candidate), ret);
567 g_signal_connect (ret->webrtc2, "on-ice-candidate",
568 G_CALLBACK (_on_ice_candidate), ret);
569 g_signal_connect (ret->webrtc1, "on-data-channel",
570 G_CALLBACK (_on_data_channel), ret);
571 g_signal_connect (ret->webrtc2, "on-data-channel",
572 G_CALLBACK (_on_data_channel), ret);
573 g_signal_connect (ret->webrtc1, "pad-added", G_CALLBACK (_on_pad_added), ret);
574 g_signal_connect (ret->webrtc2, "pad-added", G_CALLBACK (_on_pad_added), ret);
575 g_signal_connect_swapped (ret->webrtc1, "notify::ice-gathering-state",
576 G_CALLBACK (_broadcast), ret);
577 g_signal_connect_swapped (ret->webrtc2, "notify::ice-gathering-state",
578 G_CALLBACK (_broadcast), ret);
579 g_signal_connect_swapped (ret->webrtc1, "notify::ice-connection-state",
580 G_CALLBACK (_broadcast), ret);
581 g_signal_connect_swapped (ret->webrtc2, "notify::ice-connection-state",
582 G_CALLBACK (_broadcast), ret);
588 test_webrtc_reset_negotiation (struct test_webrtc *t)
591 gst_webrtc_session_description_free (t->offer_desc);
592 t->offer_desc = NULL;
593 t->offer_set_count = 0;
595 gst_webrtc_session_description_free (t->answer_desc);
596 t->answer_desc = NULL;
597 t->answer_set_count = 0;
599 test_webrtc_signal_state (t, STATE_NEGOTIATION_NEEDED);
603 test_webrtc_free (struct test_webrtc *t)
605 /* Otherwise while one webrtcbin is being destroyed, the other could
606 * generate a signal that calls into the destroyed webrtcbin */
607 g_signal_handlers_disconnect_by_data (t->webrtc1, t);
608 g_signal_handlers_disconnect_by_data (t->webrtc2, t);
610 g_main_loop_quit (t->loop);
611 g_mutex_lock (&t->lock);
613 g_cond_wait (&t->cond, &t->lock);
614 g_mutex_unlock (&t->lock);
616 g_thread_join (t->thread);
618 gst_bus_remove_watch (t->bus1);
619 gst_bus_remove_watch (t->bus2);
621 gst_bus_set_flushing (t->bus1, TRUE);
622 gst_bus_set_flushing (t->bus2, TRUE);
624 gst_object_unref (t->bus1);
625 gst_object_unref (t->bus2);
627 g_list_free_full (t->harnesses, (GDestroyNotify) gst_harness_teardown);
630 t->data_notify (t->user_data);
631 if (t->negotiation_notify)
632 t->negotiation_notify (t->negotiation_data);
633 if (t->ice_candidate_notify)
634 t->ice_candidate_notify (t->ice_candidate_data);
636 t->offer_notify (t->offer_data);
637 if (t->offer_set_notify)
638 t->offer_set_notify (t->offer_set_data);
639 if (t->answer_notify)
640 t->answer_notify (t->answer_data);
641 if (t->answer_set_notify)
642 t->answer_set_notify (t->answer_set_data);
643 if (t->pad_added_notify)
644 t->pad_added_notify (t->pad_added_data);
645 if (t->data_channel_notify)
646 t->data_channel_notify (t->data_channel_data);
648 fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
649 gst_element_set_state (t->webrtc1, GST_STATE_NULL));
650 fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
651 gst_element_set_state (t->webrtc2, GST_STATE_NULL));
653 test_webrtc_reset_negotiation (t);
655 gst_object_unref (t->webrtc1);
656 gst_object_unref (t->webrtc2);
658 g_mutex_clear (&t->lock);
659 g_cond_clear (&t->cond);
665 test_webrtc_create_offer (struct test_webrtc *t)
668 GstElement *offeror = TEST_GET_OFFEROR (t);
670 promise = gst_promise_new_with_change_func (_on_offer_received, t, NULL);
671 g_signal_emit_by_name (offeror, "create-offer", NULL, promise);
675 test_webrtc_wait_for_state_mask (struct test_webrtc *t, TestState state)
677 g_mutex_lock (&t->lock);
678 while (((1 << t->state) & state) == 0) {
679 GST_INFO ("test state 0x%x, current 0x%x", state, (1 << t->state));
680 g_cond_wait (&t->cond, &t->lock);
682 GST_INFO ("have test state 0x%x, current 0x%x", state, 1 << t->state);
683 g_mutex_unlock (&t->lock);
687 test_webrtc_wait_for_answer_error_eos (struct test_webrtc *t)
689 TestState states = 0;
690 states |= (1 << STATE_ANSWER_SET);
691 states |= (1 << STATE_EOS);
692 states |= (1 << STATE_ERROR);
693 test_webrtc_wait_for_state_mask (t, states);
697 test_webrtc_wait_for_ice_gathering_complete (struct test_webrtc *t)
699 GstWebRTCICEGatheringState ice_state1, ice_state2;
700 g_mutex_lock (&t->lock);
701 g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
702 g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
703 while (ice_state1 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE &&
704 ice_state2 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
705 g_cond_wait (&t->cond, &t->lock);
706 g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
707 g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
709 g_mutex_unlock (&t->lock);
714 test_webrtc_wait_for_ice_connection (struct test_webrtc *t,
715 GstWebRTCICEConnectionState states)
717 GstWebRTCICEConnectionState ice_state1, ice_state2, current;
718 g_mutex_lock (&t->lock);
719 g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
720 g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
721 current = (1 << ice_state1) | (1 << ice_state2);
722 while ((current & states) == 0 || (current & ~states)) {
723 g_cond_wait (&t->cond, &t->lock);
724 g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
725 g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
726 current = (1 << ice_state1) | (1 << ice_state2);
728 g_mutex_unlock (&t->lock);
732 _pad_added_fakesink (struct test_webrtc *t, GstElement * element,
733 GstPad * pad, gpointer user_data)
737 if (GST_PAD_DIRECTION (pad) != GST_PAD_SRC)
740 h = gst_harness_new_with_element (element, NULL, "src_%u");
741 gst_harness_add_sink_parse (h, "fakesink async=false sync=false");
743 t->harnesses = g_list_prepend (t->harnesses, h);
747 on_negotiation_needed_hit (struct test_webrtc *t, GstElement * element,
750 guint *flag = (guint *) user_data;
752 *flag |= 1 << ((element == t->webrtc1) ? 1 : 2);
755 typedef void (*ValidateSDPFunc) (struct test_webrtc * t, GstElement * element,
756 GstWebRTCSessionDescription * desc, gpointer user_data);
761 ValidateSDPFunc validate;
763 struct validate_sdp *next;
766 #define VAL_SDP_INIT(name,func,data,next) \
767 struct validate_sdp name = { func, data, next }
770 _check_validate_sdp (struct test_webrtc *t, GstElement * element,
771 GstPromise * promise, gpointer user_data)
773 struct validate_sdp *validate = user_data;
774 GstWebRTCSessionDescription *desc = NULL;
776 if (TEST_IS_OFFER_ELEMENT (t, element))
777 desc = t->offer_desc;
779 desc = t->answer_desc;
782 validate->validate (t, element, desc, validate->user_data);
783 validate = validate->next;
788 test_validate_sdp_full (struct test_webrtc *t, struct validate_sdp *offer,
789 struct validate_sdp *answer, TestState wait_mask,
790 gboolean perform_state_change)
793 t->offer_data = offer;
794 t->on_offer_created = _check_validate_sdp;
796 t->offer_data = NULL;
797 t->on_offer_created = NULL;
800 t->answer_data = answer;
801 t->on_answer_created = _check_validate_sdp;
803 t->answer_data = NULL;
804 t->on_answer_created = NULL;
807 if (perform_state_change) {
808 fail_if (gst_element_set_state (t->webrtc1,
809 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
810 fail_if (gst_element_set_state (t->webrtc2,
811 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
814 test_webrtc_create_offer (t);
816 if (wait_mask == 0) {
817 test_webrtc_wait_for_answer_error_eos (t);
818 fail_unless (t->state == STATE_ANSWER_SET);
820 test_webrtc_wait_for_state_mask (t, wait_mask);
825 test_validate_sdp (struct test_webrtc *t, struct validate_sdp *offer,
826 struct validate_sdp *answer)
828 test_validate_sdp_full (t, offer, answer, 0, TRUE);
832 _count_num_sdp_media (struct test_webrtc *t, GstElement * element,
833 GstWebRTCSessionDescription * desc, gpointer user_data)
835 guint expected = GPOINTER_TO_UINT (user_data);
837 fail_unless_equals_int (gst_sdp_message_medias_len (desc->sdp), expected);
840 GST_START_TEST (test_sdp_no_media)
842 struct test_webrtc *t = test_webrtc_new ();
843 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (0), NULL);
845 /* check that a no stream connection creates 0 media sections */
847 t->on_negotiation_needed = NULL;
848 test_validate_sdp (t, &count, &count);
850 test_webrtc_free (t);
856 on_sdp_media_direction (struct test_webrtc *t, GstElement * element,
857 GstWebRTCSessionDescription * desc, gpointer user_data)
859 gchar **expected_directions = user_data;
862 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
863 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
865 if (g_strcmp0 (gst_sdp_media_get_media (media), "audio") == 0
866 || g_strcmp0 (gst_sdp_media_get_media (media), "video") == 0) {
867 gboolean have_direction = FALSE;
870 for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
871 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
873 if (g_strcmp0 (attr->key, "inactive") == 0) {
874 fail_unless (have_direction == FALSE,
875 "duplicate/multiple directions for media %u", j);
876 have_direction = TRUE;
877 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
878 } else if (g_strcmp0 (attr->key, "sendonly") == 0) {
879 fail_unless (have_direction == FALSE,
880 "duplicate/multiple directions for media %u", j);
881 have_direction = TRUE;
882 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
883 } else if (g_strcmp0 (attr->key, "recvonly") == 0) {
884 fail_unless (have_direction == FALSE,
885 "duplicate/multiple directions for media %u", j);
886 have_direction = TRUE;
887 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
888 } else if (g_strcmp0 (attr->key, "sendrecv") == 0) {
889 fail_unless (have_direction == FALSE,
890 "duplicate/multiple directions for media %u", j);
891 have_direction = TRUE;
892 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
895 fail_unless (have_direction, "no direction attribute in media %u", i);
901 on_sdp_media_no_duplicate_payloads (struct test_webrtc *t, GstElement * element,
902 GstWebRTCSessionDescription * desc, gpointer user_data)
906 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
907 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
909 GArray *media_formats = g_array_new (FALSE, FALSE, sizeof (int));
910 for (j = 0; j < gst_sdp_media_formats_len (media); j++) {
911 int pt = atoi (gst_sdp_media_get_format (media, j));
912 for (k = 0; k < media_formats->len; k++) {
913 int val = g_array_index (media_formats, int, k);
915 fail ("found an unexpected duplicate payload type %u within media %u",
918 g_array_append_val (media_formats, pt);
920 g_array_free (media_formats, TRUE);
925 on_sdp_media_count_formats (struct test_webrtc *t, GstElement * element,
926 GstWebRTCSessionDescription * desc, gpointer user_data)
928 guint *expected_n_media_formats = user_data;
931 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
932 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
933 fail_unless_equals_int (gst_sdp_media_formats_len (media),
934 expected_n_media_formats[i]);
939 on_sdp_media_setup (struct test_webrtc *t, GstElement * element,
940 GstWebRTCSessionDescription * desc, gpointer user_data)
942 gchar **expected_setup = user_data;
945 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
946 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
947 gboolean have_setup = FALSE;
950 for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
951 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
953 if (g_strcmp0 (attr->key, "setup") == 0) {
954 fail_unless (have_setup == FALSE,
955 "duplicate/multiple setup for media %u", j);
957 fail_unless (g_strcmp0 (attr->value, expected_setup[i]) == 0);
960 fail_unless (have_setup, "no setup attribute in media %u", i);
965 add_fake_audio_src_harness (GstHarness * h, gint pt)
967 GstCaps *caps = gst_caps_from_string (OPUS_RTP_CAPS (pt));
968 GstStructure *s = gst_caps_get_structure (caps, 0);
969 gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
970 gst_harness_set_src_caps (h, caps);
971 gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
975 add_fake_video_src_harness (GstHarness * h, gint pt)
977 GstCaps *caps = gst_caps_from_string (VP8_RTP_CAPS (pt));
978 GstStructure *s = gst_caps_get_structure (caps, 0);
979 gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
980 gst_harness_set_src_caps (h, caps);
981 gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
984 static struct test_webrtc *
985 create_audio_test (void)
987 struct test_webrtc *t = test_webrtc_new ();
990 t->on_negotiation_needed = NULL;
991 t->on_ice_candidate = NULL;
992 t->on_pad_added = _pad_added_fakesink;
994 h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
995 add_fake_audio_src_harness (h, 96);
996 t->harnesses = g_list_prepend (t->harnesses, h);
1001 GST_START_TEST (test_audio)
1003 struct test_webrtc *t = create_audio_test ();
1004 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1006 guint media_format_count[] = { 1 };
1007 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1008 media_format_count, &no_duplicate_payloads);
1009 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
1011 const gchar *expected_offer_setup[] = { "actpass", };
1012 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1013 const gchar *expected_answer_setup[] = { "active", };
1014 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
1016 const gchar *expected_offer_direction[] = { "sendrecv", };
1017 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1019 const gchar *expected_answer_direction[] = { "recvonly", };
1020 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
1023 /* check that a single stream connection creates the associated number
1024 * of media sections */
1026 test_validate_sdp (t, &offer, &answer);
1027 test_webrtc_free (t);
1033 _check_ice_port_restriction (struct test_webrtc *t, GstElement * element,
1034 guint mlineindex, gchar * candidate, GstElement * other, gpointer user_data)
1037 GMatchInfo *match_info;
1039 gchar *candidate_port;
1040 gchar *candidate_protocol;
1041 gchar *candidate_typ;
1046 g_regex_new ("candidate:(\\d+) (1) (UDP|TCP) (\\d+) ([0-9.]+|[0-9a-f:]+)"
1047 " (\\d+) typ ([a-z]+)", 0, 0, NULL);
1049 g_regex_match (regex, candidate, 0, &match_info);
1050 fail_unless (g_match_info_get_match_count (match_info) == 8, candidate);
1052 candidate_protocol = g_match_info_fetch (match_info, 2);
1053 candidate_port = g_match_info_fetch (match_info, 6);
1054 candidate_typ = g_match_info_fetch (match_info, 7);
1056 peer_number = t->webrtc1 == element ? 1 : 2;
1058 port_as_int = atoi (candidate_port);
1060 if (!g_strcmp0 (candidate_typ, "host") && port_as_int != 9) {
1061 guint expected_min = peer_number * 10000 + 1000;
1062 guint expected_max = expected_min + 999;
1064 fail_unless (port_as_int >= expected_min);
1065 fail_unless (port_as_int <= expected_max);
1068 g_free (candidate_port);
1069 g_free (candidate_protocol);
1070 g_free (candidate_typ);
1071 g_match_info_free (match_info);
1072 g_regex_unref (regex);
1075 GST_START_TEST (test_ice_port_restriction)
1077 struct test_webrtc *t = create_audio_test ();
1080 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1081 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1084 * Ports are defined as follows "{peer}{protocol}000"
1085 * - peer number: "1" for t->webrtc1, "2" for t->webrtc2
1087 g_object_get (t->webrtc1, "ice-agent", &webrtcice, NULL);
1088 g_object_set (webrtcice, "min-rtp-port", 11000, "max-rtp-port", 11999, NULL);
1089 g_object_unref (webrtcice);
1091 g_object_get (t->webrtc2, "ice-agent", &webrtcice, NULL);
1092 g_object_set (webrtcice, "min-rtp-port", 21000, "max-rtp-port", 21999, NULL);
1093 g_object_unref (webrtcice);
1095 t->on_ice_candidate = _check_ice_port_restriction;
1096 test_validate_sdp (t, &offer, &answer);
1098 test_webrtc_wait_for_ice_gathering_complete (t);
1099 test_webrtc_free (t);
1104 static struct test_webrtc *
1105 create_audio_video_test (void)
1107 struct test_webrtc *t = create_audio_test ();
1110 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
1111 add_fake_video_src_harness (h, 97);
1112 t->harnesses = g_list_prepend (t->harnesses, h);
1117 GST_START_TEST (test_audio_video)
1119 struct test_webrtc *t = create_audio_video_test ();
1120 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1122 guint media_format_count[] = { 1, 1 };
1123 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1124 media_format_count, &no_duplicate_payloads);
1125 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
1127 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
1128 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1129 const gchar *expected_answer_setup[] = { "active", "active" };
1130 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
1132 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
1133 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1135 const gchar *expected_answer_direction[] = { "recvonly", "recvonly" };
1136 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
1139 /* check that a dual stream connection creates the associated number
1140 * of media sections */
1142 test_validate_sdp (t, &offer, &answer);
1143 test_webrtc_free (t);
1148 GST_START_TEST (test_media_direction)
1150 struct test_webrtc *t = create_audio_video_test ();
1151 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1153 guint media_format_count[] = { 1, 1 };
1154 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1155 media_format_count, &no_duplicate_payloads);
1156 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
1158 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
1159 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1160 const gchar *expected_answer_setup[] = { "active", "active" };
1161 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
1164 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
1165 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1167 const gchar *expected_answer_direction[] = { "sendrecv", "recvonly" };
1168 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
1172 /* check the default media directions for transceivers */
1174 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1175 add_fake_audio_src_harness (h, 96);
1176 t->harnesses = g_list_prepend (t->harnesses, h);
1178 test_validate_sdp (t, &offer, &answer);
1179 test_webrtc_free (t);
1185 on_sdp_media_payload_types (struct test_webrtc *t, GstElement * element,
1186 GstWebRTCSessionDescription * desc, gpointer user_data)
1188 const GstSDPMedia *vmedia;
1191 vmedia = gst_sdp_message_get_media (desc->sdp, 1);
1193 for (j = 0; j < gst_sdp_media_attributes_len (vmedia); j++) {
1194 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (vmedia, j);
1196 if (!g_strcmp0 (attr->key, "rtpmap")) {
1197 if (g_str_has_prefix (attr->value, "97")) {
1198 fail_unless_equals_string (attr->value, "97 VP8/90000");
1199 } else if (g_str_has_prefix (attr->value, "96")) {
1200 fail_unless_equals_string (attr->value, "96 red/90000");
1201 } else if (g_str_has_prefix (attr->value, "98")) {
1202 fail_unless_equals_string (attr->value, "98 ulpfec/90000");
1203 } else if (g_str_has_prefix (attr->value, "99")) {
1204 fail_unless_equals_string (attr->value, "99 rtx/90000");
1205 } else if (g_str_has_prefix (attr->value, "100")) {
1206 fail_unless_equals_string (attr->value, "100 rtx/90000");
1212 /* In this test we verify that webrtcbin will pick available payload
1213 * types when it needs to, in that example for RTX and FEC */
1214 GST_START_TEST (test_payload_types)
1216 struct test_webrtc *t = create_audio_video_test ();
1217 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1219 guint media_format_count[] = { 1, 5, };
1220 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1221 media_format_count, &no_duplicate_payloads);
1222 VAL_SDP_INIT (payloads, on_sdp_media_payload_types, NULL, &media_formats);
1223 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2), &payloads);
1224 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
1225 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1226 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
1227 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1229 GstWebRTCRTPTransceiver *trans;
1230 GArray *transceivers;
1232 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1233 fail_unless_equals_int (transceivers->len, 2);
1234 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
1235 g_object_set (trans, "fec-type", GST_WEBRTC_FEC_TYPE_ULP_RED, "do-nack", TRUE,
1237 g_array_unref (transceivers);
1239 /* We don't really care about the answer here */
1240 test_validate_sdp (t, &offer, NULL);
1241 test_webrtc_free (t);
1246 GST_START_TEST (test_no_nice_elements_request_pad)
1248 struct test_webrtc *t = test_webrtc_new ();
1249 GstPluginFeature *nicesrc, *nicesink;
1250 GstRegistry *registry;
1253 /* check that the absence of libnice elements posts an error on the bus
1254 * when requesting a pad */
1256 registry = gst_registry_get ();
1257 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1258 nicesink = gst_registry_lookup_feature (registry, "nicesink");
1261 gst_registry_remove_feature (registry, nicesrc);
1263 gst_registry_remove_feature (registry, nicesink);
1265 t->bus_message = NULL;
1267 pad = gst_element_get_request_pad (t->webrtc1, "sink_0");
1268 fail_unless (pad == NULL);
1270 test_webrtc_wait_for_answer_error_eos (t);
1271 fail_unless_equals_int (STATE_ERROR, t->state);
1272 test_webrtc_free (t);
1275 gst_registry_add_feature (registry, nicesrc);
1277 gst_registry_add_feature (registry, nicesink);
1282 GST_START_TEST (test_no_nice_elements_state_change)
1284 struct test_webrtc *t = test_webrtc_new ();
1285 GstPluginFeature *nicesrc, *nicesink;
1286 GstRegistry *registry;
1288 /* check that the absence of libnice elements posts an error on the bus */
1290 registry = gst_registry_get ();
1291 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1292 nicesink = gst_registry_lookup_feature (registry, "nicesink");
1295 gst_registry_remove_feature (registry, nicesrc);
1297 gst_registry_remove_feature (registry, nicesink);
1299 t->bus_message = NULL;
1300 gst_element_set_state (t->webrtc1, GST_STATE_READY);
1302 test_webrtc_wait_for_answer_error_eos (t);
1303 fail_unless_equals_int (STATE_ERROR, t->state);
1304 test_webrtc_free (t);
1307 gst_registry_add_feature (registry, nicesrc);
1309 gst_registry_add_feature (registry, nicesink);
1315 validate_rtc_stats (const GstStructure * s)
1317 GstWebRTCStatsType type = 0;
1321 fail_unless (gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type,
1323 fail_unless (gst_structure_get (s, "id", G_TYPE_STRING, &id, NULL));
1324 fail_unless (gst_structure_get (s, "timestamp", G_TYPE_DOUBLE, &ts, NULL));
1325 fail_unless (type != 0);
1326 fail_unless (ts != 0.);
1327 fail_unless (id != NULL);
1333 validate_codec_stats (const GstStructure * s)
1335 guint pt = 0, clock_rate = 0;
1337 fail_unless (gst_structure_get (s, "payload-type", G_TYPE_UINT, &pt, NULL));
1338 fail_unless (gst_structure_get (s, "clock-rate", G_TYPE_UINT, &clock_rate,
1340 fail_unless (pt >= 0 && pt <= 127);
1341 fail_unless (clock_rate >= 0);
1345 validate_rtc_stream_stats (const GstStructure * s, const GstStructure * stats)
1347 gchar *codec_id, *transport_id;
1348 GstStructure *codec, *transport;
1350 fail_unless (gst_structure_get (s, "codec-id", G_TYPE_STRING, &codec_id,
1352 fail_unless (gst_structure_get (s, "transport-id", G_TYPE_STRING,
1353 &transport_id, NULL));
1355 fail_unless (gst_structure_get (stats, codec_id, GST_TYPE_STRUCTURE, &codec,
1357 fail_unless (gst_structure_get (stats, transport_id, GST_TYPE_STRUCTURE,
1360 fail_unless (codec != NULL);
1361 fail_unless (transport != NULL);
1363 gst_structure_free (transport);
1364 gst_structure_free (codec);
1367 g_free (transport_id);
1371 validate_inbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1373 guint ssrc, fir, pli, nack;
1375 guint64 packets_received, bytes_received;
1378 GstStructure *remote;
1380 validate_rtc_stream_stats (s, stats);
1382 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1383 fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1384 fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1385 fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1386 fail_unless (gst_structure_get (s, "packets-received", G_TYPE_UINT64,
1387 &packets_received, NULL));
1388 fail_unless (gst_structure_get (s, "bytes-received", G_TYPE_UINT64,
1389 &bytes_received, NULL));
1390 fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1391 fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1393 fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1395 fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1397 fail_unless (remote != NULL);
1399 gst_structure_free (remote);
1404 validate_remote_inbound_rtp_stats (const GstStructure * s,
1405 const GstStructure * stats)
1411 GstStructure *local;
1413 validate_rtc_stream_stats (s, stats);
1415 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1416 fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1417 fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1419 fail_unless (gst_structure_get (s, "round-trip-time", G_TYPE_DOUBLE, &rtt,
1421 fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1423 fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1425 fail_unless (local != NULL);
1427 gst_structure_free (local);
1432 validate_outbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1434 guint ssrc, fir, pli, nack;
1435 guint64 packets_sent, bytes_sent;
1437 GstStructure *remote;
1439 validate_rtc_stream_stats (s, stats);
1441 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1442 fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1443 fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1444 fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1445 fail_unless (gst_structure_get (s, "packets-sent", G_TYPE_UINT64,
1446 &packets_sent, NULL));
1447 fail_unless (gst_structure_get (s, "bytes-sent", G_TYPE_UINT64, &bytes_sent,
1449 fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1451 fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1453 fail_unless (remote != NULL);
1455 gst_structure_free (remote);
1460 validate_remote_outbound_rtp_stats (const GstStructure * s,
1461 const GstStructure * stats)
1465 GstStructure *local;
1467 validate_rtc_stream_stats (s, stats);
1469 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1470 fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1472 fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1474 fail_unless (local != NULL);
1476 gst_structure_free (local);
1481 validate_stats_foreach (GQuark field_id, const GValue * value,
1482 const GstStructure * stats)
1484 const gchar *field = g_quark_to_string (field_id);
1485 GstWebRTCStatsType type;
1486 const GstStructure *s;
1488 fail_unless (GST_VALUE_HOLDS_STRUCTURE (value));
1490 s = gst_value_get_structure (value);
1492 GST_INFO ("validating field %s %" GST_PTR_FORMAT, field, s);
1494 validate_rtc_stats (s);
1495 gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type, NULL);
1496 if (type == GST_WEBRTC_STATS_CODEC) {
1497 validate_codec_stats (s);
1498 } else if (type == GST_WEBRTC_STATS_INBOUND_RTP) {
1499 validate_inbound_rtp_stats (s, stats);
1500 } else if (type == GST_WEBRTC_STATS_OUTBOUND_RTP) {
1501 validate_outbound_rtp_stats (s, stats);
1502 } else if (type == GST_WEBRTC_STATS_REMOTE_INBOUND_RTP) {
1503 validate_remote_inbound_rtp_stats (s, stats);
1504 } else if (type == GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP) {
1505 validate_remote_outbound_rtp_stats (s, stats);
1506 } else if (type == GST_WEBRTC_STATS_CSRC) {
1507 } else if (type == GST_WEBRTC_STATS_PEER_CONNECTION) {
1508 } else if (type == GST_WEBRTC_STATS_DATA_CHANNEL) {
1509 } else if (type == GST_WEBRTC_STATS_STREAM) {
1510 } else if (type == GST_WEBRTC_STATS_TRANSPORT) {
1511 } else if (type == GST_WEBRTC_STATS_CANDIDATE_PAIR) {
1512 } else if (type == GST_WEBRTC_STATS_LOCAL_CANDIDATE) {
1513 } else if (type == GST_WEBRTC_STATS_REMOTE_CANDIDATE) {
1514 } else if (type == GST_WEBRTC_STATS_CERTIFICATE) {
1516 g_assert_not_reached ();
1523 validate_stats (const GstStructure * stats)
1525 gst_structure_foreach (stats,
1526 (GstStructureForeachFunc) validate_stats_foreach, (gpointer) stats);
1530 _on_stats (GstPromise * promise, gpointer user_data)
1532 struct test_webrtc *t = user_data;
1533 const GstStructure *reply = gst_promise_get_reply (promise);
1536 validate_stats (reply);
1537 i = GPOINTER_TO_INT (t->user_data);
1539 t->user_data = GINT_TO_POINTER (i);
1541 test_webrtc_signal_state (t, STATE_CUSTOM);
1543 gst_promise_unref (promise);
1546 GST_START_TEST (test_session_stats)
1548 struct test_webrtc *t = test_webrtc_new ();
1551 /* test that the stats generated without any streams are sane */
1552 t->on_negotiation_needed = NULL;
1553 test_validate_sdp (t, NULL, NULL);
1555 p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1556 g_signal_emit_by_name (t->webrtc1, "get-stats", NULL, p);
1557 p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1558 g_signal_emit_by_name (t->webrtc2, "get-stats", NULL, p);
1560 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1562 test_webrtc_free (t);
1567 GST_START_TEST (test_add_transceiver)
1569 struct test_webrtc *t = test_webrtc_new ();
1570 GstWebRTCRTPTransceiverDirection direction;
1571 GstWebRTCRTPTransceiver *trans;
1573 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
1574 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, NULL,
1576 fail_unless (trans != NULL);
1577 fail_unless_equals_int (direction, trans->direction);
1579 gst_object_unref (trans);
1581 test_webrtc_free (t);
1586 GST_START_TEST (test_get_transceivers)
1588 struct test_webrtc *t = create_audio_test ();
1589 GstWebRTCRTPTransceiver *trans;
1590 GArray *transceivers;
1592 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1593 fail_unless (transceivers != NULL);
1594 fail_unless_equals_int (1, transceivers->len);
1596 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
1597 fail_unless (trans != NULL);
1599 g_array_unref (transceivers);
1601 test_webrtc_free (t);
1606 GST_START_TEST (test_add_recvonly_transceiver)
1608 struct test_webrtc *t = test_webrtc_new ();
1609 GstWebRTCRTPTransceiverDirection direction;
1610 GstWebRTCRTPTransceiver *trans;
1611 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1613 guint media_format_count[] = { 1, 1, };
1614 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1615 media_format_count, &no_duplicate_payloads);
1616 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
1618 const gchar *expected_offer_setup[] = { "actpass", };
1619 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1620 const gchar *expected_answer_setup[] = { "active", };
1621 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
1623 const gchar *expected_offer_direction[] = { "recvonly", };
1624 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1626 const gchar *expected_answer_direction[] = { "sendonly", };
1627 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
1632 /* add a transceiver that will only receive an opus stream and check that
1633 * the created offer is marked as recvonly */
1634 t->on_negotiation_needed = NULL;
1635 t->on_ice_candidate = NULL;
1636 t->on_pad_added = _pad_added_fakesink;
1638 /* setup recvonly transceiver */
1639 caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1640 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1641 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1643 gst_caps_unref (caps);
1644 fail_unless (trans != NULL);
1645 gst_object_unref (trans);
1647 /* setup sendonly peer */
1648 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1649 add_fake_audio_src_harness (h, 96);
1650 t->harnesses = g_list_prepend (t->harnesses, h);
1651 test_validate_sdp (t, &offer, &answer);
1653 test_webrtc_free (t);
1658 GST_START_TEST (test_recvonly_sendonly)
1660 struct test_webrtc *t = test_webrtc_new ();
1661 GstWebRTCRTPTransceiverDirection direction;
1662 GstWebRTCRTPTransceiver *trans;
1663 VAL_SDP_INIT (no_duplicate_payloads, on_sdp_media_no_duplicate_payloads,
1665 guint media_format_count[] = { 1, 1, };
1666 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
1667 media_format_count, &no_duplicate_payloads);
1668 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
1670 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
1671 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup, &count);
1672 const gchar *expected_answer_setup[] = { "active", "active" };
1673 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
1675 const gchar *expected_offer_direction[] = { "recvonly", "sendonly" };
1676 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
1678 const gchar *expected_answer_direction[] = { "sendonly", "recvonly" };
1679 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
1683 GArray *transceivers;
1685 /* add a transceiver that will only receive an opus stream and check that
1686 * the created offer is marked as recvonly */
1687 t->on_negotiation_needed = NULL;
1688 t->on_ice_candidate = NULL;
1689 t->on_pad_added = _pad_added_fakesink;
1691 /* setup recvonly transceiver */
1692 caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1693 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1694 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1696 gst_caps_unref (caps);
1697 fail_unless (trans != NULL);
1698 gst_object_unref (trans);
1700 /* setup sendonly stream */
1701 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
1702 add_fake_audio_src_harness (h, 96);
1703 t->harnesses = g_list_prepend (t->harnesses, h);
1704 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1705 fail_unless (transceivers != NULL);
1706 fail_unless_equals_int (transceivers->len, 2);
1707 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
1708 trans->direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
1710 g_array_unref (transceivers);
1712 /* setup sendonly peer */
1713 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1714 add_fake_audio_src_harness (h, 96);
1715 t->harnesses = g_list_prepend (t->harnesses, h);
1717 test_validate_sdp (t, &offer, &answer);
1719 test_webrtc_free (t);
1725 on_sdp_has_datachannel (struct test_webrtc *t, GstElement * element,
1726 GstWebRTCSessionDescription * desc, gpointer user_data)
1728 gboolean have_data_channel = FALSE;
1731 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
1732 if (_message_media_is_datachannel (desc->sdp, i)) {
1733 /* there should only be one data channel m= section */
1734 fail_unless_equals_int (FALSE, have_data_channel);
1735 have_data_channel = TRUE;
1739 fail_unless_equals_int (TRUE, have_data_channel);
1743 on_channel_error_not_reached (GObject * channel, GError * error,
1746 g_assert_not_reached ();
1749 GST_START_TEST (test_data_channel_create)
1751 struct test_webrtc *t = test_webrtc_new ();
1752 GObject *channel = NULL;
1753 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1754 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
1757 t->on_negotiation_needed = NULL;
1758 t->on_ice_candidate = NULL;
1760 fail_if (gst_element_set_state (t->webrtc1,
1761 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1762 fail_if (gst_element_set_state (t->webrtc2,
1763 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1765 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1767 g_assert_nonnull (channel);
1768 g_object_get (channel, "label", &label, NULL);
1769 g_assert_cmpstr (label, ==, "label");
1770 g_signal_connect (channel, "on-error",
1771 G_CALLBACK (on_channel_error_not_reached), NULL);
1773 test_validate_sdp (t, &offer, &offer);
1775 g_object_unref (channel);
1777 test_webrtc_free (t);
1783 have_data_channel (struct test_webrtc *t, GstElement * element,
1784 GObject * our, gpointer user_data)
1786 GObject *other = user_data;
1787 gchar *our_label, *other_label;
1789 g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
1792 g_object_get (our, "label", &our_label, NULL);
1793 g_object_get (other, "label", &other_label, NULL);
1795 g_assert_cmpstr (our_label, ==, other_label);
1798 g_free (other_label);
1800 test_webrtc_signal_state_unlocked (t, STATE_CUSTOM);
1803 GST_START_TEST (test_data_channel_remote_notify)
1805 struct test_webrtc *t = test_webrtc_new ();
1806 GObject *channel = NULL;
1807 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1808 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
1810 t->on_negotiation_needed = NULL;
1811 t->on_ice_candidate = NULL;
1812 t->on_data_channel = have_data_channel;
1814 fail_if (gst_element_set_state (t->webrtc1,
1815 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1816 fail_if (gst_element_set_state (t->webrtc2,
1817 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1819 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1821 g_assert_nonnull (channel);
1822 t->data_channel_data = channel;
1823 g_signal_connect (channel, "on-error",
1824 G_CALLBACK (on_channel_error_not_reached), NULL);
1826 fail_if (gst_element_set_state (t->webrtc1,
1827 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1828 fail_if (gst_element_set_state (t->webrtc2,
1829 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1831 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
1833 g_object_unref (channel);
1834 test_webrtc_free (t);
1839 static const gchar *test_string = "GStreamer WebRTC is awesome!";
1842 on_message_string (GObject * channel, const gchar * str, struct test_webrtc *t)
1844 GstWebRTCDataChannelState state;
1847 g_object_get (channel, "ready-state", &state, NULL);
1848 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1850 expected = g_object_steal_data (channel, "expected");
1851 g_assert_cmpstr (expected, ==, str);
1854 test_webrtc_signal_state (t, STATE_CUSTOM);
1858 have_data_channel_transfer_string (struct test_webrtc *t, GstElement * element,
1859 GObject * our, gpointer user_data)
1861 GObject *other = user_data;
1862 GstWebRTCDataChannelState state;
1864 g_object_get (our, "ready-state", &state, NULL);
1865 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1867 g_object_set_data_full (our, "expected", g_strdup (test_string), g_free);
1868 g_signal_connect (our, "on-message-string", G_CALLBACK (on_message_string),
1871 g_signal_connect (other, "on-error",
1872 G_CALLBACK (on_channel_error_not_reached), NULL);
1873 g_signal_emit_by_name (other, "send-string", test_string);
1876 GST_START_TEST (test_data_channel_transfer_string)
1878 struct test_webrtc *t = test_webrtc_new ();
1879 GObject *channel = NULL;
1880 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1881 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
1883 t->on_negotiation_needed = NULL;
1884 t->on_ice_candidate = NULL;
1885 t->on_data_channel = have_data_channel_transfer_string;
1887 fail_if (gst_element_set_state (t->webrtc1,
1888 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1889 fail_if (gst_element_set_state (t->webrtc2,
1890 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1892 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1894 g_assert_nonnull (channel);
1895 t->data_channel_data = channel;
1896 g_signal_connect (channel, "on-error",
1897 G_CALLBACK (on_channel_error_not_reached), NULL);
1899 fail_if (gst_element_set_state (t->webrtc1,
1900 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1901 fail_if (gst_element_set_state (t->webrtc2,
1902 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1904 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
1906 g_object_unref (channel);
1907 test_webrtc_free (t);
1912 #define g_assert_cmpbytes(b1, b2) \
1915 const guint8 *d1 = g_bytes_get_data (b1, &l1); \
1916 const guint8 *d2 = g_bytes_get_data (b2, &l2); \
1917 g_assert_cmpmem (d1, l1, d2, l2); \
1921 on_message_data (GObject * channel, GBytes * data, struct test_webrtc *t)
1923 GstWebRTCDataChannelState state;
1926 g_object_get (channel, "ready-state", &state, NULL);
1927 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1929 expected = g_object_steal_data (channel, "expected");
1930 g_assert_cmpbytes (data, expected);
1931 g_bytes_unref (expected);
1933 test_webrtc_signal_state (t, STATE_CUSTOM);
1937 have_data_channel_transfer_data (struct test_webrtc *t, GstElement * element,
1938 GObject * our, gpointer user_data)
1940 GObject *other = user_data;
1941 GBytes *data = g_bytes_new_static (test_string, strlen (test_string));
1942 GstWebRTCDataChannelState state;
1944 g_object_get (our, "ready-state", &state, NULL);
1945 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1947 g_object_set_data_full (our, "expected", g_bytes_ref (data),
1948 (GDestroyNotify) g_bytes_unref);
1949 g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
1951 g_signal_connect (other, "on-error",
1952 G_CALLBACK (on_channel_error_not_reached), NULL);
1953 g_signal_emit_by_name (other, "send-data", data);
1954 g_bytes_unref (data);
1957 GST_START_TEST (test_data_channel_transfer_data)
1959 struct test_webrtc *t = test_webrtc_new ();
1960 GObject *channel = NULL;
1961 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
1962 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
1964 t->on_negotiation_needed = NULL;
1965 t->on_ice_candidate = NULL;
1966 t->on_data_channel = have_data_channel_transfer_data;
1968 fail_if (gst_element_set_state (t->webrtc1,
1969 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1970 fail_if (gst_element_set_state (t->webrtc2,
1971 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1973 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1975 g_assert_nonnull (channel);
1976 t->data_channel_data = channel;
1977 g_signal_connect (channel, "on-error",
1978 G_CALLBACK (on_channel_error_not_reached), NULL);
1980 fail_if (gst_element_set_state (t->webrtc1,
1981 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1982 fail_if (gst_element_set_state (t->webrtc2,
1983 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1985 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
1987 g_object_unref (channel);
1988 test_webrtc_free (t);
1994 have_data_channel_create_data_channel (struct test_webrtc *t,
1995 GstElement * element, GObject * our, gpointer user_data)
1999 t->on_data_channel = have_data_channel_transfer_string;
2001 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2003 g_assert_nonnull (another);
2004 t->data_channel_data = another;
2005 t->data_channel_notify = (GDestroyNotify) g_object_unref;
2006 g_signal_connect (another, "on-error",
2007 G_CALLBACK (on_channel_error_not_reached), NULL);
2010 GST_START_TEST (test_data_channel_create_after_negotiate)
2012 struct test_webrtc *t = test_webrtc_new ();
2013 GObject *channel = NULL;
2014 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
2015 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
2017 t->on_negotiation_needed = NULL;
2018 t->on_ice_candidate = NULL;
2019 t->on_data_channel = have_data_channel_create_data_channel;
2021 fail_if (gst_element_set_state (t->webrtc1,
2022 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2023 fail_if (gst_element_set_state (t->webrtc2,
2024 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2026 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "prev-label", NULL,
2028 g_assert_nonnull (channel);
2029 t->data_channel_data = channel;
2030 g_signal_connect (channel, "on-error",
2031 G_CALLBACK (on_channel_error_not_reached), NULL);
2033 fail_if (gst_element_set_state (t->webrtc1,
2034 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2035 fail_if (gst_element_set_state (t->webrtc2,
2036 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2038 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
2040 g_object_unref (channel);
2041 test_webrtc_free (t);
2047 on_buffered_amount_low_emitted (GObject * channel, struct test_webrtc *t)
2049 test_webrtc_signal_state (t, STATE_CUSTOM);
2053 have_data_channel_check_low_threshold_emitted (struct test_webrtc *t,
2054 GstElement * element, GObject * our, gpointer user_data)
2056 g_signal_connect (our, "on-buffered-amount-low",
2057 G_CALLBACK (on_buffered_amount_low_emitted), t);
2058 g_object_set (our, "buffered-amount-low-threshold", 1, NULL);
2060 g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
2062 g_signal_emit_by_name (our, "send-string", "A");
2065 GST_START_TEST (test_data_channel_low_threshold)
2067 struct test_webrtc *t = test_webrtc_new ();
2068 GObject *channel = NULL;
2069 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
2070 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
2072 t->on_negotiation_needed = NULL;
2073 t->on_ice_candidate = NULL;
2074 t->on_data_channel = have_data_channel_check_low_threshold_emitted;
2076 fail_if (gst_element_set_state (t->webrtc1,
2077 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2078 fail_if (gst_element_set_state (t->webrtc2,
2079 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2081 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2083 g_assert_nonnull (channel);
2084 t->data_channel_data = channel;
2085 g_signal_connect (channel, "on-error",
2086 G_CALLBACK (on_channel_error_not_reached), NULL);
2088 fail_if (gst_element_set_state (t->webrtc1,
2089 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2090 fail_if (gst_element_set_state (t->webrtc2,
2091 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2093 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
2095 g_object_unref (channel);
2096 test_webrtc_free (t);
2102 on_channel_error (GObject * channel, GError * error, struct test_webrtc *t)
2104 g_assert_nonnull (error);
2106 test_webrtc_signal_state (t, STATE_CUSTOM);
2110 have_data_channel_transfer_large_data (struct test_webrtc *t,
2111 GstElement * element, GObject * our, gpointer user_data)
2113 GObject *other = user_data;
2114 const gsize size = 1024 * 1024;
2115 guint8 *random_data = g_new (guint8, size);
2119 for (i = 0; i < size; i++)
2120 random_data[i] = (guint8) (i & 0xff);
2122 data = g_bytes_new_with_free_func (random_data, size,
2123 (GDestroyNotify) g_free, random_data);
2125 g_object_set_data_full (our, "expected", g_bytes_ref (data),
2126 (GDestroyNotify) g_bytes_unref);
2127 g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
2129 g_signal_connect (other, "on-error", G_CALLBACK (on_channel_error), t);
2130 g_signal_emit_by_name (other, "send-data", data);
2131 g_bytes_unref (data);
2134 GST_START_TEST (test_data_channel_max_message_size)
2136 struct test_webrtc *t = test_webrtc_new ();
2137 GObject *channel = NULL;
2138 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
2139 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
2141 t->on_negotiation_needed = NULL;
2142 t->on_ice_candidate = NULL;
2143 t->on_data_channel = have_data_channel_transfer_large_data;
2145 fail_if (gst_element_set_state (t->webrtc1,
2146 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2147 fail_if (gst_element_set_state (t->webrtc2,
2148 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2150 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2152 g_assert_nonnull (channel);
2153 t->data_channel_data = channel;
2155 fail_if (gst_element_set_state (t->webrtc1,
2156 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2157 fail_if (gst_element_set_state (t->webrtc2,
2158 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2160 test_validate_sdp_full (t, &offer, &offer, 1 << STATE_CUSTOM, FALSE);
2162 g_object_unref (channel);
2163 test_webrtc_free (t);
2169 _on_ready_state_notify (GObject * channel, GParamSpec * pspec,
2170 struct test_webrtc *t)
2172 gint *n_ready = t->data_channel_data;
2173 GstWebRTCDataChannelState ready_state;
2175 g_object_get (channel, "ready-state", &ready_state, NULL);
2177 if (ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
2178 if (g_atomic_int_add (n_ready, 1) >= 1) {
2179 test_webrtc_signal_state (t, STATE_CUSTOM);
2184 GST_START_TEST (test_data_channel_pre_negotiated)
2186 struct test_webrtc *t = test_webrtc_new ();
2187 GObject *channel1 = NULL, *channel2 = NULL;
2188 VAL_SDP_INIT (media_count, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
2189 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, &media_count);
2193 t->on_negotiation_needed = NULL;
2194 t->on_ice_candidate = NULL;
2196 fail_if (gst_element_set_state (t->webrtc1,
2197 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2198 fail_if (gst_element_set_state (t->webrtc2,
2199 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2201 s = gst_structure_new ("application/data-channel", "negotiated",
2202 G_TYPE_BOOLEAN, TRUE, "id", G_TYPE_INT, 1, NULL);
2204 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", s,
2206 g_assert_nonnull (channel1);
2207 g_signal_emit_by_name (t->webrtc2, "create-data-channel", "label", s,
2209 g_assert_nonnull (channel2);
2211 fail_if (gst_element_set_state (t->webrtc1,
2212 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2213 fail_if (gst_element_set_state (t->webrtc2,
2214 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2216 test_validate_sdp_full (t, &offer, &offer, 0, FALSE);
2218 t->data_channel_data = &n_ready;
2220 g_signal_connect (channel1, "notify::ready-state",
2221 G_CALLBACK (_on_ready_state_notify), t);
2222 g_signal_connect (channel2, "notify::ready-state",
2223 G_CALLBACK (_on_ready_state_notify), t);
2225 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2226 test_webrtc_signal_state (t, STATE_NEW);
2228 have_data_channel_transfer_string (t, t->webrtc1, channel1, channel2);
2230 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2232 g_object_unref (channel1);
2233 g_object_unref (channel2);
2234 gst_structure_free (s);
2235 test_webrtc_free (t);
2241 _count_non_rejected_media (struct test_webrtc *t, GstElement * element,
2242 GstWebRTCSessionDescription * sd, gpointer user_data)
2244 guint expected = GPOINTER_TO_UINT (user_data);
2245 guint non_rejected_media;
2248 non_rejected_media = 0;
2250 for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
2251 const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
2253 if (gst_sdp_media_get_port (media) != 0)
2254 non_rejected_media += 1;
2257 fail_unless_equals_int (non_rejected_media, expected);
2261 _check_bundle_tag (struct test_webrtc *t, GstElement * element,
2262 GstWebRTCSessionDescription * sd, gpointer user_data)
2264 gchar **bundled = NULL;
2265 GStrv expected = user_data;
2268 fail_unless (_parse_bundle (sd->sdp, &bundled, NULL));
2271 fail_unless_equals_int (g_strv_length (expected), 0);
2273 fail_unless_equals_int (g_strv_length (bundled), g_strv_length (expected));
2276 for (i = 0; i < g_strv_length (expected); i++) {
2277 fail_unless (g_strv_contains ((const gchar **) bundled, expected[i]));
2280 g_strfreev (bundled);
2284 _check_bundle_only_media (struct test_webrtc *t, GstElement * element,
2285 GstWebRTCSessionDescription * sd, gpointer user_data)
2287 gchar **expected_bundle_only = user_data;
2290 for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
2291 const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
2292 const gchar *mid = gst_sdp_media_get_attribute_val (media, "mid");
2294 if (g_strv_contains ((const gchar **) expected_bundle_only, mid))
2295 fail_unless (_media_has_attribute_key (media, "bundle-only"));
2299 GST_START_TEST (test_bundle_audio_video_max_bundle_max_bundle)
2301 struct test_webrtc *t = create_audio_video_test ();
2302 const gchar *bundle[] = { "audio0", "video1", NULL };
2303 const gchar *offer_bundle_only[] = { "video1", NULL };
2304 const gchar *answer_bundle_only[] = { NULL };
2306 guint media_format_count[] = { 1, 1, };
2307 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2308 media_format_count, NULL);
2309 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2311 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2312 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &payloads);
2313 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
2314 GUINT_TO_POINTER (1), &bundle_tag);
2315 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
2316 GUINT_TO_POINTER (2), &bundle_tag);
2317 VAL_SDP_INIT (offer_bundle, _check_bundle_only_media, &offer_bundle_only,
2319 VAL_SDP_INIT (answer_bundle, _check_bundle_only_media, &answer_bundle_only,
2320 &answer_non_reject);
2321 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2322 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2324 const gchar *expected_answer_setup[] = { "active", "active" };
2325 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2327 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
2328 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2330 const gchar *expected_answer_direction[] = { "recvonly", "recvonly" };
2331 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2334 /* We set a max-bundle policy on the offering webrtcbin,
2335 * this means that all the offered medias should be part
2336 * of the group:BUNDLE attribute, and they should be marked
2339 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2341 /* We also set a max-bundle policy on the answering webrtcbin,
2342 * this means that all the offered medias should be part
2343 * of the group:BUNDLE attribute, but need not be marked
2346 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2349 test_validate_sdp (t, &offer, &answer);
2351 test_webrtc_free (t);
2356 GST_START_TEST (test_bundle_audio_video_max_compat_max_bundle)
2358 struct test_webrtc *t = create_audio_video_test ();
2359 const gchar *bundle[] = { "audio0", "video1", NULL };
2360 const gchar *bundle_only[] = { NULL };
2362 guint media_format_count[] = { 1, 1, };
2363 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2364 media_format_count, NULL);
2365 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2367 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &count);
2368 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
2369 GUINT_TO_POINTER (2), &bundle_tag);
2370 VAL_SDP_INIT (bundle_sdp, _check_bundle_only_media, &bundle_only,
2372 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2373 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2375 const gchar *expected_answer_setup[] = { "active", "active" };
2376 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2378 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
2379 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2381 const gchar *expected_answer_direction[] = { "recvonly", "recvonly" };
2382 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2385 /* We set a max-compat policy on the offering webrtcbin,
2386 * this means that all the offered medias should be part
2387 * of the group:BUNDLE attribute, and they should *not* be marked
2390 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2392 /* We set a max-bundle policy on the answering webrtcbin,
2393 * this means that all the offered medias should be part
2394 * of the group:BUNDLE attribute, but need not be marked
2397 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2400 test_validate_sdp (t, &offer, &answer);
2402 test_webrtc_free (t);
2407 GST_START_TEST (test_bundle_audio_video_max_bundle_none)
2409 struct test_webrtc *t = create_audio_video_test ();
2410 const gchar *offer_mid[] = { "audio0", "video1", NULL };
2411 const gchar *offer_bundle_only[] = { "video1", NULL };
2412 const gchar *answer_mid[] = { NULL };
2413 const gchar *answer_bundle_only[] = { NULL };
2415 guint media_format_count[] = { 1, 1, };
2416 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2417 media_format_count, NULL);
2418 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2420 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2421 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
2422 GUINT_TO_POINTER (1), &payloads);
2423 VAL_SDP_INIT (offer_bundle_tag, _check_bundle_tag, offer_mid,
2425 VAL_SDP_INIT (answer_bundle_tag, _check_bundle_tag, answer_mid,
2427 VAL_SDP_INIT (offer_bundle, _check_bundle_only_media, &offer_bundle_only,
2429 VAL_SDP_INIT (answer_bundle, _check_bundle_only_media, &answer_bundle_only,
2430 &answer_bundle_tag);
2431 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2432 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2434 const gchar *expected_answer_setup[] = { "active", "active" };
2435 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2437 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
2438 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2440 const gchar *expected_answer_direction[] = { "recvonly", "recvonly" };
2441 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2444 /* We set a max-bundle policy on the offering webrtcbin,
2445 * this means that all the offered medias should be part
2446 * of the group:BUNDLE attribute, and they should be marked
2449 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2451 /* We set a none policy on the answering webrtcbin,
2452 * this means that the answer should contain no bundled
2453 * medias, and as the bundle-policy of the offering webrtcbin
2454 * is set to max-bundle, only one media should be active.
2456 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy", "none");
2458 test_validate_sdp (t, &offer, &answer);
2460 test_webrtc_free (t);
2465 GST_START_TEST (test_bundle_audio_video_data)
2467 struct test_webrtc *t = create_audio_video_test ();
2468 const gchar *mids[] = { "audio0", "video1", "application2", NULL };
2469 const gchar *offer_bundle_only[] = { "video1", "application2", NULL };
2470 const gchar *answer_bundle_only[] = { NULL };
2471 GObject *channel = NULL;
2473 guint media_format_count[] = { 1, 1, 1 };
2474 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2475 media_format_count, NULL);
2476 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (3),
2478 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2479 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, mids, &payloads);
2480 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
2481 GUINT_TO_POINTER (1), &bundle_tag);
2482 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
2483 GUINT_TO_POINTER (3), &bundle_tag);
2484 VAL_SDP_INIT (offer_bundle, _check_bundle_only_media, &offer_bundle_only,
2486 VAL_SDP_INIT (answer_bundle, _check_bundle_only_media, &answer_bundle_only,
2487 &answer_non_reject);
2488 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
2489 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2491 const gchar *expected_answer_setup[] = { "active", "active", "active" };
2492 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2494 const gchar *expected_offer_direction[] =
2495 { "sendrecv", "sendrecv", "sendrecv" };
2496 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2498 const gchar *expected_answer_direction[] =
2499 { "recvonly", "recvonly", "recvonly" };
2500 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2503 /* We set a max-bundle policy on the offering webrtcbin,
2504 * this means that all the offered medias should be part
2505 * of the group:BUNDLE attribute, and they should be marked
2508 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2510 /* We also set a max-bundle policy on the answering webrtcbin,
2511 * this means that all the offered medias should be part
2512 * of the group:BUNDLE attribute, but need not be marked
2515 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2518 fail_if (gst_element_set_state (t->webrtc1,
2519 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2520 fail_if (gst_element_set_state (t->webrtc2,
2521 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2523 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2526 test_validate_sdp (t, &offer, &answer);
2528 g_object_unref (channel);
2529 test_webrtc_free (t);
2534 GST_START_TEST (test_duplicate_nego)
2536 struct test_webrtc *t = create_audio_video_test ();
2537 guint media_format_count[] = { 1, 1, };
2538 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2539 media_format_count, NULL);
2540 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2542 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2543 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2544 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2546 const gchar *expected_answer_setup[] = { "active", "active" };
2547 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2549 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
2550 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2552 const gchar *expected_answer_direction[] = { "sendrecv", "recvonly" };
2553 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2556 guint negotiation_flag = 0;
2558 /* check that negotiating twice succeeds */
2560 t->on_negotiation_needed = on_negotiation_needed_hit;
2561 t->negotiation_data = &negotiation_flag;
2563 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2564 add_fake_audio_src_harness (h, 96);
2565 t->harnesses = g_list_prepend (t->harnesses, h);
2567 test_validate_sdp (t, &offer, &answer);
2568 fail_unless (negotiation_flag & (1 << 2));
2570 test_webrtc_reset_negotiation (t);
2571 test_validate_sdp (t, &offer, &answer);
2573 test_webrtc_free (t);
2578 GST_START_TEST (test_dual_audio)
2580 struct test_webrtc *t = create_audio_test ();
2581 guint media_format_count[] = { 1, 1, };
2582 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2583 media_format_count, NULL);
2584 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2586 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2587 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2588 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2590 const gchar *expected_answer_setup[] = { "active", "active" };
2591 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2593 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
2594 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2596 const gchar *expected_answer_direction[] = { "sendrecv", "recvonly" };
2597 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2600 GstWebRTCRTPTransceiver *trans;
2601 GArray *transceivers;
2603 /* test that each mline gets a unique transceiver even with the same caps */
2605 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
2606 add_fake_audio_src_harness (h, 96);
2607 t->harnesses = g_list_prepend (t->harnesses, h);
2609 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2610 add_fake_audio_src_harness (h, 96);
2611 t->harnesses = g_list_prepend (t->harnesses, h);
2613 t->on_negotiation_needed = NULL;
2614 test_validate_sdp (t, &offer, &answer);
2616 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
2617 fail_unless (transceivers != NULL);
2618 fail_unless_equals_int (2, transceivers->len);
2620 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
2621 fail_unless (trans != NULL);
2622 fail_unless_equals_int (trans->mline, 0);
2624 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
2625 fail_unless (trans != NULL);
2626 fail_unless_equals_int (trans->mline, 1);
2628 g_array_unref (transceivers);
2629 test_webrtc_free (t);
2635 sdp_increasing_session_version (struct test_webrtc *t, GstElement * element,
2636 GstWebRTCSessionDescription * desc, gpointer user_data)
2638 GstWebRTCSessionDescription *previous;
2639 const GstSDPOrigin *our_origin, *previous_origin;
2641 guint64 our_v, previous_v;
2644 TEST_SDP_IS_LOCAL (t, element,
2645 desc) ? "current-local-description" : "current-remote-description";
2646 g_object_get (element, prop, &previous, NULL);
2648 our_origin = gst_sdp_message_get_origin (desc->sdp);
2649 previous_origin = gst_sdp_message_get_origin (previous->sdp);
2651 our_v = g_ascii_strtoull (our_origin->sess_version, NULL, 10);
2652 previous_v = g_ascii_strtoull (previous_origin->sess_version, NULL, 10);
2654 ck_assert_int_lt (previous_v, our_v);
2656 gst_webrtc_session_description_free (previous);
2660 sdp_equal_session_id (struct test_webrtc *t, GstElement * element,
2661 GstWebRTCSessionDescription * desc, gpointer user_data)
2663 GstWebRTCSessionDescription *previous;
2664 const GstSDPOrigin *our_origin, *previous_origin;
2668 TEST_SDP_IS_LOCAL (t, element,
2669 desc) ? "current-local-description" : "current-remote-description";
2670 g_object_get (element, prop, &previous, NULL);
2672 our_origin = gst_sdp_message_get_origin (desc->sdp);
2673 previous_origin = gst_sdp_message_get_origin (previous->sdp);
2675 fail_unless_equals_string (previous_origin->sess_id, our_origin->sess_id);
2676 gst_webrtc_session_description_free (previous);
2680 sdp_media_equal_attribute (struct test_webrtc *t, GstElement * element,
2681 GstWebRTCSessionDescription * desc, GstWebRTCSessionDescription * previous,
2686 n = MIN (gst_sdp_message_medias_len (previous->sdp),
2687 gst_sdp_message_medias_len (desc->sdp));
2689 for (i = 0; i < n; i++) {
2690 const GstSDPMedia *our_media, *other_media;
2691 const gchar *our_mid, *other_mid;
2693 our_media = gst_sdp_message_get_media (desc->sdp, i);
2694 other_media = gst_sdp_message_get_media (previous->sdp, i);
2696 our_mid = gst_sdp_media_get_attribute_val (our_media, attr);
2697 other_mid = gst_sdp_media_get_attribute_val (other_media, attr);
2699 fail_unless_equals_string (our_mid, other_mid);
2704 sdp_media_equal_mid (struct test_webrtc *t, GstElement * element,
2705 GstWebRTCSessionDescription * desc, gpointer user_data)
2707 GstWebRTCSessionDescription *previous;
2711 TEST_SDP_IS_LOCAL (t, element,
2712 desc) ? "current-local-description" : "current-remote-description";
2713 g_object_get (element, prop, &previous, NULL);
2715 sdp_media_equal_attribute (t, element, desc, previous, "mid");
2717 gst_webrtc_session_description_free (previous);
2721 sdp_media_equal_ice_params (struct test_webrtc *t, GstElement * element,
2722 GstWebRTCSessionDescription * desc, gpointer user_data)
2724 GstWebRTCSessionDescription *previous;
2728 TEST_SDP_IS_LOCAL (t, element,
2729 desc) ? "current-local-description" : "current-remote-description";
2730 g_object_get (element, prop, &previous, NULL);
2732 sdp_media_equal_attribute (t, element, desc, previous, "ice-ufrag");
2733 sdp_media_equal_attribute (t, element, desc, previous, "ice-pwd");
2735 gst_webrtc_session_description_free (previous);
2739 sdp_media_equal_fingerprint (struct test_webrtc *t, GstElement * element,
2740 GstWebRTCSessionDescription * desc, gpointer user_data)
2742 GstWebRTCSessionDescription *previous;
2746 TEST_SDP_IS_LOCAL (t, element,
2747 desc) ? "current-local-description" : "current-remote-description";
2748 g_object_get (element, prop, &previous, NULL);
2750 sdp_media_equal_attribute (t, element, desc, previous, "fingerprint");
2752 gst_webrtc_session_description_free (previous);
2755 GST_START_TEST (test_renego_add_stream)
2757 struct test_webrtc *t = create_audio_video_test ();
2758 guint media_format_count[] = { 1, 1, 1 };
2759 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2760 media_format_count, NULL);
2761 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2763 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2764 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
2765 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2767 const gchar *expected_answer_setup[] = { "active", "active", "active" };
2768 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2770 const gchar *expected_offer_direction[] =
2771 { "sendrecv", "sendrecv", "sendrecv" };
2772 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2774 const gchar *expected_answer_direction[] =
2775 { "sendrecv", "recvonly", "recvonly" };
2776 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2778 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2779 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2781 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2782 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2784 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2788 /* negotiate an AV stream and then renegotiate an extra stream */
2789 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2790 add_fake_audio_src_harness (h, 96);
2791 t->harnesses = g_list_prepend (t->harnesses, h);
2793 test_validate_sdp (t, &offer, &answer);
2795 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
2796 add_fake_audio_src_harness (h, 98);
2797 t->harnesses = g_list_prepend (t->harnesses, h);
2799 media_formats.next = &renego_fingerprint;
2800 count.user_data = GUINT_TO_POINTER (3);
2803 test_webrtc_reset_negotiation (t);
2804 test_validate_sdp (t, &offer, &answer);
2806 test_webrtc_free (t);
2811 GST_START_TEST (test_renego_stream_add_data_channel)
2813 struct test_webrtc *t = create_audio_video_test ();
2815 guint media_format_count[] = { 1, 1, 1 };
2816 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2817 media_format_count, NULL);
2818 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2820 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2821 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
2822 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2824 const gchar *expected_answer_setup[] = { "active", "active", "active" };
2825 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2827 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv", NULL };
2828 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2830 const gchar *expected_answer_direction[] = { "sendrecv", "recvonly", NULL };
2831 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2833 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2834 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2836 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2837 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2839 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2844 /* negotiate an AV stream and then renegotiate a data channel */
2845 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2846 add_fake_audio_src_harness (h, 96);
2847 t->harnesses = g_list_prepend (t->harnesses, h);
2849 test_validate_sdp (t, &offer, &answer);
2851 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2854 media_formats.next = &renego_fingerprint;
2855 count.user_data = GUINT_TO_POINTER (3);
2858 test_webrtc_reset_negotiation (t);
2859 test_validate_sdp (t, &offer, &answer);
2861 g_object_unref (channel);
2862 test_webrtc_free (t);
2867 GST_START_TEST (test_renego_data_channel_add_stream)
2869 struct test_webrtc *t = test_webrtc_new ();
2870 guint media_format_count[] = { 1, 1, 1 };
2871 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2872 media_format_count, NULL);
2873 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
2875 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2876 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
2877 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2879 const gchar *expected_answer_setup[] = { "active", "active" };
2880 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2882 const gchar *expected_offer_direction[] = { NULL, "sendrecv" };
2883 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2885 const gchar *expected_answer_direction[] = { NULL, "recvonly" };
2886 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2888 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2889 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2891 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2892 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2894 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2899 /* negotiate an data channel and then renegotiate to add a av stream */
2900 t->on_negotiation_needed = NULL;
2901 t->on_ice_candidate = NULL;
2902 t->on_pad_added = _pad_added_fakesink;
2904 fail_if (gst_element_set_state (t->webrtc1,
2905 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2906 fail_if (gst_element_set_state (t->webrtc2,
2907 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2909 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2912 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2914 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
2915 add_fake_audio_src_harness (h, 97);
2916 t->harnesses = g_list_prepend (t->harnesses, h);
2918 media_formats.next = &renego_fingerprint;
2919 count.user_data = GUINT_TO_POINTER (2);
2922 test_webrtc_reset_negotiation (t);
2923 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2925 g_object_unref (channel);
2926 test_webrtc_free (t);
2932 GST_START_TEST (test_renego_stream_data_channel_add_stream)
2934 struct test_webrtc *t = test_webrtc_new ();
2935 guint media_format_count[] = { 1, 1, 1 };
2936 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
2937 media_format_count, NULL);
2938 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
2940 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
2941 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
2942 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
2944 const gchar *expected_answer_setup[] = { "active", "active", "active" };
2945 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
2947 const gchar *expected_offer_direction[] = { "sendrecv", NULL, "sendrecv" };
2948 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
2950 const gchar *expected_answer_direction[] = { "recvonly", NULL, "recvonly" };
2951 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
2953 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2954 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2956 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2957 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2959 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2964 /* Negotiate a stream and a data channel, then renogotiate with a new stream */
2965 t->on_negotiation_needed = NULL;
2966 t->on_ice_candidate = NULL;
2967 t->on_pad_added = _pad_added_fakesink;
2969 h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
2970 add_fake_audio_src_harness (h, 97);
2971 t->harnesses = g_list_prepend (t->harnesses, h);
2973 fail_if (gst_element_set_state (t->webrtc1,
2974 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2975 fail_if (gst_element_set_state (t->webrtc2,
2976 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2978 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2981 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2983 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
2984 add_fake_audio_src_harness (h, 97);
2985 t->harnesses = g_list_prepend (t->harnesses, h);
2987 media_formats.next = &renego_fingerprint;
2988 count.user_data = GUINT_TO_POINTER (3);
2991 test_webrtc_reset_negotiation (t);
2992 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2994 g_object_unref (channel);
2995 test_webrtc_free (t);
3000 GST_START_TEST (test_bundle_renego_add_stream)
3002 struct test_webrtc *t = create_audio_video_test ();
3003 const gchar *bundle[] = { "audio0", "video1", "audio2", NULL };
3004 const gchar *offer_bundle_only[] = { "video1", "audio2", NULL };
3005 const gchar *answer_bundle_only[] = { NULL };
3006 guint media_format_count[] = { 1, 1, 1 };
3007 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
3008 media_format_count, NULL);
3009 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
3011 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
3012 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
3013 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3015 const gchar *expected_answer_setup[] = { "active", "active", "active" };
3016 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3018 const gchar *expected_offer_direction[] =
3019 { "sendrecv", "sendrecv", "sendrecv" };
3020 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3022 const gchar *expected_answer_direction[] =
3023 { "sendrecv", "recvonly", "recvonly" };
3024 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3027 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, &payloads);
3028 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
3030 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
3031 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
3033 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
3035 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &renego_fingerprint);
3036 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
3037 GUINT_TO_POINTER (1), &bundle_tag);
3038 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
3039 GUINT_TO_POINTER (3), &bundle_tag);
3040 VAL_SDP_INIT (offer_bundle_only_sdp, _check_bundle_only_media,
3041 &offer_bundle_only, &offer_non_reject);
3042 VAL_SDP_INIT (answer_bundle_only_sdp, _check_bundle_only_media,
3043 &answer_bundle_only, &answer_non_reject);
3046 /* We set a max-bundle policy on the offering webrtcbin,
3047 * this means that all the offered medias should be part
3048 * of the group:BUNDLE attribute, and they should be marked
3051 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
3053 /* We also set a max-bundle policy on the answering webrtcbin,
3054 * this means that all the offered medias should be part
3055 * of the group:BUNDLE attribute, but need not be marked
3058 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
3061 /* negotiate an AV stream and then renegotiate an extra stream */
3062 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
3063 add_fake_audio_src_harness (h, 96);
3064 t->harnesses = g_list_prepend (t->harnesses, h);
3066 test_validate_sdp (t, &offer, &answer);
3068 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
3069 add_fake_audio_src_harness (h, 98);
3070 t->harnesses = g_list_prepend (t->harnesses, h);
3072 offer_setup.next = &offer_bundle_only_sdp;
3073 answer_setup.next = &answer_bundle_only_sdp;
3074 count.user_data = GUINT_TO_POINTER (3);
3077 test_webrtc_reset_negotiation (t);
3078 test_validate_sdp (t, &offer, &answer);
3080 test_webrtc_free (t);
3085 GST_START_TEST (test_bundle_max_compat_max_bundle_renego_add_stream)
3087 struct test_webrtc *t = create_audio_video_test ();
3088 const gchar *bundle[] = { "audio0", "video1", "audio2", NULL };
3089 const gchar *bundle_only[] = { NULL };
3090 guint media_format_count[] = { 1, 1, 1 };
3091 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
3092 media_format_count, NULL);
3093 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
3095 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
3096 const gchar *expected_offer_setup[] = { "actpass", "actpass", "actpass" };
3097 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3099 const gchar *expected_answer_setup[] = { "active", "active", "active" };
3100 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3102 const gchar *expected_offer_direction[] =
3103 { "sendrecv", "sendrecv", "sendrecv" };
3104 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3106 const gchar *expected_answer_direction[] =
3107 { "sendrecv", "recvonly", "recvonly" };
3108 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3111 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
3112 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
3114 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
3115 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
3117 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
3119 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &renego_fingerprint);
3120 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
3121 GUINT_TO_POINTER (3), &bundle_tag);
3122 VAL_SDP_INIT (bundle_sdp, _check_bundle_only_media, &bundle_only,
3126 /* We set a max-compat policy on the offering webrtcbin,
3127 * this means that all the offered medias should be part
3128 * of the group:BUNDLE attribute, and they should *not* be marked
3131 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
3133 /* We set a max-bundle policy on the answering webrtcbin,
3134 * this means that all the offered medias should be part
3135 * of the group:BUNDLE attribute, but need not be marked
3138 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
3141 /* negotiate an AV stream and then renegotiate an extra stream */
3142 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
3143 add_fake_audio_src_harness (h, 96);
3144 t->harnesses = g_list_prepend (t->harnesses, h);
3146 test_validate_sdp (t, &offer, &answer);
3148 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
3149 add_fake_audio_src_harness (h, 98);
3150 t->harnesses = g_list_prepend (t->harnesses, h);
3152 media_formats.next = &bundle_sdp;
3153 count.user_data = GUINT_TO_POINTER (3);
3156 test_webrtc_reset_negotiation (t);
3157 test_validate_sdp (t, &offer, &answer);
3159 test_webrtc_free (t);
3164 GST_START_TEST (test_renego_transceiver_set_direction)
3166 struct test_webrtc *t = create_audio_test ();
3167 guint media_format_count[] = { 1, };
3168 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
3169 media_format_count, NULL);
3170 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (1),
3172 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
3173 const gchar *expected_offer_setup[] = { "actpass", };
3174 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3176 const gchar *expected_answer_setup[] = { "active", };
3177 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3179 const gchar *expected_offer_direction[] = { "sendrecv", };
3180 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3182 const gchar *expected_answer_direction[] = { "sendrecv", };
3183 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3185 GstWebRTCRTPTransceiver *transceiver;
3189 /* negotiate an AV stream and then change the transceiver direction */
3190 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
3191 add_fake_audio_src_harness (h, 96);
3192 t->harnesses = g_list_prepend (t->harnesses, h);
3194 test_validate_sdp (t, &offer, &answer);
3196 /* renegotiate an inactive transceiver! */
3197 pad = gst_element_get_static_pad (t->webrtc1, "sink_0");
3198 g_object_get (pad, "transceiver", &transceiver, NULL);
3199 fail_unless (transceiver != NULL);
3200 g_object_set (transceiver, "direction",
3201 GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE, NULL);
3202 expected_offer_direction[0] = "inactive";
3203 expected_answer_direction[0] = "inactive";
3205 /* TODO: also validate EOS events from the inactive change */
3207 test_webrtc_reset_negotiation (t);
3208 test_validate_sdp (t, &offer, &answer);
3210 gst_object_unref (pad);
3211 gst_object_unref (transceiver);
3212 test_webrtc_free (t);
3218 offer_remove_last_media (struct test_webrtc *t, GstElement * element,
3219 GstPromise * promise, gpointer user_data)
3222 GstSDPMessage *new, *old;
3223 const GstSDPOrigin *origin;
3224 const GstSDPConnection *conn;
3226 old = t->offer_desc->sdp;
3227 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_new (&new));
3229 origin = gst_sdp_message_get_origin (old);
3230 conn = gst_sdp_message_get_connection (old);
3231 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_version (new,
3232 gst_sdp_message_get_version (old)));
3233 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_origin (new,
3234 origin->username, origin->sess_id, origin->sess_version,
3235 origin->nettype, origin->addrtype, origin->addr));
3236 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_session_name (new,
3237 gst_sdp_message_get_session_name (old)));
3238 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_information (new,
3239 gst_sdp_message_get_information (old)));
3240 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_uri (new,
3241 gst_sdp_message_get_uri (old)));
3242 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_set_connection (new,
3243 conn->nettype, conn->addrtype, conn->address, conn->ttl,
3244 conn->addr_number));
3246 n = gst_sdp_message_attributes_len (old);
3247 for (i = 0; i < n; i++) {
3248 const GstSDPAttribute *a = gst_sdp_message_get_attribute (old, i);
3249 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_add_attribute (new,
3253 n = gst_sdp_message_medias_len (old);
3254 fail_unless (n > 0);
3255 for (i = 0; i < n - 1; i++) {
3256 const GstSDPMedia *m = gst_sdp_message_get_media (old, i);
3259 fail_unless_equals_int (GST_SDP_OK, gst_sdp_media_copy (m, &new_m));
3260 fail_unless_equals_int (GST_SDP_OK, gst_sdp_message_add_media (new, new_m));
3261 gst_sdp_media_init (new_m);
3262 gst_sdp_media_free (new_m);
3265 gst_webrtc_session_description_free (t->offer_desc);
3266 t->offer_desc = gst_webrtc_session_description_new (GST_WEBRTC_SDP_TYPE_OFFER,
3271 offer_set_produced_error (struct test_webrtc *t, GstElement * element,
3272 GstPromise * promise, gpointer user_data)
3274 const GstStructure *reply;
3275 GError *error = NULL;
3277 reply = gst_promise_get_reply (promise);
3278 fail_unless (gst_structure_get (reply, "error", G_TYPE_ERROR, &error, NULL));
3279 GST_INFO ("error produced: %s", error->message);
3280 g_clear_error (&error);
3282 test_webrtc_signal_state_unlocked (t, STATE_CUSTOM);
3285 GST_START_TEST (test_renego_lose_media_fails)
3287 struct test_webrtc *t = create_audio_video_test ();
3288 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
3289 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
3291 /* check that removing an m=line will produce an error */
3293 test_validate_sdp (t, &offer, &answer);
3295 test_webrtc_reset_negotiation (t);
3297 t->on_offer_created = offer_remove_last_media;
3298 t->on_offer_set = offer_set_produced_error;
3299 t->on_answer_created = NULL;
3301 test_webrtc_create_offer (t);
3302 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
3304 test_webrtc_free (t);
3309 GST_START_TEST (test_bundle_codec_preferences_rtx_no_duplicate_payloads)
3311 struct test_webrtc *t = test_webrtc_new ();
3312 GstWebRTCRTPTransceiverDirection direction;
3313 GstWebRTCRTPTransceiver *trans;
3314 guint offer_media_format_count[] = { 2, };
3315 guint answer_media_format_count[] = { 1, };
3316 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, NULL);
3317 VAL_SDP_INIT (offer_media_formats, on_sdp_media_count_formats,
3318 offer_media_format_count, &payloads);
3319 VAL_SDP_INIT (answer_media_formats, on_sdp_media_count_formats,
3320 answer_media_format_count, &payloads);
3321 const gchar *expected_offer_setup[] = { "actpass", };
3322 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3323 &offer_media_formats);
3324 const gchar *expected_answer_setup[] = { "active", };
3325 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3326 &answer_media_formats);
3327 const gchar *expected_offer_direction[] = { "recvonly", };
3328 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3330 const gchar *expected_answer_direction[] = { "sendonly", };
3331 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3336 /* add a transceiver that will only receive an opus stream and check that
3337 * the created offer is marked as recvonly */
3338 t->on_negotiation_needed = NULL;
3339 t->on_ice_candidate = NULL;
3340 t->on_pad_added = _pad_added_fakesink;
3342 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
3344 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
3347 /* setup recvonly transceiver */
3348 caps = gst_caps_from_string (VP8_RTP_CAPS (96));
3349 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
3350 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
3352 g_object_set (GST_OBJECT (trans), "do-nack", TRUE, NULL);
3353 gst_caps_unref (caps);
3354 fail_unless (trans != NULL);
3355 gst_object_unref (trans);
3357 /* setup sendonly peer */
3358 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
3359 add_fake_video_src_harness (h, 96);
3360 t->harnesses = g_list_prepend (t->harnesses, h);
3361 test_validate_sdp (t, &offer, &answer);
3363 test_webrtc_free (t);
3368 GST_START_TEST (test_reject_request_pad)
3370 struct test_webrtc *t = test_webrtc_new ();
3371 GstWebRTCRTPTransceiverDirection direction;
3372 GstWebRTCRTPTransceiver *trans, *trans2;
3373 guint offer_media_format_count[] = { 1, };
3374 guint answer_media_format_count[] = { 1, };
3375 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, NULL);
3376 VAL_SDP_INIT (offer_media_formats, on_sdp_media_count_formats,
3377 offer_media_format_count, &payloads);
3378 VAL_SDP_INIT (answer_media_formats, on_sdp_media_count_formats,
3379 answer_media_format_count, &payloads);
3380 const gchar *expected_offer_setup[] = { "actpass", };
3381 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3382 &offer_media_formats);
3383 const gchar *expected_answer_setup[] = { "active", };
3384 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3385 &answer_media_formats);
3386 const gchar *expected_offer_direction[] = { "recvonly", };
3387 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3389 const gchar *expected_answer_direction[] = { "sendonly", };
3390 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3395 GstPadTemplate *templ;
3397 t->on_negotiation_needed = NULL;
3398 t->on_ice_candidate = NULL;
3399 t->on_pad_added = _pad_added_fakesink;
3401 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
3403 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
3406 /* setup recvonly transceiver */
3407 caps = gst_caps_from_string (VP8_RTP_CAPS (96));
3408 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
3409 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
3411 gst_caps_unref (caps);
3412 fail_unless (trans != NULL);
3414 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
3415 add_fake_video_src_harness (h, 96);
3416 t->harnesses = g_list_prepend (t->harnesses, h);
3418 test_validate_sdp (t, &offer, &answer);
3420 /* This should fail because the direction is wrong */
3421 pad = gst_element_get_request_pad (t->webrtc1, "sink_0");
3422 fail_unless (pad == NULL);
3424 g_object_set (trans, "direction",
3425 GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV, NULL);
3427 templ = gst_element_get_pad_template (t->webrtc1, "sink_%u");
3428 fail_unless (templ != NULL);
3430 /* This should fail because the caps are wrong */
3431 caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
3432 pad = gst_element_request_pad (t->webrtc1, templ, "sink_0", caps);
3433 fail_unless (pad == NULL);
3435 gst_caps_unref (trans->codec_preferences);
3436 trans->codec_preferences = NULL;
3438 /* This should fail because the kind doesn't match */
3439 pad = gst_element_request_pad (t->webrtc1, templ, "sink_0", caps);
3440 fail_unless (pad == NULL);
3441 gst_caps_unref (caps);
3443 /* This should succeed and give us sink_0 */
3444 pad = gst_element_get_request_pad (t->webrtc1, "sink_0");
3445 fail_unless (pad != NULL);
3447 g_object_get (pad, "transceiver", &trans2, NULL);
3449 fail_unless (trans == trans2);
3451 gst_object_unref (pad);
3452 gst_object_unref (trans);
3453 gst_object_unref (trans2);
3455 test_webrtc_free (t);
3461 _verify_media_types (struct test_webrtc *t, GstElement * element,
3462 GstWebRTCSessionDescription * desc, gpointer user_data)
3464 gchar **media_types = user_data;
3467 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
3468 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
3470 fail_unless_equals_string (gst_sdp_media_get_media (media), media_types[i]);
3474 GST_START_TEST (test_reject_create_offer)
3476 struct test_webrtc *t = test_webrtc_new ();
3478 GstPromise *promise;
3479 GstPromiseResult res;
3480 const GstStructure *s;
3481 GError *error = NULL;
3483 const gchar *media_types[] = { "video", "audio" };
3484 VAL_SDP_INIT (media_type, _verify_media_types, &media_types, NULL);
3485 guint media_format_count[] = { 1, 1 };
3486 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
3487 media_format_count, &media_type);
3488 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2),
3490 VAL_SDP_INIT (payloads, on_sdp_media_no_duplicate_payloads, NULL, &count);
3491 const gchar *expected_offer_setup[] = { "actpass", "actpass" };
3492 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3494 const gchar *expected_answer_setup[] = { "active", "active" };
3495 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3497 const gchar *expected_offer_direction[] = { "sendrecv", "sendrecv" };
3498 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer_direction,
3500 const gchar *expected_answer_direction[] = { "recvonly", "recvonly" };
3501 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer_direction,
3504 t->on_negotiation_needed = NULL;
3505 t->on_ice_candidate = NULL;
3506 t->on_pad_added = _pad_added_fakesink;
3508 /* setup sendonly peer */
3509 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
3510 add_fake_audio_src_harness (h, 96);
3511 t->harnesses = g_list_prepend (t->harnesses, h);
3513 /* Check that if there is no 0, we can't create an offer with a hole */
3514 promise = gst_promise_new ();
3515 g_signal_emit_by_name (t->webrtc1, "create-offer", NULL, promise);
3516 res = gst_promise_wait (promise);
3517 fail_unless_equals_int (res, GST_PROMISE_RESULT_REPLIED);
3518 s = gst_promise_get_reply (promise);
3519 fail_unless (s != NULL);
3520 fail_unless (gst_structure_has_name (s, "application/x-gstwebrtcbin-error"));
3521 gst_structure_get (s, "error", G_TYPE_ERROR, &error, NULL);
3522 fail_unless (g_error_matches (error, GST_WEBRTC_BIN_ERROR,
3523 GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION));
3524 g_clear_error (&error);
3525 gst_promise_unref (promise);
3527 h = gst_harness_new_with_element (t->webrtc1, "sink_%u", NULL);
3528 add_fake_video_src_harness (h, 97);
3529 t->harnesses = g_list_prepend (t->harnesses, h);
3531 /* Adding a second sink, which will fill m-line 0, should fix it */
3532 test_validate_sdp (t, &offer, &answer);
3534 test_webrtc_free (t);
3539 GST_START_TEST (test_reject_set_description)
3541 struct test_webrtc *t = test_webrtc_new ();
3543 GstPromise *promise;
3544 GstPromiseResult res;
3545 const GstStructure *s;
3546 GError *error = NULL;
3547 GstWebRTCSessionDescription *desc = NULL;
3548 GstPadTemplate *templ;
3552 t->on_negotiation_needed = NULL;
3553 t->on_ice_candidate = NULL;
3554 t->on_pad_added = _pad_added_fakesink;
3557 h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
3558 add_fake_audio_src_harness (h, 96);
3559 t->harnesses = g_list_prepend (t->harnesses, h);
3561 /* Create a second side with specific video caps */
3562 templ = gst_element_get_pad_template (t->webrtc2, "sink_%u");
3563 fail_unless (templ != NULL);
3564 caps = gst_caps_from_string (VP8_RTP_CAPS (97));
3565 pad = gst_element_request_pad (t->webrtc2, templ, "sink_0", caps);
3566 fail_unless (pad != NULL);
3567 gst_caps_unref (caps);
3568 gst_object_unref (pad);
3570 /* Create an offer */
3571 promise = gst_promise_new ();
3572 g_signal_emit_by_name (t->webrtc1, "create-offer", NULL, promise);
3573 res = gst_promise_wait (promise);
3574 fail_unless_equals_int (res, GST_PROMISE_RESULT_REPLIED);
3575 s = gst_promise_get_reply (promise);
3576 fail_unless (s != NULL);
3577 fail_unless (gst_structure_has_name (s, "application/x-gst-promise"));
3578 gst_structure_get (s, "offer", GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &desc,
3580 fail_unless (desc != NULL);
3581 gst_promise_unref (promise);
3583 fail_if (gst_element_set_state (t->webrtc2,
3584 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
3586 /* Verify that setting an offer where there is a forced m-line with
3587 a different kind fails. */
3588 promise = gst_promise_new ();
3589 g_signal_emit_by_name (t->webrtc2, "set-remote-description", desc, promise);
3590 res = gst_promise_wait (promise);
3591 fail_unless_equals_int (res, GST_PROMISE_RESULT_REPLIED);
3592 s = gst_promise_get_reply (promise);
3593 fail_unless (gst_structure_has_name (s, "application/x-gstwebrtcbin-error"));
3594 gst_structure_get (s, "error", G_TYPE_ERROR, &error, NULL);
3595 fail_unless (g_error_matches (error, GST_WEBRTC_BIN_ERROR,
3596 GST_WEBRTC_BIN_ERROR_IMPOSSIBLE_MLINE_RESTRICTION));
3597 g_clear_error (&error);
3598 fail_unless (s != NULL);
3599 gst_promise_unref (promise);
3600 gst_webrtc_session_description_free (desc);
3602 test_webrtc_free (t);
3607 GST_START_TEST (test_force_second_media)
3609 struct test_webrtc *t = test_webrtc_new ();
3610 const gchar *media_types[] = { "audio" };
3611 VAL_SDP_INIT (media_type, _verify_media_types, &media_types, NULL);
3612 guint media_format_count[] = { 1, };
3613 VAL_SDP_INIT (media_formats, on_sdp_media_count_formats,
3614 media_format_count, &media_type);
3615 const gchar *expected_offer_setup[] = { "actpass", };
3616 VAL_SDP_INIT (offer_setup, on_sdp_media_setup, expected_offer_setup,
3618 const gchar *expected_answer_setup[] = { "active", };
3619 VAL_SDP_INIT (answer_setup, on_sdp_media_setup, expected_answer_setup,
3621 const gchar *expected_offer_direction[] = { "sendrecv", };
3622 VAL_SDP_INIT (offer_direction, on_sdp_media_direction,
3623 expected_offer_direction, &offer_setup);
3624 const gchar *expected_answer_direction[] = { "recvonly", };
3625 VAL_SDP_INIT (answer_direction, on_sdp_media_direction,
3626 expected_answer_direction, &answer_setup);
3627 VAL_SDP_INIT (answer_count, _count_num_sdp_media, GUINT_TO_POINTER (1),
3629 VAL_SDP_INIT (offer_count, _count_num_sdp_media, GUINT_TO_POINTER (1),
3632 const gchar *second_media_types[] = { "audio", "video" };
3633 VAL_SDP_INIT (second_media_type, _verify_media_types, &second_media_types,
3635 guint second_media_format_count[] = { 1, 1 };
3636 VAL_SDP_INIT (second_media_formats, on_sdp_media_count_formats,
3637 second_media_format_count, &second_media_type);
3638 const gchar *second_expected_offer_setup[] = { "active", "actpass" };
3639 VAL_SDP_INIT (second_offer_setup, on_sdp_media_setup,
3640 second_expected_offer_setup, &second_media_formats);
3641 const gchar *second_expected_answer_setup[] = { "passive", "active" };
3642 VAL_SDP_INIT (second_answer_setup, on_sdp_media_setup,
3643 second_expected_answer_setup, &second_media_formats);
3644 const gchar *second_expected_answer_direction[] = { "sendonly", "recvonly" };
3645 VAL_SDP_INIT (second_answer_direction, on_sdp_media_direction,
3646 second_expected_answer_direction, &second_answer_setup);
3647 const gchar *second_expected_offer_direction[] = { "recvonly", "sendrecv" };
3648 VAL_SDP_INIT (second_offer_direction, on_sdp_media_direction,
3649 second_expected_offer_direction, &second_offer_setup);
3650 VAL_SDP_INIT (second_answer_count, _count_num_sdp_media, GUINT_TO_POINTER (2),
3651 &second_answer_direction);
3652 VAL_SDP_INIT (second_offer_count, _count_num_sdp_media, GUINT_TO_POINTER (2),
3653 &second_offer_direction);
3656 guint negotiation_flag = 0;
3657 GstPadTemplate *templ;
3661 /* add a transceiver that will only receive an opus stream and check that
3662 * the created offer is marked as recvonly */
3663 t->on_negotiation_needed = on_negotiation_needed_hit;
3664 t->negotiation_data = &negotiation_flag;
3665 t->on_ice_candidate = NULL;
3666 t->on_pad_added = _pad_added_fakesink;
3669 h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
3670 add_fake_audio_src_harness (h, 96);
3671 t->harnesses = g_list_prepend (t->harnesses, h);
3673 /* Create a second side with specific video caps */
3674 templ = gst_element_get_pad_template (t->webrtc2, "sink_%u");
3675 fail_unless (templ != NULL);
3676 caps = gst_caps_from_string (VP8_RTP_CAPS (97));
3677 pad = gst_element_request_pad (t->webrtc2, templ, NULL, caps);
3678 gst_caps_unref (caps);
3679 fail_unless (pad != NULL);
3680 h = gst_harness_new_with_element (t->webrtc2, GST_PAD_NAME (pad), NULL);
3681 gst_object_unref (pad);
3682 add_fake_video_src_harness (h, 97);
3683 t->harnesses = g_list_prepend (t->harnesses, h);
3685 test_validate_sdp (t, &offer_count, &answer_count);
3686 fail_unless (negotiation_flag & 1 << 2);
3688 test_webrtc_reset_negotiation (t);
3691 test_validate_sdp (t, &second_offer_count, &second_answer_count);
3693 test_webrtc_free (t);
3699 webrtcbin_suite (void)
3701 Suite *s = suite_create ("webrtcbin");
3702 TCase *tc = tcase_create ("general");
3703 GstPluginFeature *nicesrc, *nicesink, *dtlssrtpdec, *dtlssrtpenc;
3704 GstPluginFeature *sctpenc, *sctpdec;
3705 GstRegistry *registry;
3707 registry = gst_registry_get ();
3708 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
3709 nicesink = gst_registry_lookup_feature (registry, "nicesink");
3710 dtlssrtpenc = gst_registry_lookup_feature (registry, "dtlssrtpenc");
3711 dtlssrtpdec = gst_registry_lookup_feature (registry, "dtlssrtpdec");
3712 sctpenc = gst_registry_lookup_feature (registry, "sctpenc");
3713 sctpdec = gst_registry_lookup_feature (registry, "sctpdec");
3715 tcase_add_test (tc, test_no_nice_elements_request_pad);
3716 tcase_add_test (tc, test_no_nice_elements_state_change);
3717 if (nicesrc && nicesink && dtlssrtpenc && dtlssrtpdec) {
3718 tcase_add_test (tc, test_sdp_no_media);
3719 tcase_add_test (tc, test_session_stats);
3720 tcase_add_test (tc, test_audio);
3721 tcase_add_test (tc, test_ice_port_restriction);
3722 tcase_add_test (tc, test_audio_video);
3723 tcase_add_test (tc, test_media_direction);
3724 tcase_add_test (tc, test_add_transceiver);
3725 tcase_add_test (tc, test_get_transceivers);
3726 tcase_add_test (tc, test_add_recvonly_transceiver);
3727 tcase_add_test (tc, test_recvonly_sendonly);
3728 tcase_add_test (tc, test_payload_types);
3729 tcase_add_test (tc, test_bundle_audio_video_max_bundle_max_bundle);
3730 tcase_add_test (tc, test_bundle_audio_video_max_bundle_none);
3731 tcase_add_test (tc, test_bundle_audio_video_max_compat_max_bundle);
3732 tcase_add_test (tc, test_dual_audio);
3733 tcase_add_test (tc, test_duplicate_nego);
3734 tcase_add_test (tc, test_renego_add_stream);
3735 tcase_add_test (tc, test_bundle_renego_add_stream);
3736 tcase_add_test (tc, test_bundle_max_compat_max_bundle_renego_add_stream);
3737 tcase_add_test (tc, test_renego_transceiver_set_direction);
3738 tcase_add_test (tc, test_renego_lose_media_fails);
3740 test_bundle_codec_preferences_rtx_no_duplicate_payloads);
3741 tcase_add_test (tc, test_reject_request_pad);
3742 tcase_add_test (tc, test_reject_create_offer);
3743 tcase_add_test (tc, test_reject_set_description);
3744 tcase_add_test (tc, test_force_second_media);
3745 if (sctpenc && sctpdec) {
3746 tcase_add_test (tc, test_data_channel_create);
3747 tcase_add_test (tc, test_data_channel_remote_notify);
3748 tcase_add_test (tc, test_data_channel_transfer_string);
3749 tcase_add_test (tc, test_data_channel_transfer_data);
3750 tcase_add_test (tc, test_data_channel_create_after_negotiate);
3751 tcase_add_test (tc, test_data_channel_low_threshold);
3752 tcase_add_test (tc, test_data_channel_max_message_size);
3753 tcase_add_test (tc, test_data_channel_pre_negotiated);
3754 tcase_add_test (tc, test_bundle_audio_video_data);
3755 tcase_add_test (tc, test_renego_stream_add_data_channel);
3756 tcase_add_test (tc, test_renego_data_channel_add_stream);
3757 tcase_add_test (tc, test_renego_stream_data_channel_add_stream);
3759 GST_WARNING ("Some required elements were not found. "
3760 "All datachannel tests are disabled. sctpenc %p, sctpdec %p", sctpenc,
3764 GST_WARNING ("Some required elements were not found. "
3765 "All media tests are disabled. nicesrc %p, nicesink %p, "
3766 "dtlssrtpenc %p, dtlssrtpdec %p", nicesrc, nicesink, dtlssrtpenc,
3771 gst_object_unref (nicesrc);
3773 gst_object_unref (nicesink);
3775 gst_object_unref (dtlssrtpdec);
3777 gst_object_unref (dtlssrtpenc);
3779 gst_object_unref (sctpenc);
3781 gst_object_unref (sctpdec);
3783 suite_add_tcase (s, tc);
3788 GST_CHECK_MAIN (webrtcbin);