| /* GStreamer |
| * Copyright (C) 2017 Matthew Waters <matthew@centricular.com> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include "config.h" |
| #endif |
| |
| #include "nicetransport.h" |
| #include "icestream.h" |
| |
| #define GST_CAT_DEFAULT gst_webrtc_nice_transport_debug |
| GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); |
| |
| #define gst_webrtc_nice_transport_parent_class parent_class |
| G_DEFINE_TYPE_WITH_CODE (GstWebRTCNiceTransport, gst_webrtc_nice_transport, |
| GST_TYPE_WEBRTC_ICE_TRANSPORT, |
| GST_DEBUG_CATEGORY_INIT (gst_webrtc_nice_transport_debug, |
| "webrtcnicetransport", 0, "webrtcnicetransport"); |
| ); |
| |
| enum |
| { |
| SIGNAL_0, |
| LAST_SIGNAL, |
| }; |
| |
| enum |
| { |
| PROP_0, |
| PROP_STREAM, |
| }; |
| |
| //static guint gst_webrtc_nice_transport_signals[LAST_SIGNAL] = { 0 }; |
| |
| struct _GstWebRTCNiceTransportPrivate |
| { |
| gboolean running; |
| }; |
| |
| static NiceComponentType |
| _gst_component_to_nice (GstWebRTCICEComponent component) |
| { |
| switch (component) { |
| case GST_WEBRTC_ICE_COMPONENT_RTP: |
| return NICE_COMPONENT_TYPE_RTP; |
| case GST_WEBRTC_ICE_COMPONENT_RTCP: |
| return NICE_COMPONENT_TYPE_RTCP; |
| default: |
| g_assert_not_reached (); |
| return 0; |
| } |
| } |
| |
| static GstWebRTCICEComponent |
| _nice_component_to_gst (NiceComponentType component) |
| { |
| switch (component) { |
| case NICE_COMPONENT_TYPE_RTP: |
| return GST_WEBRTC_ICE_COMPONENT_RTP; |
| case NICE_COMPONENT_TYPE_RTCP: |
| return GST_WEBRTC_ICE_COMPONENT_RTCP; |
| default: |
| g_assert_not_reached (); |
| return 0; |
| } |
| } |
| |
| static GstWebRTCICEConnectionState |
| _nice_component_state_to_gst (NiceComponentState state) |
| { |
| switch (state) { |
| case NICE_COMPONENT_STATE_DISCONNECTED: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED; |
| case NICE_COMPONENT_STATE_GATHERING: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_NEW; |
| case NICE_COMPONENT_STATE_CONNECTING: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING; |
| case NICE_COMPONENT_STATE_CONNECTED: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED; |
| case NICE_COMPONENT_STATE_READY: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED; |
| case NICE_COMPONENT_STATE_FAILED: |
| return GST_WEBRTC_ICE_CONNECTION_STATE_FAILED; |
| default: |
| g_assert_not_reached (); |
| return 0; |
| } |
| } |
| |
| static void |
| gst_webrtc_nice_transport_set_property (GObject * object, guint prop_id, |
| const GValue * value, GParamSpec * pspec) |
| { |
| GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object); |
| |
| switch (prop_id) { |
| case PROP_STREAM: |
| if (nice->stream) |
| gst_object_unref (nice->stream); |
| nice->stream = g_value_dup_object (value); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static void |
| gst_webrtc_nice_transport_get_property (GObject * object, guint prop_id, |
| GValue * value, GParamSpec * pspec) |
| { |
| GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object); |
| |
| switch (prop_id) { |
| case PROP_STREAM: |
| g_value_set_object (value, nice->stream); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static void |
| gst_webrtc_nice_transport_finalize (GObject * object) |
| { |
| GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object); |
| |
| gst_object_unref (nice->stream); |
| |
| G_OBJECT_CLASS (parent_class)->finalize (object); |
| } |
| |
| static void |
| _on_new_selected_pair (NiceAgent * agent, guint stream_id, |
| NiceComponentType component, NiceCandidate * lcandidate, |
| NiceCandidate * rcandidate, GstWebRTCNiceTransport * nice) |
| { |
| GstWebRTCICETransport *ice = GST_WEBRTC_ICE_TRANSPORT (nice); |
| GstWebRTCICEComponent comp = _nice_component_to_gst (component); |
| guint our_stream_id; |
| |
| g_object_get (nice->stream, "stream-id", &our_stream_id, NULL); |
| |
| if (stream_id != our_stream_id) |
| return; |
| if (comp != ice->component) |
| return; |
| |
| gst_webrtc_ice_transport_selected_pair_change (ice); |
| } |
| |
| static void |
| _on_component_state_changed (NiceAgent * agent, guint stream_id, |
| NiceComponentType component, NiceComponentState state, |
| GstWebRTCNiceTransport * nice) |
| { |
| GstWebRTCICETransport *ice = GST_WEBRTC_ICE_TRANSPORT (nice); |
| GstWebRTCICEComponent comp = _nice_component_to_gst (component); |
| guint our_stream_id; |
| |
| g_object_get (nice->stream, "stream-id", &our_stream_id, NULL); |
| |
| if (stream_id != our_stream_id) |
| return; |
| if (comp != ice->component) |
| return; |
| |
| GST_DEBUG_OBJECT (ice, "%u %u %s", stream_id, component, |
| nice_component_state_to_string (state)); |
| |
| gst_webrtc_ice_transport_connection_state_change (ice, |
| _nice_component_state_to_gst (state)); |
| } |
| |
| static void |
| gst_webrtc_nice_transport_constructed (GObject * object) |
| { |
| GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object); |
| GstWebRTCICETransport *ice = GST_WEBRTC_ICE_TRANSPORT (object); |
| NiceComponentType component = _gst_component_to_nice (ice->component); |
| gboolean controlling_mode; |
| guint our_stream_id; |
| NiceAgent *agent; |
| |
| g_object_get (nice->stream, "stream-id", &our_stream_id, NULL); |
| g_object_get (nice->stream->ice, "agent", &agent, NULL); |
| |
| g_object_get (agent, "controlling-mode", &controlling_mode, NULL); |
| ice->role = |
| controlling_mode ? GST_WEBRTC_ICE_ROLE_CONTROLLING : |
| GST_WEBRTC_ICE_ROLE_CONTROLLED; |
| |
| g_signal_connect (agent, "component-state-changed", |
| G_CALLBACK (_on_component_state_changed), nice); |
| g_signal_connect (agent, "new-selected-pair-full", |
| G_CALLBACK (_on_new_selected_pair), nice); |
| |
| ice->src = gst_element_factory_make ("nicesrc", NULL); |
| if (ice->src) { |
| g_object_set (ice->src, "agent", agent, "stream", our_stream_id, |
| "component", component, NULL); |
| } |
| ice->sink = gst_element_factory_make ("nicesink", NULL); |
| if (ice->sink) { |
| g_object_set (ice->sink, "agent", agent, "stream", our_stream_id, |
| "component", component, "async", FALSE, "enable-last-sample", FALSE, |
| NULL); |
| if (ice->component == GST_WEBRTC_ICE_COMPONENT_RTCP) |
| g_object_set (ice->sink, "sync", FALSE, NULL); |
| } |
| |
| g_object_unref (agent); |
| |
| G_OBJECT_CLASS (parent_class)->constructed (object); |
| } |
| |
| static void |
| gst_webrtc_nice_transport_class_init (GstWebRTCNiceTransportClass * klass) |
| { |
| GObjectClass *gobject_class = (GObjectClass *) klass; |
| |
| g_type_class_add_private (klass, sizeof (GstWebRTCNiceTransportPrivate)); |
| |
| gobject_class->constructed = gst_webrtc_nice_transport_constructed; |
| gobject_class->get_property = gst_webrtc_nice_transport_get_property; |
| gobject_class->set_property = gst_webrtc_nice_transport_set_property; |
| gobject_class->finalize = gst_webrtc_nice_transport_finalize; |
| |
| g_object_class_install_property (gobject_class, |
| PROP_STREAM, |
| g_param_spec_object ("stream", |
| "WebRTC ICE Stream", "ICE stream associated with this transport", |
| GST_TYPE_WEBRTC_ICE_STREAM, |
| G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); |
| } |
| |
| static void |
| gst_webrtc_nice_transport_init (GstWebRTCNiceTransport * nice) |
| { |
| nice->priv = |
| G_TYPE_INSTANCE_GET_PRIVATE ((nice), GST_TYPE_WEBRTC_NICE_TRANSPORT, |
| GstWebRTCNiceTransportPrivate); |
| } |
| |
| GstWebRTCNiceTransport * |
| gst_webrtc_nice_transport_new (GstWebRTCICEStream * stream, |
| GstWebRTCICEComponent component) |
| { |
| return g_object_new (GST_TYPE_WEBRTC_NICE_TRANSPORT, "stream", stream, |
| "component", component, NULL); |
| } |