static void kms_webrtc_session_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { KmsWebrtcSession *self = KMS_WEBRTC_SESSION (object); KMS_SDP_SESSION_LOCK (self); switch (prop_id) { case PROP_STUN_SERVER_IP: g_value_set_string (value, self->stun_server_ip); break; case PROP_STUN_SERVER_PORT: g_value_set_uint (value, self->stun_server_port); break; case PROP_TURN_URL: g_value_set_string (value, self->turn_url); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } KMS_SDP_SESSION_UNLOCK (self); }
static void kms_base_rtp_session_update_conn_state (KmsBaseRtpSession * self) { GHashTableIter iter; gpointer key, v; gboolean emit = FALSE; KmsConnectionState new_state = KMS_CONNECTION_STATE_CONNECTED; KMS_SDP_SESSION_LOCK (self); g_hash_table_iter_init (&iter, self->conns); while (g_hash_table_iter_next (&iter, &key, &v)) { KmsIRtpConnection *conn = KMS_I_RTP_CONNECTION (v); gboolean connected; g_object_get (conn, "connected", &connected, NULL); if (!connected) { new_state = KMS_CONNECTION_STATE_DISCONNECTED; break; } } if (self->conn_state != new_state) { GST_DEBUG_OBJECT (self, "Connection state changed to '%d'", new_state); self->conn_state = new_state; emit = TRUE; } KMS_SDP_SESSION_UNLOCK (self); if (emit) { g_signal_emit (G_OBJECT (self), obj_signals[CONNECTION_STATE_CHANGED], 0, new_state); } }
static gboolean kms_webrtc_session_gather_candidates (KmsWebrtcSession * self) { KmsBaseRtpSession *base_rtp_sess = KMS_BASE_RTP_SESSION (self); GHashTableIter iter; gpointer key, v; gboolean ret = TRUE; GST_DEBUG_OBJECT (self, "Gather candidates"); KMS_SDP_SESSION_LOCK (self); g_hash_table_iter_init (&iter, base_rtp_sess->conns); while (g_hash_table_iter_next (&iter, &key, &v)) { KmsWebRtcBaseConnection *conn = KMS_WEBRTC_BASE_CONNECTION (v); kms_webrtc_session_set_stun_server_info (self, conn); kms_webrtc_session_set_relay_info (self, conn); if (!kms_ice_base_agent_start_gathering_candidates (conn->agent, conn->stream_id)) { GST_ERROR_OBJECT (self, "Failed to start candidate gathering for '%s'.", conn->name); ret = FALSE; } } KMS_SDP_SESSION_UNLOCK (self); return ret; }
static void rtp_ssrc_demux_new_ssrc_pad (GstElement * ssrcdemux, guint ssrc, GstPad * pad, KmsBaseRtpSession * self) { const gchar *rtp_pad_name = GST_OBJECT_NAME (pad); gchar *rtcp_pad_name; SdpMediaConfig *mconf; GstPad *src, *sink; GST_DEBUG_OBJECT (self, "pad: %" GST_PTR_FORMAT " ssrc: %" G_GUINT32_FORMAT, pad, ssrc); KMS_SDP_SESSION_LOCK (self); if (self->remote_audio_ssrc == ssrc || ssrcs_are_mapped (ssrcdemux, self->local_audio_ssrc, ssrc)) { mconf = self->audio_neg_mconf; } else if (self->remote_video_ssrc == ssrc || ssrcs_are_mapped (ssrcdemux, self->local_video_ssrc, ssrc)) { mconf = self->video_neg_mconf; } else { if (!kms_i_rtp_session_manager_custom_ssrc_management (self->manager, self, ssrcdemux, ssrc, pad)) { GST_ERROR_OBJECT (pad, "SSRC %" G_GUINT32_FORMAT " not matching.", ssrc); } goto end; } /* RTP */ sink = kms_i_rtp_session_manager_request_rtp_sink (self->manager, self, mconf); kms_base_rtp_session_link_pads (pad, sink); g_object_unref (sink); /* RTCP */ rtcp_pad_name = g_strconcat ("rtcp_", rtp_pad_name, NULL); src = gst_element_get_static_pad (ssrcdemux, rtcp_pad_name); g_free (rtcp_pad_name); sink = kms_i_rtp_session_manager_request_rtcp_sink (self->manager, self, mconf); kms_base_rtp_session_link_pads (src, sink); g_object_unref (src); g_object_unref (sink); end: KMS_SDP_SESSION_UNLOCK (self); }
static void kms_base_rtp_session_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { KmsBaseRtpSession *self = KMS_BASE_RTP_SESSION (object); KMS_SDP_SESSION_LOCK (self); switch (property_id) { case PROP_CONNECTION_STATE: g_value_set_enum (value, self->conn_state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_SDP_SESSION_UNLOCK (self); }
static void kms_base_rtp_session_check_conn_status (KmsBaseRtpSession * self) { GHashTableIter iter; gpointer key, v; KMS_SDP_SESSION_LOCK (self); g_hash_table_iter_init (&iter, self->conns); while (g_hash_table_iter_next (&iter, &key, &v)) { KmsIRtpConnection *conn = KMS_I_RTP_CONNECTION (v); g_signal_connect_data (conn, "connected", G_CALLBACK (kms_base_rtp_session_connected_cb), self, NULL, 0); } KMS_SDP_SESSION_UNLOCK (self); kms_base_rtp_session_update_conn_state (self); }
static void kms_ice_nice_agent_sdp_msg_add_ice_candidate (KmsWebrtcSession * self, NiceAgent * agent, NiceCandidate * nice_cand, KmsIceBaseAgent * parent) { KmsSdpSession *sdp_sess = KMS_SDP_SESSION (self); SdpMessageContext *local_sdp_ctx = sdp_sess->local_sdp_ctx; const GSList *item = kms_sdp_message_context_get_medias (local_sdp_ctx); GList *list = NULL, *iterator = NULL; KMS_SDP_SESSION_LOCK (self); for (; item != NULL; item = g_slist_next (item)) { SdpMediaConfig *mconf = item->data; gint idx = kms_sdp_media_config_get_id (mconf); const gchar *mid; if (kms_sdp_media_config_is_inactive (mconf)) { GST_DEBUG_OBJECT (self, "Media (id=%d) inactive", idx); continue; } mid = kms_ice_nice_agent_sdp_media_add_ice_candidate (self, mconf, agent, nice_cand); if (mid != NULL) { KmsIceCandidate *candidate = kms_ice_candidate_new_from_nice (agent, nice_cand, mid, idx); list = g_list_append (list, candidate); } } KMS_SDP_SESSION_UNLOCK (self); for (iterator = list; iterator; iterator = iterator->next) { g_signal_emit_by_name (parent, "on-ice-candidate", KMS_ICE_CANDIDATE (iterator->data)); } g_list_free_full (list, g_object_unref); }
static void kms_base_rtp_session_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { KmsBaseRtpSession *self = KMS_BASE_RTP_SESSION (object); KMS_SDP_SESSION_LOCK (self); switch (property_id) { case PROP_CONNECTION_STATE: g_value_set_enum (value, self->conn_state); break; case PROP_STATS:{ gchar *struct_name, *obj_name; GstStructure *s; obj_name = gst_element_get_name (self); struct_name = g_strdup_printf ("%s-stats", obj_name); g_free (obj_name); /* Video and audio latencies are avery small values in */ /* nano seconds so there is no harm in casting them to */ /* uint64 even we might lose a bit of preccision. */ s = gst_structure_new (struct_name, "video-e2e-latency", G_TYPE_UINT64, (guint64) self->stats->vi, "audio-e2e-latency", G_TYPE_UINT64, (guint64) self->stats->ai, NULL); g_free (struct_name); g_value_take_boxed (value, s); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_SDP_SESSION_UNLOCK (self); }
static gboolean kms_webrtc_session_add_ice_candidate (KmsWebrtcSession * self, KmsIceCandidate * candidate) { guint8 index; gboolean ret; GST_DEBUG_OBJECT (self, "Add ICE candidate '%s'", kms_ice_candidate_get_candidate (candidate)); KMS_SDP_SESSION_LOCK (self); self->remote_candidates = g_slist_append (self->remote_candidates, g_object_ref (candidate)); ret = kms_webrtc_session_set_remote_ice_candidate (self, candidate); index = kms_ice_candidate_get_sdp_m_line_index (candidate); kms_webrtc_session_remote_sdp_add_ice_candidate (self, candidate, index); KMS_SDP_SESSION_UNLOCK (self); return ret; }
static void kms_webrtc_session_gathering_done (KmsIceBaseAgent * agent, gchar * stream_id, KmsWebrtcSession * self) { KmsBaseRtpSession *base_rtp_sess = KMS_BASE_RTP_SESSION (self); GHashTableIter iter; gpointer key, v; gboolean done = TRUE; GST_DEBUG_OBJECT (self, "ICE gathering done for '%s' stream.", stream_id); KMS_SDP_SESSION_LOCK (self); g_hash_table_iter_init (&iter, base_rtp_sess->conns); while (g_hash_table_iter_next (&iter, &key, &v)) { KmsWebRtcBaseConnection *conn = KMS_WEBRTC_BASE_CONNECTION (v); if (g_strcmp0 (stream_id, conn->stream_id) == 0) { conn->ice_gathering_done = TRUE; } if (!conn->ice_gathering_done) { done = FALSE; } } if (done) { kms_webrtc_session_local_sdp_add_default_info (self); } KMS_SDP_SESSION_UNLOCK (self); if (done) { g_signal_emit (G_OBJECT (self), kms_webrtc_session_signals[SIGNAL_ON_ICE_GATHERING_DONE], 0); } }