static gboolean _bus_stop_stream_cb (GstBus *bus, GstMessage *message, gpointer user_data) { FsStreamTransmitter *st = user_data; GstState oldstate, newstate, pending; if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_STATE_CHANGED || G_OBJECT_TYPE (GST_MESSAGE_SRC (message)) != GST_TYPE_PIPELINE) return bus_error_callback (bus, message, user_data); gst_message_parse_state_changed (message, &oldstate, &newstate, &pending); if (newstate != GST_STATE_PLAYING) return TRUE; if (pending != GST_STATE_VOID_PENDING) ts_fail ("New state playing, but pending is %d", pending); GST_DEBUG ("Stopping stream transmitter"); fs_stream_transmitter_stop (st); g_object_unref (st); GST_DEBUG ("Stopped stream transmitter"); g_atomic_int_set(&running, FALSE); g_main_loop_quit (loop); return TRUE; }
static void fs_rtp_stream_dispose (GObject *object) { FsRtpStream *self = FS_RTP_STREAM (object); FsStreamTransmitter *st; FsRtpParticipant *participant; FsRtpSession *session = fs_rtp_stream_get_session (self, NULL); if (!session) return; g_mutex_lock (&self->priv->mutex); self->priv->session = NULL; g_mutex_unlock (&self->priv->mutex); FS_RTP_SESSION_LOCK (session); if (self->priv->sending_changed_locked_cb && self->priv->direction & FS_DIRECTION_SEND) self->priv->sending_changed_locked_cb (self, FALSE, self->priv->user_data_for_cb); participant = self->participant; self->participant = NULL; st = self->priv->stream_transmitter; self->priv->stream_transmitter = NULL; if (st) { g_signal_handler_disconnect (st, self->priv->local_candidates_prepared_handler_id); g_signal_handler_disconnect (st, self->priv->new_active_candidate_pair_handler_id); g_signal_handler_disconnect (st, self->priv->new_local_candidate_handler_id); g_signal_handler_disconnect (st, self->priv->error_handler_id); g_signal_handler_disconnect (st, self->priv->known_source_packet_received_handler_id); g_signal_handler_disconnect (st, self->priv->state_changed_handler_id); FS_RTP_SESSION_UNLOCK (session); fs_stream_transmitter_stop (st); g_object_unref (st); FS_RTP_SESSION_LOCK (session); } while (self->substreams) { FsRtpSubStream *substream = self->substreams->data; self->substreams = g_list_remove (self->substreams, substream); FS_RTP_SESSION_UNLOCK (session); g_object_unref (substream); FS_RTP_SESSION_LOCK (session); } FS_RTP_SESSION_UNLOCK (session); g_object_unref (participant); g_object_unref (session); g_object_unref (session); G_OBJECT_CLASS (fs_rtp_stream_parent_class)->dispose (object); }
static void run_nice_transmitter_test (gint n_parameters, GParameter *params, gint flags) { GError *error = NULL; FsTransmitter *trans = NULL, *trans2 = NULL; FsStreamTransmitter *st = NULL, *st2 = NULL; GstBus *bus = NULL; GstElement *pipeline = NULL; GstElement *pipeline2 = NULL; FsNiceTestParticipant *p1 = NULL, *p2 = NULL; memset (buffer_count, 0, sizeof(gint)*4); memset (received_known, 0, sizeof(guint)*4); running = TRUE; associate_on_source = !(flags & FLAG_NO_SOURCE); is_address_local = (flags & FLAG_IS_LOCAL); force_candidates = (flags & FLAG_FORCE_CANDIDATES); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (fs_fake_filter_register ()); if (flags & FLAG_NOT_SENDING) { buffer_count[0][0] = 20; received_known[0][0] = 20; buffer_count[1][0] = 20; received_known[1][0] = 20; } loop = g_main_loop_new (NULL, FALSE); trans = fs_transmitter_new ("nice", 2, 0, &error); if (error) { ts_fail ("Error creating transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); } ts_fail_if (trans == NULL, "No transmitter create, yet error is still NULL"); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (g_signal_connect (trans, "get-recvonly-filter", G_CALLBACK (_get_recvonly_filter), NULL)); trans2 = fs_transmitter_new ("nice", 2, 0, &error); if (error) { ts_fail ("Error creating transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); } ts_fail_if (trans2 == NULL, "No transmitter create, yet error is still NULL"); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (g_signal_connect (trans2, "get-recvonly-filter", G_CALLBACK (_get_recvonly_filter), NULL)); pipeline = setup_pipeline (trans, G_CALLBACK (_handoff_handler1)); pipeline2 = setup_pipeline (trans2, G_CALLBACK (_handoff_handler2)); g_object_set_data (G_OBJECT (trans), "pipeline", pipeline); g_object_set_data (G_OBJECT (trans2), "pipeline", pipeline2); bus = gst_element_get_bus (pipeline); gst_bus_add_watch (bus, bus_error_callback, NULL); gst_object_unref (bus); bus = gst_element_get_bus (pipeline2); gst_bus_add_watch (bus, bus_error_callback, NULL); gst_object_unref (bus); /* * I'm passing the participant because any gobject will work, * but it should be the participant */ p1 = g_object_new (fs_nice_test_participant_get_type (), NULL); p2 = g_object_new (fs_nice_test_participant_get_type (), NULL); st = fs_transmitter_new_stream_transmitter (trans, FS_PARTICIPANT (p1), n_parameters, params, &error); if (error) ts_fail ("Error creating stream transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (st == NULL, "No stream transmitter created, yet error is NULL"); st2 = fs_transmitter_new_stream_transmitter (trans2, FS_PARTICIPANT (p2), n_parameters, params, &error); if (error) ts_fail ("Error creating stream transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (st2 == NULL, "No stream transmitter created, yet error is NULL"); g_object_set (st, "sending", !(flags & FLAG_NOT_SENDING), NULL); g_object_set (st2, "sending", !(flags & FLAG_NOT_SENDING), NULL); ts_fail_unless (g_signal_connect (st, "new-local-candidate", G_CALLBACK (_new_local_candidate), st2), "Could not connect new-local-candidate signal"); ts_fail_unless (g_signal_connect (st, "local-candidates-prepared", G_CALLBACK (_local_candidates_prepared), st2), "Could not connect local-candidates-prepared signal"); ts_fail_unless (g_signal_connect (st, "new-active-candidate-pair", G_CALLBACK (_new_active_candidate_pair), trans), "Could not connect new-active-candidate-pair signal"); ts_fail_unless (g_signal_connect (st, "error", G_CALLBACK (stream_transmitter_error), NULL), "Could not connect error signal"); ts_fail_unless (g_signal_connect (st, "state-changed", G_CALLBACK (_stream_state_changed), trans), "Could not connect to state-changed signal"); ts_fail_unless (g_signal_connect (st, "known-source-packet-received", G_CALLBACK (_known_source_packet_received), GUINT_TO_POINTER (1)), "Could not connect to known-source-packet-received signal"); ts_fail_unless (g_signal_connect (st2, "new-local-candidate", G_CALLBACK (_new_local_candidate), st), "Could not connect new-local-candidate signal"); ts_fail_unless (g_signal_connect (st2, "local-candidates-prepared", G_CALLBACK (_local_candidates_prepared), st), "Could not connect local-candidates-prepared signal"); ts_fail_unless (g_signal_connect (st2, "new-active-candidate-pair", G_CALLBACK (_new_active_candidate_pair), trans2), "Could not connect new-active-candidate-pair signal"); ts_fail_unless (g_signal_connect (st2, "error", G_CALLBACK (stream_transmitter_error), NULL), "Could not connect error signal"); ts_fail_unless (g_signal_connect (st2, "state-changed", G_CALLBACK (_stream_state_changed), trans2), "Could not connect to state-changed signal"); ts_fail_unless (g_signal_connect (st2, "known-source-packet-received", G_CALLBACK (_known_source_packet_received), GUINT_TO_POINTER (2)), "Could not connect to known-source-packet-received signal"); ts_fail_if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing"); ts_fail_if (gst_element_set_state (pipeline2, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing"); if (!fs_stream_transmitter_gather_local_candidates (st, &error)) { if (error) ts_fail ("Could not start gathering local candidates %s", error->message); else ts_fail ("Could not start gathering candidates" " (without a specified error)"); } if (!fs_stream_transmitter_gather_local_candidates (st2, &error)) { if (error) ts_fail ("Could not start gathering local candidates %s", error->message); else ts_fail ("Could not start gathering candidates" " (without a specified error)"); } g_idle_add (check_running, NULL); g_main_loop_run (loop); fs_stream_transmitter_stop (st); fs_stream_transmitter_stop (st2); gst_element_set_state (pipeline, GST_STATE_NULL); gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); gst_element_set_state (pipeline2, GST_STATE_NULL); gst_element_get_state (pipeline2, NULL, NULL, GST_CLOCK_TIME_NONE); if (st) g_object_unref (st); if (st2) g_object_unref (st2); g_object_unref (trans); g_object_unref (trans2); g_object_unref (p1); g_object_unref (p2); gst_object_unref (pipeline); g_main_loop_unref (loop); }
static void run_rawudp_transmitter_test (gint n_parameters, GParameter *params, gint flags) { GError *error = NULL; FsTransmitter *trans; FsStreamTransmitter *st; GstBus *bus = NULL; guint tos; buffer_count[0] = 0; buffer_count[1] = 0; received_known[0] = 0; received_known[1] = 0; pipeline_done = FALSE; has_stun = flags & FLAG_HAS_STUN; associate_on_source = !(flags & FLAG_NO_SOURCE); if ((flags & FLAG_NOT_SENDING) && (flags & FLAG_RECVONLY_FILTER)) { buffer_count[0] = 20; received_known[0] = 20; } loop = g_main_loop_new (NULL, FALSE); trans = fs_transmitter_new ("rawudp", 2, 0, &error); if (error) { ts_fail ("Error creating transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); } ts_fail_if (trans == NULL, "No transmitter create, yet error is still NULL"); g_object_set (trans, "tos", 2, NULL); g_object_get (trans, "tos", &tos, NULL); ts_fail_unless (tos == 2); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (g_signal_connect (trans, "get-recvonly-filter", G_CALLBACK (get_recvonly_filter), NULL)); pipeline = setup_pipeline (trans, G_CALLBACK (_handoff_handler)); bus = gst_element_get_bus (pipeline); gst_bus_add_watch (bus, bus_error_callback, NULL); gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message::error", G_CALLBACK (sync_error_handler), NULL); gst_object_unref (bus); st = fs_transmitter_new_stream_transmitter (trans, NULL, n_parameters, params, &error); if (error) { if (has_stun && error->domain == FS_ERROR && error->code == FS_ERROR_NETWORK && error->message && strstr (error->message, "unreachable")) { GST_WARNING ("Skipping stunserver test, we have no network"); goto skip; } else ts_fail ("Error creating stream transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); } ts_fail_if (st == NULL, "No stream transmitter created, yet error is NULL"); g_object_set (st, "sending", !(flags & FLAG_NOT_SENDING), NULL); ts_fail_unless (g_signal_connect (st, "new-local-candidate", G_CALLBACK (_new_local_candidate), GINT_TO_POINTER (flags)), "Could not connect new-local-candidate signal"); ts_fail_unless (g_signal_connect (st, "local-candidates-prepared", G_CALLBACK (_local_candidates_prepared), GINT_TO_POINTER (flags)), "Could not connect local-candidates-prepared signal"); ts_fail_unless (g_signal_connect (st, "new-active-candidate-pair", G_CALLBACK (_new_active_candidate_pair), trans), "Could not connect new-active-candidate-pair signal"); ts_fail_unless (g_signal_connect (st, "error", G_CALLBACK (stream_transmitter_error), NULL), "Could not connect error signal"); ts_fail_unless (g_signal_connect (st, "known-source-packet-received", G_CALLBACK (_known_source_packet_received), NULL), "Could not connect known-source-packet-received signal"); ts_fail_if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing"); if (!fs_stream_transmitter_gather_local_candidates (st, &error)) { if (error) { ts_fail ("Could not start gathering local candidates (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); } else ts_fail ("Could not start gathering candidates" " (without a specified error)"); } g_idle_add (check_running, NULL); g_main_loop_run (loop); skip: g_mutex_lock (&pipeline_mod_mutex); pipeline_done = TRUE; g_mutex_unlock (&pipeline_mod_mutex); gst_element_set_state (pipeline, GST_STATE_NULL); if (st) { fs_stream_transmitter_stop (st); g_object_unref (st); } g_object_unref (trans); gst_object_unref (pipeline); g_main_loop_unref (loop); }
static void run_shm_transmitter_test (gint flags) { GError *error = NULL; FsTransmitter *trans; FsStreamTransmitter *st; GstBus *bus = NULL; GParameter params[1]; GList *local_cands = NULL; GstStateChangeReturn ret; FsCandidate *cand; GList *remote_cands = NULL; int param_count = 0; gint bus_source; done = FALSE; connected_count = 0; g_cond_init (&cond); g_mutex_init (&test_mutex); buffer_count[0] = 0; buffer_count[1] = 0; received_known[0] = 0; received_known[1] = 0; got_candidates[0] = FALSE; got_candidates[1] = FALSE; got_prepared[0] = FALSE; got_prepared[1] = FALSE; if (unlink ("/tmp/src1") < 0 && errno != ENOENT) fail ("Could not unlink /tmp/src1: %s", strerror (errno)); if (unlink ("/tmp/src2") < 0 && errno != ENOENT) fail ("Could not unlink /tmp/src2: %s", strerror (errno)); local_cands = g_list_append (local_cands, fs_candidate_new (NULL, 1, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, "/tmp/src1", 0)); local_cands = g_list_append (local_cands, fs_candidate_new (NULL, 2, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, "/tmp/src2", 0)); if (flags & FLAG_LOCAL_CANDIDATES) { memset (params, 0, sizeof (GParameter)); params[0].name = "preferred-local-candidates"; g_value_init (¶ms[0].value, FS_TYPE_CANDIDATE_LIST); g_value_take_boxed (¶ms[0].value, local_cands); param_count = 1; } associate_on_source = !(flags & FLAG_NO_SOURCE); if ((flags & FLAG_NOT_SENDING) && (flags & FLAG_RECVONLY_FILTER)) { buffer_count[0] = 20; received_known[0] = 20; } trans = fs_transmitter_new ("shm", 2, 0, &error); if (error) ts_fail ("Error creating transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (trans == NULL, "No transmitter create, yet error is still NULL"); g_clear_error (&error); if (flags & FLAG_RECVONLY_FILTER) ts_fail_unless (g_signal_connect (trans, "get-recvonly-filter", G_CALLBACK (get_recvonly_filter), NULL)); pipeline = setup_pipeline (trans, G_CALLBACK (_handoff_handler)); bus = gst_element_get_bus (pipeline); bus_source = gst_bus_add_watch (bus, bus_error_callback, NULL); gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message::error", G_CALLBACK (sync_error_handler), NULL); gst_object_unref (bus); st = fs_transmitter_new_stream_transmitter (trans, NULL, param_count, params, &error); if (param_count) g_value_unset (¶ms[0].value); if (error) ts_fail ("Error creating stream transmitter: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_if (st == NULL, "No stream transmitter created, yet error is NULL"); g_clear_error (&error); g_object_set (st, "sending", !(flags & FLAG_NOT_SENDING), NULL); ts_fail_unless (g_signal_connect (st, "new-local-candidate", G_CALLBACK (_new_local_candidate), trans), "Could not connect new-local-candidate signal"); ts_fail_unless (g_signal_connect (st, "local-candidates-prepared", G_CALLBACK (_candidate_prepared), NULL), "Could not connect local-candidates-prepared signal"); ts_fail_unless (g_signal_connect (st, "error", G_CALLBACK (stream_transmitter_error), NULL), "Could not connect error signal"); ts_fail_unless (g_signal_connect (st, "known-source-packet-received", G_CALLBACK (_known_source_packet_received), NULL), "Could not connect known-source-packet-received signal"); ts_fail_unless (g_signal_connect (st, "state-changed", G_CALLBACK (_state_changed), NULL), "Could not connect state-changed signal"); if (!fs_stream_transmitter_gather_local_candidates (st, &error)) { if (error) ts_fail ("Could not start gathering local candidates (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); else ts_fail ("Could not start gathering candidates" " (without a specified error)"); } else { ts_fail_unless (error == NULL); } g_clear_error (&error); ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); ts_fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not set the pipeline to playing"); if (!(flags & FLAG_LOCAL_CANDIDATES)) { ret = fs_stream_transmitter_force_remote_candidates (st, local_cands, &error); fs_candidate_list_destroy (local_cands); if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error from add_remote_candidate"); } else { ts_fail_unless (error == NULL); } g_clear_error (&error); cand = fs_candidate_new (NULL, 1, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, 0); cand->username = g_strdup ("/tmp/src1"); remote_cands = g_list_prepend (remote_cands, cand); cand = fs_candidate_new (NULL, 2, FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_UDP, NULL, 0); cand->username = g_strdup ("/tmp/src2"); remote_cands = g_list_prepend (remote_cands, cand); ret = fs_stream_transmitter_force_remote_candidates (st, remote_cands, &error); fs_candidate_list_destroy (remote_cands); if (error) ts_fail ("Error while adding candidate: (%s:%d) %s", g_quark_to_string (error->domain), error->code, error->message); ts_fail_unless (ret == TRUE, "No detailed error from add_remote_candidate"); g_clear_error (&error); g_mutex_lock (&test_mutex); while (connected_count < 2) g_cond_wait (&cond, &test_mutex); g_mutex_unlock (&test_mutex); setup_fakesrc (trans, pipeline, 1); setup_fakesrc (trans, pipeline, 2); g_mutex_lock (&test_mutex); while (!done) g_cond_wait (&cond, &test_mutex); g_mutex_unlock (&test_mutex); fail_unless (got_prepared[0] == TRUE); fail_unless (got_prepared[1] == TRUE); fail_unless (got_candidates[0] == TRUE); fail_unless (got_candidates[1] == TRUE); gst_element_set_state (pipeline, GST_STATE_NULL); if (st) { fs_stream_transmitter_stop (st); g_object_unref (st); } g_object_unref (trans); g_source_remove (bus_source); gst_object_unref (pipeline); g_cond_clear (&cond); g_mutex_clear (&test_mutex); }