Commit 0a350c61 authored by Justin Kim's avatar Justin Kim Committed by Nicolas Dufresne

srt: Integrate server and client element into one

We have srt{client,server}{src,sink} elements in accordance to the
norm of the connection oriented protocols. However, SRT connection
mode can be changed by uri parameters so it requires an integrated
element to handle the parameters.

fix: #740
parent d7ad665d
plugin_LTLIBRARIES = libgstsrt.la
libgstsrt_la_SOURCES = \
gstsrt.c \
gstsrtbasesrc.c \
gstsrtclientsrc.c \
gstsrtserversrc.c \
gstsrtbasesink.c \
gstsrtclientsink.c \
gstsrtserversink.c \
gstsrtobject.c \
gstsrtsink.c \
gstsrtsrc.c \
$(NULL)
libgstsrt_la_CFLAGS = \
......@@ -30,13 +26,9 @@ libgstsrt_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
CLEANFILES = $(BUILT_SOURCES)
noinst_HEADERS = \
gstsrt.h \
gstsrtbasesrc.h \
gstsrtclientsrc.h \
gstsrtserversrc.h \
gstsrtbasesink.h \
gstsrtclientsink.h \
gstsrtserversink.h \
gstsrtobject.h \
gstsrtsink.h \
gstsrtsrc.h \
$(NULL)
include $(top_srcdir)/common/gst-glib-gen.mak
/* GStreamer
* Copyright (C) 2017, Collabora Ltd.
* Author: Olivier Crete <olivier.crete@collabora.com>
* Copyright (C) 2018, Collabora Ltd.
* Copyright (C) 2018, SK Telecom, Co., Ltd.
* Author: Jeongseok Kim <jeongseok.kim@sk.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -18,37 +19,49 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_SRT_H__
#define __GST_SRT_H__
#ifndef __GST_SRT_ENUM_H__
#define __GST_SRT_ENUM_H__
#include <gst/gst.h>
#include <gio/gio.h>
#include <gio/gnetworking.h>
#include <srt/srt.h>
#define SRT_URI_SCHEME "srt"
#define SRT_DEFAULT_PORT 7001
#define SRT_DEFAULT_HOST "localhost"
#define SRT_DEFAULT_URI SRT_URI_SCHEME"://"SRT_DEFAULT_HOST":"G_STRINGIFY(SRT_DEFAULT_PORT)
#define SRT_DEFAULT_LATENCY 125
#define SRT_DEFAULT_KEY_LENGTH 16
G_BEGIN_DECLS
SRTSOCKET
gst_srt_client_connect (GstElement * elem, int sender,
const gchar * host, guint16 port, int rendez_vous,
const gchar * bind_address, guint16 bind_port, int latency,
GSocketAddress ** socket_address, gint * poll_id,
const gchar * passphrase, int key_length);
/**
* GstSRTConnectionMode:
* @GST_SRT_CONNECTION_MODE_NONE: not connected
* @GST_SRT_CONNECTION_MODE_CALLER: The mode to send the connection request like a client
* @GST_SRT_CONNECTION_MODE_LISTENER: The mode to wait for being connected by peer caller
* @GST_SRT_CONNECTION_MODE_RENDEZVOUS: The mode to support one-to-one only connection
*
* SRT connection types.
*/
typedef enum
{
GST_SRT_CONNECTION_MODE_NONE = 0,
GST_SRT_CONNECTION_MODE_CALLER,
GST_SRT_CONNECTION_MODE_LISTENER,
GST_SRT_CONNECTION_MODE_RENDEZVOUS,
} GstSRTConnectionMode;
SRTSOCKET
gst_srt_server_listen (GstElement * elem, int sender,
const gchar * host, guint16 port, gint latency, gint * poll_id,
const gchar * passphrase, int key_length);
/**
* GstSRTKeyLengthBits:
* @GST_SRT_KEY_LENGTH_BITS_NO_KEY: no encryption
* @GST_SRT_KEY_LENGTH_BITS_0: no encryption
* @GST_SRT_KEY_LENGTH_BITS_128: 128-bit length
* @GST_SRT_KEY_LENGTH_BITS_192: 192-bit length
* @GST_SRT_KEY_LENGTH_BITS_256: 256-bit length
*
* Crypto key length in bits
*/
typedef enum
{
GST_SRT_KEY_LENGTH_BITS_NO_KEY = 0,
GST_SRT_KEY_LENGTH_BITS_0 = GST_SRT_KEY_LENGTH_BITS_NO_KEY,
GST_SRT_KEY_LENGTH_BITS_128 = 128,
GST_SRT_KEY_LENGTH_BITS_192 = 192,
GST_SRT_KEY_LENGTH_BITS_256 = 256,
} GstSRTKeyLengthBits;
G_END_DECLS
#endif /* __GST_SRT_H__ */
#endif // __GST_SRT_ENUM_H__
......@@ -22,317 +22,35 @@
#include "config.h"
#endif
#include "gstsrt.h"
#include "gstsrtclientsrc.h"
#include "gstsrtserversrc.h"
#include "gstsrtclientsink.h"
#include "gstsrtserversink.h"
#define GST_CAT_DEFAULT gst_debug_srt
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
static GSocketAddress *
gst_srt_socket_address_new (GstElement * elem, const gchar * host, guint16 port)
{
GInetAddress *iaddr = NULL;
GSocketAddress *addr = NULL;
GError *error = NULL;
if (host == NULL) {
iaddr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
} else {
iaddr = g_inet_address_new_from_string (host);
}
if (!iaddr) {
GList *results;
GResolver *resolver = g_resolver_get_default ();
results = g_resolver_lookup_by_name (resolver, host, NULL, &error);
if (!results) {
GST_ERROR_OBJECT (elem, "Failed to resolve %s: %s", host, error->message);
g_object_unref (resolver);
goto failed;
}
iaddr = G_INET_ADDRESS (g_object_ref (results->data));
g_resolver_free_addresses (results);
g_object_unref (resolver);
}
#ifndef GST_DISABLE_GST_DEBUG
{
gchar *ip = g_inet_address_to_string (iaddr);
GST_DEBUG_OBJECT (elem, "IP address for host %s is %s", host, ip);
g_free (ip);
}
#endif
addr = g_inet_socket_address_new (iaddr, port);
g_object_unref (iaddr);
return addr;
failed:
g_clear_error (&error);
return NULL;
}
SRTSOCKET
gst_srt_client_connect (GstElement * elem, int sender,
const gchar * host, guint16 port, int rendez_vous,
const gchar * bind_address, guint16 bind_port, int latency,
GSocketAddress ** socket_address, gint * poll_id, const gchar * passphrase,
int key_length)
{
SRTSOCKET sock = SRT_INVALID_SOCK;
GError *error = NULL;
gpointer sa;
size_t sa_len;
int poll_event = SRT_EPOLL_ERR;
poll_event |= sender ? SRT_EPOLL_OUT : SRT_EPOLL_IN;
if (host == NULL) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid host"),
("Unspecified NULL host"));
goto failed;
}
*socket_address = gst_srt_socket_address_new (elem, host, port);
if (*socket_address == NULL) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid host"),
("Failed to parse host"));
goto failed;
}
sa_len = g_socket_address_get_native_size (*socket_address);
sa = g_alloca (sa_len);
if (!g_socket_address_to_native (*socket_address, sa, sa_len, &error)) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid address"),
("cannot resolve address (reason: %s)", error->message));
goto failed;
}
sock = srt_socket (g_socket_address_get_family (*socket_address), SOCK_DGRAM,
0);
if (sock == SRT_ERROR) {
GST_ELEMENT_ERROR (elem, LIBRARY, INIT, (NULL),
("failed to create SRT socket (reason: %s)", srt_getlasterror_str ()));
goto failed;
}
/* Make sure TSBPD mode is enable (SRT mode) */
srt_setsockopt (sock, 0, SRTO_TSBPDMODE, &(int) {
1}, sizeof (int));
srt_setsockopt (sock, 0, SRTO_SENDER, &sender, sizeof (int));
srt_setsockopt (sock, 0, SRTO_TSBPDDELAY, &latency, sizeof (int));
srt_setsockopt (sock, 0, SRTO_RENDEZVOUS, &rendez_vous, sizeof (int));
if (passphrase != NULL && passphrase[0] != '\0') {
srt_setsockopt (sock, 0, SRTO_PASSPHRASE, passphrase, strlen (passphrase));
srt_setsockopt (sock, 0, SRTO_PBKEYLEN, &key_length, sizeof (int));
}
if (bind_address || bind_port || rendez_vous) {
gpointer bsa;
size_t bsa_len;
GSocketAddress *b_socket_address = NULL;
if (bind_address == NULL)
bind_address = "0.0.0.0";
if (rendez_vous)
bind_port = port;
b_socket_address = g_inet_socket_address_new_from_string (bind_address,
bind_port);
if (b_socket_address == NULL) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid bind address"),
("Failed to parse bind address: %s:%d", bind_address, bind_port));
goto failed;
}
bsa_len = g_socket_address_get_native_size (b_socket_address);
bsa = g_alloca (bsa_len);
if (!g_socket_address_to_native (b_socket_address, bsa, bsa_len, &error)) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid bind address"),
("Can't parse bind address to sockaddr: %s", error->message));
g_clear_object (&b_socket_address);
goto failed;
}
g_clear_object (&b_socket_address);
if (srt_bind (sock, bsa, bsa_len) == SRT_ERROR) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ,
("Can't bind to address"),
("Can't bind to %s:%d (reason: %s)", bind_address, bind_port,
srt_getlasterror_str ()));
goto failed;
}
}
*poll_id = srt_epoll_create ();
if (*poll_id == -1) {
GST_ELEMENT_ERROR (elem, LIBRARY, INIT, (NULL),
("failed to create poll id for SRT socket (reason: %s)",
srt_getlasterror_str ()));
goto failed;
}
srt_epoll_add_usock (*poll_id, sock, &poll_event);
if (srt_connect (sock, sa, sa_len) == SRT_ERROR) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Connection error"),
("failed to connect to host (reason: %s)", srt_getlasterror_str ()));
goto failed;
}
return sock;
failed:
if (*poll_id != SRT_ERROR) {
srt_epoll_release (*poll_id);
*poll_id = SRT_ERROR;
}
if (sock != SRT_INVALID_SOCK) {
srt_close (sock);
sock = SRT_INVALID_SOCK;
}
g_clear_error (&error);
g_clear_object (socket_address);
return SRT_INVALID_SOCK;
}
SRTSOCKET
gst_srt_server_listen (GstElement * elem, int sender, const gchar * host,
guint16 port, int latency, gint * poll_id, const gchar * passphrase,
int key_length)
{
SRTSOCKET sock = SRT_INVALID_SOCK;
GError *error = NULL;
struct sockaddr sa;
size_t sa_len;
GSocketAddress *addr = NULL;
addr = gst_srt_socket_address_new (elem, host, port);
if (addr == NULL) {
GST_WARNING_OBJECT (elem,
"failed to extract host or port from the given URI");
goto failed;
}
sa_len = g_socket_address_get_native_size (addr);
if (!g_socket_address_to_native (addr, &sa, sa_len, &error)) {
GST_ELEMENT_ERROR (elem, RESOURCE, OPEN_READ, ("Invalid address"),
("cannot resolve address (reason: %s)", error->message));
goto failed;
}
sock = srt_socket (sa.sa_family, SOCK_DGRAM, 0);
if (sock == SRT_INVALID_SOCK) {
GST_WARNING_OBJECT (elem, "failed to create SRT socket (reason: %s)",
srt_getlasterror_str ());
goto failed;
}
/* Make SRT server socket non-blocking */
/* for non-blocking srt_close() */
srt_setsockopt (sock, 0, SRTO_SNDSYN, &(int) {
0}, sizeof (int));
/* for non-blocking srt_accept() */
srt_setsockopt (sock, 0, SRTO_RCVSYN, &(int) {
0}, sizeof (int));
/* Make sure TSBPD mode is enable (SRT mode) */
srt_setsockopt (sock, 0, SRTO_TSBPDMODE, &(int) {
1}, sizeof (int));
srt_setsockopt (sock, 0, SRTO_SENDER, &sender, sizeof (int));
srt_setsockopt (sock, 0, SRTO_TSBPDDELAY, &latency, sizeof (int));
if (passphrase != NULL && passphrase[0] != '\0') {
srt_setsockopt (sock, 0, SRTO_PASSPHRASE, passphrase, strlen (passphrase));
srt_setsockopt (sock, 0, SRTO_PBKEYLEN, &key_length, sizeof (int));
}
*poll_id = srt_epoll_create ();
if (*poll_id == -1) {
GST_ELEMENT_ERROR (elem, LIBRARY, INIT, (NULL),
("failed to create poll id for SRT socket (reason: %s)",
srt_getlasterror_str ()));
goto failed;
}
srt_epoll_add_usock (*poll_id, sock, &(int) {
SRT_EPOLL_IN | SRT_EPOLL_ERR});
if (srt_bind (sock, &sa, sa_len) == SRT_ERROR) {
GST_WARNING_OBJECT (elem, "failed to bind SRT server socket (reason: %s)",
srt_getlasterror_str ());
goto failed;
}
if (srt_listen (sock, 1) == SRT_ERROR) {
GST_WARNING_OBJECT (elem, "failed to listen SRT socket (reason: %s)",
srt_getlasterror_str ());
goto failed;
}
g_clear_object (&addr);
return sock;
failed:
if (*poll_id != SRT_ERROR) {
srt_epoll_release (*poll_id);
*poll_id = SRT_ERROR;
}
if (sock != SRT_INVALID_SOCK) {
srt_close (sock);
sock = SRT_INVALID_SOCK;
}
g_clear_error (&error);
g_clear_object (&addr);
return SRT_INVALID_SOCK;
}
#include "gstsrtsrc.h"
#include "gstsrtsink.h"
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "srt", 0, "SRT Common code");
if (!gst_element_register (plugin, "srtsrc", GST_RANK_PRIMARY,
GST_TYPE_SRT_SRC))
return FALSE;
if (!gst_element_register (plugin, "srtsink", GST_RANK_PRIMARY,
GST_TYPE_SRT_SINK))
return FALSE;
if (!gst_element_register (plugin, "srtclientsrc", GST_RANK_PRIMARY,
GST_TYPE_SRT_CLIENT_SRC))
/* deprecated */
if (!gst_element_register (plugin, "srtclientsrc", GST_RANK_NONE,
GST_TYPE_SRT_SRC))
return FALSE;
if (!gst_element_register (plugin, "srtserversrc", GST_RANK_PRIMARY,
GST_TYPE_SRT_SERVER_SRC))
if (!gst_element_register (plugin, "srtserversrc", GST_RANK_NONE,
GST_TYPE_SRT_SRC))
return FALSE;
if (!gst_element_register (plugin, "srtclientsink", GST_RANK_PRIMARY,
GST_TYPE_SRT_CLIENT_SINK))
if (!gst_element_register (plugin, "srtclientsink", GST_RANK_NONE,
GST_TYPE_SRT_SINK))
return FALSE;
if (!gst_element_register (plugin, "srtserversink", GST_RANK_PRIMARY,
GST_TYPE_SRT_SERVER_SINK))
if (!gst_element_register (plugin, "srtserversink", GST_RANK_NONE,
GST_TYPE_SRT_SINK))
return FALSE;
return TRUE;
......
/* GStreamer
* Copyright (C) 2017, Collabora Ltd.
* Author:Justin Kim <justin.kim@collabora.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_SRT_BASE_SINK_H__
#define __GST_SRT_BASE_SINK_H__
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include <gio/gio.h>
#include <srt/srt.h>
G_BEGIN_DECLS
#define GST_TYPE_SRT_BASE_SINK (gst_srt_base_sink_get_type ())
#define GST_IS_SRT_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SRT_BASE_SINK))
#define GST_IS_SRT_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SRT_BASE_SINK))
#define GST_SRT_BASE_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_SRT_BASE_SINK, GstSRTBaseSinkClass))
#define GST_SRT_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SRT_BASE_SINK, GstSRTBaseSink))
#define GST_SRT_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SRT_BASE_SINK, GstSRTBaseSinkClass))
#define GST_SRT_BASE_SINK_CAST(obj) ((GstSRTBaseSink*)(obj))
#define GST_SRT_BASE_SINK_CLASS_CAST(klass) ((GstSRTBaseSinkClass*)(klass))
typedef struct _GstSRTBaseSink GstSRTBaseSink;
typedef struct _GstSRTBaseSinkClass GstSRTBaseSinkClass;
struct _GstSRTBaseSink {
GstBaseSink parent;
GstUri *uri;
GstBufferList *headers;
gint latency;
gchar *passphrase;
gint key_length;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstSRTBaseSinkClass {
GstBaseSinkClass parent_class;
/* ask the subclass to send a buffer */
gboolean (*send_buffer) (GstSRTBaseSink *self, const GstMapInfo *mapinfo);
gpointer _gst_reserved[GST_PADDING_LARGE];
};
GST_EXPORT
GType gst_srt_base_sink_get_type (void);
typedef gboolean (*GstSRTBaseSinkSendCallback) (GstSRTBaseSink *sink,
const GstMapInfo *mapinfo, gpointer user_data);
gboolean gst_srt_base_sink_send_headers (GstSRTBaseSink *sink,
GstSRTBaseSinkSendCallback send_cb, gpointer user_data);
GstStructure * gst_srt_base_sink_get_stats (GSocketAddress *sockaddr,
SRTSOCKET sock);
G_END_DECLS
#endif /* __GST_SRT_BASE_SINK_H__ */
/* GStreamer SRT plugin based on libsrt
* Copyright (C) 2017, Collabora Ltd.
* Author:Justin Kim <justin.kim@collabora.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 "gstsrtbasesrc.h"
#include "gstsrt.h"
#include <srt/srt.h>
#include <gio/gio.h>
#define GST_CAT_DEFAULT gst_debug_srt_base_src
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
enum
{
PROP_URI = 1,
PROP_CAPS,
PROP_LATENCY,
PROP_PASSPHRASE,
PROP_KEY_LENGTH,
/*< private > */
PROP_LAST
};
static GParamSpec *properties[PROP_LAST];
static void gst_srt_base_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static gchar *gst_srt_base_src_uri_get_uri (GstURIHandler * handler);
static gboolean gst_srt_base_src_uri_set_uri (GstURIHandler * handler,
const gchar * uri, GError ** error);
#define gst_srt_base_src_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstSRTBaseSrc, gst_srt_base_src,
GST_TYPE_PUSH_SRC, G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
gst_srt_base_src_uri_handler_init)
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "srtbasesrc", 0,
"SRT Base Source"));
static void
gst_srt_base_src_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstSRTBaseSrc *self = GST_SRT_BASE_SRC (object);
switch (prop_id) {
case PROP_URI:
if (self->uri != NULL) {
gchar *uri_str = gst_srt_base_src_uri_get_uri (GST_URI_HANDLER (self));
g_value_take_string (value, uri_str);
}
break;
case PROP_CAPS:
GST_OBJECT_LOCK (self);
gst_value_set_caps (value, self->caps);
GST_OBJECT_UNLOCK (self);
break;
case PROP_LATENCY:
g_value_set_int (value, self->latency);
break;
case PROP_PASSPHRASE:
g_value_set_string (value, self->passphrase);
break;
case PROP_KEY_LENGTH:
g_value_set_int (value, self->key_length);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_srt_base_src_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstSRTBaseSrc *self = GST_SRT_BASE_SRC (object);
switch (prop_id) {
case PROP_URI:
gst_srt_base_src_uri_set_uri (GST_URI_HANDLER (self),
g_value_get_string (value), NULL);
break;
case PROP_CAPS:
GST_OBJECT_LOCK (self);
g_clear_pointer (&self->caps, gst_caps_unref);
self->caps = gst_caps_copy (gst_value_get_caps (value));
GST_OBJECT_UNLOCK (self);
break;
case PROP_LATENCY:
self->latency = g_value_get_int (value);
break;
case PROP_PASSPHRASE:
g_free (self->passphrase);
self->passphrase = g_value_dup_string (value);
break;
case PROP_KEY_LENGTH:
{
gint key_length = g_value_get_int (value);
g_return_if_fail (key_length == 16 || key_length == 24
|| key_length == 32);
self->key_length = key_length;
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_srt_base_src_finalize (GObject * object)
{
GstSRTBaseSrc *self = GST_SRT_BASE_SRC (object);
g_clear_pointer (&self->uri, gst_uri_unref);
g_clear_pointer (&self->caps, gst_caps_unref);
g_clear_pointer (&self->passphrase, g_free);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GstCaps *
gst_srt_base_src_get_caps (GstBaseSrc * src, GstCaps * filter)
{
GstSRTBaseSrc *self = GST_SRT_BASE_SRC (src);
GstCaps *result, *caps = NULL;
GST_OBJECT_LOCK (self);
if (self->caps != NULL) {
caps = gst_caps_ref (self->caps);
}
GST_OBJECT_UNLOCK (self);
if (caps) {
if (filter) {
result = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (caps);
} else {
result = caps;
}
} else {
result = (filter) ? gst_caps_ref (filter) : gst_caps_new_any ();
}
return result;
}
static void
gst_srt_base_src_class_init (GstSRTBaseSrcClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
gobject_class->set_property = gst_srt_base_src_set_property;
gobject_class->get_property = gst_srt_base_src_get_property;
gobject_class->finalize = gst_srt_base_src_finalize;
/**
* GstSRTBaseSrc:uri:
*
* The URI used by SRT Connection.
*/
properties[PROP_URI] = g_param_spec_string ("uri", "URI",
"URI in the form of srt://address:port", SRT_DEFAULT_URI,
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS);
/**
* GstSRTBaseSrc:caps:
*
* The Caps used by the source pad.
*/
properties[PROP_CAPS] =
g_param_spec_boxed ("caps", "Caps", "The caps of the source pad",
GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
properties[PROP_LATENCY] =
g_param_spec_int ("latency", "latency",
"Minimum latency (milliseconds)", 0,
G_MAXINT32, SRT_DEFAULT_LATENCY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
properties[PROP_PASSPHRASE] = g_param_spec_string ("passphrase", "Passphrase",
"The password for the encrypted transmission", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);