mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
8e3472faee
Instead of synchronising at the ICE transport, do clock sync for the RTP stream at the DTLS transport via the dtlssrtpenc rtp-sync property. This avoids delaying RTCP while waiting until it is time to output an RTP packet when rtcp-mux is enabled. https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/1212
262 lines
7.7 KiB
C
262 lines
7.7 KiB
C
/* 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);
|
|
|
|
enum
|
|
{
|
|
SIGNAL_0,
|
|
LAST_SIGNAL,
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_STREAM,
|
|
};
|
|
|
|
//static guint gst_webrtc_nice_transport_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
struct _GstWebRTCNiceTransportPrivate
|
|
{
|
|
gboolean running;
|
|
};
|
|
|
|
#define gst_webrtc_nice_transport_parent_class parent_class
|
|
G_DEFINE_TYPE_WITH_CODE (GstWebRTCNiceTransport, gst_webrtc_nice_transport,
|
|
GST_TYPE_WEBRTC_ICE_TRANSPORT, G_ADD_PRIVATE (GstWebRTCNiceTransport)
|
|
GST_DEBUG_CATEGORY_INIT (gst_webrtc_nice_transport_debug,
|
|
"webrtcnicetransport", 0, "webrtcnicetransport");
|
|
);
|
|
|
|
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,
|
|
"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;
|
|
|
|
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 = gst_webrtc_nice_transport_get_instance_private (nice);
|
|
}
|
|
|
|
GstWebRTCNiceTransport *
|
|
gst_webrtc_nice_transport_new (GstWebRTCICEStream * stream,
|
|
GstWebRTCICEComponent component)
|
|
{
|
|
return g_object_new (GST_TYPE_WEBRTC_NICE_TRANSPORT, "stream", stream,
|
|
"component", component, NULL);
|
|
}
|