Commit 07e9374e authored by Matthew Waters's avatar Matthew Waters 🐨

webrtcbin: add support for data channels based on SCTP

Mostly follows the W3C specification
https://www.w3.org/TR/webrtc/#peer-to-peer-data-api

With contributions from:
Mathieu Duponchelle <mathieu@centricular.com>

https://bugzilla.gnome.org/show_bug.cgi?id=794351
parent cf46d49b
......@@ -7,11 +7,13 @@ noinst_HEADERS = \
gstwebrtcstats.h \
icestream.h \
nicetransport.h \
sctptransport.h \
transportstream.h \
transportsendbin.h \
transportreceivebin.h \
utils.h \
webrtcsdp.h \
webrtcdatachannel.h \
webrtctransceiver.h
libgstwebrtc_la_SOURCES = \
......@@ -21,11 +23,13 @@ libgstwebrtc_la_SOURCES = \
gstwebrtcstats.c \
icestream.c \
nicetransport.c \
sctptransport.c \
transportstream.c \
transportsendbin.c \
transportreceivebin.c \
utils.c \
webrtcsdp.c \
webrtcdatachannel.c \
webrtctransceiver.c
libgstwebrtc_la_SOURCES += $(BUILT_SOURCES)
......@@ -40,12 +44,14 @@ libgstwebrtc_la_CFLAGS = \
$(GST_SDP_CFLAGS) \
$(NICE_CFLAGS)
libgstwebrtc_la_LIBADD = \
-lgstapp-@GST_API_VERSION@ \
$(GST_PLUGINS_BASE_LIBS) \
$(GST_BASE_LIBS) \
$(GST_LIBS) \
$(GST_SDP_LIBS) \
$(NICE_LIBS) \
$(top_builddir)/gst-libs/gst/webrtc/libgstwebrtc-@GST_API_VERSION@.la
$(top_builddir)/gst-libs/gst/webrtc/libgstwebrtc-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/sctp/libgstsctp-@GST_API_VERSION@.la
libgstwebrtc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstwebrtc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
......
......@@ -41,6 +41,10 @@ typedef struct _GstWebRTCNiceTransport GstWebRTCNiceTransport;
typedef struct _GstWebRTCNiceTransportClass GstWebRTCNiceTransportClass;
typedef struct _GstWebRTCNiceTransportPrivate GstWebRTCNiceTransportPrivate;
typedef struct _GstWebRTCSCTPTransport GstWebRTCSCTPTransport;
typedef struct _GstWebRTCSCTPTransportClass GstWebRTCSCTPTransportClass;
typedef struct _GstWebRTCSCTPTransportPrivate GstWebRTCSCTPTransportPrivate;
typedef struct _TransportStream TransportStream;
typedef struct _TransportStreamClass TransportStreamClass;
......
This diff is collapsed.
......@@ -23,6 +23,7 @@
#include <gst/sdp/sdp.h>
#include "fwd.h"
#include "gstwebrtcice.h"
#include "transportstream.h"
G_BEGIN_DECLS
......@@ -37,7 +38,9 @@ typedef enum
GST_WEBRTC_BIN_ERROR_INVALID_STATE,
GST_WEBRTC_BIN_ERROR_BAD_SDP,
GST_WEBRTC_BIN_ERROR_FINGERPRINT,
} GstWebRTCJSEPSDPError;
GST_WEBRTC_BIN_ERROR_SCTP_FAILURE,
GST_WEBRTC_BIN_ERROR_DATA_CHANNEL_FAILURE,
} GstWebRTCError;
GType gst_webrtc_bin_pad_get_type(void);
#define GST_TYPE_WEBRTC_BIN_PAD (gst_webrtc_bin_pad_get_type())
......@@ -107,6 +110,13 @@ struct _GstWebRTCBinPrivate
GArray *transceivers;
GArray *session_mid_map;
GArray *transports;
GArray *data_channels;
/* list of data channels we've received a sctp stream for but no data
* channel protocol for */
GArray *pending_data_channels;
GstWebRTCSCTPTransport *sctp_transport;
TransportStream *data_channel_transport;
GstWebRTCICE *ice;
GArray *ice_stream_map;
......@@ -115,7 +125,6 @@ struct _GstWebRTCBinPrivate
/* peerconnection variables */
gboolean is_closed;
gboolean need_negotiation;
gpointer sctp_transport; /* FIXME */
/* peerconnection helper thread for promises */
GMainContext *main_context;
......
......@@ -4,6 +4,7 @@ webrtc_sources = [
'gstwebrtcstats.c',
'icestream.c',
'nicetransport.c',
'sctptransport.c',
'gstwebrtcbin.c',
'transportreceivebin.c',
'transportsendbin.c',
......@@ -11,6 +12,7 @@ webrtc_sources = [
'utils.c',
'webrtcsdp.c',
'webrtctransceiver.c',
'webrtcdatachannel.c',
]
libnice_dep = dependency('nice', version : '>=0.1.14', required : get_option('webrtc'),
......@@ -22,7 +24,7 @@ if libnice_dep.found()
webrtc_sources,
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
include_directories : [configinc],
dependencies : [libnice_dep, gstbase_dep, gstsdp_dep, gstwebrtc_dep],
dependencies : [libnice_dep, gstbase_dep, gstsdp_dep, gstapp_dep, gstwebrtc_dep, gstsctp_dep],
install : true,
install_dir : plugins_install_dir,
)
......
/* GStreamer
* Copyright (C) 2018 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 <stdio.h>
#include "sctptransport.h"
#include "gstwebrtcbin.h"
#define GST_CAT_DEFAULT gst_webrtc_sctp_transport_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
enum
{
SIGNAL_0,
ON_RESET_STREAM_SIGNAL,
LAST_SIGNAL,
};
enum
{
PROP_0,
PROP_TRANSPORT,
PROP_STATE,
PROP_MAX_MESSAGE_SIZE,
PROP_MAX_CHANNELS,
};
static guint gst_webrtc_sctp_transport_signals[LAST_SIGNAL] = { 0 };
#define gst_webrtc_sctp_transport_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstWebRTCSCTPTransport, gst_webrtc_sctp_transport,
GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (gst_webrtc_sctp_transport_debug,
"webrtcsctptransport", 0, "webrtcsctptransport"););
typedef void (*SCTPTask) (GstWebRTCSCTPTransport * sctp, gpointer user_data);
struct task
{
GstWebRTCSCTPTransport *sctp;
SCTPTask func;
gpointer user_data;
GDestroyNotify notify;
};
static void
_execute_task (GstWebRTCBin * webrtc, struct task *task)
{
if (task->func)
task->func (task->sctp, task->user_data);
}
static void
_free_task (struct task *task)
{
gst_object_unref (task->sctp);
if (task->notify)
task->notify (task->user_data);
g_free (task);
}
static void
_sctp_enqueue_task (GstWebRTCSCTPTransport * sctp, SCTPTask func,
gpointer user_data, GDestroyNotify notify)
{
struct task *task = g_new0 (struct task, 1);
task->sctp = gst_object_ref (sctp);
task->func = func;
task->user_data = user_data;
task->notify = notify;
gst_webrtc_bin_enqueue_task (sctp->webrtcbin,
(GstWebRTCBinFunc) _execute_task, task, (GDestroyNotify) _free_task);
}
static void
_emit_stream_reset (GstWebRTCSCTPTransport * sctp, gpointer user_data)
{
guint stream_id = GPOINTER_TO_UINT (user_data);
g_signal_emit (sctp,
gst_webrtc_sctp_transport_signals[ON_RESET_STREAM_SIGNAL], 0, stream_id);
}
static void
_on_sctp_dec_pad_removed (GstElement * sctpdec, GstPad * pad,
GstWebRTCSCTPTransport * sctp)
{
guint stream_id;
if (sscanf (GST_PAD_NAME (pad), "src_%u", &stream_id) != 1)
return;
_sctp_enqueue_task (sctp, (SCTPTask) _emit_stream_reset,
GUINT_TO_POINTER (stream_id), NULL);
}
static void
_on_sctp_association_established (GstElement * sctpenc, gboolean established,
GstWebRTCSCTPTransport * sctp)
{
GST_OBJECT_LOCK (sctp);
if (established)
sctp->state = GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTED;
else
sctp->state = GST_WEBRTC_SCTP_TRANSPORT_STATE_CLOSED;
sctp->association_established = established;
GST_OBJECT_UNLOCK (sctp);
g_object_notify (G_OBJECT (sctp), "state");
}
static void
gst_webrtc_sctp_transport_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
// GstWebRTCSCTPTransport *sctp = GST_WEBRTC_SCTP_TRANSPORT (object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_webrtc_sctp_transport_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstWebRTCSCTPTransport *sctp = GST_WEBRTC_SCTP_TRANSPORT (object);
switch (prop_id) {
case PROP_TRANSPORT:
g_value_set_object (value, sctp->transport);
break;
case PROP_STATE:
g_value_set_enum (value, sctp->state);
break;
case PROP_MAX_MESSAGE_SIZE:
g_value_set_uint64 (value, sctp->max_message_size);
break;
case PROP_MAX_CHANNELS:
g_value_set_uint (value, sctp->max_channels);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_webrtc_sctp_transport_finalize (GObject * object)
{
GstWebRTCSCTPTransport *sctp = GST_WEBRTC_SCTP_TRANSPORT (object);
g_signal_handlers_disconnect_by_data (sctp->sctpdec, sctp);
g_signal_handlers_disconnect_by_data (sctp->sctpenc, sctp);
gst_object_unref (sctp->sctpdec);
gst_object_unref (sctp->sctpenc);
g_clear_object (&sctp->transport);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_webrtc_sctp_transport_constructed (GObject * object)
{
GstWebRTCSCTPTransport *sctp = GST_WEBRTC_SCTP_TRANSPORT (object);
guint association_id;
association_id = g_random_int_range (0, G_MAXUINT16);
sctp->sctpdec =
g_object_ref_sink (gst_element_factory_make ("sctpdec", NULL));
g_object_set (sctp->sctpdec, "sctp-association-id", association_id, NULL);
sctp->sctpenc =
g_object_ref_sink (gst_element_factory_make ("sctpenc", NULL));
g_object_set (sctp->sctpenc, "sctp-association-id", association_id, NULL);
g_signal_connect (sctp->sctpdec, "pad-removed",
G_CALLBACK (_on_sctp_dec_pad_removed), sctp);
g_signal_connect (sctp->sctpenc, "sctp-association-established",
G_CALLBACK (_on_sctp_association_established), sctp);
G_OBJECT_CLASS (parent_class)->constructed (object);
}
static void
gst_webrtc_sctp_transport_class_init (GstWebRTCSCTPTransportClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->constructed = gst_webrtc_sctp_transport_constructed;
gobject_class->get_property = gst_webrtc_sctp_transport_get_property;
gobject_class->set_property = gst_webrtc_sctp_transport_set_property;
gobject_class->finalize = gst_webrtc_sctp_transport_finalize;
g_object_class_install_property (gobject_class,
PROP_TRANSPORT,
g_param_spec_object ("transport",
"WebRTC DTLS Transport",
"DTLS transport used for this SCTP transport",
GST_TYPE_WEBRTC_DTLS_TRANSPORT,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_STATE,
g_param_spec_enum ("state",
"WebRTC SCTP Transport state", "WebRTC SCTP Transport state",
GST_TYPE_WEBRTC_SCTP_TRANSPORT_STATE,
GST_WEBRTC_SCTP_TRANSPORT_STATE_NEW,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_MAX_MESSAGE_SIZE,
g_param_spec_uint64 ("max-message-size",
"Maximum message size",
"Maximum message size as reported by the transport", 0, G_MAXUINT64,
0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_MAX_CHANNELS,
g_param_spec_uint ("max-channels",
"Maximum number of channels", "Maximum number of channels",
0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GstWebRTCSCTPTransport::reset-stream:
* @object: the #GstWebRTCSCTPTransport
* @stream_id: the SCTP stream that was reset
*/
gst_webrtc_sctp_transport_signals[ON_RESET_STREAM_SIGNAL] =
g_signal_new ("stream-reset", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic,
G_TYPE_NONE, 1, G_TYPE_UINT);
}
static void
gst_webrtc_sctp_transport_init (GstWebRTCSCTPTransport * nice)
{
}
GstWebRTCSCTPTransport *
gst_webrtc_sctp_transport_new (void)
{
return g_object_new (GST_TYPE_WEBRTC_SCTP_TRANSPORT, NULL);
}
/* GStreamer
* Copyright (C) 2018 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.
*/
#ifndef __GST_WEBRTC_SCTP_TRANSPORT_H__
#define __GST_WEBRTC_SCTP_TRANSPORT_H__
#include <gst/gst.h>
/* libnice */
#include <agent.h>
#include <gst/webrtc/webrtc.h>
#include "gstwebrtcice.h"
G_BEGIN_DECLS
GType gst_webrtc_sctp_transport_get_type(void);
#define GST_TYPE_WEBRTC_SCTP_TRANSPORT (gst_webrtc_sctp_transport_get_type())
#define GST_WEBRTC_SCTP_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WEBRTC_SCTP_TRANSPORT,GstWebRTCSCTPTransport))
#define GST_IS_WEBRTC_SCTP_TRANSPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WEBRTC_SCTP_TRANSPORT))
#define GST_WEBRTC_SCTP_TRANSPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_WEBRTC_SCTP_TRANSPORT,GstWebRTCSCTPTransportClass))
#define GST_IS_WEBRTC_SCTP_TRANSPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_WEBRTC_SCTP_TRANSPORT))
#define GST_WEBRTC_SCTP_TRANSPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_WEBRTC_SCTP_TRANSPORT,GstWebRTCSCTPTransportClass))
struct _GstWebRTCSCTPTransport
{
GstObject parent;
GstWebRTCDTLSTransport *transport;
GstWebRTCSCTPTransportState state;
guint64 max_message_size;
guint max_channels;
gboolean association_established;
GstElement *sctpdec;
GstElement *sctpenc;
GstWebRTCBin *webrtcbin;
};
struct _GstWebRTCSCTPTransportClass
{
GstObjectClass parent_class;
};
GstWebRTCSCTPTransport * gst_webrtc_sctp_transport_new (void);
G_END_DECLS
#endif /* __GST_WEBRTC_SCTP_TRANSPORT_H__ */
......@@ -25,23 +25,24 @@
#include "utils.h"
/*
* ,----------------------------transport_receive_%u-----------------------------,
* ; (rtp) ;
* ; ,---nicesrc----, ,-capsfilter-, ,----dtlssrtpdec----, ,--funnel--, ;
* ; ; src o--o sink src o--o sink rtp_src o------o sink_0 ; ;
* ; '--------------' '------------' ; ; ; src o--o rtp_src
* ; ; rtcp_src o-, ,--o sink_1 ; ;
* ; '-------------------' ; ; '----------' ;
* ; ; ; ,--funnel--, ;
* ; '-+--o sink_0 ; ;
* ; ,-' ; src o--o rtcp_src
* ; (rtcp) ; ,-o sink_1 ; ;
* ; ,---nicesrc----, ,-capsfilter-, ,----dtlssrtpdec----, ; ; '----------' ;
* ; ; src o--o sink src o--o sink rtp_src o-' ; ;
* ; '--------------' '------------' ; ; ; ;
* ; ; rtcp_src o----' ;
* ; '-------------------' ;
* '-----------------------------------------------------------------------------'
* ,----------------------------transport_receive_%u----------------------------,
* ; (rtp/data) ;
* ; ,---nicesrc----, ,-capsfilter-, ,---dtlssrtpdec---, ,--funnel--, ;
* ; ; src o--o sink src o--o sink rtp_src o-------o sink_0 ; ;
* ; '--------------' '------------' ; ; ; src o--o rtp_src
* ; ; rtcp_src o---, ,-o sink_1 ; ;
* ; ; ; ; ; '----------' ;
* ; ; data_src o-, ; ; ,--funnel--, ;
* ; '-----------------' ; '-+-o sink_0 ; ;
* ; ,---dtlssrtpdec---, ; ,-' ; src o--o rtcp_src
* ; (rtcp) ; rtp_src o-+-' ,-o sink_1 ; ;
* ; ,---nicesrc----, ,-capsfilter-, ; ; ; ; '----------' ;
* ; ; src o--o sink src o--o sink rtcp_src o-+---' ,--funnel--, ;
* ; '--------------' '------------' ; ; '-----o sink_0 ; ;
* ; ; data_src o-, ; src o--o data_src
* ; '-----------------' '-----o sink_1 ; ;
* ; '----------' ;
* '----------------------------------------------------------------------------'
*
* Do we really wnat to be *that* permissive in what we accept?
*
......@@ -70,6 +71,12 @@ GST_STATIC_PAD_TEMPLATE ("rtcp_src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-rtp"));
static GstStaticPadTemplate data_sink_template =
GST_STATIC_PAD_TEMPLATE ("data_src",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
enum
{
PROP_0,
......@@ -336,6 +343,21 @@ transport_receive_bin_constructed (GObject * object)
gst_element_add_pad (GST_ELEMENT (receive), ghost);
gst_object_unref (pad);
/* create funnel for data_src */
funnel = gst_element_factory_make ("funnel", NULL);
gst_bin_add (GST_BIN (receive), funnel);
if (!gst_element_link_pads (receive->stream->transport->dtlssrtpdec,
"data_src", funnel, "sink_0"))
g_warn_if_reached ();
if (!gst_element_link_pads (receive->stream->rtcp_transport->dtlssrtpdec,
"data_src", funnel, "sink_1"))
g_warn_if_reached ();
pad = gst_element_get_static_pad (funnel, "src");
ghost = gst_ghost_pad_new ("data_src", pad);
gst_element_add_pad (GST_ELEMENT (receive), ghost);
gst_object_unref (pad);
G_OBJECT_CLASS (parent_class)->constructed (object);
}
......@@ -350,6 +372,8 @@ transport_receive_bin_class_init (TransportReceiveBinClass * klass)
gst_element_class_add_static_pad_template (element_class, &rtp_sink_template);
gst_element_class_add_static_pad_template (element_class,
&rtcp_sink_template);
gst_element_class_add_static_pad_template (element_class,
&data_sink_template);
gst_element_class_set_metadata (element_class, "WebRTC Transport Receive Bin",
"Filter/Network/WebRTC", "A bin for webrtc connections",
......
......@@ -27,9 +27,11 @@
/*
* ,------------------------transport_send_%u-------------------------,
* ; ,-----dtlssrtpenc---, ;
* rtp_sink o--------------------------o rtp_sink_0 ; ,---nicesink---, ;
* ; ; src o--o sink ; ;
* ; ,--outputselector--, ,-o rtcp_sink_0 ; '--------------' ;
* data_sink o--------------------------o data_sink ; ;
* ; ; ; ,---nicesink---, ;
* rtp_sink o--------------------------o rtp_sink_0 src o--o sink ; ;
* ; ; ; '--------------' ;
* ; ,--outputselector--, ,-o rtcp_sink_0 ; ;
* ; ; src_0 o-' '-------------------' ;
* rtcp_sink ;---o sink ; ,----dtlssrtpenc----, ,---nicesink---, ;
* ; ; src_1 o---o rtcp_sink_0 src o--o sink ; ;
......@@ -61,6 +63,12 @@ GST_STATIC_PAD_TEMPLATE ("rtcp_sink",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("application/x-rtp"));
static GstStaticPadTemplate data_sink_template =
GST_STATIC_PAD_TEMPLATE ("data_sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
enum
{
PROP_0,
......@@ -422,6 +430,16 @@ transport_send_bin_constructed (GObject * object)
gst_element_add_pad (GST_ELEMENT (send), ghost);
gst_object_unref (pad);
/* push the data stream onto the RTP dtls element */
templ = _find_pad_template (transport->dtlssrtpenc,
GST_PAD_SINK, GST_PAD_REQUEST, "data_sink");
pad = gst_element_request_pad (transport->dtlssrtpenc, templ, "data_sink",
NULL);
ghost = gst_ghost_pad_new ("data_sink", pad);
gst_element_add_pad (GST_ELEMENT (send), ghost);
gst_object_unref (pad);
/* RTCP */
transport = send->stream->rtcp_transport;
/* Do the common init for the context struct */
......@@ -509,6 +527,8 @@ transport_send_bin_class_init (TransportSendBinClass * klass)
gst_element_class_add_static_pad_template (element_class, &rtp_sink_template);
gst_element_class_add_static_pad_template (element_class,
&rtcp_sink_template);
gst_element_class_add_static_pad_template (element_class,
&data_sink_template);
gst_element_class_set_metadata (element_class, "WebRTC Transport Send Bin",
"Filter/Network/WebRTC", "A bin for webrtc connections",
......
This diff is collapsed.
/* GStreamer
* Copyright (C) 2018 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.
*/
#ifndef __GST_WEBRTC_DATA_CHANNEL_H__
#define __GST_WEBRTC_DATA_CHANNEL_H__
#include <gst/gst.h>
#include <gst/webrtc/webrtc_fwd.h>
#include <gst/webrtc/dtlstransport.h>
#include "sctptransport.h"
G_BEGIN_DECLS
GST_WEBRTC_API
GType gst_webrtc_data_channel_get_type(void);
#define GST_TYPE_WEBRTC_DATA_CHANNEL (gst_webrtc_data_channel_get_type())
#define GST_WEBRTC_DATA_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WEBRTC_DATA_CHANNEL,GstWebRTCDataChannel))
#define GST_IS_WEBRTC_DATA_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WEBRTC_DATA_CHANNEL))
#define GST_WEBRTC_DATA_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_WEBRTC_DATA_CHANNEL,GstWebRTCDataChannelClass))
#define GST_IS_WEBRTC_DATA_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_WEBRTC_DATA_CHANNEL))
#define GST_WEBRTC_DATA_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_WEBRTC_DATA_CHANNEL,GstWebRTCDataChannelClass))
typedef struct _GstWebRTCDataChannel GstWebRTCDataChannel;
typedef struct _GstWebRTCDataChannelClass GstWebRTCDataChannelClass;
struct _GstWebRTCDataChannel
{
GstObject parent;
GstWebRTCSCTPTransport *sctp_transport;
GstElement *appsrc;
GstElement *appsink;
gchar *label;
gboolean ordered;
guint max_packet_lifetime;
guint max_retransmits;
gchar *protocol;
gboolean negotiated;
gint id;
GstWebRTCPriorityType priority;
GstWebRTCDataChannelState ready_state;
guint64 buffered_amount;
guint64 buffered_amount_low_threshold;
GstWebRTCBin *webrtcbin;
gboolean opened;
gulong src_probe;
GError *stored_error;
gpointer _padding[GST_PADDING];
};
struct _GstWebRTCDataChannelClass
{
GstObjectClass parent_class;
gpointer _padding[GST_PADDING];
};
void gst_webrtc_data_channel_start_negotiation (GstWebRTCDataChannel *channel);
void gst_webrtc_data_channel_set_sctp_transport (GstWebRTCDataChannel *channel,
GstWebRTCSCTPTransport *sctp);
G_END_DECLS
#endif /* __GST_WEBRTC_DATA_CHANNEL_H__ */
......@@ -714,3 +714,38 @@ _generate_ice_credentials (gchar ** ufrag, gchar ** password)
ice_credential_chars[g_random_int_range (0,
strlen (ice_credential_chars))];
}
int
_get_sctp_port_from_media (const GstSDPMedia * media)
{
int sctpmap = -1, i;
for (i = 0; i < gst_sdp_media_attributes_len (media); i++) {
const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);
if (g_strcmp0 (attr->key, "sctp-port") == 0) {
return atoi (attr->value);
} else if (g_strcmp0 (attr->key, "sctpmap") == 0) {
sctpmap = atoi (attr->value);
}
}
if (sctpmap >= 0)
GST_LOG ("no sctp-port attribute in media");
return sctpmap;
}
guint64
_get_sctp_max_message_size_from_media (const GstSDPMedia * media)
{
int i;
for (i = 0; i < gst_sdp_media_attributes_len (media); i++) {
const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);
if (g_strcmp0 (attr->key, "max-message-size") == 0)
return atoi (attr->value);
}
return 65536;
}
......@@ -76,5 +76,9 @@ G_GNUC_INTERNAL
gboolean _media_has_attribute_key (const GstSDPMedia * media,
const gchar * key);
G_GNUC_INTERNAL
int _get_sctp_port_from_media (const GstSDPMedia * media);
G_GNUC_INTERNAL
guint64 _get_sctp_max_message_size_from_media (const GstSDPMedia * media);
#endif /* __WEBRTC_UTILS_H__ */
......@@ -264,4 +264,57 @@ typedef enum /*< underscore_name=gst_webrtc_fec_type >*/
GST_WEBRTC_FEC_TYPE_ULP_RED,
} GstWebRTCFECType;
/**
* GstWebRTCSCTPTransportState:
* GST_WEBRTC_SCTP_TRANSPORT_STATE_NEW: new
* GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTING: connecting
* GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTED: connected
* GST_WEBRTC_SCTP_TRANSPORT_STATE_CLOSED: closed
*
* See <ulink url="http://w3c.github.io/webrtc-pc/#dom-rtcsctptransportstate">http://w3c.github.io/webrtc-pc/#dom-rtcsctptransportstate</ulink>
*/
typedef enum /*< underscore_name=gst_webrtc_sctp_transport_state >*/
{
GST_WEBRTC_SCTP_TRANSPORT_STATE_NEW,
GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTING,
GST_WEBRTC_SCTP_TRANSPORT_STATE_CONNECTED,