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 ? 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;
182 reply = gst_promise_get_reply (promise);
183 gst_structure_get (reply, "answer",
184 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &answer, NULL);
185 desc = gst_sdp_message_as_text (answer->sdp);
186 GST_INFO ("Created Answer: %s", desc);
189 g_mutex_lock (&t->lock);
191 g_assert (t->answer_desc == NULL);
192 t->answer_desc = answer;
194 if (t->on_answer_created) {
195 t->on_answer_created (t, answerer, promise, t->answer_data);
197 gst_promise_unref (promise);
199 promise = gst_promise_new_with_change_func (_on_answer_set, t, NULL);
200 g_signal_emit_by_name (answerer, "set-local-description", t->answer_desc,
202 promise = gst_promise_new_with_change_func (_on_answer_set, t, NULL);
203 g_signal_emit_by_name (offeror, "set-remote-description", t->answer_desc,
206 test_webrtc_signal_state_unlocked (t, STATE_ANSWER_CREATED);
207 g_mutex_unlock (&t->lock);
211 _on_offer_set (GstPromise * promise, gpointer user_data)
213 struct test_webrtc *t = user_data;
214 GstElement *offeror = TEST_GET_OFFEROR (t);
216 g_mutex_lock (&t->lock);
217 if (++t->offer_set_count >= 2 && t->on_offer_set) {
218 t->on_offer_set (t, offeror, promise, t->offer_set_data);
220 if (t->state == STATE_OFFER_CREATED)
221 t->state = STATE_OFFER_SET;
222 g_cond_broadcast (&t->cond);
223 gst_promise_unref (promise);
224 g_mutex_unlock (&t->lock);
228 _on_offer_received (GstPromise * promise, gpointer user_data)
230 struct test_webrtc *t = user_data;
231 GstElement *offeror = TEST_GET_OFFEROR (t);
232 GstElement *answerer = TEST_GET_ANSWERER (t);
233 const GstStructure *reply;
234 GstWebRTCSessionDescription *offer = NULL;
237 reply = gst_promise_get_reply (promise);
238 gst_structure_get (reply, "offer",
239 GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
240 desc = gst_sdp_message_as_text (offer->sdp);
241 GST_INFO ("Created offer: %s", desc);
244 g_mutex_lock (&t->lock);
246 g_assert (t->offer_desc == NULL);
247 t->offer_desc = offer;
249 if (t->on_offer_created) {
250 t->on_offer_created (t, offeror, promise, t->offer_data);
252 gst_promise_unref (promise);
254 promise = gst_promise_new_with_change_func (_on_offer_set, t, NULL);
255 g_signal_emit_by_name (offeror, "set-local-description", t->offer_desc,
257 promise = gst_promise_new_with_change_func (_on_offer_set, t, NULL);
258 g_signal_emit_by_name (answerer, "set-remote-description", t->offer_desc,
261 promise = gst_promise_new_with_change_func (_on_answer_received, t, NULL);
262 g_signal_emit_by_name (answerer, "create-answer", NULL, promise);
264 test_webrtc_signal_state_unlocked (t, STATE_OFFER_CREATED);
265 g_mutex_unlock (&t->lock);
269 _bus_watch (GstBus * bus, GstMessage * msg, struct test_webrtc *t)
271 g_mutex_lock (&t->lock);
272 switch (GST_MESSAGE_TYPE (msg)) {
273 case GST_MESSAGE_STATE_CHANGED:
274 if (GST_ELEMENT (msg->src) == t->webrtc1
275 || GST_ELEMENT (msg->src) == t->webrtc2) {
276 GstState old, new, pending;
278 gst_message_parse_state_changed (msg, &old, &new, &pending);
281 gchar *dump_name = g_strconcat ("%s-state_changed-",
282 GST_OBJECT_NAME (msg->src), gst_element_state_get_name (old), "_",
283 gst_element_state_get_name (new), NULL);
284 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (msg->src),
285 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
290 case GST_MESSAGE_ERROR:{
292 gchar *dbg_info = NULL;
297 g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc1), NULL);
298 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
299 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
302 g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc2), NULL);
303 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
304 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
308 gst_message_parse_error (msg, &err, &dbg_info);
309 GST_WARNING ("ERROR from element %s: %s\n",
310 GST_OBJECT_NAME (msg->src), err->message);
311 GST_WARNING ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
314 test_webrtc_signal_state_unlocked (t, STATE_ERROR);
317 case GST_MESSAGE_EOS:{
320 dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc1), NULL);
321 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
322 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
324 dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc2), NULL);
325 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
326 GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
329 GST_INFO ("EOS received\n");
330 test_webrtc_signal_state_unlocked (t, STATE_EOS);
338 t->bus_message (t, bus, msg, t->bus_data);
339 g_mutex_unlock (&t->lock);
345 _on_negotiation_needed (GstElement * webrtc, struct test_webrtc *t)
347 g_mutex_lock (&t->lock);
348 if (t->on_negotiation_needed)
349 t->on_negotiation_needed (t, webrtc, t->negotiation_data);
350 if (t->state == STATE_NEW)
351 t->state = STATE_NEGOTIATION_NEEDED;
352 g_cond_broadcast (&t->cond);
353 g_mutex_unlock (&t->lock);
357 _on_ice_candidate (GstElement * webrtc, guint mlineindex, gchar * candidate,
358 struct test_webrtc *t)
362 g_mutex_lock (&t->lock);
363 other = webrtc == t->webrtc1 ? t->webrtc2 : t->webrtc1;
365 if (t->on_ice_candidate)
366 t->on_ice_candidate (t, webrtc, mlineindex, candidate, other,
367 t->ice_candidate_data);
369 g_signal_emit_by_name (other, "add-ice-candidate", mlineindex, candidate);
370 g_mutex_unlock (&t->lock);
374 _on_pad_added (GstElement * webrtc, GstPad * new_pad, struct test_webrtc *t)
376 g_mutex_lock (&t->lock);
378 t->on_pad_added (t, webrtc, new_pad, t->pad_added_data);
379 g_mutex_unlock (&t->lock);
383 _on_data_channel (GstElement * webrtc, GObject * data_channel,
384 struct test_webrtc *t)
386 g_mutex_lock (&t->lock);
387 if (t->on_data_channel)
388 t->on_data_channel (t, webrtc, data_channel, t->data_channel_data);
389 g_mutex_unlock (&t->lock);
393 _pad_added_not_reached (struct test_webrtc *t, GstElement * element,
394 GstPad * pad, gpointer user_data)
396 g_assert_not_reached ();
400 _ice_candidate_not_reached (struct test_webrtc *t, GstElement * element,
401 guint mlineindex, gchar * candidate, GstElement * other, gpointer user_data)
403 g_assert_not_reached ();
407 _negotiation_not_reached (struct test_webrtc *t, GstElement * element,
410 g_assert_not_reached ();
414 _bus_no_errors (struct test_webrtc *t, GstBus * bus, GstMessage * msg,
417 switch (GST_MESSAGE_TYPE (msg)) {
418 case GST_MESSAGE_ERROR:{
419 g_assert_not_reached ();
428 _offer_answer_not_reached (struct test_webrtc *t, GstElement * element,
429 GstPromise * promise, gpointer user_data)
431 g_assert_not_reached ();
435 _on_data_channel_not_reached (struct test_webrtc *t, GstElement * element,
436 GObject * data_channel, gpointer user_data)
438 g_assert_not_reached ();
442 _broadcast (struct test_webrtc *t)
444 g_mutex_lock (&t->lock);
445 g_cond_broadcast (&t->cond);
446 g_mutex_unlock (&t->lock);
450 _unlock_create_thread (GMutex * lock)
452 g_mutex_unlock (lock);
453 return G_SOURCE_REMOVE;
457 _bus_thread (struct test_webrtc *t)
459 g_mutex_lock (&t->lock);
460 t->loop = g_main_loop_new (NULL, FALSE);
461 g_idle_add ((GSourceFunc) _unlock_create_thread, &t->lock);
462 g_cond_broadcast (&t->cond);
464 g_main_loop_run (t->loop);
466 g_mutex_lock (&t->lock);
467 g_main_loop_unref (t->loop);
469 g_cond_broadcast (&t->cond);
470 g_mutex_unlock (&t->lock);
476 element_added_disable_sync (GstBin * bin, GstBin * sub_bin,
477 GstElement * element, gpointer user_data)
479 GObjectClass *class = G_OBJECT_GET_CLASS (element);
480 if (g_object_class_find_property (class, "async"))
481 g_object_set (element, "async", FALSE, NULL);
482 if (g_object_class_find_property (class, "sync"))
483 g_object_set (element, "sync", FALSE, NULL);
486 static struct test_webrtc *
487 test_webrtc_new (void)
489 struct test_webrtc *ret = g_new0 (struct test_webrtc, 1);
491 ret->on_negotiation_needed = _negotiation_not_reached;
492 ret->on_ice_candidate = _ice_candidate_not_reached;
493 ret->on_pad_added = _pad_added_not_reached;
494 ret->on_offer_created = _offer_answer_not_reached;
495 ret->on_answer_created = _offer_answer_not_reached;
496 ret->on_data_channel = _on_data_channel_not_reached;
497 ret->bus_message = _bus_no_errors;
499 g_mutex_init (&ret->lock);
500 g_cond_init (&ret->cond);
502 ret->bus1 = gst_bus_new ();
503 ret->bus2 = gst_bus_new ();
504 gst_bus_add_watch (ret->bus1, (GstBusFunc) _bus_watch, ret);
505 gst_bus_add_watch (ret->bus2, (GstBusFunc) _bus_watch, ret);
506 ret->webrtc1 = gst_element_factory_make ("webrtcbin", NULL);
507 ret->webrtc2 = gst_element_factory_make ("webrtcbin", NULL);
508 fail_unless (ret->webrtc1 != NULL && ret->webrtc2 != NULL);
510 gst_element_set_bus (ret->webrtc1, ret->bus1);
511 gst_element_set_bus (ret->webrtc2, ret->bus2);
513 g_signal_connect (ret->webrtc1, "deep-element-added",
514 G_CALLBACK (element_added_disable_sync), NULL);
515 g_signal_connect (ret->webrtc2, "deep-element-added",
516 G_CALLBACK (element_added_disable_sync), NULL);
517 g_signal_connect (ret->webrtc1, "on-negotiation-needed",
518 G_CALLBACK (_on_negotiation_needed), ret);
519 g_signal_connect (ret->webrtc2, "on-negotiation-needed",
520 G_CALLBACK (_on_negotiation_needed), ret);
521 g_signal_connect (ret->webrtc1, "on-ice-candidate",
522 G_CALLBACK (_on_ice_candidate), ret);
523 g_signal_connect (ret->webrtc2, "on-ice-candidate",
524 G_CALLBACK (_on_ice_candidate), ret);
525 g_signal_connect (ret->webrtc1, "on-data-channel",
526 G_CALLBACK (_on_data_channel), ret);
527 g_signal_connect (ret->webrtc2, "on-data-channel",
528 G_CALLBACK (_on_data_channel), ret);
529 g_signal_connect (ret->webrtc1, "pad-added", G_CALLBACK (_on_pad_added), ret);
530 g_signal_connect (ret->webrtc2, "pad-added", G_CALLBACK (_on_pad_added), ret);
531 g_signal_connect_swapped (ret->webrtc1, "notify::ice-gathering-state",
532 G_CALLBACK (_broadcast), ret);
533 g_signal_connect_swapped (ret->webrtc2, "notify::ice-gathering-state",
534 G_CALLBACK (_broadcast), ret);
535 g_signal_connect_swapped (ret->webrtc1, "notify::ice-connection-state",
536 G_CALLBACK (_broadcast), ret);
537 g_signal_connect_swapped (ret->webrtc2, "notify::ice-connection-state",
538 G_CALLBACK (_broadcast), ret);
540 ret->thread = g_thread_new ("test-webrtc", (GThreadFunc) _bus_thread, ret);
542 g_mutex_lock (&ret->lock);
544 g_cond_wait (&ret->cond, &ret->lock);
545 g_mutex_unlock (&ret->lock);
551 test_webrtc_reset_negotiation (struct test_webrtc *t)
554 gst_webrtc_session_description_free (t->offer_desc);
555 t->offer_desc = NULL;
556 t->offer_set_count = 0;
558 gst_webrtc_session_description_free (t->answer_desc);
559 t->answer_desc = NULL;
560 t->answer_set_count = 0;
562 test_webrtc_signal_state (t, STATE_NEGOTIATION_NEEDED);
566 test_webrtc_free (struct test_webrtc *t)
568 /* Otherwise while one webrtcbin is being destroyed, the other could
569 * generate a signal that calls into the destroyed webrtcbin */
570 g_signal_handlers_disconnect_by_data (t->webrtc1, t);
571 g_signal_handlers_disconnect_by_data (t->webrtc2, t);
573 g_main_loop_quit (t->loop);
574 g_mutex_lock (&t->lock);
576 g_cond_wait (&t->cond, &t->lock);
577 g_mutex_unlock (&t->lock);
579 g_thread_join (t->thread);
581 gst_bus_remove_watch (t->bus1);
582 gst_bus_remove_watch (t->bus2);
584 gst_bus_set_flushing (t->bus1, TRUE);
585 gst_bus_set_flushing (t->bus2, TRUE);
587 gst_object_unref (t->bus1);
588 gst_object_unref (t->bus2);
590 g_list_free_full (t->harnesses, (GDestroyNotify) gst_harness_teardown);
593 t->data_notify (t->user_data);
594 if (t->negotiation_notify)
595 t->negotiation_notify (t->negotiation_data);
596 if (t->ice_candidate_notify)
597 t->ice_candidate_notify (t->ice_candidate_data);
599 t->offer_notify (t->offer_data);
600 if (t->offer_set_notify)
601 t->offer_set_notify (t->offer_set_data);
602 if (t->answer_notify)
603 t->answer_notify (t->answer_data);
604 if (t->answer_set_notify)
605 t->answer_set_notify (t->answer_set_data);
606 if (t->pad_added_notify)
607 t->pad_added_notify (t->pad_added_data);
608 if (t->data_channel_notify)
609 t->data_channel_notify (t->data_channel_data);
611 fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
612 gst_element_set_state (t->webrtc1, GST_STATE_NULL));
613 fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
614 gst_element_set_state (t->webrtc2, GST_STATE_NULL));
616 test_webrtc_reset_negotiation (t);
618 gst_object_unref (t->webrtc1);
619 gst_object_unref (t->webrtc2);
621 g_mutex_clear (&t->lock);
622 g_cond_clear (&t->cond);
628 test_webrtc_create_offer (struct test_webrtc *t, GstElement * webrtc)
632 t->offerror = webrtc == t->webrtc1 ? 1 : 2;
633 promise = gst_promise_new_with_change_func (_on_offer_received, t, NULL);
634 g_signal_emit_by_name (webrtc, "create-offer", NULL, promise);
638 test_webrtc_wait_for_state_mask (struct test_webrtc *t, TestState state)
640 g_mutex_lock (&t->lock);
641 while (((1 << t->state) & state) == 0) {
642 GST_INFO ("test state 0x%x, current 0x%x", state, (1 << t->state));
643 g_cond_wait (&t->cond, &t->lock);
645 GST_INFO ("have test state 0x%x, current 0x%x", state, 1 << t->state);
646 g_mutex_unlock (&t->lock);
650 test_webrtc_wait_for_answer_error_eos (struct test_webrtc *t)
652 TestState states = 0;
653 states |= (1 << STATE_ANSWER_SET);
654 states |= (1 << STATE_EOS);
655 states |= (1 << STATE_ERROR);
656 test_webrtc_wait_for_state_mask (t, states);
661 test_webrtc_wait_for_ice_gathering_complete (struct test_webrtc *t)
663 GstWebRTCICEGatheringState ice_state1, ice_state2;
664 g_mutex_lock (&t->lock);
665 g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
666 g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
667 while (ice_state1 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE &&
668 ice_state2 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
669 g_cond_wait (&t->cond, &t->lock);
670 g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
671 g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
673 g_mutex_unlock (&t->lock);
677 test_webrtc_wait_for_ice_connection (struct test_webrtc *t,
678 GstWebRTCICEConnectionState states)
680 GstWebRTCICEConnectionState ice_state1, ice_state2, current;
681 g_mutex_lock (&t->lock);
682 g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
683 g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
684 current = (1 << ice_state1) | (1 << ice_state2);
685 while ((current & states) == 0 || (current & ~states)) {
686 g_cond_wait (&t->cond, &t->lock);
687 g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
688 g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
689 current = (1 << ice_state1) | (1 << ice_state2);
691 g_mutex_unlock (&t->lock);
695 _pad_added_fakesink (struct test_webrtc *t, GstElement * element,
696 GstPad * pad, gpointer user_data)
700 if (GST_PAD_DIRECTION (pad) != GST_PAD_SRC)
703 h = gst_harness_new_with_element (element, NULL, "src_%u");
704 gst_harness_add_sink_parse (h, "fakesink async=false sync=false");
706 t->harnesses = g_list_prepend (t->harnesses, h);
710 on_negotiation_needed_hit (struct test_webrtc *t, GstElement * element,
713 guint *flag = (guint *) user_data;
718 typedef void (*ValidateSDPFunc) (struct test_webrtc * t, GstElement * element,
719 GstWebRTCSessionDescription * desc, gpointer user_data);
724 ValidateSDPFunc validate;
726 struct validate_sdp *next;
729 #define VAL_SDP_INIT(name,func,data,next) \
730 struct validate_sdp name = { func, data, next }
733 _check_validate_sdp (struct test_webrtc *t, GstElement * element,
734 GstPromise * promise, gpointer user_data)
736 struct validate_sdp *validate = user_data;
737 GstWebRTCSessionDescription *desc = NULL;
739 if (t->offerror == 1 && t->webrtc1 == element)
740 desc = t->offer_desc;
742 desc = t->answer_desc;
745 validate->validate (t, element, desc, validate->user_data);
746 validate = validate->next;
751 test_validate_sdp_full (struct test_webrtc *t, struct validate_sdp *offer,
752 struct validate_sdp *answer, TestState wait_mask,
753 gboolean perform_state_change)
756 t->offer_data = offer;
757 t->on_offer_created = _check_validate_sdp;
759 t->offer_data = NULL;
760 t->on_offer_created = NULL;
763 t->answer_data = answer;
764 t->on_answer_created = _check_validate_sdp;
766 t->answer_data = NULL;
767 t->on_answer_created = NULL;
770 if (perform_state_change) {
771 fail_if (gst_element_set_state (t->webrtc1,
772 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
773 fail_if (gst_element_set_state (t->webrtc2,
774 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
777 test_webrtc_create_offer (t, t->webrtc1);
779 if (wait_mask == 0) {
780 test_webrtc_wait_for_answer_error_eos (t);
781 fail_unless (t->state == STATE_ANSWER_SET);
783 test_webrtc_wait_for_state_mask (t, wait_mask);
788 test_validate_sdp (struct test_webrtc *t, struct validate_sdp *offer,
789 struct validate_sdp *answer)
791 test_validate_sdp_full (t, offer, answer, 0, TRUE);
795 _count_num_sdp_media (struct test_webrtc *t, GstElement * element,
796 GstWebRTCSessionDescription * desc, gpointer user_data)
798 guint expected = GPOINTER_TO_UINT (user_data);
800 fail_unless_equals_int (gst_sdp_message_medias_len (desc->sdp), expected);
803 GST_START_TEST (test_sdp_no_media)
805 struct test_webrtc *t = test_webrtc_new ();
806 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (0), NULL);
807 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (0), NULL);
809 /* check that a no stream connection creates 0 media sections */
811 t->on_negotiation_needed = NULL;
812 test_validate_sdp (t, &offer, &answer);
814 test_webrtc_free (t);
820 add_fake_audio_src_harness (GstHarness * h, gint pt)
822 GstCaps *caps = gst_caps_from_string (OPUS_RTP_CAPS (pt));
823 GstStructure *s = gst_caps_get_structure (caps, 0);
824 gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
825 gst_harness_set_src_caps (h, caps);
826 gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
830 add_fake_video_src_harness (GstHarness * h, gint pt)
832 GstCaps *caps = gst_caps_from_string (VP8_RTP_CAPS (pt));
833 GstStructure *s = gst_caps_get_structure (caps, 0);
834 gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
835 gst_harness_set_src_caps (h, caps);
836 gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
839 static struct test_webrtc *
840 create_audio_test (void)
842 struct test_webrtc *t = test_webrtc_new ();
845 t->on_negotiation_needed = NULL;
846 t->on_ice_candidate = NULL;
847 t->on_pad_added = _pad_added_fakesink;
849 h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
850 add_fake_audio_src_harness (h, 96);
851 t->harnesses = g_list_prepend (t->harnesses, h);
856 GST_START_TEST (test_audio)
858 struct test_webrtc *t = create_audio_test ();
859 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
860 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (1), NULL);
862 /* check that a single stream connection creates the associated number
863 * of media sections */
865 test_validate_sdp (t, &offer, &answer);
866 test_webrtc_free (t);
871 static struct test_webrtc *
872 create_audio_video_test (void)
874 struct test_webrtc *t = create_audio_test ();
877 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
878 add_fake_video_src_harness (h, 97);
879 t->harnesses = g_list_prepend (t->harnesses, h);
884 GST_START_TEST (test_audio_video)
886 struct test_webrtc *t = create_audio_video_test ();
887 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
888 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
890 /* check that a dual stream connection creates the associated number
891 * of media sections */
893 test_validate_sdp (t, &offer, &answer);
894 test_webrtc_free (t);
900 on_sdp_media_direction (struct test_webrtc *t, GstElement * element,
901 GstWebRTCSessionDescription * desc, gpointer user_data)
903 gchar **expected_directions = 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 if (g_strcmp0 (gst_sdp_media_get_media (media), "audio") == 0
910 || g_strcmp0 (gst_sdp_media_get_media (media), "video") == 0) {
911 gboolean have_direction = FALSE;
914 for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
915 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
917 if (g_strcmp0 (attr->key, "inactive") == 0) {
918 fail_unless (have_direction == FALSE,
919 "duplicate/multiple directions for media %u", j);
920 have_direction = TRUE;
921 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
922 } else if (g_strcmp0 (attr->key, "sendonly") == 0) {
923 fail_unless (have_direction == FALSE,
924 "duplicate/multiple directions for media %u", j);
925 have_direction = TRUE;
926 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
927 } else if (g_strcmp0 (attr->key, "recvonly") == 0) {
928 fail_unless (have_direction == FALSE,
929 "duplicate/multiple directions for media %u", j);
930 have_direction = TRUE;
931 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
932 } else if (g_strcmp0 (attr->key, "sendrecv") == 0) {
933 fail_unless (have_direction == FALSE,
934 "duplicate/multiple directions for media %u", j);
935 have_direction = TRUE;
936 fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
939 fail_unless (have_direction, "no direction attribute in media %u", i);
944 GST_START_TEST (test_media_direction)
946 struct test_webrtc *t = create_audio_video_test ();
947 const gchar *expected_offer[] = { "sendrecv", "sendrecv" };
948 const gchar *expected_answer[] = { "sendrecv", "recvonly" };
950 VAL_SDP_INIT (offer_direction, on_sdp_media_direction, expected_offer, NULL);
951 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (2),
953 VAL_SDP_INIT (answer_direction, on_sdp_media_direction, expected_answer,
955 VAL_SDP_INIT (answer, _count_num_sdp_media, GUINT_TO_POINTER (2),
958 /* check the default media directions for transceivers */
960 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
961 add_fake_audio_src_harness (h, 96);
962 t->harnesses = g_list_prepend (t->harnesses, h);
964 test_validate_sdp (t, &offer, &answer);
965 test_webrtc_free (t);
971 on_sdp_media_payload_types (struct test_webrtc *t, GstElement * element,
972 GstWebRTCSessionDescription * desc, gpointer user_data)
974 const GstSDPMedia *vmedia;
977 vmedia = gst_sdp_message_get_media (desc->sdp, 1);
979 for (j = 0; j < gst_sdp_media_attributes_len (vmedia); j++) {
980 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (vmedia, j);
982 if (!g_strcmp0 (attr->key, "rtpmap")) {
983 if (g_str_has_prefix (attr->value, "97")) {
984 fail_unless_equals_string (attr->value, "97 VP8/90000");
985 } else if (g_str_has_prefix (attr->value, "96")) {
986 fail_unless_equals_string (attr->value, "96 red/90000");
987 } else if (g_str_has_prefix (attr->value, "98")) {
988 fail_unless_equals_string (attr->value, "98 ulpfec/90000");
989 } else if (g_str_has_prefix (attr->value, "99")) {
990 fail_unless_equals_string (attr->value, "99 rtx/90000");
991 } else if (g_str_has_prefix (attr->value, "100")) {
992 fail_unless_equals_string (attr->value, "100 rtx/90000");
998 /* In this test we verify that webrtcbin will pick available payload
999 * types when it needs to, in that example for RTX and FEC */
1000 GST_START_TEST (test_payload_types)
1002 struct test_webrtc *t = create_audio_video_test ();
1003 VAL_SDP_INIT (payloads, on_sdp_media_payload_types, NULL, NULL);
1004 VAL_SDP_INIT (offer, _count_num_sdp_media, GUINT_TO_POINTER (2), &payloads);
1005 GstWebRTCRTPTransceiver *trans;
1006 GArray *transceivers;
1008 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1009 fail_unless_equals_int (transceivers->len, 2);
1010 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
1011 g_object_set (trans, "fec-type", GST_WEBRTC_FEC_TYPE_ULP_RED, "do-nack", TRUE,
1013 g_array_unref (transceivers);
1015 /* We don't really care about the answer here */
1016 test_validate_sdp (t, &offer, NULL);
1017 test_webrtc_free (t);
1023 on_sdp_media_setup (struct test_webrtc *t, GstElement * element,
1024 GstWebRTCSessionDescription * desc, gpointer user_data)
1026 gchar **expected_setup = user_data;
1029 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
1030 const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
1031 gboolean have_setup = FALSE;
1034 for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
1035 const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
1037 if (g_strcmp0 (attr->key, "setup") == 0) {
1038 fail_unless (have_setup == FALSE,
1039 "duplicate/multiple setup for media %u", j);
1041 fail_unless (g_strcmp0 (attr->value, expected_setup[i]) == 0);
1044 fail_unless (have_setup, "no setup attribute in media %u", i);
1048 GST_START_TEST (test_media_setup)
1050 struct test_webrtc *t = create_audio_test ();
1051 const gchar *expected_offer[] = { "actpass" };
1052 const gchar *expected_answer[] = { "active" };
1053 VAL_SDP_INIT (offer, on_sdp_media_setup, expected_offer, NULL);
1054 VAL_SDP_INIT (answer, on_sdp_media_setup, expected_answer, NULL);
1056 /* check the default dtls setup negotiation values */
1057 test_validate_sdp (t, &offer, &answer);
1058 test_webrtc_free (t);
1063 GST_START_TEST (test_no_nice_elements_request_pad)
1065 struct test_webrtc *t = test_webrtc_new ();
1066 GstPluginFeature *nicesrc, *nicesink;
1067 GstRegistry *registry;
1070 /* check that the absence of libnice elements posts an error on the bus
1071 * when requesting a pad */
1073 registry = gst_registry_get ();
1074 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1075 nicesink = gst_registry_lookup_feature (registry, "nicesink");
1078 gst_registry_remove_feature (registry, nicesrc);
1080 gst_registry_remove_feature (registry, nicesink);
1082 t->bus_message = NULL;
1084 pad = gst_element_get_request_pad (t->webrtc1, "sink_0");
1085 fail_unless (pad == NULL);
1087 test_webrtc_wait_for_answer_error_eos (t);
1088 fail_unless_equals_int (STATE_ERROR, t->state);
1089 test_webrtc_free (t);
1092 gst_registry_add_feature (registry, nicesrc);
1094 gst_registry_add_feature (registry, nicesink);
1099 GST_START_TEST (test_no_nice_elements_state_change)
1101 struct test_webrtc *t = test_webrtc_new ();
1102 GstPluginFeature *nicesrc, *nicesink;
1103 GstRegistry *registry;
1105 /* check that the absence of libnice elements posts an error on the bus */
1107 registry = gst_registry_get ();
1108 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1109 nicesink = gst_registry_lookup_feature (registry, "nicesink");
1112 gst_registry_remove_feature (registry, nicesrc);
1114 gst_registry_remove_feature (registry, nicesink);
1116 t->bus_message = NULL;
1117 gst_element_set_state (t->webrtc1, GST_STATE_READY);
1119 test_webrtc_wait_for_answer_error_eos (t);
1120 fail_unless_equals_int (STATE_ERROR, t->state);
1121 test_webrtc_free (t);
1124 gst_registry_add_feature (registry, nicesrc);
1126 gst_registry_add_feature (registry, nicesink);
1132 validate_rtc_stats (const GstStructure * s)
1134 GstWebRTCStatsType type = 0;
1138 fail_unless (gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type,
1140 fail_unless (gst_structure_get (s, "id", G_TYPE_STRING, &id, NULL));
1141 fail_unless (gst_structure_get (s, "timestamp", G_TYPE_DOUBLE, &ts, NULL));
1142 fail_unless (type != 0);
1143 fail_unless (ts != 0.);
1144 fail_unless (id != NULL);
1150 validate_codec_stats (const GstStructure * s)
1152 guint pt = 0, clock_rate = 0;
1154 fail_unless (gst_structure_get (s, "payload-type", G_TYPE_UINT, &pt, NULL));
1155 fail_unless (gst_structure_get (s, "clock-rate", G_TYPE_UINT, &clock_rate,
1157 fail_unless (pt >= 0 && pt <= 127);
1158 fail_unless (clock_rate >= 0);
1162 validate_rtc_stream_stats (const GstStructure * s, const GstStructure * stats)
1164 gchar *codec_id, *transport_id;
1165 GstStructure *codec, *transport;
1167 fail_unless (gst_structure_get (s, "codec-id", G_TYPE_STRING, &codec_id,
1169 fail_unless (gst_structure_get (s, "transport-id", G_TYPE_STRING,
1170 &transport_id, NULL));
1172 fail_unless (gst_structure_get (stats, codec_id, GST_TYPE_STRUCTURE, &codec,
1174 fail_unless (gst_structure_get (stats, transport_id, GST_TYPE_STRUCTURE,
1177 fail_unless (codec != NULL);
1178 fail_unless (transport != NULL);
1180 gst_structure_free (transport);
1181 gst_structure_free (codec);
1184 g_free (transport_id);
1188 validate_inbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1190 guint ssrc, fir, pli, nack;
1192 guint64 packets_received, bytes_received;
1195 GstStructure *remote;
1197 validate_rtc_stream_stats (s, stats);
1199 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1200 fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1201 fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1202 fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1203 fail_unless (gst_structure_get (s, "packets-received", G_TYPE_UINT64,
1204 &packets_received, NULL));
1205 fail_unless (gst_structure_get (s, "bytes-received", G_TYPE_UINT64,
1206 &bytes_received, NULL));
1207 fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1208 fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1210 fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1212 fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1214 fail_unless (remote != NULL);
1216 gst_structure_free (remote);
1221 validate_remote_inbound_rtp_stats (const GstStructure * s,
1222 const GstStructure * stats)
1228 GstStructure *local;
1230 validate_rtc_stream_stats (s, stats);
1232 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1233 fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1234 fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1236 fail_unless (gst_structure_get (s, "round-trip-time", G_TYPE_DOUBLE, &rtt,
1238 fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1240 fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1242 fail_unless (local != NULL);
1244 gst_structure_free (local);
1249 validate_outbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1251 guint ssrc, fir, pli, nack;
1252 guint64 packets_sent, bytes_sent;
1254 GstStructure *remote;
1256 validate_rtc_stream_stats (s, stats);
1258 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1259 fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1260 fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1261 fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1262 fail_unless (gst_structure_get (s, "packets-sent", G_TYPE_UINT64,
1263 &packets_sent, NULL));
1264 fail_unless (gst_structure_get (s, "bytes-sent", G_TYPE_UINT64, &bytes_sent,
1266 fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1268 fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1270 fail_unless (remote != NULL);
1272 gst_structure_free (remote);
1277 validate_remote_outbound_rtp_stats (const GstStructure * s,
1278 const GstStructure * stats)
1282 GstStructure *local;
1284 validate_rtc_stream_stats (s, stats);
1286 fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1287 fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1289 fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1291 fail_unless (local != NULL);
1293 gst_structure_free (local);
1298 validate_stats_foreach (GQuark field_id, const GValue * value,
1299 const GstStructure * stats)
1301 const gchar *field = g_quark_to_string (field_id);
1302 GstWebRTCStatsType type;
1303 const GstStructure *s;
1305 fail_unless (GST_VALUE_HOLDS_STRUCTURE (value));
1307 s = gst_value_get_structure (value);
1309 GST_INFO ("validating field %s %" GST_PTR_FORMAT, field, s);
1311 validate_rtc_stats (s);
1312 gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type, NULL);
1313 if (type == GST_WEBRTC_STATS_CODEC) {
1314 validate_codec_stats (s);
1315 } else if (type == GST_WEBRTC_STATS_INBOUND_RTP) {
1316 validate_inbound_rtp_stats (s, stats);
1317 } else if (type == GST_WEBRTC_STATS_OUTBOUND_RTP) {
1318 validate_outbound_rtp_stats (s, stats);
1319 } else if (type == GST_WEBRTC_STATS_REMOTE_INBOUND_RTP) {
1320 validate_remote_inbound_rtp_stats (s, stats);
1321 } else if (type == GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP) {
1322 validate_remote_outbound_rtp_stats (s, stats);
1323 } else if (type == GST_WEBRTC_STATS_CSRC) {
1324 } else if (type == GST_WEBRTC_STATS_PEER_CONNECTION) {
1325 } else if (type == GST_WEBRTC_STATS_DATA_CHANNEL) {
1326 } else if (type == GST_WEBRTC_STATS_STREAM) {
1327 } else if (type == GST_WEBRTC_STATS_TRANSPORT) {
1328 } else if (type == GST_WEBRTC_STATS_CANDIDATE_PAIR) {
1329 } else if (type == GST_WEBRTC_STATS_LOCAL_CANDIDATE) {
1330 } else if (type == GST_WEBRTC_STATS_REMOTE_CANDIDATE) {
1331 } else if (type == GST_WEBRTC_STATS_CERTIFICATE) {
1333 g_assert_not_reached ();
1340 validate_stats (const GstStructure * stats)
1342 gst_structure_foreach (stats,
1343 (GstStructureForeachFunc) validate_stats_foreach, (gpointer) stats);
1347 _on_stats (GstPromise * promise, gpointer user_data)
1349 struct test_webrtc *t = user_data;
1350 const GstStructure *reply = gst_promise_get_reply (promise);
1353 validate_stats (reply);
1354 i = GPOINTER_TO_INT (t->user_data);
1356 t->user_data = GINT_TO_POINTER (i);
1358 test_webrtc_signal_state (t, STATE_CUSTOM);
1360 gst_promise_unref (promise);
1363 GST_START_TEST (test_session_stats)
1365 struct test_webrtc *t = test_webrtc_new ();
1368 /* test that the stats generated without any streams are sane */
1369 t->on_negotiation_needed = NULL;
1370 test_validate_sdp (t, NULL, NULL);
1372 p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1373 g_signal_emit_by_name (t->webrtc1, "get-stats", NULL, p);
1374 p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1375 g_signal_emit_by_name (t->webrtc2, "get-stats", NULL, p);
1377 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1379 test_webrtc_free (t);
1384 GST_START_TEST (test_add_transceiver)
1386 struct test_webrtc *t = test_webrtc_new ();
1387 GstWebRTCRTPTransceiverDirection direction;
1388 GstWebRTCRTPTransceiver *trans;
1390 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
1391 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, NULL,
1393 fail_unless (trans != NULL);
1394 fail_unless_equals_int (direction, trans->direction);
1396 gst_object_unref (trans);
1398 test_webrtc_free (t);
1403 GST_START_TEST (test_get_transceivers)
1405 struct test_webrtc *t = create_audio_test ();
1406 GstWebRTCRTPTransceiver *trans;
1407 GArray *transceivers;
1409 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1410 fail_unless (transceivers != NULL);
1411 fail_unless_equals_int (1, transceivers->len);
1413 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
1414 fail_unless (trans != NULL);
1416 g_array_unref (transceivers);
1418 test_webrtc_free (t);
1423 GST_START_TEST (test_add_recvonly_transceiver)
1425 struct test_webrtc *t = test_webrtc_new ();
1426 GstWebRTCRTPTransceiverDirection direction;
1427 GstWebRTCRTPTransceiver *trans;
1428 const gchar *expected_offer[] = { "recvonly" };
1429 const gchar *expected_answer[] = { "sendonly" };
1430 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
1431 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
1435 /* add a transceiver that will only receive an opus stream and check that
1436 * the created offer is marked as recvonly */
1437 t->on_negotiation_needed = NULL;
1438 t->on_ice_candidate = NULL;
1439 t->on_pad_added = _pad_added_fakesink;
1441 /* setup recvonly transceiver */
1442 caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1443 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1444 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1446 gst_caps_unref (caps);
1447 fail_unless (trans != NULL);
1448 gst_object_unref (trans);
1450 /* setup sendonly peer */
1451 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1452 add_fake_audio_src_harness (h, 96);
1453 t->harnesses = g_list_prepend (t->harnesses, h);
1454 test_validate_sdp (t, &offer, &answer);
1456 test_webrtc_free (t);
1461 GST_START_TEST (test_recvonly_sendonly)
1463 struct test_webrtc *t = test_webrtc_new ();
1464 GstWebRTCRTPTransceiverDirection direction;
1465 GstWebRTCRTPTransceiver *trans;
1466 const gchar *expected_offer[] = { "recvonly", "sendonly" };
1467 const gchar *expected_answer[] = { "sendonly", "recvonly" };
1468 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
1469 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
1472 GArray *transceivers;
1474 /* add a transceiver that will only receive an opus stream and check that
1475 * the created offer is marked as recvonly */
1476 t->on_negotiation_needed = NULL;
1477 t->on_ice_candidate = NULL;
1478 t->on_pad_added = _pad_added_fakesink;
1480 /* setup recvonly transceiver */
1481 caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1482 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1483 g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1485 gst_caps_unref (caps);
1486 fail_unless (trans != NULL);
1487 gst_object_unref (trans);
1489 /* setup sendonly stream */
1490 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
1491 add_fake_audio_src_harness (h, 96);
1492 t->harnesses = g_list_prepend (t->harnesses, h);
1493 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1494 fail_unless (transceivers != NULL);
1495 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
1496 trans->direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
1498 g_array_unref (transceivers);
1500 /* setup sendonly peer */
1501 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1502 add_fake_audio_src_harness (h, 96);
1503 t->harnesses = g_list_prepend (t->harnesses, h);
1505 test_validate_sdp (t, &offer, &answer);
1507 test_webrtc_free (t);
1513 on_sdp_has_datachannel (struct test_webrtc *t, GstElement * element,
1514 GstWebRTCSessionDescription * desc, gpointer user_data)
1516 gboolean have_data_channel = FALSE;
1519 for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
1520 if (_message_media_is_datachannel (desc->sdp, i)) {
1521 /* there should only be one data channel m= section */
1522 fail_unless_equals_int (FALSE, have_data_channel);
1523 have_data_channel = TRUE;
1527 fail_unless_equals_int (TRUE, have_data_channel);
1531 on_channel_error_not_reached (GObject * channel, GError * error,
1534 g_assert_not_reached ();
1537 GST_START_TEST (test_data_channel_create)
1539 struct test_webrtc *t = test_webrtc_new ();
1540 GObject *channel = NULL;
1541 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1542 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1545 t->on_negotiation_needed = NULL;
1546 t->on_ice_candidate = NULL;
1548 fail_if (gst_element_set_state (t->webrtc1,
1549 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1550 fail_if (gst_element_set_state (t->webrtc2,
1551 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1553 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1555 g_assert_nonnull (channel);
1556 g_object_get (channel, "label", &label, NULL);
1557 g_assert_cmpstr (label, ==, "label");
1558 g_signal_connect (channel, "on-error",
1559 G_CALLBACK (on_channel_error_not_reached), NULL);
1561 test_validate_sdp (t, &offer, &answer);
1563 g_object_unref (channel);
1565 test_webrtc_free (t);
1571 have_data_channel (struct test_webrtc *t, GstElement * element,
1572 GObject * our, gpointer user_data)
1574 GObject *other = user_data;
1575 gchar *our_label, *other_label;
1577 g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
1580 g_object_get (our, "label", &our_label, NULL);
1581 g_object_get (other, "label", &other_label, NULL);
1583 g_assert_cmpstr (our_label, ==, other_label);
1586 g_free (other_label);
1588 test_webrtc_signal_state_unlocked (t, STATE_CUSTOM);
1591 GST_START_TEST (test_data_channel_remote_notify)
1593 struct test_webrtc *t = test_webrtc_new ();
1594 GObject *channel = NULL;
1595 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1596 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1598 t->on_negotiation_needed = NULL;
1599 t->on_ice_candidate = NULL;
1600 t->on_data_channel = have_data_channel;
1602 fail_if (gst_element_set_state (t->webrtc1,
1603 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1604 fail_if (gst_element_set_state (t->webrtc2,
1605 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1607 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1609 g_assert_nonnull (channel);
1610 t->data_channel_data = channel;
1611 g_signal_connect (channel, "on-error",
1612 G_CALLBACK (on_channel_error_not_reached), NULL);
1614 fail_if (gst_element_set_state (t->webrtc1,
1615 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1616 fail_if (gst_element_set_state (t->webrtc2,
1617 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1619 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1621 g_object_unref (channel);
1622 test_webrtc_free (t);
1627 static const gchar *test_string = "GStreamer WebRTC is awesome!";
1630 on_message_string (GObject * channel, const gchar * str, struct test_webrtc *t)
1632 gchar *expected = g_object_steal_data (channel, "expected");
1633 g_assert_cmpstr (expected, ==, str);
1636 test_webrtc_signal_state (t, STATE_CUSTOM);
1640 have_data_channel_transfer_string (struct test_webrtc *t, GstElement * element,
1641 GObject * our, gpointer user_data)
1643 GObject *other = user_data;
1644 GstWebRTCDataChannelState state;
1646 g_object_get (our, "ready-state", &state, NULL);
1647 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1648 g_object_get (other, "ready-state", &state, NULL);
1649 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1651 g_object_set_data_full (our, "expected", g_strdup (test_string), g_free);
1652 g_signal_connect (our, "on-message-string", G_CALLBACK (on_message_string),
1655 g_signal_connect (other, "on-error",
1656 G_CALLBACK (on_channel_error_not_reached), NULL);
1657 g_signal_emit_by_name (other, "send-string", test_string);
1660 GST_START_TEST (test_data_channel_transfer_string)
1662 struct test_webrtc *t = test_webrtc_new ();
1663 GObject *channel = NULL;
1664 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1665 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1667 t->on_negotiation_needed = NULL;
1668 t->on_ice_candidate = NULL;
1669 t->on_data_channel = have_data_channel_transfer_string;
1671 fail_if (gst_element_set_state (t->webrtc1,
1672 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1673 fail_if (gst_element_set_state (t->webrtc2,
1674 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1676 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1678 g_assert_nonnull (channel);
1679 t->data_channel_data = channel;
1680 g_signal_connect (channel, "on-error",
1681 G_CALLBACK (on_channel_error_not_reached), NULL);
1683 fail_if (gst_element_set_state (t->webrtc1,
1684 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1685 fail_if (gst_element_set_state (t->webrtc2,
1686 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1688 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1690 g_object_unref (channel);
1691 test_webrtc_free (t);
1696 #define g_assert_cmpbytes(b1, b2) \
1699 const guint8 *d1 = g_bytes_get_data (b1, &l1); \
1700 const guint8 *d2 = g_bytes_get_data (b2, &l2); \
1701 g_assert_cmpmem (d1, l1, d2, l2); \
1705 on_message_data (GObject * channel, GBytes * data, struct test_webrtc *t)
1707 GBytes *expected = g_object_steal_data (channel, "expected");
1708 g_assert_cmpbytes (data, expected);
1709 g_bytes_unref (expected);
1711 test_webrtc_signal_state (t, STATE_CUSTOM);
1715 have_data_channel_transfer_data (struct test_webrtc *t, GstElement * element,
1716 GObject * our, gpointer user_data)
1718 GObject *other = user_data;
1719 GBytes *data = g_bytes_new_static (test_string, strlen (test_string));
1720 GstWebRTCDataChannelState state;
1722 g_object_get (our, "ready-state", &state, NULL);
1723 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1724 g_object_get (other, "ready-state", &state, NULL);
1725 fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1727 g_object_set_data_full (our, "expected", g_bytes_ref (data),
1728 (GDestroyNotify) g_bytes_unref);
1729 g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
1731 g_signal_connect (other, "on-error",
1732 G_CALLBACK (on_channel_error_not_reached), NULL);
1733 g_signal_emit_by_name (other, "send-data", data);
1736 GST_START_TEST (test_data_channel_transfer_data)
1738 struct test_webrtc *t = test_webrtc_new ();
1739 GObject *channel = NULL;
1740 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1741 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1743 t->on_negotiation_needed = NULL;
1744 t->on_ice_candidate = NULL;
1745 t->on_data_channel = have_data_channel_transfer_data;
1747 fail_if (gst_element_set_state (t->webrtc1,
1748 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1749 fail_if (gst_element_set_state (t->webrtc2,
1750 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1752 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1754 g_assert_nonnull (channel);
1755 t->data_channel_data = channel;
1756 g_signal_connect (channel, "on-error",
1757 G_CALLBACK (on_channel_error_not_reached), NULL);
1759 fail_if (gst_element_set_state (t->webrtc1,
1760 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1761 fail_if (gst_element_set_state (t->webrtc2,
1762 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1764 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1766 g_object_unref (channel);
1767 test_webrtc_free (t);
1773 have_data_channel_create_data_channel (struct test_webrtc *t,
1774 GstElement * element, GObject * our, gpointer user_data)
1778 t->on_data_channel = have_data_channel_transfer_string;
1780 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1782 g_assert_nonnull (another);
1783 t->data_channel_data = another;
1784 g_signal_connect (another, "on-error",
1785 G_CALLBACK (on_channel_error_not_reached), NULL);
1788 GST_START_TEST (test_data_channel_create_after_negotiate)
1790 struct test_webrtc *t = test_webrtc_new ();
1791 GObject *channel = NULL;
1792 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1793 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1795 t->on_negotiation_needed = NULL;
1796 t->on_ice_candidate = NULL;
1797 t->on_data_channel = have_data_channel_create_data_channel;
1799 fail_if (gst_element_set_state (t->webrtc1,
1800 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1801 fail_if (gst_element_set_state (t->webrtc2,
1802 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1804 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "prev-label", NULL,
1806 g_assert_nonnull (channel);
1807 t->data_channel_data = channel;
1808 g_signal_connect (channel, "on-error",
1809 G_CALLBACK (on_channel_error_not_reached), NULL);
1811 fail_if (gst_element_set_state (t->webrtc1,
1812 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1813 fail_if (gst_element_set_state (t->webrtc2,
1814 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1816 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1818 g_object_unref (channel);
1819 test_webrtc_free (t);
1825 on_buffered_amount_low_emitted (GObject * channel, struct test_webrtc *t)
1827 test_webrtc_signal_state (t, STATE_CUSTOM);
1831 have_data_channel_check_low_threshold_emitted (struct test_webrtc *t,
1832 GstElement * element, GObject * our, gpointer user_data)
1834 g_signal_connect (our, "on-buffered-amount-low",
1835 G_CALLBACK (on_buffered_amount_low_emitted), t);
1836 g_object_set (our, "buffered-amount-low-threshold", 1, NULL);
1838 g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
1840 g_signal_emit_by_name (our, "send-string", "DATA");
1843 GST_START_TEST (test_data_channel_low_threshold)
1845 struct test_webrtc *t = test_webrtc_new ();
1846 GObject *channel = NULL;
1847 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1848 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1850 t->on_negotiation_needed = NULL;
1851 t->on_ice_candidate = NULL;
1852 t->on_data_channel = have_data_channel_check_low_threshold_emitted;
1854 fail_if (gst_element_set_state (t->webrtc1,
1855 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1856 fail_if (gst_element_set_state (t->webrtc2,
1857 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1859 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1861 g_assert_nonnull (channel);
1862 t->data_channel_data = channel;
1863 g_signal_connect (channel, "on-error",
1864 G_CALLBACK (on_channel_error_not_reached), NULL);
1866 fail_if (gst_element_set_state (t->webrtc1,
1867 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1868 fail_if (gst_element_set_state (t->webrtc2,
1869 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1871 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1873 g_object_unref (channel);
1874 test_webrtc_free (t);
1880 on_channel_error (GObject * channel, GError * error, struct test_webrtc *t)
1882 g_assert_nonnull (error);
1884 test_webrtc_signal_state (t, STATE_CUSTOM);
1888 have_data_channel_transfer_large_data (struct test_webrtc *t,
1889 GstElement * element, GObject * our, gpointer user_data)
1891 GObject *other = user_data;
1892 const gsize size = 1024 * 1024;
1893 guint8 *random_data = g_new (guint8, size);
1897 for (i = 0; i < size; i++)
1898 random_data[i] = (guint8) (i & 0xff);
1900 data = g_bytes_new_static (random_data, size);
1902 g_object_set_data_full (our, "expected", g_bytes_ref (data),
1903 (GDestroyNotify) g_bytes_unref);
1904 g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
1906 g_signal_connect (other, "on-error", G_CALLBACK (on_channel_error), t);
1907 g_signal_emit_by_name (other, "send-data", data);
1910 GST_START_TEST (test_data_channel_max_message_size)
1912 struct test_webrtc *t = test_webrtc_new ();
1913 GObject *channel = NULL;
1914 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1915 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1917 t->on_negotiation_needed = NULL;
1918 t->on_ice_candidate = NULL;
1919 t->on_data_channel = have_data_channel_transfer_large_data;
1921 fail_if (gst_element_set_state (t->webrtc1,
1922 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1923 fail_if (gst_element_set_state (t->webrtc2,
1924 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1926 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1928 g_assert_nonnull (channel);
1929 t->data_channel_data = channel;
1931 fail_if (gst_element_set_state (t->webrtc1,
1932 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1933 fail_if (gst_element_set_state (t->webrtc2,
1934 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1936 test_validate_sdp_full (t, &offer, &answer, 1 << STATE_CUSTOM, FALSE);
1938 g_object_unref (channel);
1939 test_webrtc_free (t);
1945 _on_ready_state_notify (GObject * channel, GParamSpec * pspec,
1946 struct test_webrtc *t)
1948 gint *n_ready = t->data_channel_data;
1949 GstWebRTCDataChannelState ready_state;
1951 g_object_get (channel, "ready-state", &ready_state, NULL);
1953 if (ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
1954 if (g_atomic_int_add (n_ready, 1) >= 1) {
1955 test_webrtc_signal_state (t, STATE_CUSTOM);
1960 GST_START_TEST (test_data_channel_pre_negotiated)
1962 struct test_webrtc *t = test_webrtc_new ();
1963 GObject *channel1 = NULL, *channel2 = NULL;
1964 VAL_SDP_INIT (offer, on_sdp_has_datachannel, NULL, NULL);
1965 VAL_SDP_INIT (answer, on_sdp_has_datachannel, NULL, NULL);
1969 t->on_negotiation_needed = NULL;
1970 t->on_ice_candidate = NULL;
1972 fail_if (gst_element_set_state (t->webrtc1,
1973 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1974 fail_if (gst_element_set_state (t->webrtc2,
1975 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1977 s = gst_structure_new ("application/data-channel", "negotiated",
1978 G_TYPE_BOOLEAN, TRUE, "id", G_TYPE_INT, 1, NULL);
1980 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", s,
1982 g_assert_nonnull (channel1);
1983 g_signal_emit_by_name (t->webrtc2, "create-data-channel", "label", s,
1985 g_assert_nonnull (channel2);
1987 fail_if (gst_element_set_state (t->webrtc1,
1988 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1989 fail_if (gst_element_set_state (t->webrtc2,
1990 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1992 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
1994 t->data_channel_data = &n_ready;
1996 g_signal_connect (channel1, "notify::ready-state",
1997 G_CALLBACK (_on_ready_state_notify), t);
1998 g_signal_connect (channel2, "notify::ready-state",
1999 G_CALLBACK (_on_ready_state_notify), t);
2001 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2002 test_webrtc_signal_state (t, STATE_NEW);
2004 have_data_channel_transfer_string (t, t->webrtc1, channel1, channel2);
2006 test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2008 g_object_unref (channel1);
2009 g_object_unref (channel2);
2010 gst_structure_free (s);
2011 test_webrtc_free (t);
2017 _count_non_rejected_media (struct test_webrtc *t, GstElement * element,
2018 GstWebRTCSessionDescription * sd, gpointer user_data)
2020 guint expected = GPOINTER_TO_UINT (user_data);
2021 guint non_rejected_media;
2024 non_rejected_media = 0;
2026 for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
2027 const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
2029 if (gst_sdp_media_get_port (media) != 0)
2030 non_rejected_media += 1;
2033 fail_unless_equals_int (non_rejected_media, expected);
2037 _check_bundle_tag (struct test_webrtc *t, GstElement * element,
2038 GstWebRTCSessionDescription * sd, gpointer user_data)
2040 gchar **bundled = NULL;
2041 GStrv expected = user_data;
2044 fail_unless (_parse_bundle (sd->sdp, &bundled));
2047 fail_unless_equals_int (g_strv_length (expected), 0);
2049 fail_unless_equals_int (g_strv_length (bundled), g_strv_length (expected));
2052 for (i = 0; i < g_strv_length (expected); i++) {
2053 fail_unless (g_strv_contains ((const gchar **) bundled, expected[i]));
2056 g_strfreev (bundled);
2060 _check_bundle_only_media (struct test_webrtc *t, GstElement * element,
2061 GstWebRTCSessionDescription * sd, gpointer user_data)
2063 gchar **expected_bundle_only = user_data;
2066 for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
2067 const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
2068 const gchar *mid = gst_sdp_media_get_attribute_val (media, "mid");
2070 if (g_strv_contains ((const gchar **) expected_bundle_only, mid))
2071 fail_unless (_media_has_attribute_key (media, "bundle-only"));
2075 GST_START_TEST (test_bundle_audio_video_max_bundle_max_bundle)
2077 struct test_webrtc *t = create_audio_video_test ();
2078 const gchar *bundle[] = { "audio0", "video1", NULL };
2079 const gchar *offer_bundle_only[] = { "video1", NULL };
2080 const gchar *answer_bundle_only[] = { NULL };
2082 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
2083 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &count);
2084 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
2085 GUINT_TO_POINTER (1), &bundle_tag);
2086 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
2087 GUINT_TO_POINTER (2), &bundle_tag);
2088 VAL_SDP_INIT (offer, _check_bundle_only_media, &offer_bundle_only,
2090 VAL_SDP_INIT (answer, _check_bundle_only_media, &answer_bundle_only,
2091 &answer_non_reject);
2093 /* We set a max-bundle policy on the offering webrtcbin,
2094 * this means that all the offered medias should be part
2095 * of the group:BUNDLE attribute, and they should be marked
2098 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2100 /* We also set a max-bundle policy on the answering webrtcbin,
2101 * this means that all the offered medias should be part
2102 * of the group:BUNDLE attribute, but need not be marked
2105 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2108 test_validate_sdp (t, &offer, &answer);
2110 test_webrtc_free (t);
2115 GST_START_TEST (test_bundle_audio_video_max_compat_max_bundle)
2117 struct test_webrtc *t = create_audio_video_test ();
2118 const gchar *bundle[] = { "audio0", "video1", NULL };
2119 const gchar *bundle_only[] = { NULL };
2121 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
2122 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &count);
2123 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
2124 GUINT_TO_POINTER (2), &bundle_tag);
2125 VAL_SDP_INIT (bundle_sdp, _check_bundle_only_media, &bundle_only,
2128 /* We set a max-compat policy on the offering webrtcbin,
2129 * this means that all the offered medias should be part
2130 * of the group:BUNDLE attribute, and they should *not* be marked
2133 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2135 /* We set a max-bundle policy on the answering webrtcbin,
2136 * this means that all the offered medias should be part
2137 * of the group:BUNDLE attribute, but need not be marked
2140 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2143 test_validate_sdp (t, &bundle_sdp, &bundle_sdp);
2145 test_webrtc_free (t);
2150 GST_START_TEST (test_bundle_audio_video_max_bundle_none)
2152 struct test_webrtc *t = create_audio_video_test ();
2153 const gchar *offer_bundle[] = { "audio0", "video1", NULL };
2154 const gchar *offer_bundle_only[] = { "video1", NULL };
2155 const gchar *answer_bundle[] = { NULL };
2156 const gchar *answer_bundle_only[] = { NULL };
2158 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (2), NULL);
2159 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
2160 GUINT_TO_POINTER (1), &count);
2161 VAL_SDP_INIT (offer_bundle_tag, _check_bundle_tag, offer_bundle,
2163 VAL_SDP_INIT (answer_bundle_tag, _check_bundle_tag, answer_bundle,
2165 VAL_SDP_INIT (offer, _check_bundle_only_media, &offer_bundle_only,
2167 VAL_SDP_INIT (answer, _check_bundle_only_media, &answer_bundle_only,
2168 &answer_bundle_tag);
2170 /* We set a max-bundle policy on the offering webrtcbin,
2171 * this means that all the offered medias should be part
2172 * of the group:BUNDLE attribute, and they should be marked
2175 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2177 /* We set a none policy on the answering webrtcbin,
2178 * this means that the answer should contain no bundled
2179 * medias, and as the bundle-policy of the offering webrtcbin
2180 * is set to max-bundle, only one media should be active.
2182 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy", "none");
2184 test_validate_sdp (t, &offer, &answer);
2186 test_webrtc_free (t);
2191 GST_START_TEST (test_bundle_audio_video_data)
2193 struct test_webrtc *t = create_audio_video_test ();
2194 const gchar *bundle[] = { "audio0", "video1", "application2", NULL };
2195 const gchar *offer_bundle_only[] = { "video1", "application2", NULL };
2196 const gchar *answer_bundle_only[] = { NULL };
2197 GObject *channel = NULL;
2199 VAL_SDP_INIT (count, _count_num_sdp_media, GUINT_TO_POINTER (3), NULL);
2200 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &count);
2201 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
2202 GUINT_TO_POINTER (1), &bundle_tag);
2203 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
2204 GUINT_TO_POINTER (3), &bundle_tag);
2205 VAL_SDP_INIT (offer, _check_bundle_only_media, &offer_bundle_only,
2207 VAL_SDP_INIT (answer, _check_bundle_only_media, &answer_bundle_only,
2208 &answer_non_reject);
2210 /* We set a max-bundle policy on the offering webrtcbin,
2211 * this means that all the offered medias should be part
2212 * of the group:BUNDLE attribute, and they should be marked
2215 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2217 /* We also set a max-bundle policy on the answering webrtcbin,
2218 * this means that all the offered medias should be part
2219 * of the group:BUNDLE attribute, but need not be marked
2222 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2225 fail_if (gst_element_set_state (t->webrtc1,
2226 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2227 fail_if (gst_element_set_state (t->webrtc2,
2228 GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2230 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2233 test_validate_sdp (t, &offer, &answer);
2235 g_object_unref (channel);
2236 test_webrtc_free (t);
2241 GST_START_TEST (test_duplicate_nego)
2243 struct test_webrtc *t = create_audio_video_test ();
2244 const gchar *expected_offer[] = { "sendrecv", "sendrecv" };
2245 const gchar *expected_answer[] = { "sendrecv", "recvonly" };
2246 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2247 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2249 guint negotiation_flag = 0;
2251 /* check that negotiating twice succeeds */
2253 t->on_negotiation_needed = on_negotiation_needed_hit;
2254 t->negotiation_data = &negotiation_flag;
2256 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2257 add_fake_audio_src_harness (h, 96);
2258 t->harnesses = g_list_prepend (t->harnesses, h);
2260 test_validate_sdp (t, &offer, &answer);
2261 fail_unless_equals_int (negotiation_flag, 1);
2263 test_webrtc_reset_negotiation (t);
2264 test_validate_sdp (t, &offer, &answer);
2266 test_webrtc_free (t);
2271 GST_START_TEST (test_dual_audio)
2273 struct test_webrtc *t = create_audio_test ();
2274 const gchar *expected_offer[] = { "sendrecv", "sendrecv", };
2275 const gchar *expected_answer[] = { "sendrecv", "recvonly" };
2276 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2277 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2279 GstWebRTCRTPTransceiver *trans;
2280 GArray *transceivers;
2282 /* test that each mline gets a unique transceiver even with the same caps */
2284 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
2285 add_fake_audio_src_harness (h, 96);
2286 t->harnesses = g_list_prepend (t->harnesses, h);
2288 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2289 add_fake_audio_src_harness (h, 96);
2290 t->harnesses = g_list_prepend (t->harnesses, h);
2292 t->on_negotiation_needed = NULL;
2293 test_validate_sdp (t, &offer, &answer);
2295 g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
2296 fail_unless (transceivers != NULL);
2297 fail_unless_equals_int (2, transceivers->len);
2299 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
2300 fail_unless (trans != NULL);
2301 fail_unless_equals_int (trans->mline, 0);
2303 trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
2304 fail_unless (trans != NULL);
2305 fail_unless_equals_int (trans->mline, 1);
2307 g_array_unref (transceivers);
2308 test_webrtc_free (t);
2314 sdp_increasing_session_version (struct test_webrtc *t, GstElement * element,
2315 GstWebRTCSessionDescription * desc, gpointer user_data)
2317 GstWebRTCSessionDescription *previous;
2318 const GstSDPOrigin *our_origin, *previous_origin;
2320 guint64 our_v, previous_v;
2323 TEST_SDP_IS_LOCAL (t, element,
2324 desc) ? "current-local-description" : "current-remote-description";
2325 g_object_get (element, prop, &previous, NULL);
2327 our_origin = gst_sdp_message_get_origin (desc->sdp);
2328 previous_origin = gst_sdp_message_get_origin (previous->sdp);
2330 our_v = g_ascii_strtoull (our_origin->sess_version, NULL, 10);
2331 previous_v = g_ascii_strtoull (previous_origin->sess_version, NULL, 10);
2333 ck_assert_int_lt (previous_v, our_v);
2335 gst_webrtc_session_description_free (previous);
2339 sdp_equal_session_id (struct test_webrtc *t, GstElement * element,
2340 GstWebRTCSessionDescription * desc, gpointer user_data)
2342 GstWebRTCSessionDescription *previous;
2343 const GstSDPOrigin *our_origin, *previous_origin;
2347 TEST_SDP_IS_LOCAL (t, element,
2348 desc) ? "current-local-description" : "current-remote-description";
2349 g_object_get (element, prop, &previous, NULL);
2351 our_origin = gst_sdp_message_get_origin (desc->sdp);
2352 previous_origin = gst_sdp_message_get_origin (previous->sdp);
2354 fail_unless_equals_string (previous_origin->sess_id, our_origin->sess_id);
2355 gst_webrtc_session_description_free (previous);
2359 sdp_media_equal_attribute (struct test_webrtc *t, GstElement * element,
2360 GstWebRTCSessionDescription * desc, GstWebRTCSessionDescription * previous,
2365 n = MIN (gst_sdp_message_medias_len (previous->sdp),
2366 gst_sdp_message_medias_len (desc->sdp));
2368 for (i = 0; i < n; i++) {
2369 const GstSDPMedia *our_media, *other_media;
2370 const gchar *our_mid, *other_mid;
2372 our_media = gst_sdp_message_get_media (desc->sdp, i);
2373 other_media = gst_sdp_message_get_media (previous->sdp, i);
2375 our_mid = gst_sdp_media_get_attribute_val (our_media, attr);
2376 other_mid = gst_sdp_media_get_attribute_val (other_media, attr);
2378 fail_unless_equals_string (our_mid, other_mid);
2383 sdp_media_equal_mid (struct test_webrtc *t, GstElement * element,
2384 GstWebRTCSessionDescription * desc, gpointer user_data)
2386 GstWebRTCSessionDescription *previous;
2390 TEST_SDP_IS_LOCAL (t, element,
2391 desc) ? "current-local-description" : "current-remote-description";
2392 g_object_get (element, prop, &previous, NULL);
2394 sdp_media_equal_attribute (t, element, desc, previous, "mid");
2396 gst_webrtc_session_description_free (previous);
2400 sdp_media_equal_ice_params (struct test_webrtc *t, GstElement * element,
2401 GstWebRTCSessionDescription * desc, gpointer user_data)
2403 GstWebRTCSessionDescription *previous;
2407 TEST_SDP_IS_LOCAL (t, element,
2408 desc) ? "current-local-description" : "current-remote-description";
2409 g_object_get (element, prop, &previous, NULL);
2411 sdp_media_equal_attribute (t, element, desc, previous, "ice-ufrag");
2412 sdp_media_equal_attribute (t, element, desc, previous, "ice-pwd");
2414 gst_webrtc_session_description_free (previous);
2418 sdp_media_equal_fingerprint (struct test_webrtc *t, GstElement * element,
2419 GstWebRTCSessionDescription * desc, gpointer user_data)
2421 GstWebRTCSessionDescription *previous;
2425 TEST_SDP_IS_LOCAL (t, element,
2426 desc) ? "current-local-description" : "current-remote-description";
2427 g_object_get (element, prop, &previous, NULL);
2429 sdp_media_equal_attribute (t, element, desc, previous, "fingerprint");
2431 gst_webrtc_session_description_free (previous);
2434 GST_START_TEST (test_renego_add_stream)
2436 struct test_webrtc *t = create_audio_video_test ();
2437 const gchar *expected_offer[] = { "sendrecv", "sendrecv", "sendrecv" };
2438 const gchar *expected_answer[] = { "sendrecv", "recvonly", "recvonly" };
2439 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2440 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2441 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2442 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2444 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2445 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2447 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2451 /* negotiate an AV stream and then renegotiate an extra stream */
2452 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2453 add_fake_audio_src_harness (h, 96);
2454 t->harnesses = g_list_prepend (t->harnesses, h);
2456 test_validate_sdp (t, &offer, &answer);
2458 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
2459 add_fake_audio_src_harness (h, 98);
2460 t->harnesses = g_list_prepend (t->harnesses, h);
2462 offer.next = &renego_fingerprint;
2463 answer.next = &renego_fingerprint;
2466 test_webrtc_reset_negotiation (t);
2467 test_validate_sdp (t, &offer, &answer);
2469 test_webrtc_free (t);
2474 GST_START_TEST (test_renego_stream_add_data_channel)
2476 struct test_webrtc *t = create_audio_video_test ();
2477 const gchar *expected_offer[] = { "sendrecv", "sendrecv" };
2478 const gchar *expected_answer[] = { "sendrecv", "recvonly" };
2480 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2481 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2482 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2483 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2485 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2486 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2488 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2493 /* negotiate an AV stream and then renegotiate a data channel */
2494 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2495 add_fake_audio_src_harness (h, 96);
2496 t->harnesses = g_list_prepend (t->harnesses, h);
2498 test_validate_sdp (t, &offer, &answer);
2500 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2503 offer.next = &renego_fingerprint;
2504 answer.next = &renego_fingerprint;
2507 test_webrtc_reset_negotiation (t);
2508 test_validate_sdp (t, &offer, &answer);
2510 g_object_unref (channel);
2511 test_webrtc_free (t);
2516 GST_START_TEST (test_renego_data_channel_add_stream)
2518 struct test_webrtc *t = test_webrtc_new ();
2519 const gchar *expected_offer[] = { NULL, "sendrecv" };
2520 const gchar *expected_answer[] = { NULL, "recvonly" };
2521 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2522 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2523 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2524 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2526 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2527 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2529 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2534 /* negotiate an AV stream and then renegotiate a data channel */
2535 t->on_negotiation_needed = NULL;
2536 t->on_ice_candidate = NULL;
2537 t->on_pad_added = _pad_added_fakesink;
2539 fail_if (gst_element_set_state (t->webrtc1,
2540 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2541 fail_if (gst_element_set_state (t->webrtc2,
2542 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2544 g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2547 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2549 h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
2550 add_fake_audio_src_harness (h, 97);
2551 t->harnesses = g_list_prepend (t->harnesses, h);
2553 offer.next = &renego_fingerprint;
2554 answer.next = &renego_fingerprint;
2557 test_webrtc_reset_negotiation (t);
2558 test_validate_sdp_full (t, &offer, &answer, 0, FALSE);
2560 g_object_unref (channel);
2561 test_webrtc_free (t);
2566 GST_START_TEST (test_bundle_renego_add_stream)
2568 struct test_webrtc *t = create_audio_video_test ();
2569 const gchar *expected_offer[] = { "sendrecv", "sendrecv", "sendrecv" };
2570 const gchar *expected_answer[] = { "sendrecv", "recvonly", "recvonly" };
2571 const gchar *bundle[] = { "audio0", "video1", "audio2", NULL };
2572 const gchar *offer_bundle_only[] = { "video1", "audio2", NULL };
2573 const gchar *answer_bundle_only[] = { NULL };
2574 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2575 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2577 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2578 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2580 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2581 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2583 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2585 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &renego_fingerprint);
2586 VAL_SDP_INIT (offer_non_reject, _count_non_rejected_media,
2587 GUINT_TO_POINTER (1), &bundle_tag);
2588 VAL_SDP_INIT (answer_non_reject, _count_non_rejected_media,
2589 GUINT_TO_POINTER (3), &bundle_tag);
2590 VAL_SDP_INIT (offer_bundle_only_sdp, _check_bundle_only_media,
2591 &offer_bundle_only, &offer_non_reject);
2592 VAL_SDP_INIT (answer_bundle_only_sdp, _check_bundle_only_media,
2593 &answer_bundle_only, &answer_non_reject);
2596 /* We set a max-bundle policy on the offering webrtcbin,
2597 * this means that all the offered medias should be part
2598 * of the group:BUNDLE attribute, and they should be marked
2601 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2603 /* We also set a max-bundle policy on the answering webrtcbin,
2604 * this means that all the offered medias should be part
2605 * of the group:BUNDLE attribute, but need not be marked
2608 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2611 /* negotiate an AV stream and then renegotiate an extra stream */
2612 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2613 add_fake_audio_src_harness (h, 96);
2614 t->harnesses = g_list_prepend (t->harnesses, h);
2616 test_validate_sdp (t, &offer, &answer);
2618 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
2619 add_fake_audio_src_harness (h, 98);
2620 t->harnesses = g_list_prepend (t->harnesses, h);
2622 offer.next = &offer_bundle_only_sdp;
2623 answer.next = &answer_bundle_only_sdp;
2626 test_webrtc_reset_negotiation (t);
2627 test_validate_sdp (t, &offer, &answer);
2629 test_webrtc_free (t);
2634 GST_START_TEST (test_bundle_max_compat_max_bundle_renego_add_stream)
2636 struct test_webrtc *t = create_audio_video_test ();
2637 const gchar *expected_offer[] = { "sendrecv", "sendrecv", "sendrecv" };
2638 const gchar *expected_answer[] = { "sendrecv", "recvonly", "recvonly" };
2639 const gchar *bundle[] = { "audio0", "video1", "audio2", NULL };
2640 const gchar *bundle_only[] = { NULL };
2641 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2642 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2644 VAL_SDP_INIT (renego_mid, sdp_media_equal_mid, NULL, NULL);
2645 VAL_SDP_INIT (renego_ice_params, sdp_media_equal_ice_params, NULL,
2647 VAL_SDP_INIT (renego_sess_id, sdp_equal_session_id, NULL, &renego_ice_params);
2648 VAL_SDP_INIT (renego_sess_ver, sdp_increasing_session_version, NULL,
2650 VAL_SDP_INIT (renego_fingerprint, sdp_media_equal_fingerprint, NULL,
2652 VAL_SDP_INIT (bundle_tag, _check_bundle_tag, bundle, &renego_fingerprint);
2653 VAL_SDP_INIT (count_non_reject, _count_non_rejected_media,
2654 GUINT_TO_POINTER (3), &bundle_tag);
2655 VAL_SDP_INIT (bundle_sdp, _check_bundle_only_media, &bundle_only,
2659 /* We set a max-compat policy on the offering webrtcbin,
2660 * this means that all the offered medias should be part
2661 * of the group:BUNDLE attribute, and they should *not* be marked
2664 gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2666 /* We set a max-bundle policy on the answering webrtcbin,
2667 * this means that all the offered medias should be part
2668 * of the group:BUNDLE attribute, but need not be marked
2671 gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2674 /* negotiate an AV stream and then renegotiate an extra stream */
2675 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2676 add_fake_audio_src_harness (h, 96);
2677 t->harnesses = g_list_prepend (t->harnesses, h);
2679 test_validate_sdp (t, &offer, &answer);
2681 h = gst_harness_new_with_element (t->webrtc1, "sink_2", NULL);
2682 add_fake_audio_src_harness (h, 98);
2683 t->harnesses = g_list_prepend (t->harnesses, h);
2685 offer.next = &bundle_sdp;
2686 answer.next = &bundle_sdp;
2689 test_webrtc_reset_negotiation (t);
2690 test_validate_sdp (t, &offer, &answer);
2692 test_webrtc_free (t);
2697 GST_START_TEST (test_renego_transceiver_set_direction)
2699 struct test_webrtc *t = create_audio_test ();
2700 const gchar *expected_offer[] = { "sendrecv" };
2701 const gchar *expected_answer[] = { "sendrecv" };
2702 VAL_SDP_INIT (offer, on_sdp_media_direction, expected_offer, NULL);
2703 VAL_SDP_INIT (answer, on_sdp_media_direction, expected_answer, NULL);
2704 GstWebRTCRTPTransceiver *transceiver;
2708 /* negotiate an AV stream and then change the transceiver direction */
2709 h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
2710 add_fake_audio_src_harness (h, 96);
2711 t->harnesses = g_list_prepend (t->harnesses, h);
2713 test_validate_sdp (t, &offer, &answer);
2715 /* renegotiate an inactive transceiver! */
2716 pad = gst_element_get_static_pad (t->webrtc1, "sink_0");
2717 g_object_get (pad, "transceiver", &transceiver, NULL);
2718 fail_unless (transceiver != NULL);
2719 g_object_set (transceiver, "direction",
2720 GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE, NULL);
2721 expected_offer[0] = "inactive";
2722 expected_answer[0] = "inactive";
2724 /* TODO: also validate EOS events from the inactive change */
2726 test_webrtc_reset_negotiation (t);
2727 test_validate_sdp (t, &offer, &answer);
2729 gst_object_unref (pad);
2730 gst_object_unref (transceiver);
2731 test_webrtc_free (t);
2737 webrtcbin_suite (void)
2739 Suite *s = suite_create ("webrtcbin");
2740 TCase *tc = tcase_create ("general");
2741 GstPluginFeature *nicesrc, *nicesink, *dtlssrtpdec, *dtlssrtpenc;
2742 GstPluginFeature *sctpenc, *sctpdec;
2743 GstRegistry *registry;
2745 registry = gst_registry_get ();
2746 nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
2747 nicesink = gst_registry_lookup_feature (registry, "nicesink");
2748 dtlssrtpenc = gst_registry_lookup_feature (registry, "dtlssrtpenc");
2749 dtlssrtpdec = gst_registry_lookup_feature (registry, "dtlssrtpdec");
2750 sctpenc = gst_registry_lookup_feature (registry, "sctpenc");
2751 sctpdec = gst_registry_lookup_feature (registry, "sctpdec");
2753 tcase_add_test (tc, test_no_nice_elements_request_pad);
2754 tcase_add_test (tc, test_no_nice_elements_state_change);
2755 if (nicesrc && nicesink && dtlssrtpenc && dtlssrtpdec) {
2756 tcase_add_test (tc, test_sdp_no_media);
2757 tcase_add_test (tc, test_session_stats);
2758 tcase_add_test (tc, test_audio);
2759 tcase_add_test (tc, test_audio_video);
2760 tcase_add_test (tc, test_media_direction);
2761 tcase_add_test (tc, test_media_setup);
2762 tcase_add_test (tc, test_add_transceiver);
2763 tcase_add_test (tc, test_get_transceivers);
2764 tcase_add_test (tc, test_add_recvonly_transceiver);
2765 tcase_add_test (tc, test_recvonly_sendonly);
2766 tcase_add_test (tc, test_payload_types);
2767 tcase_add_test (tc, test_bundle_audio_video_max_bundle_max_bundle);
2768 tcase_add_test (tc, test_bundle_audio_video_max_bundle_none);
2769 tcase_add_test (tc, test_bundle_audio_video_max_compat_max_bundle);
2770 tcase_add_test (tc, test_dual_audio);
2771 tcase_add_test (tc, test_duplicate_nego);
2772 tcase_add_test (tc, test_renego_add_stream);
2773 tcase_add_test (tc, test_bundle_renego_add_stream);
2774 tcase_add_test (tc, test_bundle_max_compat_max_bundle_renego_add_stream);
2775 tcase_add_test (tc, test_renego_transceiver_set_direction);
2776 if (sctpenc && sctpdec) {
2777 tcase_add_test (tc, test_data_channel_create);
2778 tcase_add_test (tc, test_data_channel_remote_notify);
2779 tcase_add_test (tc, test_data_channel_transfer_string);
2780 tcase_add_test (tc, test_data_channel_transfer_data);
2781 tcase_add_test (tc, test_data_channel_create_after_negotiate);
2782 tcase_add_test (tc, test_data_channel_low_threshold);
2783 tcase_add_test (tc, test_data_channel_max_message_size);
2784 tcase_add_test (tc, test_data_channel_pre_negotiated);
2785 tcase_add_test (tc, test_bundle_audio_video_data);
2786 tcase_add_test (tc, test_renego_stream_add_data_channel);
2787 tcase_add_test (tc, test_renego_data_channel_add_stream);
2789 GST_WARNING ("Some required elements were not found. "
2790 "All datachannel tests are disabled. sctpenc %p, sctpdec %p", sctpenc,
2794 GST_WARNING ("Some required elements were not found. "
2795 "All media tests are disabled. nicesrc %p, nicesink %p, "
2796 "dtlssrtpenc %p, dtlssrtpdec %p", nicesrc, nicesink, dtlssrtpenc,
2801 gst_object_unref (nicesrc);
2803 gst_object_unref (nicesink);
2805 gst_object_unref (dtlssrtpdec);
2807 gst_object_unref (dtlssrtpenc);
2809 gst_object_unref (sctpenc);
2811 gst_object_unref (sctpdec);
2813 suite_add_tcase (s, tc);
2818 GST_CHECK_MAIN (webrtcbin);