2 * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "nicestream.h"
25 #include "nicetransport.h"
27 #define GST_CAT_DEFAULT gst_webrtc_nice_transport_debug
28 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
40 PROP_SEND_BUFFER_SIZE,
41 PROP_RECEIVE_BUFFER_SIZE
44 //static guint gst_webrtc_nice_transport_signals[LAST_SIGNAL] = { 0 };
46 struct _GstWebRTCNiceTransportPrivate
50 gint send_buffer_size;
51 gint receive_buffer_size;
52 gulong on_new_selected_pair_id;
53 gulong on_component_state_changed_id;
56 #define gst_webrtc_nice_transport_parent_class parent_class
57 G_DEFINE_TYPE_WITH_CODE (GstWebRTCNiceTransport, gst_webrtc_nice_transport,
58 GST_TYPE_WEBRTC_ICE_TRANSPORT, G_ADD_PRIVATE (GstWebRTCNiceTransport)
59 GST_DEBUG_CATEGORY_INIT (gst_webrtc_nice_transport_debug,
60 "webrtcnicetransport", 0, "webrtcnicetransport");
63 static NiceComponentType
64 _gst_component_to_nice (GstWebRTCICEComponent component)
67 case GST_WEBRTC_ICE_COMPONENT_RTP:
68 return NICE_COMPONENT_TYPE_RTP;
69 case GST_WEBRTC_ICE_COMPONENT_RTCP:
70 return NICE_COMPONENT_TYPE_RTCP;
72 g_assert_not_reached ();
77 static GstWebRTCICEComponent
78 _nice_component_to_gst (NiceComponentType component)
81 case NICE_COMPONENT_TYPE_RTP:
82 return GST_WEBRTC_ICE_COMPONENT_RTP;
83 case NICE_COMPONENT_TYPE_RTCP:
84 return GST_WEBRTC_ICE_COMPONENT_RTCP;
86 g_assert_not_reached ();
91 static GstWebRTCICEConnectionState
92 _nice_component_state_to_gst (NiceComponentState state)
95 case NICE_COMPONENT_STATE_DISCONNECTED:
96 return GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED;
97 case NICE_COMPONENT_STATE_GATHERING:
98 return GST_WEBRTC_ICE_CONNECTION_STATE_NEW;
99 case NICE_COMPONENT_STATE_CONNECTING:
100 return GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING;
101 case NICE_COMPONENT_STATE_CONNECTED:
102 return GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED;
103 case NICE_COMPONENT_STATE_READY:
104 return GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED;
105 case NICE_COMPONENT_STATE_FAILED:
106 return GST_WEBRTC_ICE_CONNECTION_STATE_FAILED;
108 g_assert_not_reached ();
114 gst_webrtc_nice_transport_set_property (GObject * object, guint prop_id,
115 const GValue * value, GParamSpec * pspec)
117 GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object);
122 gst_object_unref (nice->stream);
123 nice->stream = g_value_dup_object (value);
125 case PROP_SEND_BUFFER_SIZE:
126 nice->priv->send_buffer_size = g_value_get_int (value);
127 gst_webrtc_nice_transport_update_buffer_size (nice);
129 case PROP_RECEIVE_BUFFER_SIZE:
130 nice->priv->receive_buffer_size = g_value_get_int (value);
131 gst_webrtc_nice_transport_update_buffer_size (nice);
134 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 gst_webrtc_nice_transport_get_property (GObject * object, guint prop_id,
141 GValue * value, GParamSpec * pspec)
143 GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object);
147 g_value_set_object (value, nice->stream);
149 case PROP_SEND_BUFFER_SIZE:
150 g_value_set_int (value, nice->priv->send_buffer_size);
152 case PROP_RECEIVE_BUFFER_SIZE:
153 g_value_set_int (value, nice->priv->receive_buffer_size);
156 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
162 gst_webrtc_nice_transport_finalize (GObject * object)
164 GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object);
166 GstWebRTCNice *webrtc_ice;
169 g_object_get (GST_WEBRTC_NICE_STREAM (nice->stream), "ice", &ice_weak, NULL);
170 webrtc_ice = g_weak_ref_get (&ice_weak);
173 g_object_get (webrtc_ice, "agent", &agent, NULL);
175 if (nice->priv->on_component_state_changed_id != 0) {
176 g_signal_handler_disconnect (agent,
177 nice->priv->on_component_state_changed_id);
180 if (nice->priv->on_new_selected_pair_id != 0) {
181 g_signal_handler_disconnect (agent, nice->priv->on_new_selected_pair_id);
184 g_object_unref (agent);
185 gst_object_unref (webrtc_ice);
188 gst_object_unref (nice->stream);
190 G_OBJECT_CLASS (parent_class)->finalize (object);
194 gst_webrtc_nice_transport_update_buffer_size (GstWebRTCNiceTransport * nice)
196 NiceAgent *agent = NULL;
199 GstWebRTCNice *webrtc_ice;
202 g_object_get (GST_WEBRTC_NICE_STREAM (nice->stream), "ice", &ice_weak, NULL);
203 webrtc_ice = g_weak_ref_get (&ice_weak);
205 g_assert (webrtc_ice != NULL);
207 g_object_get (webrtc_ice, "agent", &agent, NULL);
208 g_assert (agent != NULL);
211 nice_agent_get_sockets (agent,
212 GST_WEBRTC_ICE_STREAM (nice->stream)->stream_id, 1);
213 if (sockets == NULL) {
214 g_object_unref (agent);
215 gst_object_unref (webrtc_ice);
219 for (i = 0; i < sockets->len; i++) {
220 GSocket *gsocket = g_ptr_array_index (sockets, i);
222 if (nice->priv->send_buffer_size != 0) {
223 GError *gerror = NULL;
224 if (!g_socket_set_option (gsocket, SOL_SOCKET, SO_SNDBUF,
225 nice->priv->send_buffer_size, &gerror))
226 GST_WARNING_OBJECT (nice, "Could not set send buffer size : %s",
228 g_clear_error (&gerror);
232 if (nice->priv->receive_buffer_size != 0) {
233 GError *gerror = NULL;
234 if (!g_socket_set_option (gsocket, SOL_SOCKET, SO_RCVBUF,
235 nice->priv->receive_buffer_size, &gerror))
236 GST_WARNING_OBJECT (nice, "Could not set send receive size : %s",
238 g_clear_error (&gerror);
242 g_ptr_array_unref (sockets);
243 g_object_unref (agent);
244 gst_object_unref (webrtc_ice);
249 _on_new_selected_pair (NiceAgent * agent, guint stream_id,
250 NiceComponentType component, NiceCandidate * lcandidate,
251 NiceCandidate * rcandidate, GWeakRef * nice_weak)
253 GstWebRTCNiceTransport *nice = g_weak_ref_get (nice_weak);
254 GstWebRTCICETransport *ice;
255 GstWebRTCICEComponent comp = _nice_component_to_gst (component);
261 ice = GST_WEBRTC_ICE_TRANSPORT (nice);
263 g_object_get (nice->stream, "stream-id", &our_stream_id, NULL);
265 if (stream_id != our_stream_id)
267 if (comp != ice->component)
270 gst_webrtc_ice_transport_selected_pair_change (ice);
273 gst_object_unref (nice);
277 _on_component_state_changed (NiceAgent * agent, guint stream_id,
278 NiceComponentType component, NiceComponentState state, GWeakRef * nice_weak)
280 GstWebRTCNiceTransport *nice = g_weak_ref_get (nice_weak);
281 GstWebRTCICETransport *ice;
282 GstWebRTCICEComponent comp = _nice_component_to_gst (component);
288 ice = GST_WEBRTC_ICE_TRANSPORT (nice);
290 g_object_get (nice->stream, "stream-id", &our_stream_id, NULL);
292 if (stream_id != our_stream_id)
294 if (comp != ice->component)
297 GST_DEBUG_OBJECT (ice, "%u %u %s", stream_id, component,
298 nice_component_state_to_string (state));
300 gst_webrtc_ice_transport_connection_state_change (ice,
301 _nice_component_state_to_gst (state));
304 gst_object_unref (nice);
308 weak_new (GstWebRTCNiceTransport * nice)
310 GWeakRef *weak = g_new0 (GWeakRef, 1);
311 g_weak_ref_init (weak, nice);
316 weak_free (GWeakRef * weak)
318 g_weak_ref_clear (weak);
323 gst_webrtc_nice_transport_constructed (GObject * object)
325 GstWebRTCNiceTransport *nice = GST_WEBRTC_NICE_TRANSPORT (object);
326 GstWebRTCICETransport *ice = GST_WEBRTC_ICE_TRANSPORT (object);
327 NiceComponentType component = _gst_component_to_nice (ice->component);
328 gboolean controlling_mode;
331 GstWebRTCNice *webrtc_ice;
334 g_object_get (GST_WEBRTC_NICE_STREAM (nice->stream), "ice", &ice_weak, NULL);
335 webrtc_ice = g_weak_ref_get (&ice_weak);
337 g_assert (webrtc_ice != NULL);
338 g_object_get (nice->stream, "stream-id", &our_stream_id, NULL);
339 g_object_get (webrtc_ice, "agent", &agent, NULL);
341 g_object_get (agent, "controlling-mode", &controlling_mode, NULL);
343 controlling_mode ? GST_WEBRTC_ICE_ROLE_CONTROLLING :
344 GST_WEBRTC_ICE_ROLE_CONTROLLED;
346 nice->priv->on_component_state_changed_id = g_signal_connect_data (agent,
347 "component-state-changed", G_CALLBACK (_on_component_state_changed),
348 weak_new (nice), (GClosureNotify) weak_free, (GConnectFlags) 0);
349 nice->priv->on_new_selected_pair_id = g_signal_connect_data (agent,
350 "new-selected-pair-full", G_CALLBACK (_on_new_selected_pair),
351 weak_new (nice), (GClosureNotify) weak_free, (GConnectFlags) 0);
353 ice->src = gst_element_factory_make ("nicesrc", NULL);
355 g_object_set (ice->src, "agent", agent, "stream", our_stream_id,
356 "component", component, NULL);
358 ice->sink = gst_element_factory_make ("nicesink", NULL);
360 g_object_set (ice->sink, "agent", agent, "stream", our_stream_id,
361 "component", component, "async", FALSE, "enable-last-sample", FALSE,
362 "sync", FALSE, NULL);
365 g_object_unref (agent);
366 gst_object_unref (webrtc_ice);
368 G_OBJECT_CLASS (parent_class)->constructed (object);
372 gst_webrtc_nice_transport_class_init (GstWebRTCNiceTransportClass * klass)
374 GObjectClass *gobject_class = (GObjectClass *) klass;
376 gobject_class->constructed = gst_webrtc_nice_transport_constructed;
377 gobject_class->get_property = gst_webrtc_nice_transport_get_property;
378 gobject_class->set_property = gst_webrtc_nice_transport_set_property;
379 gobject_class->finalize = gst_webrtc_nice_transport_finalize;
381 g_object_class_install_property (gobject_class,
383 g_param_spec_object ("stream",
384 "WebRTC ICE Stream", "ICE stream associated with this transport",
385 GST_TYPE_WEBRTC_NICE_STREAM,
386 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
389 * GstWebRTCNiceTransport:send-buffer-size:
391 * Size of the kernel send buffer in bytes, 0=default
396 g_object_class_install_property (G_OBJECT_CLASS (klass),
397 PROP_SEND_BUFFER_SIZE, g_param_spec_int ("send-buffer-size",
399 "Size of the kernel send buffer in bytes, 0=default", 0, G_MAXINT, 0,
400 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
403 * GstWebRTCNiceTransport:receive-buffer-size:
405 * Size of the kernel receive buffer in bytes, 0=default
410 g_object_class_install_property (G_OBJECT_CLASS (klass),
411 PROP_RECEIVE_BUFFER_SIZE, g_param_spec_int ("receive-buffer-size",
412 "Receive Buffer Size",
413 "Size of the kernel receive buffer in bytes, 0=default", 0, G_MAXINT,
414 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
418 gst_webrtc_nice_transport_init (GstWebRTCNiceTransport * nice)
420 nice->priv = gst_webrtc_nice_transport_get_instance_private (nice);
423 GstWebRTCNiceTransport *
424 gst_webrtc_nice_transport_new (GstWebRTCNiceStream * stream,
425 GstWebRTCICEComponent component)
427 return g_object_new (GST_TYPE_WEBRTC_NICE_TRANSPORT, "stream", stream,
428 "component", component, NULL);