From 32e0a0e330802b9aeede568a6ce105af343219dd Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Thu, 6 Oct 2022 10:00:28 +0200 Subject: [PATCH 01/27] Start on work to support recvmmsg and buffer lists for udp main path --- agent/agent-priv.h | 6 +- agent/agent.c | 48 +++++++++- nice/memlist.h | 65 +++++++++++++ nice/nice.h | 1 + socket/socket.c | 22 +++++ socket/socket.h | 7 ++ socket/udp-bsd.c | 231 +++++++++++++++++++++++++++++++++++++++++++++ socket/udp-bsd.h | 7 ++ 8 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 nice/memlist.h diff --git a/agent/agent-priv.h b/agent/agent-priv.h index cea86b3b..e6f2a5a8 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -61,6 +61,8 @@ #include "stun/usages/turn.h" #include "stun/usages/ice.h" +#include "memlist.h" + /* XXX: starting from ICE ID-18, Ta SHOULD now be set according * to session bandwidth -> this is not yet implemented in NICE */ @@ -103,7 +105,7 @@ struct _NiceAgent gboolean aggressive_mode; /* property: use aggressive nomination when controller */ guint regular_nomination_timeout; /* property: timeout (ms) before regular nomination starts nominating non-optimal media paths */ - GSList *local_addresses; /* list of NiceAddresses for local + GSList *local_addresses; /* list of NiceAddresses for loca interfaces */ GSList *streams; /* list of Stream objects */ GMainContext *main_context; /* main context pointer */ @@ -125,6 +127,8 @@ struct _NiceAgent gboolean media_after_tick; /* Received media after keepalive tick */ gchar *software_attribute; /* SOFTWARE attribute */ gboolean reliable; /* property: reliable */ + + MemlistInterface *mem_list_interface; /* property: mem_list_interface */ /* XXX: add pointer to internal data struct for ABI-safe extensions */ }; diff --git a/agent/agent.c b/agent/agent.c index f6fa8f0a..31b9cbe1 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -108,7 +108,8 @@ enum PROP_CONNCHECK_RETRANSMISSIONS, PROP_AGGRESSIVE_MODE, PROP_REGULAR_NOMINATION_TIMEOUT, - PROP_TIE_BREAKER + PROP_TIE_BREAKER, + PROP_MEM_LIST_INTERFACE }; @@ -146,6 +147,8 @@ static gboolean priv_attach_stream_component (NiceAgent * agent, Stream * stream, Component * component); static void priv_detach_stream_component (NiceAgent * agent, Stream * stream, Component * component); +static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface* replacement); +static void mem_list_interface_propagate (NiceAgent * agent); void agent_lock (NiceAgent * agent) @@ -569,6 +572,12 @@ nice_agent_class_init (NiceAgentClass * klass) 0, /* Not construct time so ignored */ G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, + g_param_spec_pointer ("mem-list-interface", + "Memory list interface", + "Interface for allocating and releasing memory buffers", + G_PARAM_CONSTRUCT_ONLY)); + /* install signals */ /** @@ -807,6 +816,9 @@ nice_agent_get_property (GObject * object, agent_lock (agent); switch (property_id) { + case PROP_MEM_LIST_INTERFACE: + g_value_set_pointer (value, (gpointer)agent->mem_list_interface); + break; case PROP_MAIN_CONTEXT: g_value_set_pointer (value, agent->main_context); break; @@ -1001,6 +1013,12 @@ nice_agent_set_property (GObject * object, agent->proxy_password = g_value_dup_string (value); break; + case PROP_MEM_LIST_INTERFACE: + mem_list_interface_clean_up_and_replace (agent, (gpointer)agent->mem_list_interface); + /* TODO: The new interface must be passed down to any existing sockets */ + g_value_set_pointer ((gpointer)agent->mem_list_interface, (gpointer)value); + break; + case PROP_UPNP_TIMEOUT: break; @@ -1020,6 +1038,34 @@ nice_agent_set_property (GObject * object, } +static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface* replacement) +{ + (void)agent; + if (agent->mem_list_interface != NULL){ + agent_lock (agent); + /* We need to go trough all (udp) sockets and release any pending buffers */ + GSList *stream_index; + + for (stream_index = agent->streams; stream_index; stream_index = stream_index->next) { + GSList *component_index; + Stream *stream = stream_index->data; + for (component_index = stream->components; component_index; component_index = component_index->next) { + GSList *socket_index; + Component *component = component_index->data; + for (socket_index = component->sockets; socket_index; socket_index = socket_index->next) { + NiceSocket *udpsocket = socket_index->data; + nice_udp_socket_buffers_and_interface_unref(udpsocket); + if (replacement != NULL) + { + nice_udp_socket_interface_set(udpsocket, replacement); + } + } + } + } + agent_unlock (agent); + } +} + static void log_local_candidate_event (NiceAgent * agent, NiceCandidate * local_candidate) { diff --git a/nice/memlist.h b/nice/memlist.h new file mode 100644 index 00000000..9a48492e --- /dev/null +++ b/nice/memlist.h @@ -0,0 +1,65 @@ +/* + * Lightweight abstraction over GStreamers buffer lists / buffer pools to allow + * allocating buffers for use with recvmmsg. + * This file is part of the Nice GLib ICE library. + * + * + * (C) 2022 Pexip AS + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Nice GLib ICE library. + * + * The Initial Developers of the Original Code are Collabora Ltd and Nokia + * Corporation. All Rights Reserved. + * + * Contributors: + * Frederik Vestre, Pexip AS + * + * Alternatively, the contents of this file may be used under the terms of the + * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which + * case the provisions of LGPL are applicable instead of those above. If you + * wish to allow use of your version of this file only under the terms of the + * LGPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replace + * them with the notice and other provisions required by the LGPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the LGPL. + */ + +#ifndef _NICE_MEMLIST_H +#define _NICE_MEMLIST_H + +#include + +typedef struct _MemlistInterface MemlistInterface; +typedef void NiceMemoryBufferRef; +/* Libnice expects the buffers received trough the interface to be accessable until they are either + returned though nice_return_memory_buffer or by passing them as a result of a read operation. + All buffers will be returned when the corresponding agent is destroyed */ +typedef NiceMemoryBufferRef* (*nice_memory_buffer_get)(MemlistInterface *interface, gsize size); +/* Return a memory buffer to the provider */ +typedef void (*nice_memory_buffer_return)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); +/* Get a pointer to the contents (i.e. bytes) of the memory buffer */ +typedef char* (*nice_memory_buffer_contents)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); +/* Get the size of the memory buffer */ +typedef gsize (*nice_memory_buffer_size)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); +typedef gsize (*nice_memory_memlist_unref)(MemlistInterface *interface); + +struct _MemlistInterface { + nice_memory_buffer_get buffer_get; + nice_memory_buffer_return buffer_return; + nice_memory_buffer_contents buffer_contents; + nice_memory_buffer_size buffer_size; + nice_memory_memlist_unref unref; +}; +#endif /* _NICE_MEMLIST_H */ + diff --git a/nice/nice.h b/nice/nice.h index 5587ec49..afec4fc6 100644 --- a/nice/nice.h +++ b/nice/nice.h @@ -39,6 +39,7 @@ #ifndef _NICE_H #define _NICE_H +#include "memlist.h" #include "agent.h" #include "interfaces.h" diff --git a/socket/socket.c b/socket/socket.c index 0f73f5ef..d3ea0bed 100644 --- a/socket/socket.c +++ b/socket/socket.c @@ -98,6 +98,28 @@ nice_socket_attach (NiceSocket *sock, GMainContext* ctx) } } +void +nice_socket_buffers_and_interface_unref (NiceSocket *sock) +{ + if (sock) { + if (sock->type == NICE_SOCKET_TYPE_UDP_BSD) + { + nice_udp_socket_buffers_and_interface_unref (sock); + } + } +} + +void +nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface *interface) +{ + if (sock) { + if (sock->type == NICE_SOCKET_TYPE_UDP_BSD) + { + nice_udp_socket_interface_set(sock, interface); + } + } +} + const char* socket_type_to_string (NiceSocketType type) { switch (type) { diff --git a/socket/socket.h b/socket/socket.h index 0b68d497..2bda120c 100644 --- a/socket/socket.h +++ b/socket/socket.h @@ -37,6 +37,7 @@ #ifndef _SOCKET_H #define _SOCKET_H +#include "memlist.h" #include "address.h" #include @@ -111,6 +112,12 @@ nice_socket_set_rx_enabled (NiceSocket *sock, gboolean enabled); void nice_socket_free (NiceSocket *sock); +void +nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface *interface); + +void +nice_socket_buffers_and_interface_unref (NiceSocket *sock); + const char *socket_type_to_string (NiceSocketType type); #include "udp-bsd.h" diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 31941e1d..aac359e2 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -40,6 +40,14 @@ * Implementation of UDP socket interface using Berkeley sockets. (See * http://en.wikipedia.org/wiki/Berkeley_sockets.) */ + +#define HAVE_RECVMMSG 1 + +#ifdef HAVE_RECVMMSG +#define _GNU_SOURCE +#include +#endif + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -49,12 +57,24 @@ #include #include +#include "agent-priv.h" +#include "memlist.h" #include "udp-bsd.h" + #ifndef G_OS_WIN32 #include #endif +#ifdef HAVE_RECVMMSG +#define MSG_RECEIVE_TIMES 1 +#define MMSG_LEN 32 +#else +#define MSG_RECEIVE_TIMES 32 +#define MMSG_LEN 1 +#endif +#define BUFFER_ALLOC_SIZE 1500 +#define MMSG_TOTAL (MSG_RECEIVE_TIMES * MMSG_LEN) static void socket_close (NiceSocket *sock); static gint socket_recv (NiceSocket *sock, NiceAddress *from, @@ -62,11 +82,39 @@ static gint socket_recv (NiceSocket *sock, NiceAddress *from, static gint socket_send (NiceSocket *sock, const NiceAddress *to, guint len, const gchar *buf); static gboolean socket_is_reliable (NiceSocket *sock); +static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket); + +#ifdef HAVE_RECVMMSG + +struct _MessageData +{ + NiceMemoryBufferRef *buffer; + + struct iovec iovec; + struct sockaddr_storage remote; +}; +typedef struct _MessageData MessageData; + +static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface *memory_interface, + MessageData *message_data, struct mmsghdr *hdr); +static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket); +#endif + struct UdpBsdSocketPrivate { NiceAddress niceaddr; GSocketAddress *gaddr; +#ifdef HAVE_RECVMMSG + /* Alloc buffers outside callback, to avoid reallocing buffers for messages + that are not received. Any messages that are passed along are replaced with + freshly allocated memory. */ + MessageData *message_datas; + /* This is stored outside the MessageData struct as this must be in a + continous list to be able to be passed to recvmmsg */ + struct mmsghdr *message_headers; + MemlistInterface *interface; +#endif }; NiceSocket * @@ -156,6 +204,10 @@ socket_close (NiceSocket *sock) if (priv->gaddr) g_object_unref (priv->gaddr); + + nice_udp_socket_buffers_and_interface_unref(sock); + socket_recvmmsg_structures_clean_up(sock); + g_slice_free (struct UdpBsdSocketPrivate, sock->priv); if (sock->fileno) { @@ -163,8 +215,26 @@ socket_close (NiceSocket *sock) g_object_unref (sock->fileno); sock->fileno = NULL; } + } +#ifdef HAVE_RECVMMSG +gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received) +{ + struct UdpBsdSocketPrivate *priv = sock->priv; + + int socket_fd = g_socket_get_fd(sock->fileno); + gssize result; + + if ((result = + recvmmsg (socket_fd, priv->message_headers, MMSG_LEN, MSG_WAITFORONE, NULL)) >= 0) { + *num_messages_received = result; + } else { + *num_messages_received = 0; + } + return result; +} +#endif static gint socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) { @@ -225,3 +295,164 @@ socket_is_reliable (NiceSocket *sock) return FALSE; } +#ifdef HAVE_RECVMMSG + +/* TODO: We need a way to extract and replenish buffers once they have been received */ + +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *interface){ + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + g_assert(priv->interface == NULL); +} + +NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, + guint packet_index, NiceAddress *from) +{ + g_assert(packet_index < MMSG_TOTAL); + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + MessageData *message_data = &priv->message_datas[packet_index]; + nice_address_set_from_sockaddr (from, (struct sockaddr *)&message_data->remote); + + NiceMemoryBufferRef *result = message_data->buffer; + message_data->buffer = NULL; + /* Replace the entry with a fresh buffer for next recvmmsg call */ + socket_recvmmsg_structures_fill_entry_with_buffer (priv->interface, + message_data, &priv->message_headers[packet_index]); + return result; +} + +/* This ensures no references to any buffers are present for this socket. + If this function is called the mem_interface may be changed, as long as it + happens before any more data is received or sent (practically while the agent + lock is locked). It is safe to call this function even if no MessageInterface + has been set earlier, and thus no buffers are in need of beeing cleaned up. */ +void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) +{ + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + MemlistInterface *memory_interface = priv->interface; + for(int i = 0; i < MMSG_TOTAL; i++) + { + MessageData* msgdata = &(priv->message_datas[i]); + struct mmsghdr *message_header = &(priv->message_headers[i]); + + if (msgdata != NULL){ + if (msgdata->buffer != NULL){ + memory_interface->buffer_return(memory_interface, msgdata->buffer); + } + msgdata->iovec.iov_len = 0; + msgdata->iovec.iov_base = NULL; + + memset(message_header, 0, sizeof(struct mmsghdr)); + + memory_interface->buffer_return(memory_interface, priv->message_datas[i].buffer); + priv->message_datas[i].buffer = NULL; + } + } + /* Currently we don't manage buffers when not recvmmsg is supported. + This may change in the future. However until then do nothing here. */ + priv->interface = NULL; +} + +static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) +{ + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + if (priv->message_datas != NULL) + { + free(priv->message_datas); + } + if (priv->message_headers != NULL) + { + free(priv->message_headers); + } + /* priv->interface is owned by agent, which again owns (indirectly) this udp + connection. Therefore this connection does not reference count the + interface, but rather piggybacks the ownership of the agent */ +} + +static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface *memory_interface, + MessageData *message_data, struct mmsghdr *hdr) +{ + if (message_data->buffer == NULL) + { + message_data->buffer = memory_interface->buffer_get(memory_interface, BUFFER_ALLOC_SIZE); + } + + gsize buffer_size = memory_interface->buffer_size(memory_interface, message_data->buffer); + message_data->iovec.iov_len = buffer_size; + message_data->iovec.iov_base = memory_interface->buffer_contents(memory_interface, message_data->buffer); + hdr->msg_len = buffer_size; + +} + +static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) +{ + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + MemlistInterface *memory_interface = priv->interface; + + for(int i = 0; i < MMSG_TOTAL; i++) + { + MessageData *message_data = &priv->message_datas[i]; + struct mmsghdr *hdr = &priv->message_headers[i]; + + hdr->msg_hdr.msg_control = NULL; + hdr->msg_hdr.msg_controllen = 0; + hdr->msg_hdr.msg_iovlen = 1; + hdr->msg_hdr.msg_iov = &message_data->iovec; + hdr->msg_hdr.msg_name = (struct sockaddr *) &message_data->remote; + hdr->msg_hdr.msg_namelen = sizeof (struct sockaddr_storage); + + if (memory_interface != NULL){ + socket_recvmmsg_structures_fill_entry_with_buffer(memory_interface, message_data, hdr); + } else { + message_data->iovec.iov_len = 0; + message_data->iovec.iov_base = NULL; + hdr->msg_len = 0; + } + } +} + +static void socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, guint iter_start, guint iter_end) +{ + struct UdpBsdSocketPrivate *priv = udp_socket->priv; + MemlistInterface *memory_interface = priv->interface; + g_assert(iter_start < iter_end); + g_assert(iter_end < MMSG_TOTAL); + g_assert(memory_interface != NULL); + + for(int i = iter_start; i < iter_end; i++) + { + MessageData *message_data = &priv->message_datas[i]; + struct mmsghdr *hdr = &priv->message_headers[i]; + + socket_recvmmsg_structures_fill_entry_with_buffer(memory_interface, message_data, hdr); + } +} + +#else + +void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) +{ + (void) udp_socket; +} +void clean_up_recvmmsg_structures(NiceSocket *udp_socket) +{ + (void)udp_socket; +} +void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) +{ + (void)udp_socket; +} +NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, + guint packet_index, NiceAddress *from) +{ + (void)udp_socket; + (void)packet_index; + (void)from; + return NULL; +} +gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received) +{ + (void)sock; + num_messages_received = 0; + return -ENOTSUP; +} +#endif \ No newline at end of file diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index c8d61901..cc494699 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -40,12 +40,19 @@ #define _UDP_BSD_H #include "socket.h" +#include "agent.h" G_BEGIN_DECLS NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr); +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *interface); +void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket); +gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received); +NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, + guint packet_index, NiceAddress *from); + G_END_DECLS #endif /* _UDP_BSD_H */ From bab190b14c8cac05db0e5c39b109b990692986de Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Thu, 6 Oct 2022 12:42:33 +0200 Subject: [PATCH 02/27] WIP --- agent/agent.c | 162 +++++++++++++++++++++++----------------------- agent/agent.h | 22 +++++++ agent/component.h | 1 + nice/nice.h | 1 - 4 files changed, 105 insertions(+), 81 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 31b9cbe1..5ffafeea 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -147,7 +147,8 @@ static gboolean priv_attach_stream_component (NiceAgent * agent, Stream * stream, Component * component); static void priv_detach_stream_component (NiceAgent * agent, Stream * stream, Component * component); -static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface* replacement); +static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, + MemlistInterface * replacement); static void mem_list_interface_propagate (NiceAgent * agent); void @@ -556,20 +557,10 @@ nice_agent_class_init (NiceAgentClass * klass) "Use aggressive nomination when controller", TRUE, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_REGULAR_NOMINATION_TIMEOUT, - g_param_spec_uint ("regular-nomination-timeout", - "Timeout (in ms) before regular nomination will select non-optimal media path", - "Timeout (in ms) before regular nomination will select non-optimal media path", - 1, 0xffffffff, - NICE_AGENT_REGULAR_NOMINATION_TIMEOUT_DEFAULT, /* Not construct time so ignored */ + g_object_class_install_property (gobject_class, PROP_REGULAR_NOMINATION_TIMEOUT, g_param_spec_uint ("regular-nomination-timeout", "Timeout (in ms) before regular nomination will select non-optimal media path", "Timeout (in ms) before regular nomination will select non-optimal media path", 1, 0xffffffff, NICE_AGENT_REGULAR_NOMINATION_TIMEOUT_DEFAULT, /* Not construct time so ignored */ G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_TIE_BREAKER, - g_param_spec_uint64 ("tie-breaker", - "Tie breaker value to send in connectivity checks", - "Tie breaker value to send in connectivity checks", - 0, 0xffffffffffffffffLL, - 0, /* Not construct time so ignored */ + g_object_class_install_property (gobject_class, PROP_TIE_BREAKER, g_param_spec_uint64 ("tie-breaker", "Tie breaker value to send in connectivity checks", "Tie breaker value to send in connectivity checks", 0, 0xffffffffffffffffLL, 0, /* Not construct time so ignored */ G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, @@ -817,7 +808,7 @@ nice_agent_get_property (GObject * object, switch (property_id) { case PROP_MEM_LIST_INTERFACE: - g_value_set_pointer (value, (gpointer)agent->mem_list_interface); + g_value_set_pointer (value, (gpointer) agent->mem_list_interface); break; case PROP_MAIN_CONTEXT: g_value_set_pointer (value, agent->main_context); @@ -1014,9 +1005,11 @@ nice_agent_set_property (GObject * object, break; case PROP_MEM_LIST_INTERFACE: - mem_list_interface_clean_up_and_replace (agent, (gpointer)agent->mem_list_interface); + mem_list_interface_clean_up_and_replace (agent, + (gpointer) agent->mem_list_interface); /* TODO: The new interface must be passed down to any existing sockets */ - g_value_set_pointer ((gpointer)agent->mem_list_interface, (gpointer)value); + g_value_set_pointer ((gpointer) agent->mem_list_interface, + (gpointer) value); break; case PROP_UPNP_TIMEOUT: @@ -1038,26 +1031,30 @@ nice_agent_set_property (GObject * object, } -static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface* replacement) +static void +mem_list_interface_clean_up_and_replace (NiceAgent * agent, + MemlistInterface * replacement) { - (void)agent; - if (agent->mem_list_interface != NULL){ + (void) agent; + if (agent->mem_list_interface != NULL) { agent_lock (agent); /* We need to go trough all (udp) sockets and release any pending buffers */ GSList *stream_index; - for (stream_index = agent->streams; stream_index; stream_index = stream_index->next) { + for (stream_index = agent->streams; stream_index; + stream_index = stream_index->next) { GSList *component_index; Stream *stream = stream_index->data; - for (component_index = stream->components; component_index; component_index = component_index->next) { + for (component_index = stream->components; component_index; + component_index = component_index->next) { GSList *socket_index; Component *component = component_index->data; - for (socket_index = component->sockets; socket_index; socket_index = socket_index->next) { + for (socket_index = component->sockets; socket_index; + socket_index = socket_index->next) { NiceSocket *udpsocket = socket_index->data; - nice_udp_socket_buffers_and_interface_unref(udpsocket); - if (replacement != NULL) - { - nice_udp_socket_interface_set(udpsocket, replacement); + nice_udp_socket_buffers_and_interface_unref (udpsocket); + if (replacement != NULL) { + nice_udp_socket_interface_set (udpsocket, replacement); } } } @@ -1982,28 +1979,31 @@ nice_agent_add_stream_local_address_from_string (NiceAgent * agent, * having a specific remote candidate, and eventually update the * priority of the selected pair as well. */ -static void priv_update_pair_foundations (NiceAgent *agent, - guint stream_id, guint component_id, NiceCandidate *remote) +static void +priv_update_pair_foundations (NiceAgent * agent, + guint stream_id, guint component_id, NiceCandidate * remote) { Stream *stream; Component *component; if (agent_find_component (agent, stream_id, component_id, &stream, - &component)) { + &component)) { GSList *i; for (i = stream->conncheck_list; i; i = i->next) { CandidateCheckPair *pair = i->data; if (pair->remote == remote) { - gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION+1]; + gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION + 1]; g_snprintf (foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s", pair->local->foundation, pair->remote->foundation); - if (strncmp (pair->foundation, foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION)) { + if (strncmp (pair->foundation, foundation, + NICE_CANDIDATE_PAIR_MAX_FOUNDATION)) { - g_strlcpy (pair->foundation, foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION); + g_strlcpy (pair->foundation, foundation, + NICE_CANDIDATE_PAIR_MAX_FOUNDATION); GST_DEBUG_OBJECT (agent, "%u/%u: Updating pair %p foundation to '%s'", stream_id, component_id, pair, pair->foundation); @@ -2017,12 +2017,13 @@ static void priv_update_pair_foundations (NiceAgent *agent, * an update of its priority. stun_priority doesn't change * because only the remote candidate foundation is modified. */ - GST_DEBUG_OBJECT (agent, "%u/%u : pair %p is the selected pair, updating " + GST_DEBUG_OBJECT (agent, + "%u/%u : pair %p is the selected pair, updating " "its priority.", stream_id, component_id, pair); component->selected_pair.priority = pair->priority; agent_signal_new_selected_pair (agent, pair->stream_id, - component->id, pair->local, pair->remote); + component->id, pair->local, pair->remote); } } } @@ -2036,10 +2037,8 @@ static void priv_update_pair_foundations (NiceAgent *agent, * pair */ static void -priv_check_for_new_selected_pair ( - NiceAgent *agent, - guint stream_id, - guint component_id) +priv_check_for_new_selected_pair (NiceAgent * agent, + guint stream_id, guint component_id) { Stream *stream; Component *component; @@ -2047,17 +2046,17 @@ priv_check_for_new_selected_pair ( GSList *i; if (agent_find_component (agent, stream_id, component_id, &stream, - &component)) { + &component)) { for (i = stream->conncheck_list; i; i = i->next) { pair = i->data; if (pair->component_id == component_id && pair->state == NICE_CHECK_SUCCEEDED && - pair->valid_pair != NULL && - pair->valid_pair->nominated) { + pair->valid_pair != NULL && pair->valid_pair->nominated) { if (pair->priority > component->selected_pair.priority) { - GST_INFO_OBJECT (agent, "%u/%u: New trickle candidate has promoted %p as the selected pair", + GST_INFO_OBJECT (agent, + "%u/%u: New trickle candidate has promoted %p as the selected pair", stream_id, component_id, pair); conn_check_update_selected_pair (agent, component, pair->valid_pair); } @@ -2083,7 +2082,8 @@ priv_add_remote_candidate (NiceAgent * agent, Stream *stream; NiceCandidate *candidate; - if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) + if (!agent_find_component (agent, stream_id, component_id, &stream, + &component)) return FALSE; /* step: check whether the candidate already exists */ @@ -2093,8 +2093,9 @@ priv_add_remote_candidate (NiceAgent * agent, if (stream->trickle_ice) { if (candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) { - GST_DEBUG_OBJECT (agent, "%u/%u: Updating existing prflx candidate to %s", - stream_id, component_id, candidate_type_to_string(type)); + GST_DEBUG_OBJECT (agent, + "%u/%u: Updating existing prflx candidate to %s", stream_id, + component_id, candidate_type_to_string (type)); candidate->type = type; } @@ -2102,11 +2103,10 @@ priv_add_remote_candidate (NiceAgent * agent, if (candidate && candidate->type == type) { gchar tmpbuf[INET6_ADDRSTRLEN]; nice_address_to_string (addr, tmpbuf); - GST_DEBUG_OBJECT (agent, "%u/%u: Updating existing remote candidate with addr [%s]:%u" - " U/P '%s'/'%s' prio: %08x", - stream_id, component_id, - tmpbuf, nice_address_get_port (addr), - username, password, priority); + GST_DEBUG_OBJECT (agent, + "%u/%u: Updating existing remote candidate with addr [%s]:%u" + " U/P '%s'/'%s' prio: %08x", stream_id, component_id, tmpbuf, + nice_address_get_port (addr), username, password, priority); updated = TRUE; @@ -2114,26 +2114,26 @@ priv_add_remote_candidate (NiceAgent * agent, candidate->base_addr = *base_addr; candidate->priority = priority; if (foundation) - g_strlcpy(candidate->foundation, foundation, + g_strlcpy (candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION); if (username) { if (candidate->username == NULL) candidate->username = g_strdup (username); else if (g_strcmp0 (username, candidate->username)) - GST_WARNING_OBJECT (agent, "%u/%u: Candidate username '%s' is not allowed " - "to change to '%s' now (ICE restart only).", - stream_id, component_id, - candidate->username, username); + GST_WARNING_OBJECT (agent, + "%u/%u: Candidate username '%s' is not allowed " + "to change to '%s' now (ICE restart only).", stream_id, + component_id, candidate->username, username); } if (password) { if (candidate->password == NULL) candidate->password = g_strdup (password); else if (g_strcmp0 (password, candidate->password)) - GST_WARNING_OBJECT (agent, "%u/%u: Candidate password '%s' is not allowed " - "to change to '%s' now (ICE restart only).", - stream_id, component_id, - candidate->password, password); + GST_WARNING_OBJECT (agent, + "%u/%u: Candidate password '%s' is not allowed " + "to change to '%s' now (ICE restart only).", stream_id, + component_id, candidate->password, password); } /* since the type of the existing candidate may have changed, @@ -2141,7 +2141,8 @@ priv_add_remote_candidate (NiceAgent * agent, * to be recomputed... */ conn_check_recalculate_pair_priorities (agent); - priv_update_pair_foundations (agent, stream_id, component_id, candidate); + priv_update_pair_foundations (agent, stream_id, component_id, + candidate); /* ... and maybe we now have another nominated pair with a higher * priority as the result of this priorities update. @@ -2155,9 +2156,9 @@ priv_add_remote_candidate (NiceAgent * agent, nice_address_to_string (addr, tmpbuf); GST_DEBUG_OBJECT (agent, "%u/%u: Not updating existing remote candidate with addr [%s]:%u" - " U/P '%s'/'%s' prio: %u type:%s transport:%d", stream_id, component_id, - tmpbuf, nice_address_get_port (addr), username, password, priority, - candidate_type_to_string(type), transport); + " U/P '%s'/'%s' prio: %u type:%s transport:%d", stream_id, + component_id, tmpbuf, nice_address_get_port (addr), username, + password, priority, candidate_type_to_string (type), transport); } } } else { @@ -2566,7 +2567,7 @@ nice_agent_get_remote_candidates (NiceAgent * agent, } gboolean -nice_agent_restart (NiceAgent *agent) +nice_agent_restart (NiceAgent * agent) { GSList *i; @@ -2588,8 +2589,7 @@ nice_agent_restart (NiceAgent *agent) } gboolean -nice_agent_restart_stream (NiceAgent *agent, - guint stream_id) +nice_agent_restart_stream (NiceAgent * agent, guint stream_id) { gboolean res = FALSE; Stream *stream; @@ -2610,7 +2610,7 @@ nice_agent_restart_stream (NiceAgent *agent, stream_restart (agent, stream, agent->rng); res = TRUE; - done: +done: agent_unlock (agent); return res; } @@ -3036,7 +3036,9 @@ NICEAPI_EXPORT gboolean nice_agent_attach_recv (NiceAgent * agent, guint stream_id, guint component_id, - GMainContext * ctx, NiceAgentRecvFunc func, gpointer data) + GMainContext * ctx, + NiceAgentRecvFunc func, + NiceAgentRecvMultipleFunc multiple_func, gpointer data) { Component *component = NULL; Stream *stream = NULL; @@ -3067,6 +3069,8 @@ nice_agent_attach_recv (NiceAgent * agent, if (func) { component->g_source_io_cb = func; + component->g_source_io_multiple_cb = multiple_func; + component->data = data; component->ctx = ctx; if (ctx) @@ -3256,8 +3260,7 @@ nice_agent_set_stream_max_tcp_queue_size (NiceAgent * agent, void nice_agent_set_stream_trickle_ice (NiceAgent * agent, - guint stream_id, - gboolean trickle_ice) + guint stream_id, gboolean trickle_ice) { Stream *stream; @@ -3269,8 +3272,7 @@ nice_agent_set_stream_trickle_ice (NiceAgent * agent, } GST_DEBUG_OBJECT (agent, "%u/*: setting trickle_ice to %s", - stream_id, - trickle_ice ? "TRUE" : "FALSE"); + stream_id, trickle_ice ? "TRUE" : "FALSE"); stream->trickle_ice = trickle_ice; done: @@ -3278,10 +3280,8 @@ nice_agent_set_stream_trickle_ice (NiceAgent * agent, } NICE_EXPORT void -nice_agent_end_of_candidates ( - NiceAgent *agent, - guint stream_id, - guint component_id) +nice_agent_end_of_candidates (NiceAgent * agent, + guint stream_id, guint component_id) { Component *component; Stream *stream; @@ -3290,11 +3290,14 @@ nice_agent_end_of_candidates ( if (agent_find_component (agent, stream_id, component_id, &stream, &component)) { - GST_DEBUG_OBJECT (agent, "%u/%u: end-of-candidates", stream_id, component_id); + GST_DEBUG_OBJECT (agent, "%u/%u: end-of-candidates", stream_id, + component_id); component->peer_gathering_done = TRUE; conn_check_end_of_candidates (agent, stream, component); } else { - GST_WARNING_OBJECT (agent, "%u/%u: end-of-candidates unknown stream/component", stream_id, component_id); + GST_WARNING_OBJECT (agent, + "%u/%u: end-of-candidates unknown stream/component", stream_id, + component_id); } agent_unlock (agent); @@ -3368,8 +3371,7 @@ nice_agent_set_rx_enabled (NiceAgent * agent, agent_unlock (agent); } -NICEAPI_EXPORT -const char * +NICEAPI_EXPORT const char * nice_component_state_to_string (NiceComponentState state) { return component_state_to_string (state); diff --git a/agent/agent.h b/agent/agent.h index c97447e4..0fc21a54 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -112,6 +112,7 @@ typedef struct _NiceAgent NiceAgent; #include "address.h" #include "candidate.h" #include "debug.h" +#include "memlist.h" G_BEGIN_DECLS @@ -263,6 +264,27 @@ typedef void (*NiceAgentRecvFunc) ( NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data, const NiceAddress *from, const NiceAddress *to); +/** + * NiceAgentRecvMultipleFunc: + * @agent: The #NiceAgent Object + * @stream_id: The id of the stream + * @component_id: The id of the component of the stream + * which received the data + * @len: The length of the data + * @buf: The buffer containing the data received + * @user_data: The user data set in nice_agent_attach_recv() + * + * Callback function when data is received on a component + * + */ +typedef void (*NiceAgentRecvMultipleFunc) ( + NiceAgent *agent, guint stream_id, guint component_id, guint num_buffers, + gpointer user_data); + +/* This function should only be called inside the NiceAgentRecvMultipleFunc callback */ +NICE_EXPORT NiceMemoryBufferRef *nice_agent_memory_buffer_retrieve(NiceAgent *agent, + guint stream_id, guint component_id, gsize buffer_index, + const NiceAddress *from, const NiceAddress *to); /** * nice_agent_new: diff --git a/agent/component.h b/agent/component.h index fdf40ba8..ab135df2 100644 --- a/agent/component.h +++ b/agent/component.h @@ -118,6 +118,7 @@ struct _Component see ICE 11.1. "Sending Media" (ID-19) */ NiceCandidate *restart_candidate; /**< for storing active remote candidate during a restart */ NiceAgentRecvFunc g_source_io_cb; /**< function called on io cb */ + NiceAgentRecvMultipleFunc g_source_io_multiple_cb; /**< function called on io cb for multiple packets */ gpointer data; /**< data passed to the io function */ GMainContext *ctx; /**< context for data callbacks for this component */ diff --git a/nice/nice.h b/nice/nice.h index afec4fc6..5587ec49 100644 --- a/nice/nice.h +++ b/nice/nice.h @@ -39,7 +39,6 @@ #ifndef _NICE_H #define _NICE_H -#include "memlist.h" #include "agent.h" #include "interfaces.h" From 6c9814b176494a582eb6efc456257a0afd5609f9 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Thu, 6 Oct 2022 15:27:59 +0200 Subject: [PATCH 03/27] WIP2 --- agent/agent.c | 143 +++++++++++++++++++++++++++++++++++++---------- agent/agent.h | 13 +++-- gst/gstnicesrc.c | 20 ++++++- nice/memlist.h | 2 +- nice/meson.build | 2 +- socket/udp-bsd.c | 50 +++++------------ socket/udp-bsd.h | 19 ++++++- 7 files changed, 174 insertions(+), 75 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 5ffafeea..dc9b9e3c 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -2368,14 +2368,15 @@ _nice_should_have_padding (NiceCompatibility compatibility) return TRUE; } } - -static gint -_nice_agent_recv (NiceAgent * agent, +/* Returns whether the buffer is processed (TRUE) or if it should be forwarded + to the client (FALSE) */ +static gboolean nice_agent_recv_process(NiceAgent * agent, + NiceSocket *socket, Stream * stream, Component * component, - NiceSocket * socket, guint buf_len, gchar * buf, NiceAddress * from) + guint buf_len, gchar * buf, NiceAddress * from) { - gint len; + gint len = buf_len; GList *item; gboolean has_padding = _nice_should_have_padding (agent->compatibility); NiceAddress stun_server; @@ -2383,30 +2384,6 @@ _nice_agent_recv (NiceAgent * agent, gchar *stun_server_ip = NULL; guint stun_server_port; - len = nice_socket_recv (socket, from, buf_len, buf); - - if (len <= 0) - return len; - -#ifndef NDEBUG - if (len > 0) { - gchar tmpbuf[INET6_ADDRSTRLEN]; - nice_address_to_string (from, tmpbuf); - GST_LOG_OBJECT (agent, - "Packet received on local %s socket %u from [%s]:%u (%u octets).", - socket_type_to_string (socket->type), - socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, - nice_address_get_port (from), len); - } -#endif - - - if ((guint) len > buf_len) { - /* buffer is not big enough to accept this packet */ - /* XXX: test this case */ - return 0; - } - /* * If the packet comes from a relayed candidate then let the turn socket * have first crack at it @@ -2478,14 +2455,117 @@ _nice_agent_recv (NiceAgent * agent, if (stun_message_validate_buffer_length ((uint8_t *) buf, (size_t) len, has_padding) != len) { /* If the retval is no 0, its not a valid stun packet, probably data */ - return len; + return TRUE; } if (conn_check_handle_inbound_stun (agent, stream, component, socket, from, buf, len)) /* handled STUN message */ - return 0; + return FALSE; + } + return TRUE; + +} + +gint +_nice_agent_recv_multiple (NiceAgent * agent, + Stream * stream, + Component * component, + NiceSocket * socket, + gsize *num_buffers_received) +{ + gint num_packets_received; + + /* Make sure the agent user has set a mem list interface, and that this socket + sopports receiving multiple messages in one call. */ + if (agent->mem_list_interface == NULL){ + return -ENOTSUP; + } + + if (socket->type != NICE_SOCKET_TYPE_UDP_BSD){ + return -ENOTSUP; + } + + num_packets_received = nice_udp_socket_recvmmsg (socket); + + if (num_packets_received <= 0) + return num_packets_received; + + MemlistInterface *memlist_interface = agent->mem_list_interface; + NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; + NiceAddress from_addresses[NICE_UDP_SOCKET_MMSG_TOTAL]; + int out_pkt_idx = 0; + + for(int pkt_idx = 0; pkt_idx < num_packets_received; pkt_idx++) + { + gboolean handled_internally; + NiceMemoryBufferRef *retrieved_buffer; + retrieved_buffer = nice_udp_socket_packet_retrieve(socket, pkt_idx, &from_addresses[out_pkt_idx]); + gsize buf_len = memlist_interface->buffer_size(memlist_interface, retrieved_buffer); + char* buf_contents = memlist_interface->buffer_contents(memlist_interface, retrieved_buffer); + +#ifndef NDEBUG + if (buf_len > 0) { + gchar tmpbuf[INET6_ADDRSTRLEN]; + nice_address_to_string (&from_addresses[out_pkt_idx], tmpbuf); + GST_LOG_OBJECT (agent, + "Packet received on local %s socket %u from [%s]:%u (%lu octets).", + socket_type_to_string (socket->type), + socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, + nice_address_get_port (&from_addresses[out_pkt_idx]), buf_len); + } +#endif + /* Figure out if this is a buffer that we handle internally, or if we should forward it on to the client */ + handled_internally = nice_agent_recv_process(agent, + socket, stream, component, buf_len, buf_contents, &from_addresses[out_pkt_idx]); + + if (handled_internally){ + /* Unref buffer */ + memlist_interface->buffer_return(memlist_interface, retrieved_buffer); + } + else{ + buffers[out_pkt_idx] = retrieved_buffer; + + out_pkt_idx++; + } + } + + /* unhandled STUN, pass to client */ + return out_pkt_idx; +} + + +static gint +_nice_agent_recv (NiceAgent * agent, + Stream * stream, + Component * component, + NiceSocket * socket, guint buf_len, gchar * buf, NiceAddress * from) +{ + gint len; + + len = nice_socket_recv (socket, from, buf_len, buf); + + if (len <= 0) + return len; + +#ifndef NDEBUG + if (len > 0) { + gchar tmpbuf[INET6_ADDRSTRLEN]; + nice_address_to_string (from, tmpbuf); + GST_LOG_OBJECT (agent, + "Packet received on local %s socket %u from [%s]:%u (%u octets).", + socket_type_to_string (socket->type), + socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, + nice_address_get_port (from), len); } +#endif + if ((guint) len > buf_len) { + /* buffer is not big enough to accept this packet */ + /* XXX: test this case */ + return FALSE; + } + + nice_agent_recv_process(agent, socket, stream, component, buf_len, buf, from); /* unhandled STUN, pass to client */ return len; @@ -3062,6 +3142,7 @@ nice_agent_attach_recv (NiceAgent * agent, ret = TRUE; component->g_source_io_cb = NULL; + component->g_source_io_multiple_cb = NULL; component->data = NULL; if (component->ctx) g_main_context_unref (component->ctx); diff --git a/agent/agent.h b/agent/agent.h index 0fc21a54..ea1314f9 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -270,12 +270,13 @@ typedef void (*NiceAgentRecvFunc) ( * @stream_id: The id of the stream * @component_id: The id of the component of the stream * which received the data - * @len: The length of the data - * @buf: The buffer containing the data received + * @num_buffers: Count of buffers retrieved * @user_data: The user data set in nice_agent_attach_recv() * * Callback function when data is received on a component - * + * In order to get the buffers that are retrieved, call + * nice_agent_memory_buffer_retrieve with indices from 0 to num_buffers-1 + * while executing this function. */ typedef void (*NiceAgentRecvMultipleFunc) ( NiceAgent *agent, guint stream_id, guint component_id, guint num_buffers, @@ -283,7 +284,7 @@ typedef void (*NiceAgentRecvMultipleFunc) ( /* This function should only be called inside the NiceAgentRecvMultipleFunc callback */ NICE_EXPORT NiceMemoryBufferRef *nice_agent_memory_buffer_retrieve(NiceAgent *agent, - guint stream_id, guint component_id, gsize buffer_index, + guint stream_id, guint component_id, gsize buffer_index, gpointer user_data, const NiceAddress *from, const NiceAddress *to); /** @@ -785,6 +786,9 @@ nice_agent_restart_stream ( * @ctx: The Glib Mainloop Context to use for listening on the component * @func: The callback function to be called when data is received on * the stream's component + * @func: The callback function to be called when data spanning multiple buffers + * is received on the stream's component, or null if receiving mutiple buffers + * are not received by the agent user. * @data: user data associated with the callback * * Attaches the stream's component's sockets to the Glib Mainloop Context in @@ -799,6 +803,7 @@ nice_agent_attach_recv ( guint component_id, GMainContext *ctx, NiceAgentRecvFunc func, + NiceAgentRecvMultipleFunc multi_func, gpointer data); /** diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index d8f82ec5..bfe22564 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -429,6 +429,22 @@ gst_nice_src_read_callback (NiceAgent *agent, g_main_loop_quit (nicesrc->mainloop); } +static void +gst_nice_src_read_multiple_callback (NiceAgent *agent, + guint stream_id, + guint component_id, + gpointer data, + const NiceAddress *from, + const NiceAddress *to) +{ + (void)agent; + (void)stream_id; + (void)component_id; + (void)data; + (void)from; + (void)to; +} + static gboolean gst_nice_src_unlock_idler (gpointer data) { @@ -727,12 +743,12 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) else { nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, - src->mainctx, gst_nice_src_read_callback, (gpointer) src); + src->mainctx, gst_nice_src_read_callback, gst_nice_src_read_multiple_callback, (gpointer) src); } break; case GST_STATE_CHANGE_READY_TO_NULL: nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, - src->mainctx, NULL, NULL); + src->mainctx, NULL, NULL, NULL); break; default: break; diff --git a/nice/memlist.h b/nice/memlist.h index 9a48492e..b755f7dd 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -6,7 +6,7 @@ * * (C) 2022 Pexip AS * - * The contents of this file are subject to the Mozilla Public License Version + * The contents of this file are subject to the Mozilla Public License VersioVn * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ diff --git a/nice/meson.build b/nice/meson.build index afe31941..afcfec3d 100644 --- a/nice/meson.build +++ b/nice/meson.build @@ -1,4 +1,4 @@ -install_headers('nice.h', 'niceconfig.h', subdir : 'nice') +install_headers('nice.h', 'niceconfig.h', 'memlist.h', subdir : 'nice') pkg_install_dir = join_paths(get_option('libdir'), 'pkgconfig') pkgconf = configuration_data() diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index aac359e2..f5dcdff7 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -41,41 +41,26 @@ * http://en.wikipedia.org/wiki/Berkeley_sockets.) */ -#define HAVE_RECVMMSG 1 - -#ifdef HAVE_RECVMMSG -#define _GNU_SOURCE -#include -#endif - #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include "udp-bsd.h" #include #include #include + #include "agent-priv.h" #include "memlist.h" -#include "udp-bsd.h" + #ifndef G_OS_WIN32 #include #endif -#ifdef HAVE_RECVMMSG -#define MSG_RECEIVE_TIMES 1 -#define MMSG_LEN 32 -#else -#define MSG_RECEIVE_TIMES 32 -#define MMSG_LEN 1 -#endif -#define BUFFER_ALLOC_SIZE 1500 -#define MMSG_TOTAL (MSG_RECEIVE_TIMES * MMSG_LEN) - static void socket_close (NiceSocket *sock); static gint socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf); @@ -84,7 +69,7 @@ static gint socket_send (NiceSocket *sock, const NiceAddress *to, static gboolean socket_is_reliable (NiceSocket *sock); static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket); -#ifdef HAVE_RECVMMSG +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG struct _MessageData { @@ -105,7 +90,7 @@ struct UdpBsdSocketPrivate { NiceAddress niceaddr; GSocketAddress *gaddr; -#ifdef HAVE_RECVMMSG +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG /* Alloc buffers outside callback, to avoid reallocing buffers for messages that are not received. Any messages that are passed along are replaced with freshly allocated memory. */ @@ -218,20 +203,15 @@ socket_close (NiceSocket *sock) } -#ifdef HAVE_RECVMMSG -gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received) +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG +gint nice_udp_socket_recvmmsg(NiceSocket *sock) { struct UdpBsdSocketPrivate *priv = sock->priv; int socket_fd = g_socket_get_fd(sock->fileno); - gssize result; + gssize result = + recvmmsg (socket_fd, priv->message_headers, NICE_UDP_SOCKET_MMSG_LEN, MSG_WAITFORONE, NULL); - if ((result = - recvmmsg (socket_fd, priv->message_headers, MMSG_LEN, MSG_WAITFORONE, NULL)) >= 0) { - *num_messages_received = result; - } else { - *num_messages_received = 0; - } return result; } #endif @@ -295,7 +275,7 @@ socket_is_reliable (NiceSocket *sock) return FALSE; } -#ifdef HAVE_RECVMMSG +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG /* TODO: We need a way to extract and replenish buffers once they have been received */ @@ -307,7 +287,7 @@ void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *int NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, guint packet_index, NiceAddress *from) { - g_assert(packet_index < MMSG_TOTAL); + g_assert(packet_index < NICE_UDP_SOCKET_MMSG_TOTAL); struct UdpBsdSocketPrivate *priv = udp_socket->priv; MessageData *message_data = &priv->message_datas[packet_index]; nice_address_set_from_sockaddr (from, (struct sockaddr *)&message_data->remote); @@ -329,7 +309,7 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface *memory_interface = priv->interface; - for(int i = 0; i < MMSG_TOTAL; i++) + for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { MessageData* msgdata = &(priv->message_datas[i]); struct mmsghdr *message_header = &(priv->message_headers[i]); @@ -373,7 +353,7 @@ static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface * { if (message_data->buffer == NULL) { - message_data->buffer = memory_interface->buffer_get(memory_interface, BUFFER_ALLOC_SIZE); + message_data->buffer = memory_interface->buffer_get(memory_interface, NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE); } gsize buffer_size = memory_interface->buffer_size(memory_interface, message_data->buffer); @@ -388,7 +368,7 @@ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface *memory_interface = priv->interface; - for(int i = 0; i < MMSG_TOTAL; i++) + for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { MessageData *message_data = &priv->message_datas[i]; struct mmsghdr *hdr = &priv->message_headers[i]; @@ -415,7 +395,7 @@ static void socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface *memory_interface = priv->interface; g_assert(iter_start < iter_end); - g_assert(iter_end < MMSG_TOTAL); + g_assert(iter_end < NICE_UDP_SOCKET_MMSG_TOTAL); g_assert(memory_interface != NULL); for(int i = iter_start; i < iter_end; i++) diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index cc494699..eedc7d16 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -39,17 +39,34 @@ #ifndef _UDP_BSD_H #define _UDP_BSD_H +#define NICE_UDP_SOCKET_HAVE_RECVMMSG 1 + +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG +#define _GNU_SOURCE +#include +#endif + #include "socket.h" #include "agent.h" G_BEGIN_DECLS +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG +#define NICE_UDP_SOCKET_MSG_RECEIVE_TIMES 1 +#define NICE_UDP_SOCKET_MMSG_LEN 32 +#else +#define NICE_UDP_SOCKET_MSG_RECEIVE_TIMES 32 +#define NICE_UDP_SOCKET_MMSG_LEN 1 +#endif +#define NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE 1500 +#define NICE_UDP_SOCKET_MMSG_TOTAL (NICE_UDP_SOCKET_MSG_RECEIVE_TIMES * NICE_UDP_SOCKET_MMSG_LEN) + NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr); void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *interface); void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket); -gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received); +gint nice_udp_socket_recvmmsg(NiceSocket *sock); NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, guint packet_index, NiceAddress *from); From 74f030e7d9aa135393debfec8508386d4275b9bd Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 7 Oct 2022 15:56:28 +0200 Subject: [PATCH 04/27] WIP3 --- agent/agent-priv.h | 2 +- agent/agent.c | 90 ++++++++++++++------ agent/agent.h | 5 +- gst/gstnicesrc.c | 203 +++++++++++++++++++++++++++++---------------- gst/gstnicesrc.h | 21 +++++ nice/memlist.h | 10 +-- socket/udp-bsd.c | 34 +++++--- socket/udp-bsd.h | 4 +- 8 files changed, 252 insertions(+), 117 deletions(-) diff --git a/agent/agent-priv.h b/agent/agent-priv.h index e6f2a5a8..a7c4e9c7 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -128,7 +128,7 @@ struct _NiceAgent gchar *software_attribute; /* SOFTWARE attribute */ gboolean reliable; /* property: reliable */ - MemlistInterface *mem_list_interface; /* property: mem_list_interface */ + MemlistInterface **mem_list_interface; /* property: mem_list_interface */ /* XXX: add pointer to internal data struct for ABI-safe extensions */ }; diff --git a/agent/agent.c b/agent/agent.c index dc9b9e3c..85259651 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -566,7 +566,7 @@ nice_agent_class_init (NiceAgentClass * klass) g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, g_param_spec_pointer ("mem-list-interface", "Memory list interface", - "Interface for allocating and releasing memory buffers", + "Interface for allocating and releasing memory buffers (should be a double ptr)", G_PARAM_CONSTRUCT_ONLY)); /* install signals */ @@ -2467,17 +2467,19 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, } +/* Buffers and addresses should be of at least NICE_UDP_SOCKET_MMSG_TOTAL size */ gint _nice_agent_recv_multiple (NiceAgent * agent, Stream * stream, Component * component, NiceSocket * socket, - gsize *num_buffers_received) + NiceMemoryBufferRef ** buffers, + NiceAddress * from_addresses) { gint num_packets_received; /* Make sure the agent user has set a mem list interface, and that this socket - sopports receiving multiple messages in one call. */ + supports receiving multiple messages in one call. */ if (agent->mem_list_interface == NULL){ return -ENOTSUP; } @@ -2492,8 +2494,6 @@ _nice_agent_recv_multiple (NiceAgent * agent, return num_packets_received; MemlistInterface *memlist_interface = agent->mem_list_interface; - NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; - NiceAddress from_addresses[NICE_UDP_SOCKET_MMSG_TOTAL]; int out_pkt_idx = 0; for(int pkt_idx = 0; pkt_idx < num_packets_received; pkt_idx++) @@ -2530,6 +2530,8 @@ _nice_agent_recv_multiple (NiceAgent * agent, } } + nice_udp_socket_recvmmsg_structures_fill_new_buffers(socket, 0, num_packets_received); + /* unhandled STUN, pass to client */ return out_pkt_idx; } @@ -2997,8 +2999,6 @@ nice_agent_g_source_cb (GSocket * gsocket, NiceAgent *agent = ctx->agent; Stream *stream = ctx->stream; Component *component = ctx->component; - NiceAddress from; - gchar buf[MAX_BUFFER_SIZE]; gint len; agent_lock (agent); @@ -3008,27 +3008,67 @@ nice_agent_g_source_cb (GSocket * gsocket, return FALSE; } - len = _nice_agent_recv (agent, stream, component, ctx->socket, - MAX_BUFFER_SIZE, buf, &from); +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + if (component->g_source_io_multiple_cb){ + NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; + NiceAddress from_addresses[NICE_UDP_SOCKET_MMSG_TOTAL]; - if (len > 0 && component->g_source_io_cb) { - gpointer data = component->data; - gint sid = stream->id; - gint cid = component->id; - NiceAgentRecvFunc callback = component->g_source_io_cb; - /* Unlock the agent before calling the callback */ - agent_unlock (agent); - callback (agent, sid, cid, len, buf, data, &from, &ctx->socket->addr); - goto done; - } else if (len < 0) { - GSource *source = ctx->source; + len = _nice_agent_recv_multiple(agent, stream, component, ctx->socket, + buffers, from_addresses); - GST_WARNING_OBJECT (agent, "_nice_agent_recv returned %d, errno (%d) : %s", - len, errno, g_strerror (errno)); - component->gsources = g_slist_remove (component->gsources, source); - g_source_destroy (source); - g_source_unref (source); + if (len > 0) { + gpointer data = component->data; + gint sid = stream->id; + gint cid = component->id; + NiceAgentRecvMultipleFunc callback = component->g_source_io_multiple_cb; + /* Unlock the agent before calling the callback */ + agent_unlock (agent); + callback (agent, sid, cid, len, buffers, from_addresses, + &ctx->socket->addr, data); + goto done; + } else if (len < 0 && len != -ENOTSUP) { + /* If ENOTSUP is received, try to call the non mmsg receive function */ + GSource *source = ctx->source; + + GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple returned %d, errno (%d) : %s", + len, errno, g_strerror (errno)); + component->gsources = g_slist_remove (component->gsources, source); + g_source_destroy (source); + g_source_unref (source); + /* If a unknown error is received, skip the non mmsg receive function, + by unlocking the agent and going to done. */ + agent_unlock(agent); + goto done; + } + } +#else + { + NiceAddress from; + gchar buf[MAX_BUFFER_SIZE]; + + len = _nice_agent_recv (agent, stream, component, ctx->socket, + MAX_BUFFER_SIZE, buf, &from); + + if (len > 0 && component->g_source_io_cb) { + gpointer data = component->data; + gint sid = stream->id; + gint cid = component->id; + NiceAgentRecvFunc callback = component->g_source_io_cb; + /* Unlock the agent before calling the callback */ + agent_unlock (agent); + callback (agent, sid, cid, len, buf, data, &from, &ctx->socket->addr); + goto done; + } else if (len < 0) { + GSource *source = ctx->source; + + GST_WARNING_OBJECT (agent, "_nice_agent_recv returned %d, errno (%d) : %s", + len, errno, g_strerror (errno)); + component->gsources = g_slist_remove (component->gsources, source); + g_source_destroy (source); + g_source_unref (source); + } } +#endif agent_unlock (agent); diff --git a/agent/agent.h b/agent/agent.h index ea1314f9..a617210a 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -271,6 +271,9 @@ typedef void (*NiceAgentRecvFunc) ( * @component_id: The id of the component of the stream * which received the data * @num_buffers: Count of buffers retrieved + * @buffers: Pointers to received buffers (of num_buffers length) + * @from: Pointers to from addresses (of num_buffers length) + * @to: Ponter to to address (i.e addr of agent, of 1 length) * @user_data: The user data set in nice_agent_attach_recv() * * Callback function when data is received on a component @@ -280,7 +283,7 @@ typedef void (*NiceAgentRecvFunc) ( */ typedef void (*NiceAgentRecvMultipleFunc) ( NiceAgent *agent, guint stream_id, guint component_id, guint num_buffers, - gpointer user_data); + NiceMemoryBufferRef **buffers, const NiceAddress *from, const NiceAddress *to, gpointer user_data); /* This function should only be called inside the NiceAgentRecvMultipleFunc callback */ NICE_EXPORT NiceMemoryBufferRef *nice_agent_memory_buffer_retrieve(NiceAgent *agent, diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index bfe22564..923d9da9 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -41,11 +41,7 @@ #include #include "gstnicesrc.h" -#if GST_CHECK_VERSION (1,0,0) #include -#else -#include -#endif GST_DEBUG_CATEGORY_STATIC (nicesrc_debug); #define GST_CAT_DEFAULT nicesrc_debug @@ -93,6 +89,21 @@ gst_nice_src_change_state ( GstElement * element, GstStateChange transition); + +static void gst_nice_src_mem_buffer_ref_array_clear(void *element); + +NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize size); +void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer); + +static const MemlistInterface nice_src_mem_interface = { + .buffer_get = gst_nice_src_buffer_get, + .buffer_return = gst_nice_src_buffer_return, + .buffer_contents = gst_nice_src_buffer_contents, + .buffer_size = gst_nice_src_buffer_size, +}; + static GstStaticPadTemplate gst_nice_src_src_template = GST_STATIC_PAD_TEMPLATE ( "src", @@ -178,11 +189,7 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_nice_src_src_template)); -#if GST_CHECK_VERSION (1,0,0) gst_element_class_set_metadata (gstelement_class, -#else - gst_element_class_set_details_simple (gstelement_class, -#endif "ICE source", "Source", "Interactive UDP connectivity establishment", @@ -345,8 +352,29 @@ gst_nice_src_init (GstNiceSrc *src) gst_nice_src_nice_address_compare, gst_nice_src_destroy_hash_key, gst_object_unref); + src->mem_list_interface.function_interface = &nice_src_mem_interface; + src->mem_list_interface.gst_src = src; + src->mem_list_interface.temp_refs = g_array_sized_new(FALSE, TRUE, + sizeof(GstNiceSrcMemoryBufferRef*), GST_NICE_SRC_MEM_BUFFERS_PREALLOCATED); + g_array_set_clear_func(src->mem_list_interface.temp_refs, &gst_nice_src_mem_buffer_ref_array_clear); } +static void gst_nice_buffer_address_meta_add( + GstNiceSrc *nicesrc, + const NiceAddress *from, + GstBuffer* buffer + ){ + if (from != NULL) { + GSocketAddress * saddr = gst_nice_src_gsocket_addr_create_or_retrieve( + nicesrc, from); + if (saddr != NULL) { + gst_buffer_add_net_address_meta (buffer, saddr); + g_object_unref (saddr); + } else { + GST_ERROR_OBJECT (nicesrc, "Could not convert address to GSocketAddress"); + } + } +} static void gst_nice_src_read_callback (NiceAgent *agent, guint stream_id, @@ -360,9 +388,6 @@ gst_nice_src_read_callback (NiceAgent *agent, GstBaseSrc *basesrc = GST_BASE_SRC (data); GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); -#if !GST_CHECK_VERSION (1,0,0) - GstNetBuffer *netbuffer = NULL; -#endif GstBuffer *buffer = NULL; (void)stream_id; @@ -370,7 +395,6 @@ gst_nice_src_read_callback (NiceAgent *agent, GST_LOG_OBJECT (agent, "Got buffer, getting out of the main loop"); -#if GST_CHECK_VERSION (1,0,0) (void)to; GstFlowReturn status = bclass->alloc(basesrc, 0, len, &buffer); if (status != GST_FLOW_OK) @@ -381,68 +405,48 @@ gst_nice_src_read_callback (NiceAgent *agent, } gst_buffer_fill (buffer, 0, buf, len); - if (from != NULL) { - GSocketAddress * saddr = gst_nice_src_gsocket_addr_create_or_retrieve( - nicesrc, from); - if (saddr != NULL) { - gst_buffer_add_net_address_meta (buffer, saddr); - g_object_unref (saddr); - } else { - GST_ERROR_OBJECT (nicesrc, "Could not convert address to GSocketAddress"); - } - } -#else - if (from != NULL && to != NULL) { - netbuffer = gst_netbuffer_new(); - - GST_BUFFER_DATA(netbuffer) = g_memdup(buf, len); - GST_BUFFER_MALLOCDATA(netbuffer) = GST_BUFFER_DATA(netbuffer); - GST_BUFFER_SIZE(netbuffer) = len; - - switch (from->s.addr.sa_family) { - case AF_INET: - { - gst_netaddress_set_ip4_address (&netbuffer->from, from->s.ip4.sin_addr.s_addr, from->s.ip4.sin_port); - gst_netaddress_set_ip4_address (&netbuffer->to, to->s.ip4.sin_addr.s_addr, to->s.ip4.sin_port); - } - break; - case AF_INET6: - { - gst_netaddress_set_ip6_address (&netbuffer->from, (guint8 *)(&from->s.ip6.sin6_addr), from->s.ip6.sin6_port); - gst_netaddress_set_ip6_address (&netbuffer->to, (guint8 *)(&to->s.ip6.sin6_addr), to->s.ip6.sin6_port); - } - break; - default: - GST_ERROR_OBJECT (nicesrc, "Unknown address family"); - break; - } - + gst_nice_buffer_address_meta_add(nicesrc, from, buffer); - buffer = GST_BUFFER_CAST(netbuffer); - } else { - buffer = gst_buffer_new_and_alloc (len); - memcpy (GST_BUFFER_DATA (buffer), buf, len); - } -#endif g_queue_push_tail (nicesrc->outbufs, buffer); g_main_loop_quit (nicesrc->mainloop); } +/* typedef void (*NiceAgentRecvMultipleFunc) ( + NiceAgent *agent, guint stream_id, guint component_id, + guint num_buffers, + NiceMemoryBufferRef **buffers, const NiceAddress *from, const NiceAddress *to, gpointer user_data); +*/ +/* NB: This function does not support pre 1.0 gstreamer */ static void gst_nice_src_read_multiple_callback (NiceAgent *agent, guint stream_id, guint component_id, - gpointer data, + guint num_buffers, + NiceMemoryBufferRef **buffers, const NiceAddress *from, - const NiceAddress *to) + const NiceAddress *to, + gpointer data) { - (void)agent; - (void)stream_id; - (void)component_id; - (void)data; - (void)from; - (void)to; + /*(void)agent; + (void)stream_id; + (void)component_id; + (void)data; + (void)from; + (void)to;*/ + GstBaseSrc *basesrc = GST_BASE_SRC (data); + GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); + + GstBufferList *outlist = gst_buffer_list_new_sized (num_buffers); + for (int i = 0; i < num_buffers; ++i) { + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)&buffers[i]; + GstBuffer *gbuffer = buffer_ref->buffer; + gst_buffer_unmap(gbuffer, &(buffer_ref->buf_map)); + gst_nice_buffer_address_meta_add(nicesrc, &from[i], gbuffer); + gst_buffer_list_insert (outlist, -1, gbuffer); + buffer_ref->buffer = NULL; + gst_nice_src_buffer_return((MemlistInterface**)&(nicesrc->mem_list_interface.function_interface), buffer_ref); + } } static gboolean @@ -554,11 +558,7 @@ gst_nice_src_create ( GST_OBJECT_LOCK (basesrc); if (nicesrc->unlocked) { GST_OBJECT_UNLOCK (basesrc); -#if GST_CHECK_VERSION (1,0,0) return GST_FLOW_FLUSHING; -#else - return GST_FLOW_WRONG_STATE; -#endif } GST_OBJECT_UNLOCK (basesrc); @@ -571,11 +571,7 @@ gst_nice_src_create ( return GST_FLOW_OK; } else { GST_LOG_OBJECT (nicesrc, "Got interrupting, returning wrong-state"); -#if GST_CHECK_VERSION (1,0,0) return GST_FLOW_FLUSHING; -#else - return GST_FLOW_WRONG_STATE; -#endif } } @@ -595,6 +591,14 @@ gst_nice_src_dispose (GObject *object) g_object_unref (src->agent); src->agent = NULL; + if (src->mem_list_interface.temp_refs){ + GArray *temp_refs = src->mem_list_interface.temp_refs; + /* Clean up all elements in array */ + for(int i=temp_refs->len-1;i==0; i--) + { + g_array_remove_index(temp_refs, i); + } + } if (src->mainloop) g_main_loop_unref (src->mainloop); src->mainloop = NULL; @@ -759,3 +763,62 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) return ret; } + +NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interface){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; + + GstNiceSrcMemoryBufferRef* ref; + if (mem_list_interface->temp_refs->len > 0) + { + /* Use an existing allocated reference */ + int last_index = mem_list_interface->temp_refs->len-1; + ref = (GstNiceSrcMemoryBufferRef*) g_array_index(mem_list_interface->temp_refs, GstNiceSrcMemoryBufferRef*, last_index); + g_array_remove_index(mem_list_interface->temp_refs, last_index); + } + else{ + /* No existing elements are stored, allocate a new one */ + ref = g_new0(GstNiceSrcMemoryBufferRef, 1); + } + g_assert_cmpint((gsize)ref, !=, (gsize)NULL); + return ref; +} + +NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize size){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; + + GstBaseSrc *basesrc = GST_BASE_SRC (mem_list_interface->gst_src); + //GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); + GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); + + GstNiceSrcMemoryBufferRef *ref = gst_nice_src_buffer_ref_allocate(interface); + GstBuffer *buffer = NULL; + GstFlowReturn status = bclass->alloc(basesrc, 0, size, &buffer); + g_assert_cmpint(status, ==, GST_FLOW_OK); + + gboolean mapped = gst_buffer_map (ref->buffer, &ref->buf_map, + GST_MAP_WRITE | GST_MAP_READ); + g_assert(mapped); + + return (NiceMemoryBufferRef*) ref; +} +void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ + /* TODO: Implement */ + +} +char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; + return (char*) buffer_ref->buf_map.data; +} +gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; + return buffer_ref->buf_map.size; +} + +/* Only to be used as a clear function for the temp_refs array, which contains uninitialised refs */ +static void gst_nice_src_mem_buffer_ref_array_clear(void *element){ + GstNiceSrcMemoryBufferRef **ref = (GstNiceSrcMemoryBufferRef**)element; + if (ref != NULL){ + g_free(*ref); + *ref = NULL; + } +} \ No newline at end of file diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 8d81502f..0cf41097 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -44,6 +44,7 @@ #include G_BEGIN_DECLS +#define GST_NICE_SRC_MEM_BUFFERS_PREALLOCATED 32 #define GST_TYPE_NICE_SRC \ (gst_nice_src_get_type()) @@ -60,6 +61,25 @@ G_BEGIN_DECLS typedef struct _GstNiceSrc GstNiceSrc; +typedef struct _GstNiceSrcMemoryBufferRef GstNiceSrcMemoryBufferRef; + +struct _GstNiceSrcMemoryBufferRef{ + GstBuffer *buffer; + GstMapInfo buf_map; +}; + +struct _GstNiceMemlistInterface{ + /* This must be first in struct for upcasts to work */ + const MemlistInterface *function_interface; + /* When embedded in GstNiceSrc this will be a self referencing pointer, + that is not refcounted */ + GstNiceSrc *gst_src; + /* Pointers to GstNiceSrcMemoryBufferRefs that have been returned that are + waiting to be given out again. It is assumed that the buffer and mapping + refed to by the reference is in an unintitialised state */ + GArray *temp_refs; +}; + struct _GstNiceSrc { GstPushSrc parent; @@ -74,6 +94,7 @@ struct _GstNiceSrc GSource *idle_source; GstCaps *caps; GHashTable *socket_addresses; + struct _GstNiceMemlistInterface mem_list_interface; }; typedef struct _GstNiceSrcClass GstNiceSrcClass; diff --git a/nice/memlist.h b/nice/memlist.h index b755f7dd..50c7f977 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -45,21 +45,19 @@ typedef void NiceMemoryBufferRef; /* Libnice expects the buffers received trough the interface to be accessable until they are either returned though nice_return_memory_buffer or by passing them as a result of a read operation. All buffers will be returned when the corresponding agent is destroyed */ -typedef NiceMemoryBufferRef* (*nice_memory_buffer_get)(MemlistInterface *interface, gsize size); +typedef NiceMemoryBufferRef* (*nice_memory_buffer_get)(MemlistInterface **interface, gsize size); /* Return a memory buffer to the provider */ -typedef void (*nice_memory_buffer_return)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); +typedef void (*nice_memory_buffer_return)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); /* Get a pointer to the contents (i.e. bytes) of the memory buffer */ -typedef char* (*nice_memory_buffer_contents)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); +typedef char* (*nice_memory_buffer_contents)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); /* Get the size of the memory buffer */ -typedef gsize (*nice_memory_buffer_size)(MemlistInterface *interface, NiceMemoryBufferRef* buffer); -typedef gsize (*nice_memory_memlist_unref)(MemlistInterface *interface); +typedef gsize (*nice_memory_buffer_size)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); struct _MemlistInterface { nice_memory_buffer_get buffer_get; nice_memory_buffer_return buffer_return; nice_memory_buffer_contents buffer_contents; nice_memory_buffer_size buffer_size; - nice_memory_memlist_unref unref; }; #endif /* _NICE_MEMLIST_H */ diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index f5dcdff7..36c92339 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -80,8 +80,9 @@ struct _MessageData }; typedef struct _MessageData MessageData; -static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface *memory_interface, +static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface **memory_interface, MessageData *message_data, struct mmsghdr *hdr); +/* TODO: Use those where appropriate */ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket); #endif @@ -98,7 +99,7 @@ struct UdpBsdSocketPrivate /* This is stored outside the MessageData struct as this must be in a continous list to be able to be passed to recvmmsg */ struct mmsghdr *message_headers; - MemlistInterface *interface; + MemlistInterface **interface; #endif }; @@ -179,6 +180,9 @@ nice_udp_bsd_socket_new (NiceAddress *addr) sock->close = socket_close; sock->attach = NULL; + priv->message_datas = NULL; + priv->message_headers = NULL; + return sock; } @@ -279,9 +283,11 @@ socket_is_reliable (NiceSocket *sock) /* TODO: We need a way to extract and replenish buffers once they have been received */ -void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *interface){ +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ struct UdpBsdSocketPrivate *priv = udp_socket->priv; g_assert(priv->interface == NULL); + priv->interface = interface; + socket_recvmmsg_structures_set_up(udp_socket); } NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, @@ -308,7 +314,8 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface *memory_interface = priv->interface; + MemlistInterface **memory_interface_ptr = priv->interface; + MemlistInterface *memory_interface = *memory_interface_ptr; for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { MessageData* msgdata = &(priv->message_datas[i]); @@ -316,14 +323,14 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) if (msgdata != NULL){ if (msgdata->buffer != NULL){ - memory_interface->buffer_return(memory_interface, msgdata->buffer); + memory_interface->buffer_return(memory_interface_ptr, msgdata->buffer); } msgdata->iovec.iov_len = 0; msgdata->iovec.iov_base = NULL; memset(message_header, 0, sizeof(struct mmsghdr)); - memory_interface->buffer_return(memory_interface, priv->message_datas[i].buffer); + memory_interface->buffer_return(memory_interface_ptr, priv->message_datas[i].buffer); priv->message_datas[i].buffer = NULL; } } @@ -348,17 +355,18 @@ static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) interface, but rather piggybacks the ownership of the agent */ } -static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface *memory_interface, +static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface **memory_interface_ptr, MessageData *message_data, struct mmsghdr *hdr) { + MemlistInterface *memory_interface = *memory_interface_ptr; if (message_data->buffer == NULL) { - message_data->buffer = memory_interface->buffer_get(memory_interface, NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE); + message_data->buffer = memory_interface->buffer_get(memory_interface_ptr, NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE); } - gsize buffer_size = memory_interface->buffer_size(memory_interface, message_data->buffer); + gsize buffer_size = memory_interface->buffer_size(memory_interface_ptr, message_data->buffer); message_data->iovec.iov_len = buffer_size; - message_data->iovec.iov_base = memory_interface->buffer_contents(memory_interface, message_data->buffer); + message_data->iovec.iov_base = memory_interface->buffer_contents(memory_interface_ptr, message_data->buffer); hdr->msg_len = buffer_size; } @@ -366,7 +374,7 @@ static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface * static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface *memory_interface = priv->interface; + MemlistInterface **memory_interface = priv->interface; for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { @@ -390,10 +398,10 @@ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) } } -static void socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, guint iter_start, guint iter_end) +void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, guint iter_start, guint iter_end) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface *memory_interface = priv->interface; + MemlistInterface **memory_interface = priv->interface; g_assert(iter_start < iter_end); g_assert(iter_end < NICE_UDP_SOCKET_MMSG_TOTAL); g_assert(memory_interface != NULL); diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index eedc7d16..a2c1a3ab 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -64,11 +64,13 @@ G_BEGIN_DECLS NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr); -void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface *interface); +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface); void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket); gint nice_udp_socket_recvmmsg(NiceSocket *sock); NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, guint packet_index, NiceAddress *from); +void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, + guint iter_start, guint iter_end); G_END_DECLS From 7f97115787d31787b9046d96ad833d8d4824b83f Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 10 Oct 2022 14:08:22 +0200 Subject: [PATCH 05/27] WIP4 --- agent/agent-priv.h | 2 +- agent/agent.c | 15 ++++---- gst/gstnicesrc.c | 90 +++++++++++++++++++++++++++++++++++++++++----- gst/gstnicesrc.h | 5 +++ socket/udp-bsd.c | 33 +++++++++-------- 5 files changed, 114 insertions(+), 31 deletions(-) diff --git a/agent/agent-priv.h b/agent/agent-priv.h index a7c4e9c7..ae592e39 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -105,7 +105,7 @@ struct _NiceAgent gboolean aggressive_mode; /* property: use aggressive nomination when controller */ guint regular_nomination_timeout; /* property: timeout (ms) before regular nomination starts nominating non-optimal media paths */ - GSList *local_addresses; /* list of NiceAddresses for loca + GSList *local_addresses; /* list of NiceAddresses for local interfaces */ GSList *streams; /* list of Stream objects */ GMainContext *main_context; /* main context pointer */ diff --git a/agent/agent.c b/agent/agent.c index 85259651..4330dca3 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -75,7 +75,7 @@ * will it work tcp relaying?? */ #define MAX_BUFFER_SIZE 65536 -#define DEFAULT_STUN_PORT 3478 +#define DEFAULT_STUN_PORT 3478 #define DEFAULT_UPNP_TIMEOUT 200 #define MAX_TCP_MTU 1400 /* Use 1400 because of VPNs and we assume IEE 802.3 */ @@ -149,7 +149,6 @@ static void priv_detach_stream_component (NiceAgent * agent, Stream * stream, Component * component); static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface * replacement); -static void mem_list_interface_propagate (NiceAgent * agent); void agent_lock (NiceAgent * agent) @@ -1005,11 +1004,13 @@ nice_agent_set_property (GObject * object, break; case PROP_MEM_LIST_INTERFACE: - mem_list_interface_clean_up_and_replace (agent, - (gpointer) agent->mem_list_interface); - /* TODO: The new interface must be passed down to any existing sockets */ - g_value_set_pointer ((gpointer) agent->mem_list_interface, - (gpointer) value); + { + /* Clean up and propagate new mem_list_interface */ + MemlistInterface * interface = g_value_get_pointer(value); + mem_list_interface_clean_up_and_replace (agent, + (gpointer) agent->mem_list_interface); + agent->mem_list_interface = interface; + } break; case PROP_UPNP_TIMEOUT: diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 923d9da9..ba51ea03 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -48,6 +48,7 @@ GST_DEBUG_CATEGORY_STATIC (nicesrc_debug); #define BUFFER_SIZE (65536) +//#define BUFFER_SIZE (4096) static GstFlowReturn gst_nice_src_create ( @@ -83,6 +84,8 @@ gst_nice_src_get_property ( static void gst_nice_src_dispose (GObject *object); +static +void gst_nice_src_clean_up_pool(GstNiceSrc * src); static GstStateChangeReturn gst_nice_src_change_state ( @@ -525,7 +528,6 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) GST_OBJECT_UNLOCK (src); gst_caps_take (&caps, intersect); - if (!gst_caps_is_empty (caps)) { if (gst_caps_is_any (caps)) { GST_DEBUG_OBJECT (basesrc, "any caps, negotiation not needed"); @@ -539,6 +541,57 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) result = gst_base_src_set_caps (basesrc, caps); } } + + // Start pool setup + if (src->mem_list_interface.pool) { + /* Clean up old pool, unmap all existing memory and allocate new */ + gst_nice_src_clean_up_pool (src); + } + + GstQuery *query = gst_query_new_allocation (caps, TRUE); + if (!gst_pad_peer_query (GST_BASE_SRC_PAD(basesrc), query)) + GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "didn't get downstream ALLOCATION hints"); + + if (src->mem_list_interface.allocator != NULL) + gst_object_unref (src->mem_list_interface.allocator); + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, + &src->mem_list_interface.allocator, &src->mem_list_interface.params); + } else { + src->mem_list_interface.allocator = NULL; + gst_allocation_params_init (&src->mem_list_interface.params); + } + + if (gst_query_get_n_allocation_pools (query) > 0) { + GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "Got n allocation pools: %d", + gst_query_get_n_allocation_pools (query)); + gst_query_parse_nth_allocation_pool (query, 0, &src->mem_list_interface.pool, NULL, NULL, + NULL); + } else { + GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "Creating evsrc buffer pool"); + src->mem_list_interface.pool = gst_buffer_pool_new (); + } + + { + guint size = BUFFER_SIZE, min = 0, max = 0; + GstStructure *config; + config = gst_buffer_pool_get_config (src->mem_list_interface.pool); + /* Ensure we don't pass unfixed caps to the buffer pool config as that will + trigger an assert */ + GstCaps *poolcaps; + if (caps != NULL && gst_caps_is_fixed (caps)) { + poolcaps = caps; + } else { + poolcaps = NULL; + } + gst_buffer_pool_config_set_params (config, poolcaps, (guint) size, min, + max); + gst_buffer_pool_config_set_allocator (config, src->mem_list_interface.allocator, + &src->mem_list_interface.params); + gst_buffer_pool_set_config (src->mem_list_interface.pool, config); + } + // End pool setup + gst_caps_unref (caps); } else { GST_DEBUG_OBJECT (basesrc, "no common caps"); @@ -546,6 +599,22 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) return result; } +static void gst_nice_src_clean_up_pool(GstNiceSrc * src) +{ + if (src->mem_list_interface.allocator != NULL) { + gst_object_unref (src->mem_list_interface.allocator); + src->mem_list_interface.allocator = NULL; + } + + if (src->mem_list_interface.pool != NULL) { + /* The entries that already exists will be with the old pool until they die + as we have no way of moving them to the new pool. */ + gst_buffer_pool_set_active (src->mem_list_interface.pool, FALSE); + gst_object_unref (src->mem_list_interface.pool); + src->mem_list_interface.pool = NULL; + } +} + static GstFlowReturn gst_nice_src_create ( GstPushSrc *basesrc, @@ -785,14 +854,12 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize size){ struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; - - GstBaseSrc *basesrc = GST_BASE_SRC (mem_list_interface->gst_src); - //GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); - GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); - + GstBufferPoolAcquireParams params = { 0 }; GstNiceSrcMemoryBufferRef *ref = gst_nice_src_buffer_ref_allocate(interface); GstBuffer *buffer = NULL; - GstFlowReturn status = bclass->alloc(basesrc, 0, size, &buffer); + + gint status = gst_buffer_pool_acquire_buffer (mem_list_interface->pool, &buffer, + ¶ms); g_assert_cmpint(status, ==, GST_FLOW_OK); gboolean mapped = gst_buffer_map (ref->buffer, &ref->buf_map, @@ -801,10 +868,17 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize return (NiceMemoryBufferRef*) ref; } + void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ - /* TODO: Implement */ + //struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; + /* Return allocated buffer to the pool after it has been used */ + gst_buffer_unmap (buffer_ref->buffer, &buffer_ref->buf_map); + gst_buffer_unref (buffer_ref->buffer); + memset (buffer_ref, 0, sizeof (GstNiceSrcMemoryBufferRef)); } + char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; return (char*) buffer_ref->buf_map.data; diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 0cf41097..28fe4efd 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -78,6 +78,11 @@ struct _GstNiceMemlistInterface{ waiting to be given out again. It is assumed that the buffer and mapping refed to by the reference is in an unintitialised state */ GArray *temp_refs; + /* Buffer variables needed for allocating and releasing buffers trough a pool */ + GstAllocator *allocator; + GstAllocationParams params; + GstBufferPool *pool; + }; struct _GstNiceSrc diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 36c92339..8342ecfb 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -315,23 +315,26 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface **memory_interface_ptr = priv->interface; - MemlistInterface *memory_interface = *memory_interface_ptr; - for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) + if(memory_interface_ptr != NULL) { - MessageData* msgdata = &(priv->message_datas[i]); - struct mmsghdr *message_header = &(priv->message_headers[i]); - - if (msgdata != NULL){ - if (msgdata->buffer != NULL){ - memory_interface->buffer_return(memory_interface_ptr, msgdata->buffer); + MemlistInterface *memory_interface = *memory_interface_ptr; + for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) + { + MessageData* msgdata = &(priv->message_datas[i]); + struct mmsghdr *message_header = &(priv->message_headers[i]); + + if (msgdata != NULL){ + if (msgdata->buffer != NULL){ + memory_interface->buffer_return(memory_interface_ptr, msgdata->buffer); + } + msgdata->iovec.iov_len = 0; + msgdata->iovec.iov_base = NULL; + + memset(message_header, 0, sizeof(struct mmsghdr)); + + memory_interface->buffer_return(memory_interface_ptr, priv->message_datas[i].buffer); + priv->message_datas[i].buffer = NULL; } - msgdata->iovec.iov_len = 0; - msgdata->iovec.iov_base = NULL; - - memset(message_header, 0, sizeof(struct mmsghdr)); - - memory_interface->buffer_return(memory_interface_ptr, priv->message_datas[i].buffer); - priv->message_datas[i].buffer = NULL; } } /* Currently we don't manage buffers when not recvmmsg is supported. From b5149e95d0d43dac0eb61def1c99efd4d29ce01e Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 11 Oct 2022 07:37:52 +0200 Subject: [PATCH 06/27] WIP: Handle and resize packets in gstnicesrc --- agent/agent.c | 21 ++++++++++++++------- gst/gstnicesrc.c | 18 ++++++++++++++++++ nice/memlist.h | 3 +++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 4330dca3..68a74c9f 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -2375,9 +2375,9 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, NiceSocket *socket, Stream * stream, Component * component, - guint buf_len, gchar * buf, NiceAddress * from) + guint *buf_len, gchar * buf, NiceAddress * from) { - gint len = buf_len; + gint len = *buf_len; GList *item; gboolean has_padding = _nice_should_have_padding (agent->compatibility); NiceAddress stun_server; @@ -2451,6 +2451,7 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, } agent->media_after_tick = TRUE; + *buf_len = len; if (len > 0) { if (stun_message_validate_buffer_length ((uint8_t *) buf, (size_t) len, @@ -2510,17 +2511,21 @@ _nice_agent_recv_multiple (NiceAgent * agent, gchar tmpbuf[INET6_ADDRSTRLEN]; nice_address_to_string (&from_addresses[out_pkt_idx], tmpbuf); GST_LOG_OBJECT (agent, - "Packet received on local %s socket %u from [%s]:%u (%lu octets).", + "Packet received multiple on local %s socket %u from [%s]:%u (%lu octets).", socket_type_to_string (socket->type), socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, nice_address_get_port (&from_addresses[out_pkt_idx]), buf_len); } #endif /* Figure out if this is a buffer that we handle internally, or if we should forward it on to the client */ + gsize new_len = buf_len; handled_internally = nice_agent_recv_process(agent, - socket, stream, component, buf_len, buf_contents, &from_addresses[out_pkt_idx]); + socket, stream, component, &new_len, buf_contents, &from_addresses[out_pkt_idx]); - if (handled_internally){ + if (buf_len != new_len) { + memlist_interface->buffer_resize(memlist_interface, retrieved_buffer, new_len); + } + if (handled_internally) { /* Unref buffer */ memlist_interface->buffer_return(memlist_interface, retrieved_buffer); } @@ -2568,7 +2573,10 @@ _nice_agent_recv (NiceAgent * agent, return FALSE; } - nice_agent_recv_process(agent, socket, stream, component, buf_len, buf, from); + if (nice_agent_recv_process(agent, socket, stream, component, &len, buf, from)) { + /* Handeled stun, don't pass to the client */ + return FALSE; + } /* unhandled STUN, pass to client */ return len; @@ -3042,7 +3050,6 @@ nice_agent_g_source_cb (GSocket * gsocket, goto done; } } -#else { NiceAddress from; gchar buf[MAX_BUFFER_SIZE]; diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index ba51ea03..bcb5bfe1 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -99,12 +99,15 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer); char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer); gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +void gst_nice_src_buffer_resize(MemlistInterface **interface, + NiceMemoryBufferRef* buffer, gsize new_size); static const MemlistInterface nice_src_mem_interface = { .buffer_get = gst_nice_src_buffer_get, .buffer_return = gst_nice_src_buffer_return, .buffer_contents = gst_nice_src_buffer_contents, .buffer_size = gst_nice_src_buffer_size, + .buffer_resize = gst_nice_src_buffer_resize, }; static GstStaticPadTemplate gst_nice_src_src_template = @@ -883,11 +886,26 @@ char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBuffe GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; return (char*) buffer_ref->buf_map.data; } + gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; return buffer_ref->buf_map.size; } +void gst_nice_src_buffer_resize(MemlistInterface **interface, NiceMemoryBufferRef* buffer, gsize new_size) { + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; + guint8* data_location; + g_assert(new_size <= buffer_ref->buf_map.size); + data_location = buffer_ref->buf_map.data; + gst_buffer_unmap (buffer_ref->buffer, &buffer_ref->buf_map); + gst_buffer_resize(buffer_ref->buffer, 0, new_size); + gboolean mapped = gst_buffer_map (buffer_ref->buffer, &buffer_ref->buf_map, + GST_MAP_WRITE | GST_MAP_READ); + g_assert(mapped); + g_assert(buffer_ref->buf_map.data == data_location); + g_assert(buffer_ref->buf_map.size == new_size); +} + /* Only to be used as a clear function for the temp_refs array, which contains uninitialised refs */ static void gst_nice_src_mem_buffer_ref_array_clear(void *element){ GstNiceSrcMemoryBufferRef **ref = (GstNiceSrcMemoryBufferRef**)element; diff --git a/nice/memlist.h b/nice/memlist.h index 50c7f977..039d961d 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -52,12 +52,15 @@ typedef void (*nice_memory_buffer_return)(MemlistInterface **interface, NiceMemo typedef char* (*nice_memory_buffer_contents)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); /* Get the size of the memory buffer */ typedef gsize (*nice_memory_buffer_size)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +/* Reduce the size of the memory buffer */ +typedef void (*nice_memory_buffer_resize)(MemlistInterface **interface, NiceMemoryBufferRef* buffer, gsize new_size); struct _MemlistInterface { nice_memory_buffer_get buffer_get; nice_memory_buffer_return buffer_return; nice_memory_buffer_contents buffer_contents; nice_memory_buffer_size buffer_size; + nice_memory_buffer_resize buffer_resize; }; #endif /* _NICE_MEMLIST_H */ From 4db9de0bc5a2cdb556e7cd8986d73ba50d748464 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 11 Oct 2022 10:41:10 +0200 Subject: [PATCH 07/27] WIP --- agent/agent.c | 23 ++++++++--------------- agent/agent.h | 2 ++ gst/gstnicesrc.c | 4 +++- socket/udp-bsd.c | 3 +++ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 68a74c9f..5bc11bff 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -562,11 +562,11 @@ nice_agent_class_init (NiceAgentClass * klass) g_object_class_install_property (gobject_class, PROP_TIE_BREAKER, g_param_spec_uint64 ("tie-breaker", "Tie breaker value to send in connectivity checks", "Tie breaker value to send in connectivity checks", 0, 0xffffffffffffffffLL, 0, /* Not construct time so ignored */ G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, + /*g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, g_param_spec_pointer ("mem-list-interface", "Memory list interface", "Interface for allocating and releasing memory buffers (should be a double ptr)", - G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_CONSTRUCT_ONLY));*/ /* install signals */ @@ -806,9 +806,6 @@ nice_agent_get_property (GObject * object, agent_lock (agent); switch (property_id) { - case PROP_MEM_LIST_INTERFACE: - g_value_set_pointer (value, (gpointer) agent->mem_list_interface); - break; case PROP_MAIN_CONTEXT: g_value_set_pointer (value, agent->main_context); break; @@ -1003,16 +1000,6 @@ nice_agent_set_property (GObject * object, agent->proxy_password = g_value_dup_string (value); break; - case PROP_MEM_LIST_INTERFACE: - { - /* Clean up and propagate new mem_list_interface */ - MemlistInterface * interface = g_value_get_pointer(value); - mem_list_interface_clean_up_and_replace (agent, - (gpointer) agent->mem_list_interface); - agent->mem_list_interface = interface; - } - break; - case PROP_UPNP_TIMEOUT: break; @@ -1032,6 +1019,12 @@ nice_agent_set_property (GObject * object, } +void nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface *interface){ + /* Clean up and propagate new mem_list_interface */ + mem_list_interface_clean_up_and_replace (agent, interface); + agent->mem_list_interface = interface; +} + static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, MemlistInterface * replacement) diff --git a/agent/agent.h b/agent/agent.h index a617210a..de00ee49 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -304,6 +304,8 @@ NICE_EXPORT NiceMemoryBufferRef *nice_agent_memory_buffer_retrieve(NiceAgent *ag NICE_EXPORT NiceAgent * nice_agent_new (GMainContext *ctx, NiceCompatibility compat, NiceCompatibility turn_compat); +NICE_EXPORT void +nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface *interface); /** * nice_agent_add_local_address: (skip) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index bcb5bfe1..77304ed6 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -707,8 +707,10 @@ gst_nice_src_set_property ( if (src->agent) GST_ERROR_OBJECT (object, "Changing the agent on a nice src not allowed"); - else + else{ src->agent = g_value_dup_object (value); + nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + } break; case PROP_STREAM: diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 8342ecfb..afb10b9d 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -379,6 +379,9 @@ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface **memory_interface = priv->interface; + if (priv->message_headers == 0){ + priv->message_headers = g_new0(struct mmsghdr, NICE_UDP_SOCKET_MMSG_TOTAL); + } for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { MessageData *message_data = &priv->message_datas[i]; From ab00eed6fbe4b20a065d511829d7702ed52568fd Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 14 Oct 2022 10:38:28 +0200 Subject: [PATCH 08/27] WIP --- agent/agent.c | 71 ++++++++++++++++++--------------- agent/agent.h | 2 +- gst/gstnicesrc.c | 55 ++++++++++++++++++++++---- gst/gstnicesrc.h | 1 + socket/udp-bsd.c | 101 +++++++++++++++++++++++++++++++++-------------- 5 files changed, 160 insertions(+), 70 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 5bc11bff..59c224eb 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -147,8 +147,8 @@ static gboolean priv_attach_stream_component (NiceAgent * agent, Stream * stream, Component * component); static void priv_detach_stream_component (NiceAgent * agent, Stream * stream, Component * component); -static void mem_list_interface_clean_up_and_replace (NiceAgent * agent, - MemlistInterface * replacement); +static void mem_list_interface_clean_up_and_replace_locked (NiceAgent * agent, + MemlistInterface ** replacement); void agent_lock (NiceAgent * agent) @@ -1019,41 +1019,45 @@ nice_agent_set_property (GObject * object, } -void nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface *interface){ +void nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **interface){ /* Clean up and propagate new mem_list_interface */ - mem_list_interface_clean_up_and_replace (agent, interface); + agent_lock (agent); + mem_list_interface_clean_up_and_replace_locked (agent, interface); agent->mem_list_interface = interface; + agent_unlock (agent); } static void -mem_list_interface_clean_up_and_replace (NiceAgent * agent, - MemlistInterface * replacement) +mem_list_interface_clean_up_and_replace_locked (NiceAgent * agent, + MemlistInterface ** replacement) { (void) agent; - if (agent->mem_list_interface != NULL) { - agent_lock (agent); - /* We need to go trough all (udp) sockets and release any pending buffers */ - GSList *stream_index; - - for (stream_index = agent->streams; stream_index; - stream_index = stream_index->next) { - GSList *component_index; - Stream *stream = stream_index->data; - for (component_index = stream->components; component_index; - component_index = component_index->next) { - GSList *socket_index; - Component *component = component_index->data; - for (socket_index = component->sockets; socket_index; - socket_index = socket_index->next) { - NiceSocket *udpsocket = socket_index->data; - nice_udp_socket_buffers_and_interface_unref (udpsocket); + MemlistInterface **old_interface = agent->mem_list_interface; + /* We need to go trough all (udp) sockets and release any pending buffers */ + GSList *stream_index; + + for (stream_index = agent->streams; stream_index; + stream_index = stream_index->next) { + GSList *component_index; + Stream *stream = stream_index->data; + for (component_index = stream->components; component_index; + component_index = component_index->next) { + GSList *socket_index; + Component *component = component_index->data; + for (socket_index = component->sockets; socket_index; + socket_index = socket_index->next) { + NiceSocket *udpsocket = socket_index->data; + if (udpsocket->type == NICE_SOCKET_TYPE_UDP_BSD) + { + if ( old_interface != NULL){ + nice_udp_socket_buffers_and_interface_unref (udpsocket); + } if (replacement != NULL) { nice_udp_socket_interface_set (udpsocket, replacement); } } } } - agent_unlock (agent); } } @@ -2488,7 +2492,8 @@ _nice_agent_recv_multiple (NiceAgent * agent, if (num_packets_received <= 0) return num_packets_received; - MemlistInterface *memlist_interface = agent->mem_list_interface; + MemlistInterface **memlist_interface_ptr = agent->mem_list_interface; + MemlistInterface *memlist_interface = *(agent->mem_list_interface); int out_pkt_idx = 0; for(int pkt_idx = 0; pkt_idx < num_packets_received; pkt_idx++) @@ -2496,8 +2501,9 @@ _nice_agent_recv_multiple (NiceAgent * agent, gboolean handled_internally; NiceMemoryBufferRef *retrieved_buffer; retrieved_buffer = nice_udp_socket_packet_retrieve(socket, pkt_idx, &from_addresses[out_pkt_idx]); - gsize buf_len = memlist_interface->buffer_size(memlist_interface, retrieved_buffer); - char* buf_contents = memlist_interface->buffer_contents(memlist_interface, retrieved_buffer); + g_assert(retrieved_buffer != NULL); + gsize buf_len = memlist_interface->buffer_size(memlist_interface_ptr, retrieved_buffer); + char* buf_contents = memlist_interface->buffer_contents(memlist_interface_ptr, retrieved_buffer); #ifndef NDEBUG if (buf_len > 0) { @@ -2516,11 +2522,11 @@ _nice_agent_recv_multiple (NiceAgent * agent, socket, stream, component, &new_len, buf_contents, &from_addresses[out_pkt_idx]); if (buf_len != new_len) { - memlist_interface->buffer_resize(memlist_interface, retrieved_buffer, new_len); + memlist_interface->buffer_resize(memlist_interface_ptr, retrieved_buffer, new_len); } if (handled_internally) { /* Unref buffer */ - memlist_interface->buffer_return(memlist_interface, retrieved_buffer); + memlist_interface->buffer_return(memlist_interface_ptr, retrieved_buffer); } else{ buffers[out_pkt_idx] = retrieved_buffer; @@ -2531,7 +2537,6 @@ _nice_agent_recv_multiple (NiceAgent * agent, nice_udp_socket_recvmmsg_structures_fill_new_buffers(socket, 0, num_packets_received); - /* unhandled STUN, pass to client */ return out_pkt_idx; } @@ -3028,7 +3033,7 @@ nice_agent_g_source_cb (GSocket * gsocket, callback (agent, sid, cid, len, buffers, from_addresses, &ctx->socket->addr, data); goto done; - } else if (len < 0 && len != -ENOTSUP) { + } else if (len < 0 && len != -ENOTSUP && len != -ENOMEM) { /* If ENOTSUP is received, try to call the non mmsg receive function */ GSource *source = ctx->source; @@ -3042,6 +3047,10 @@ nice_agent_g_source_cb (GSocket * gsocket, agent_unlock(agent); goto done; } + else{ + GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple skipped, returned %d, errno (%d) : %s", + len, errno, g_strerror (errno)); + } } { NiceAddress from; diff --git a/agent/agent.h b/agent/agent.h index de00ee49..31d23ee6 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -305,7 +305,7 @@ NICE_EXPORT NiceAgent * nice_agent_new (GMainContext *ctx, NiceCompatibility compat, NiceCompatibility turn_compat); NICE_EXPORT void -nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface *interface); +nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **interface); /** * nice_agent_add_local_address: (skip) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 77304ed6..296ac75a 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -363,6 +363,7 @@ gst_nice_src_init (GstNiceSrc *src) src->mem_list_interface.temp_refs = g_array_sized_new(FALSE, TRUE, sizeof(GstNiceSrcMemoryBufferRef*), GST_NICE_SRC_MEM_BUFFERS_PREALLOCATED); g_array_set_clear_func(src->mem_list_interface.temp_refs, &gst_nice_src_mem_buffer_ref_array_clear); + src->mem_list_interface_set = FALSE; } static void gst_nice_buffer_address_meta_add( @@ -453,6 +454,13 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, buffer_ref->buffer = NULL; gst_nice_src_buffer_return((MemlistInterface**)&(nicesrc->mem_list_interface.function_interface), buffer_ref); } + + GST_LOG_OBJECT (agent, "Got multiple buffers (%d), getting out of the main loop", num_buffers); + GST_ERROR_OBJECT (agent, "Pushing multiple buffers are not implemented for gstnicesrc yet. Dropping buffer."); +/* + g_queue_push_tail (nicesrc->outbufs, buffer); + + g_main_loop_quit (nicesrc->mainloop);*/ } static gboolean @@ -595,6 +603,15 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) } // End pool setup + /* Now that we have set up a memory pool and the rest of the pipeline, + we can set the mem list interface in the agent, + which will retrieve and initialise memory buffers */ + if (src->mem_list_interface_set == FALSE) + { + nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + src->mem_list_interface_set = TRUE; + } + gst_caps_unref (caps); } else { GST_DEBUG_OBJECT (basesrc, "no common caps"); @@ -629,6 +646,7 @@ gst_nice_src_create ( GST_OBJECT_LOCK (basesrc); if (nicesrc->unlocked) { + GST_LOG_OBJECT (nicesrc, "Source unlinkend, transitioning to flushing"); GST_OBJECT_UNLOCK (basesrc); return GST_FLOW_FLUSHING; } @@ -707,10 +725,8 @@ gst_nice_src_set_property ( if (src->agent) GST_ERROR_OBJECT (object, "Changing the agent on a nice src not allowed"); - else{ + else src->agent = g_value_dup_object (value); - nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); - } break; case PROP_STREAM: @@ -824,6 +840,18 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) src->mainctx, gst_nice_src_read_callback, gst_nice_src_read_multiple_callback, (gpointer) src); } break; +#if 0 + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + g_assert(src->agent != NULL); + /* Now that we have set up a memory pool and the rest of the pipeline, + we can set the mem list interface in the agent, + which will retrieve and initialise memory buffers */ + nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + + } + break; +#endif case GST_STATE_CHANGE_READY_TO_NULL: nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, src->mainctx, NULL, NULL, NULL); @@ -842,6 +870,7 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; GstNiceSrcMemoryBufferRef* ref; +#if 0 if (mem_list_interface->temp_refs->len > 0) { /* Use an existing allocated reference */ @@ -849,7 +878,9 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa ref = (GstNiceSrcMemoryBufferRef*) g_array_index(mem_list_interface->temp_refs, GstNiceSrcMemoryBufferRef*, last_index); g_array_remove_index(mem_list_interface->temp_refs, last_index); } - else{ + else +#endif + { /* No existing elements are stored, allocate a new one */ ref = g_new0(GstNiceSrcMemoryBufferRef, 1); } @@ -863,8 +894,14 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize GstNiceSrcMemoryBufferRef *ref = gst_nice_src_buffer_ref_allocate(interface); GstBuffer *buffer = NULL; + g_assert(mem_list_interface->pool != NULL); gint status = gst_buffer_pool_acquire_buffer (mem_list_interface->pool, &buffer, ¶ms); + if(status != GST_FLOW_OK) + { + gst_nice_src_buffer_return(interface, ref); + return NULL; + } g_assert_cmpint(status, ==, GST_FLOW_OK); gboolean mapped = gst_buffer_map (ref->buffer, &ref->buf_map, @@ -877,10 +914,12 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ //struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; - - /* Return allocated buffer to the pool after it has been used */ - gst_buffer_unmap (buffer_ref->buffer, &buffer_ref->buf_map); - gst_buffer_unref (buffer_ref->buffer); + if(buffer_ref->buffer){ + /* Return allocated buffer to the pool after it has been used */ + gst_buffer_unmap (buffer_ref->buffer, &buffer_ref->buf_map); + gst_buffer_unref (buffer_ref->buffer); + } + /* TODO: The ref should be added to the array, this is not done at the moment */ memset (buffer_ref, 0, sizeof (GstNiceSrcMemoryBufferRef)); } diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 28fe4efd..95c734a7 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -100,6 +100,7 @@ struct _GstNiceSrc GstCaps *caps; GHashTable *socket_addresses; struct _GstNiceMemlistInterface mem_list_interface; + gboolean mem_list_interface_set; }; typedef struct _GstNiceSrcClass GstNiceSrcClass; diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index afb10b9d..69b27465 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -92,14 +92,16 @@ struct UdpBsdSocketPrivate NiceAddress niceaddr; GSocketAddress *gaddr; #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + MemlistInterface **interface; /* Alloc buffers outside callback, to avoid reallocing buffers for messages that are not received. Any messages that are passed along are replaced with freshly allocated memory. */ - MessageData *message_datas; + MessageData message_datas[NICE_UDP_SOCKET_MMSG_TOTAL]; /* This is stored outside the MessageData struct as this must be in a continous list to be able to be passed to recvmmsg */ - struct mmsghdr *message_headers; - MemlistInterface **interface; + struct mmsghdr message_headers[NICE_UDP_SOCKET_MMSG_TOTAL]; + uint64_t buffer_available[((NICE_UDP_SOCKET_MMSG_TOTAL-1)/sizeof(uint64_t))+1]; + gboolean missing_buffers; #endif }; @@ -180,8 +182,9 @@ nice_udp_bsd_socket_new (NiceAddress *addr) sock->close = socket_close; sock->attach = NULL; - priv->message_datas = NULL; - priv->message_headers = NULL; + memset(priv->message_datas, 0, sizeof(MessageData)*NICE_UDP_SOCKET_MMSG_TOTAL); + memset(priv->message_headers, 0, sizeof(struct mmsghdr)*NICE_UDP_SOCKET_MMSG_TOTAL); + priv->missing_buffers = TRUE; return sock; } @@ -210,8 +213,19 @@ socket_close (NiceSocket *sock) #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG gint nice_udp_socket_recvmmsg(NiceSocket *sock) { + g_assert(sock->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = sock->priv; + if(priv->missing_buffers){ + priv->missing_buffers = FALSE; + nice_udp_socket_recvmmsg_structures_fill_new_buffers(sock, 0, NICE_UDP_SOCKET_MMSG_LEN); + if(priv->missing_buffers == TRUE){ + return -ENOMEM; + } + } + + //g_assert(priv->message_headers != NULL); + /* What do we do here if we haven't been able to initiate enough buffers to put data in?*/ int socket_fd = g_socket_get_fd(sock->fileno); gssize result = recvmmsg (socket_fd, priv->message_headers, NICE_UDP_SOCKET_MMSG_LEN, MSG_WAITFORONE, NULL); @@ -284,6 +298,7 @@ socket_is_reliable (NiceSocket *sock) /* TODO: We need a way to extract and replenish buffers once they have been received */ void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ + g_assert(udp_socket->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = udp_socket->priv; g_assert(priv->interface == NULL); priv->interface = interface; @@ -295,14 +310,14 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, { g_assert(packet_index < NICE_UDP_SOCKET_MMSG_TOTAL); struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MessageData *message_data = &priv->message_datas[packet_index]; - nice_address_set_from_sockaddr (from, (struct sockaddr *)&message_data->remote); + MessageData *message_data = &(priv->message_datas[packet_index]); + nice_address_set_from_sockaddr (from, (struct sockaddr *)&(message_data->remote)); NiceMemoryBufferRef *result = message_data->buffer; message_data->buffer = NULL; /* Replace the entry with a fresh buffer for next recvmmsg call */ socket_recvmmsg_structures_fill_entry_with_buffer (priv->interface, - message_data, &priv->message_headers[packet_index]); + message_data, message_data); return result; } @@ -317,6 +332,7 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) MemlistInterface **memory_interface_ptr = priv->interface; if(memory_interface_ptr != NULL) { + g_assert(priv->message_datas != NULL); MemlistInterface *memory_interface = *memory_interface_ptr; for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { @@ -332,27 +348,31 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) memset(message_header, 0, sizeof(struct mmsghdr)); - memory_interface->buffer_return(memory_interface_ptr, priv->message_datas[i].buffer); - priv->message_datas[i].buffer = NULL; + memory_interface->buffer_return(memory_interface_ptr, msgdata); + msgdata = NULL; } } } /* Currently we don't manage buffers when not recvmmsg is supported. This may change in the future. However until then do nothing here. */ + + /* Clear the interface pointer, regardless if it is set or not */ priv->interface = NULL; } static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - if (priv->message_datas != NULL) + /*if (priv->message_datas != NULL) { free(priv->message_datas); + priv->message_datas = NULL; } if (priv->message_headers != NULL) { free(priv->message_headers); - } + priv->message_datas = NULL; + }*/ /* priv->interface is owned by agent, which again owns (indirectly) this udp connection. Therefore this connection does not reference count the interface, but rather piggybacks the ownership of the agent */ @@ -366,6 +386,14 @@ static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface * { message_data->buffer = memory_interface->buffer_get(memory_interface_ptr, NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE); } +#if 0 + else{ + uint64_t bufval = *((uint64_t*)message_data->buffer); /* Breakpoint */ + } +#endif + if (message_data->buffer == NULL){ + return; + } gsize buffer_size = memory_interface->buffer_size(memory_interface_ptr, message_data->buffer); message_data->iovec.iov_len = buffer_size; @@ -378,30 +406,37 @@ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface **memory_interface = priv->interface; + gboolean missing_buffers = FALSE; - if (priv->message_headers == 0){ - priv->message_headers = g_new0(struct mmsghdr, NICE_UDP_SOCKET_MMSG_TOTAL); - } for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) { - MessageData *message_data = &priv->message_datas[i]; - struct mmsghdr *hdr = &priv->message_headers[i]; + MessageData *message_data = &(priv->message_datas[i]); + struct mmsghdr *hdr = &(priv->message_headers[i]); + g_assert(i < NICE_UDP_SOCKET_MMSG_TOTAL); - hdr->msg_hdr.msg_control = NULL; - hdr->msg_hdr.msg_controllen = 0; - hdr->msg_hdr.msg_iovlen = 1; - hdr->msg_hdr.msg_iov = &message_data->iovec; - hdr->msg_hdr.msg_name = (struct sockaddr *) &message_data->remote; - hdr->msg_hdr.msg_namelen = sizeof (struct sockaddr_storage); + priv->message_headers[i].msg_hdr.msg_control = NULL; + priv->message_headers[i].msg_hdr.msg_controllen = 0; + priv->message_headers[i].msg_hdr.msg_iovlen = 1; + priv->message_headers[i].msg_hdr.msg_iov = &message_data->iovec; + priv->message_headers[i].msg_hdr.msg_name = (struct sockaddr *) &message_data->remote; + priv->message_headers[i].msg_hdr.msg_namelen = sizeof (struct sockaddr_storage); if (memory_interface != NULL){ socket_recvmmsg_structures_fill_entry_with_buffer(memory_interface, message_data, hdr); - } else { - message_data->iovec.iov_len = 0; - message_data->iovec.iov_base = NULL; - hdr->msg_len = 0; + if (message_data->buffer != NULL){ + continue; + } + else{ + missing_buffers = TRUE; + } } + + message_data->iovec.iov_len = 0; + message_data->iovec.iov_base = NULL; + hdr->msg_len = 0; } + priv->missing_buffers = missing_buffers; + } void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, guint iter_start, guint iter_end) @@ -409,15 +444,21 @@ void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket struct UdpBsdSocketPrivate *priv = udp_socket->priv; MemlistInterface **memory_interface = priv->interface; g_assert(iter_start < iter_end); - g_assert(iter_end < NICE_UDP_SOCKET_MMSG_TOTAL); + g_assert(iter_end <= NICE_UDP_SOCKET_MMSG_TOTAL); g_assert(memory_interface != NULL); for(int i = iter_start; i < iter_end; i++) { - MessageData *message_data = &priv->message_datas[i]; - struct mmsghdr *hdr = &priv->message_headers[i]; + MessageData *message_data = &(priv->message_datas[i]); + struct mmsghdr *hdr = &(priv->message_headers[i]); socket_recvmmsg_structures_fill_entry_with_buffer(memory_interface, message_data, hdr); + if (message_data->buffer == NULL){ + message_data->iovec.iov_len = 0; + message_data->iovec.iov_base = NULL; + hdr->msg_len = 0; + priv->missing_buffers = TRUE; + } } } From 00a7762a37a11efb44b4117484d0db1160c0f6b4 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 14 Oct 2022 17:01:24 +0200 Subject: [PATCH 09/27] WIP: Avoid using GstPushSrc, use GstBaseSrc directly instead --- gst/gstnicesrc.c | 126 ++++++++++++++++++++++++++++++++++++++++------- gst/gstnicesrc.h | 6 ++- 2 files changed, 111 insertions(+), 21 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 296ac75a..2b2d98e0 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -50,10 +50,27 @@ GST_DEBUG_CATEGORY_STATIC (nicesrc_debug); #define BUFFER_SIZE (65536) //#define BUFFER_SIZE (4096) -static GstFlowReturn -gst_nice_src_create ( - GstPushSrc *basesrc, - GstBuffer **buffer); +static gboolean gst_nice_src_query ( + GstBaseSrc * src, + GstQuery * query); + +static GstFlowReturn gst_nice_src_create ( + GstBaseSrc * bsrc, + guint64 offset, + guint length, + GstBuffer ** ret); + +static GstFlowReturn gst_nice_src_alloc ( + GstBaseSrc * bsrc, + guint64 offset, + guint length, + GstBuffer ** ret); + +static GstFlowReturn gst_nice_src_fill ( + GstBaseSrc * bsrc, + guint64 offset, + guint length, + GstBuffer * ret); static gboolean gst_nice_src_unlock ( @@ -119,7 +136,7 @@ GST_STATIC_PAD_TEMPLATE ( #define gst_nice_src_parent_class parent_class -G_DEFINE_TYPE (GstNiceSrc, gst_nice_src, GST_TYPE_PUSH_SRC); +G_DEFINE_TYPE (GstNiceSrc, gst_nice_src, GST_TYPE_BASE_SRC); enum { @@ -168,7 +185,6 @@ gst_nice_src_handle_event (GstBaseSrc *basesrc, GstEvent * event) static void gst_nice_src_class_init (GstNiceSrcClass *klass) { - GstPushSrcClass *gstpushsrc_class; GstBaseSrcClass *gstbasesrc_class; GstElementClass *gstelement_class; GObjectClass *gobject_class; @@ -176,15 +192,21 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) GST_DEBUG_CATEGORY_INIT (nicesrc_debug, "nicesrc", 0, "libnice source"); - gstpushsrc_class = (GstPushSrcClass *) klass; - gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create); - + //gstpushsrc_class = (GstPushSrcClass *) klass; + //gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create); + gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop); gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_nice_src_negotiate); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_nice_src_handle_event); + /* Reimplementation of gstpushsrc in order to support buffer lists */ + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create); + gstbasesrc_class->alloc = GST_DEBUG_FUNCPTR (gst_nice_src_alloc); + gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_nice_src_fill); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_nice_src_query); + gobject_class = (GObjectClass *) klass; gobject_class->set_property = gst_nice_src_set_property; gobject_class->get_property = gst_nice_src_get_property; @@ -457,10 +479,10 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, GST_LOG_OBJECT (agent, "Got multiple buffers (%d), getting out of the main loop", num_buffers); GST_ERROR_OBJECT (agent, "Pushing multiple buffers are not implemented for gstnicesrc yet. Dropping buffer."); -/* - g_queue_push_tail (nicesrc->outbufs, buffer); - g_main_loop_quit (nicesrc->mainloop);*/ + g_queue_push_tail (nicesrc->outbufs, outlist); + + g_main_loop_quit (nicesrc->mainloop); } static gboolean @@ -608,7 +630,7 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) which will retrieve and initialise memory buffers */ if (src->mem_list_interface_set == FALSE) { - nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + nice_agent_set_mem_list_interface(src->agent, (MemlistInterface**)&src->mem_list_interface); src->mem_list_interface_set = TRUE; } @@ -635,10 +657,35 @@ static void gst_nice_src_clean_up_pool(GstNiceSrc * src) } } + +static gboolean +gst_nice_src_query (GstBaseSrc * src, GstQuery * query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_SCHEDULING: + { + /* a pushsrc can by default never operate in pull mode override + * if you want something different. */ + gst_query_set_scheduling (query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1, + 0); + gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH); + + ret = TRUE; + break; + } + default: + ret = GST_BASE_SRC_CLASS (parent_class)->query (src, query); + break; + } + return ret; +} + + static GstFlowReturn -gst_nice_src_create ( - GstPushSrc *basesrc, - GstBuffer **buffer) +gst_nice_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer ** ret) { GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); @@ -655,17 +702,58 @@ gst_nice_src_create ( if (g_queue_is_empty (nicesrc->outbufs)) g_main_loop_run (nicesrc->mainloop); - *buffer = g_queue_pop_head (nicesrc->outbufs); - if (*buffer != NULL) { - GST_LOG_OBJECT (nicesrc, "Got buffer, pushing"); + gpointer bufptr = g_queue_pop_head (nicesrc->outbufs); + + if (bufptr != NULL) { + if (GST_IS_BUFFER_LIST(ret)){ + gst_base_src_submit_buffer_list (basesrc, ret); + *ret = NULL; + GST_LOG_OBJECT (nicesrc, "Got buffer list, pushing"); + } + else + { + *ret = bufptr; + GST_LOG_OBJECT (nicesrc, "Got buffer, pushing"); + } return GST_FLOW_OK; } else { + *ret = NULL; GST_LOG_OBJECT (nicesrc, "Got interrupting, returning wrong-state"); return GST_FLOW_FLUSHING; } } +static GstFlowReturn +gst_nice_src_alloc (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer ** ret) +{ + GstFlowReturn fret; + GstNiceSrc *src; + GstNiceSrcClass *pclass; + + src = GST_NICE_SRC (bsrc); + pclass = GST_NICE_SRC_GET_CLASS (src); + fret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, ret); + + return fret; +} + +static GstFlowReturn +gst_nice_src_fill (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer * ret) +{ + GstFlowReturn fret; + GstNiceSrc *src; + GstNiceSrcClass *pclass; + + src = GST_NICE_SRC (bsrc); + pclass = GST_NICE_SRC_GET_CLASS (src); + fret = GST_BASE_SRC_CLASS (parent_class)->fill (bsrc, offset, length, ret); + + return fret; +} + static void gst_nice_src_dispose (GObject *object) { diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 95c734a7..8c3c0730 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -58,6 +58,8 @@ G_BEGIN_DECLS (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NICE_SRC)) #define GST_NICE_SRC_CAST(obj) \ ((GstNiceSrc *)(obj)) +#define GST_NICE_SRC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_NICE_SRC, GstNiceSrcClass)) typedef struct _GstNiceSrc GstNiceSrc; @@ -87,7 +89,7 @@ struct _GstNiceMemlistInterface{ struct _GstNiceSrc { - GstPushSrc parent; + GstBaseSrc parent; GstPad *srcpad; NiceAgent *agent; guint stream_id; @@ -107,7 +109,7 @@ typedef struct _GstNiceSrcClass GstNiceSrcClass; struct _GstNiceSrcClass { - GstPushSrcClass parent_class; + GstBaseSrcClass parent_class; }; GType gst_nice_src_get_type (void); From 3a0b3f8fcdd54f81b45981e3bc8fd579470b6e5a Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 17 Oct 2022 13:52:22 +0200 Subject: [PATCH 10/27] WIP: Some tests are now passing with buffer lists --- agent/agent.c | 30 +++++++++++++++++++++--------- gst/gstnicesrc.c | 35 +++++++++++++++++++---------------- socket/udp-bsd.c | 28 +++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 59c224eb..73da2c13 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -2372,7 +2372,7 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, NiceSocket *socket, Stream * stream, Component * component, - guint *buf_len, gchar * buf, NiceAddress * from) + gint *buf_len, gchar * buf, NiceAddress * from) { gint len = *buf_len; GList *item; @@ -2454,15 +2454,15 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, if (stun_message_validate_buffer_length ((uint8_t *) buf, (size_t) len, has_padding) != len) { /* If the retval is no 0, its not a valid stun packet, probably data */ - return TRUE; + return FALSE; } if (conn_check_handle_inbound_stun (agent, stream, component, socket, from, buf, len)) /* handled STUN message */ - return FALSE; + return TRUE; } - return TRUE; + return FALSE; } @@ -2566,12 +2566,23 @@ _nice_agent_recv (NiceAgent * agent, } #endif if ((guint) len > buf_len) { +#ifndef NDEBUG + gchar tmpbuf[INET6_ADDRSTRLEN]; + nice_address_to_string (from, tmpbuf); + GST_WARNING_OBJECT (agent, + "TOO BIG Packet received on local %s socket %u from [%s]:%u (%u octets).", + socket_type_to_string (socket->type), + socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, + nice_address_get_port (from), len); +#endif /* buffer is not big enough to accept this packet */ /* XXX: test this case */ return FALSE; } if (nice_agent_recv_process(agent, socket, stream, component, &len, buf, from)) { + GST_LOG_OBJECT (agent, + "Handled packet as an internal STUN packet, don't pass it downstream to the client."); /* Handeled stun, don't pass to the client */ return FALSE; } @@ -3048,10 +3059,12 @@ nice_agent_g_source_cb (GSocket * gsocket, goto done; } else{ - GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple skipped, returned %d, errno (%d) : %s", - len, errno, g_strerror (errno)); + GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple skipped, returned %d", + len); + goto done; } } +#endif { NiceAddress from; gchar buf[MAX_BUFFER_SIZE]; @@ -3078,7 +3091,6 @@ nice_agent_g_source_cb (GSocket * gsocket, g_source_unref (source); } } -#endif agent_unlock (agent); @@ -3329,13 +3341,13 @@ _priv_set_socket_tos (NiceAgent * agent, NiceSocket * sock, gint tos) if (sock->fileno && setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IP, IP_TOS, (const char *) &tos, sizeof (tos)) < 0) { - GST_WARNING_OBJECT (agent, "Could not set socket ToS", g_strerror (errno)); + GST_WARNING_OBJECT (agent, "Could not set socket ToS %s", g_strerror (errno)); } #ifdef IPV6_TCLASS if (sock->fileno && setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IPV6, IPV6_TCLASS, (const char *) &tos, sizeof (tos)) < 0) { - GST_DEBUG_OBJECT (agent, "Could not set IPV6 socket ToS", + GST_DEBUG_OBJECT (agent, "Could not set IPV6 socket ToS %s", g_strerror (errno)); } #endif diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 2b2d98e0..b6a281dd 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -468,7 +468,7 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, GstBufferList *outlist = gst_buffer_list_new_sized (num_buffers); for (int i = 0; i < num_buffers; ++i) { - GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)&buffers[i]; + GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffers[i]; GstBuffer *gbuffer = buffer_ref->buffer; gst_buffer_unmap(gbuffer, &(buffer_ref->buf_map)); gst_nice_buffer_address_meta_add(nicesrc, &from[i], gbuffer); @@ -478,7 +478,7 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, } GST_LOG_OBJECT (agent, "Got multiple buffers (%d), getting out of the main loop", num_buffers); - GST_ERROR_OBJECT (agent, "Pushing multiple buffers are not implemented for gstnicesrc yet. Dropping buffer."); + //GST_ERROR_OBJECT (agent, "Pushing multiple buffers are not implemented for gstnicesrc yet. Dropping buffer."); g_queue_push_tail (nicesrc->outbufs, outlist); @@ -551,6 +551,7 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) GstCaps *caps, *intersect; GstNiceSrc *src = GST_NICE_SRC_CAST (basesrc); gboolean result = FALSE; + gboolean update; caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); if (!caps) @@ -600,9 +601,11 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) gst_query_get_n_allocation_pools (query)); gst_query_parse_nth_allocation_pool (query, 0, &src->mem_list_interface.pool, NULL, NULL, NULL); + update = TRUE; } else { GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "Creating evsrc buffer pool"); src->mem_list_interface.pool = gst_buffer_pool_new (); + update = FALSE; } { @@ -622,6 +625,16 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) gst_buffer_pool_config_set_allocator (config, src->mem_list_interface.allocator, &src->mem_list_interface.params); gst_buffer_pool_set_config (src->mem_list_interface.pool, config); + if (update) + { + gst_query_set_nth_allocation_pool (query, 0, src->mem_list_interface.pool, size, 0, 0); + } + else + { + gst_query_add_allocation_pool (query, src->mem_list_interface.pool, size, 0, 0); + } + gst_buffer_pool_set_active (src->mem_list_interface.pool, TRUE); + } // End pool setup @@ -705,9 +718,9 @@ gst_nice_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, gpointer bufptr = g_queue_pop_head (nicesrc->outbufs); if (bufptr != NULL) { - if (GST_IS_BUFFER_LIST(ret)){ - gst_base_src_submit_buffer_list (basesrc, ret); + if (GST_IS_BUFFER_LIST(bufptr)){ *ret = NULL; + gst_base_src_submit_buffer_list (basesrc, bufptr); GST_LOG_OBJECT (nicesrc, "Got buffer list, pushing"); } else @@ -928,18 +941,6 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) src->mainctx, gst_nice_src_read_callback, gst_nice_src_read_multiple_callback, (gpointer) src); } break; -#if 0 - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - { - g_assert(src->agent != NULL); - /* Now that we have set up a memory pool and the rest of the pipeline, - we can set the mem list interface in the agent, - which will retrieve and initialise memory buffers */ - nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); - - } - break; -#endif case GST_STATE_CHANGE_READY_TO_NULL: nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, src->mainctx, NULL, NULL, NULL); @@ -991,6 +992,8 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize return NULL; } g_assert_cmpint(status, ==, GST_FLOW_OK); + g_assert(buffer != NULL); + ref->buffer = buffer; gboolean mapped = gst_buffer_map (ref->buffer, &ref->buf_map, GST_MAP_WRITE | GST_MAP_READ); diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 69b27465..5c3257a6 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -215,6 +215,17 @@ gint nice_udp_socket_recvmmsg(NiceSocket *sock) { g_assert(sock->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = sock->priv; + MemlistInterface **memory_interface_ptr = priv->interface; + MemlistInterface *memory_interface; + + if(memory_interface_ptr != NULL) + { + memory_interface = *memory_interface_ptr; + } + else + { + return -ENOTSUP; + } if(priv->missing_buffers){ priv->missing_buffers = FALSE; @@ -230,6 +241,12 @@ gint nice_udp_socket_recvmmsg(NiceSocket *sock) gssize result = recvmmsg (socket_fd, priv->message_headers, NICE_UDP_SOCKET_MMSG_LEN, MSG_WAITFORONE, NULL); + // Resize buffers to the actual received length + for( int i = 0; i < result; i++ ) { + MessageData* message_data = &(priv->message_datas[i]); + struct mmsghdr *message_header = &(priv->message_headers[i]); + memory_interface->buffer_resize(memory_interface_ptr, message_data->buffer, message_header->msg_len); + } return result; } #endif @@ -311,13 +328,14 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, g_assert(packet_index < NICE_UDP_SOCKET_MMSG_TOTAL); struct UdpBsdSocketPrivate *priv = udp_socket->priv; MessageData *message_data = &(priv->message_datas[packet_index]); + struct mmsghdr *message_header = &(priv->message_headers[packet_index]); nice_address_set_from_sockaddr (from, (struct sockaddr *)&(message_data->remote)); NiceMemoryBufferRef *result = message_data->buffer; message_data->buffer = NULL; /* Replace the entry with a fresh buffer for next recvmmsg call */ socket_recvmmsg_structures_fill_entry_with_buffer (priv->interface, - message_data, message_data); + message_data, message_header); return result; } @@ -348,22 +366,22 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) memset(message_header, 0, sizeof(struct mmsghdr)); - memory_interface->buffer_return(memory_interface_ptr, msgdata); + memory_interface->buffer_return(memory_interface_ptr, msgdata->buffer); msgdata = NULL; } } } /* Currently we don't manage buffers when not recvmmsg is supported. This may change in the future. However until then do nothing here. */ - + /* Clear the interface pointer, regardless if it is set or not */ priv->interface = NULL; } static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) { - struct UdpBsdSocketPrivate *priv = udp_socket->priv; - /*if (priv->message_datas != NULL) + /*struct UdpBsdSocketPrivate *priv = udp_socket->priv; + if (priv->message_datas != NULL) { free(priv->message_datas); priv->message_datas = NULL; From ac85400ac08148220f29e3cee944db9790a90e78 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 17 Oct 2022 15:14:59 +0200 Subject: [PATCH 11/27] WIP: Misc cleanups and support not enabling recvmmsg --- agent/agent.c | 4 +++- gst/gstnicesrc.c | 7 ++----- socket/udp-bsd.c | 31 +++++++++++++++++++++++++++---- socket/udp-bsd.h | 2 ++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index 73da2c13..ca9b62e7 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -2467,7 +2467,8 @@ static gboolean nice_agent_recv_process(NiceAgent * agent, } /* Buffers and addresses should be of at least NICE_UDP_SOCKET_MMSG_TOTAL size */ -gint +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG +static gint _nice_agent_recv_multiple (NiceAgent * agent, Stream * stream, Component * component, @@ -2539,6 +2540,7 @@ _nice_agent_recv_multiple (NiceAgent * agent, return out_pkt_idx; } +#endif static gint diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index b6a281dd..c9997b00 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -47,8 +47,8 @@ GST_DEBUG_CATEGORY_STATIC (nicesrc_debug); #define GST_CAT_DEFAULT nicesrc_debug -#define BUFFER_SIZE (65536) -//#define BUFFER_SIZE (4096) +//#define BUFFER_SIZE (65536) +#define BUFFER_SIZE (4096) static gboolean gst_nice_src_query ( GstBaseSrc * src, @@ -959,7 +959,6 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; GstNiceSrcMemoryBufferRef* ref; -#if 0 if (mem_list_interface->temp_refs->len > 0) { /* Use an existing allocated reference */ @@ -968,7 +967,6 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa g_array_remove_index(mem_list_interface->temp_refs, last_index); } else -#endif { /* No existing elements are stored, allocate a new one */ ref = g_new0(GstNiceSrcMemoryBufferRef, 1); @@ -1003,7 +1001,6 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize } void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ - //struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; if(buffer_ref->buffer){ /* Return allocated buffer to the pool after it has been used */ diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 5c3257a6..7723e665 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -182,9 +182,11 @@ nice_udp_bsd_socket_new (NiceAddress *addr) sock->close = socket_close; sock->attach = NULL; +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG memset(priv->message_datas, 0, sizeof(MessageData)*NICE_UDP_SOCKET_MMSG_TOTAL); memset(priv->message_headers, 0, sizeof(struct mmsghdr)*NICE_UDP_SOCKET_MMSG_TOTAL); priv->missing_buffers = TRUE; +#endif return sock; } @@ -494,18 +496,39 @@ void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) { (void)udp_socket; } +gint nice_udp_socket_recvmmsg(NiceSocket *sock); +NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, + guint packet_index, NiceAddress *from); + NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, guint packet_index, NiceAddress *from) { (void)udp_socket; (void)packet_index; (void)from; + (void)socket_recvmmsg_structures_clean_up; return NULL; } -gint nice_udp_socket_recvmmsg(NiceSocket *sock, gsize * num_messages_received) +void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, + guint iter_start, guint iter_end) +{ + (void)udp_socket; + (void)iter_start; + (void)iter_end; +} +static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) { - (void)sock; - num_messages_received = 0; - return -ENOTSUP; + (void)udp_socket; } +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ + (void)udp_socket; + (void)interface; +} + +#if 0 +static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) +{ + (void)udp_socket; +} +#endif #endif \ No newline at end of file diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index a2c1a3ab..df9582e4 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -39,7 +39,9 @@ #ifndef _UDP_BSD_H #define _UDP_BSD_H +#ifdef __linux__ #define NICE_UDP_SOCKET_HAVE_RECVMMSG 1 +#endif #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG #define _GNU_SOURCE From b1a7279e6bfec67e2aff58345f0c16ef994eecda Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 17 Oct 2022 16:04:27 +0200 Subject: [PATCH 12/27] Reduce footprint when mmsg in not enabled --- gst/gstnicesrc.c | 28 ++++++++++++++++++++++------ gst/gstnicesrc.h | 2 ++ nice/memlist.h | 7 +++++++ socket/socket.c | 2 +- socket/socket.h | 2 +- socket/udp-bsd.h | 4 ---- 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index c9997b00..4b82dcf7 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -194,7 +194,7 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) //gstpushsrc_class = (GstPushSrcClass *) klass; //gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create); - + gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop); @@ -380,12 +380,14 @@ gst_nice_src_init (GstNiceSrc *src) gst_nice_src_nice_address_compare, gst_nice_src_destroy_hash_key, gst_object_unref); +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG src->mem_list_interface.function_interface = &nice_src_mem_interface; src->mem_list_interface.gst_src = src; src->mem_list_interface.temp_refs = g_array_sized_new(FALSE, TRUE, sizeof(GstNiceSrcMemoryBufferRef*), GST_NICE_SRC_MEM_BUFFERS_PREALLOCATED); g_array_set_clear_func(src->mem_list_interface.temp_refs, &gst_nice_src_mem_buffer_ref_array_clear); src->mem_list_interface_set = FALSE; +#endif } static void gst_nice_buffer_address_meta_add( @@ -440,7 +442,7 @@ gst_nice_src_read_callback (NiceAgent *agent, g_main_loop_quit (nicesrc->mainloop); } - +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG /* typedef void (*NiceAgentRecvMultipleFunc) ( NiceAgent *agent, guint stream_id, guint component_id, guint num_buffers, @@ -484,6 +486,7 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, g_main_loop_quit (nicesrc->mainloop); } +#endif static gboolean gst_nice_src_unlock_idler (gpointer data) @@ -551,7 +554,6 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) GstCaps *caps, *intersect; GstNiceSrc *src = GST_NICE_SRC_CAST (basesrc); gboolean result = FALSE; - gboolean update; caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); if (!caps) @@ -576,6 +578,8 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) } } +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + gboolean update; // Start pool setup if (src->mem_list_interface.pool) { /* Clean up old pool, unmap all existing memory and allocate new */ @@ -639,13 +643,14 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) // End pool setup /* Now that we have set up a memory pool and the rest of the pipeline, - we can set the mem list interface in the agent, + we can set the mem list interface in the agent, which will retrieve and initialise memory buffers */ if (src->mem_list_interface_set == FALSE) { nice_agent_set_mem_list_interface(src->agent, (MemlistInterface**)&src->mem_list_interface); src->mem_list_interface_set = TRUE; } +#endif gst_caps_unref (caps); } else { @@ -654,6 +659,7 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) return result; } +#if NICE_UDP_SOCKET_HAVE_RECVMMSG static void gst_nice_src_clean_up_pool(GstNiceSrc * src) { if (src->mem_list_interface.allocator != NULL) { @@ -669,7 +675,7 @@ static void gst_nice_src_clean_up_pool(GstNiceSrc * src) src->mem_list_interface.pool = NULL; } } - +#endif static gboolean gst_nice_src_query (GstBaseSrc * src, GstQuery * query) @@ -782,6 +788,7 @@ gst_nice_src_dispose (GObject *object) g_object_unref (src->agent); src->agent = NULL; +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG if (src->mem_list_interface.temp_refs){ GArray *temp_refs = src->mem_list_interface.temp_refs; /* Clean up all elements in array */ @@ -790,6 +797,9 @@ gst_nice_src_dispose (GObject *object) g_array_remove_index(temp_refs, i); } } + gst_nice_src_clean_up_pool(src); +#endif + if (src->mainloop) g_main_loop_unref (src->mainloop); src->mainloop = NULL; @@ -938,7 +948,13 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) else { nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, - src->mainctx, gst_nice_src_read_callback, gst_nice_src_read_multiple_callback, (gpointer) src); + src->mainctx, gst_nice_src_read_callback, +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + gst_nice_src_read_multiple_callback, +#else + NULL, +#endif + (gpointer) src); } break; case GST_STATE_CHANGE_READY_TO_NULL: diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 8c3c0730..074ce1bb 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -101,8 +101,10 @@ struct _GstNiceSrc GSource *idle_source; GstCaps *caps; GHashTable *socket_addresses; +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG struct _GstNiceMemlistInterface mem_list_interface; gboolean mem_list_interface_set; +#endif }; typedef struct _GstNiceSrcClass GstNiceSrcClass; diff --git a/nice/memlist.h b/nice/memlist.h index 039d961d..eb6c30f5 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -38,6 +38,13 @@ #ifndef _NICE_MEMLIST_H #define _NICE_MEMLIST_H +//#if 0 +#ifdef __linux__ +#define NICE_UDP_SOCKET_HAVE_RECVMMSG 1 +#define _GNU_SOURCE +#endif + + #include typedef struct _MemlistInterface MemlistInterface; diff --git a/socket/socket.c b/socket/socket.c index d3ea0bed..55ada911 100644 --- a/socket/socket.c +++ b/socket/socket.c @@ -110,7 +110,7 @@ nice_socket_buffers_and_interface_unref (NiceSocket *sock) } void -nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface *interface) +nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface) { if (sock) { if (sock->type == NICE_SOCKET_TYPE_UDP_BSD) diff --git a/socket/socket.h b/socket/socket.h index 2bda120c..c7287ff5 100644 --- a/socket/socket.h +++ b/socket/socket.h @@ -113,7 +113,7 @@ void nice_socket_free (NiceSocket *sock); void -nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface *interface); +nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface); void nice_socket_buffers_and_interface_unref (NiceSocket *sock); diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index df9582e4..9875a8dd 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -39,10 +39,6 @@ #ifndef _UDP_BSD_H #define _UDP_BSD_H -#ifdef __linux__ -#define NICE_UDP_SOCKET_HAVE_RECVMMSG 1 -#endif - #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG #define _GNU_SOURCE #include From d52d2387f661992418238349e2f107d1e146a81d Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 18 Oct 2022 08:19:16 +0200 Subject: [PATCH 13/27] Try to move some macros around to see if MSVC gets more happy --- agent/agent.c | 14 ++++++++++++-- nice/memlist.h | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index ca9b62e7..d6d6ea73 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -556,10 +556,20 @@ nice_agent_class_init (NiceAgentClass * klass) "Use aggressive nomination when controller", TRUE, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_REGULAR_NOMINATION_TIMEOUT, g_param_spec_uint ("regular-nomination-timeout", "Timeout (in ms) before regular nomination will select non-optimal media path", "Timeout (in ms) before regular nomination will select non-optimal media path", 1, 0xffffffff, NICE_AGENT_REGULAR_NOMINATION_TIMEOUT_DEFAULT, /* Not construct time so ignored */ + g_object_class_install_property (gobject_class, PROP_REGULAR_NOMINATION_TIMEOUT, + g_param_spec_uint ("regular-nomination-timeout", + "Timeout (in ms) before regular nomination will select non-optimal media path", + "Timeout (in ms) before regular nomination will select non-optimal media path", + 1, 0xffffffff, + NICE_AGENT_REGULAR_NOMINATION_TIMEOUT_DEFAULT, /* Not construct time so ignored */ G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_TIE_BREAKER, g_param_spec_uint64 ("tie-breaker", "Tie breaker value to send in connectivity checks", "Tie breaker value to send in connectivity checks", 0, 0xffffffffffffffffLL, 0, /* Not construct time so ignored */ + g_object_class_install_property (gobject_class, PROP_TIE_BREAKER, + g_param_spec_uint64 ("tie-breaker", + "Tie breaker value to send in connectivity checks", + "Tie breaker value to send in connectivity checks", + 0, 0xffffffffffffffffLL, + 0, /* Not construct time so ignored */ G_PARAM_READWRITE)); /*g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, diff --git a/nice/memlist.h b/nice/memlist.h index eb6c30f5..390e3d80 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -47,6 +47,8 @@ #include +G_BEGIN_DECLS + typedef struct _MemlistInterface MemlistInterface; typedef void NiceMemoryBufferRef; /* Libnice expects the buffers received trough the interface to be accessable until they are either @@ -69,5 +71,7 @@ struct _MemlistInterface { nice_memory_buffer_size buffer_size; nice_memory_buffer_resize buffer_resize; }; +G_END_DECLS + #endif /* _NICE_MEMLIST_H */ From 266923b09293caf2bf9eb6be7f81ddd3dbccc9de Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 18 Oct 2022 13:43:08 +0200 Subject: [PATCH 14/27] Fix handling of buffers when not able to recvmmsg --- agent/agent.c | 18 ++++++++++-------- gst/gstnicesrc.c | 11 ++++++++++- socket/udp-bsd.c | 3 +-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index d6d6ea73..cdc0d7e8 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -2520,11 +2520,11 @@ _nice_agent_recv_multiple (NiceAgent * agent, if (buf_len > 0) { gchar tmpbuf[INET6_ADDRSTRLEN]; nice_address_to_string (&from_addresses[out_pkt_idx], tmpbuf); - GST_LOG_OBJECT (agent, - "Packet received multiple on local %s socket %u from [%s]:%u (%lu octets).", + GST_INFO_OBJECT (agent, + "Packet received multiple on local %s socket %u from [%s]:%u (%lu octets, %lu packets).", socket_type_to_string (socket->type), socket->fileno ? g_socket_get_fd (socket->fileno) : 0, tmpbuf, - nice_address_get_port (&from_addresses[out_pkt_idx]), buf_len); + nice_address_get_port (&from_addresses[out_pkt_idx]), buf_len, num_packets_received); } #endif /* Figure out if this is a buffer that we handle internally, or if we should forward it on to the client */ @@ -2533,6 +2533,7 @@ _nice_agent_recv_multiple (NiceAgent * agent, socket, stream, component, &new_len, buf_contents, &from_addresses[out_pkt_idx]); if (buf_len != new_len) { + GST_INFO_OBJECT (agent, "Packet resized: %d -> %d", buf_len, new_len); memlist_interface->buffer_resize(memlist_interface_ptr, retrieved_buffer, new_len); } if (handled_internally) { @@ -3039,7 +3040,7 @@ nice_agent_g_source_cb (GSocket * gsocket, } #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG - if (component->g_source_io_multiple_cb){ + if (component->g_source_io_multiple_cb && ctx->socket->type == NICE_SOCKET_TYPE_UDP_BSD) { NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; NiceAddress from_addresses[NICE_UDP_SOCKET_MMSG_TOTAL]; @@ -3070,11 +3071,12 @@ nice_agent_g_source_cb (GSocket * gsocket, agent_unlock(agent); goto done; } - else{ - GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple skipped, returned %d", - len); - goto done; + else + { + GST_WARNING_OBJECT (agent, "_nice_agent_recv_multiple skipped, returned %d", + len); } + /* If receiving multiple packets were not supported, fall back to receiving single packets below */ } #endif { diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 4b82dcf7..fac6e01b 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -784,8 +784,17 @@ gst_nice_src_dispose (GObject *object) } src->idle_source = NULL; - if (src->agent) + if (src->agent){ +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + if (src->mem_list_interface_set == TRUE) + { + nice_agent_set_mem_list_interface(src->agent, NULL); + src->mem_list_interface_set = FALSE; + } +#endif g_object_unref (src->agent); + } + src->agent = NULL; #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 7723e665..f24a0f38 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -367,9 +367,8 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) msgdata->iovec.iov_base = NULL; memset(message_header, 0, sizeof(struct mmsghdr)); + memset(msgdata, 0, sizeof(MessageData)); - memory_interface->buffer_return(memory_interface_ptr, msgdata->buffer); - msgdata = NULL; } } } From 75fbf422845ab4924f9ef32f25785324845bc707 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 18 Oct 2022 14:58:52 +0200 Subject: [PATCH 15/27] Cleanups and try to make msvc more happy by avoinding typedefs --- nice/memlist.h | 2 +- socket/socket.h | 2 +- socket/udp-bsd.c | 30 ------------------------------ 3 files changed, 2 insertions(+), 32 deletions(-) diff --git a/nice/memlist.h b/nice/memlist.h index 390e3d80..aa9ac9b4 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -38,7 +38,6 @@ #ifndef _NICE_MEMLIST_H #define _NICE_MEMLIST_H -//#if 0 #ifdef __linux__ #define NICE_UDP_SOCKET_HAVE_RECVMMSG 1 #define _GNU_SOURCE @@ -71,6 +70,7 @@ struct _MemlistInterface { nice_memory_buffer_size buffer_size; nice_memory_buffer_resize buffer_resize; }; + G_END_DECLS #endif /* _NICE_MEMLIST_H */ diff --git a/socket/socket.h b/socket/socket.h index c7287ff5..94e90776 100644 --- a/socket/socket.h +++ b/socket/socket.h @@ -113,7 +113,7 @@ void nice_socket_free (NiceSocket *sock); void -nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface); +nice_socket_buffer_interface_set (NiceSocket *sock, struct _MemlistInterface **interface); void nice_socket_buffers_and_interface_unref (NiceSocket *sock); diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index f24a0f38..d3993f21 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -67,7 +67,6 @@ static gint socket_recv (NiceSocket *sock, NiceAddress *from, static gint socket_send (NiceSocket *sock, const NiceAddress *to, guint len, const gchar *buf); static gboolean socket_is_reliable (NiceSocket *sock); -static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket); #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG @@ -200,7 +199,6 @@ socket_close (NiceSocket *sock) g_object_unref (priv->gaddr); nice_udp_socket_buffers_and_interface_unref(sock); - socket_recvmmsg_structures_clean_up(sock); g_slice_free (struct UdpBsdSocketPrivate, sock->priv); @@ -379,23 +377,6 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) priv->interface = NULL; } -static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) -{ - /*struct UdpBsdSocketPrivate *priv = udp_socket->priv; - if (priv->message_datas != NULL) - { - free(priv->message_datas); - priv->message_datas = NULL; - } - if (priv->message_headers != NULL) - { - free(priv->message_headers); - priv->message_datas = NULL; - }*/ - /* priv->interface is owned by agent, which again owns (indirectly) this udp - connection. Therefore this connection does not reference count the - interface, but rather piggybacks the ownership of the agent */ -} static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface **memory_interface_ptr, MessageData *message_data, struct mmsghdr *hdr) @@ -505,7 +486,6 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, (void)udp_socket; (void)packet_index; (void)from; - (void)socket_recvmmsg_structures_clean_up; return NULL; } void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, @@ -515,19 +495,9 @@ void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket (void)iter_start; (void)iter_end; } -static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) -{ - (void)udp_socket; -} void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ (void)udp_socket; (void)interface; } -#if 0 -static void socket_recvmmsg_structures_clean_up(NiceSocket *udp_socket) -{ - (void)udp_socket; -} -#endif #endif \ No newline at end of file From 84626849747ef61b4abce1698310466968ca6688 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Wed, 19 Oct 2022 09:02:05 +0200 Subject: [PATCH 16/27] Fix valgrind errors in tests --- gst/gstnicesrc.c | 10 +++++++++- socket/socket.h | 6 ------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index fac6e01b..8d361473 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -638,8 +638,10 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) gst_query_add_allocation_pool (query, src->mem_list_interface.pool, size, 0, 0); } gst_buffer_pool_set_active (src->mem_list_interface.pool, TRUE); - + /* NB: This pool is not used by the basesrc when allocating buffers from it, as it is not possible + to set it when we negotiate caps ourselves (and not overwrite the appropriate functions in gstbasesrc) */ } + gst_query_unref(query); // End pool setup /* Now that we have set up a memory pool and the rest of the pipeline, @@ -805,6 +807,7 @@ gst_nice_src_dispose (GObject *object) { g_array_remove_index(temp_refs, i); } + g_array_free(temp_refs, TRUE); } gst_nice_src_clean_up_pool(src); #endif @@ -989,6 +992,8 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa /* Use an existing allocated reference */ int last_index = mem_list_interface->temp_refs->len-1; ref = (GstNiceSrcMemoryBufferRef*) g_array_index(mem_list_interface->temp_refs, GstNiceSrcMemoryBufferRef*, last_index); + // Make sure the ref is not freed when removed from the array + g_array_index(mem_list_interface->temp_refs, GstNiceSrcMemoryBufferRef*, last_index) = NULL; g_array_remove_index(mem_list_interface->temp_refs, last_index); } else @@ -1026,6 +1031,7 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize } void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; if(buffer_ref->buffer){ /* Return allocated buffer to the pool after it has been used */ @@ -1034,6 +1040,8 @@ void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRe } /* TODO: The ref should be added to the array, this is not done at the moment */ memset (buffer_ref, 0, sizeof (GstNiceSrcMemoryBufferRef)); + g_array_append_vals(mem_list_interface->temp_refs, &buffer_ref, 1); + } char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ diff --git a/socket/socket.h b/socket/socket.h index 94e90776..2b431e42 100644 --- a/socket/socket.h +++ b/socket/socket.h @@ -112,12 +112,6 @@ nice_socket_set_rx_enabled (NiceSocket *sock, gboolean enabled); void nice_socket_free (NiceSocket *sock); -void -nice_socket_buffer_interface_set (NiceSocket *sock, struct _MemlistInterface **interface); - -void -nice_socket_buffers_and_interface_unref (NiceSocket *sock); - const char *socket_type_to_string (NiceSocketType type); #include "udp-bsd.h" From 6e060920fd94e2ac3894717277de007564f63d24 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Wed, 19 Oct 2022 09:50:06 +0200 Subject: [PATCH 17/27] See if removing the word type from headers makes MSVC more happy --- socket/socket.c | 4 ++-- socket/socket.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/socket/socket.c b/socket/socket.c index 55ada911..65eb4678 100644 --- a/socket/socket.c +++ b/socket/socket.c @@ -120,9 +120,9 @@ nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface } } -const char* socket_type_to_string (NiceSocketType type) +const char* socket_type_to_string (NiceSocketType socket_type) { - switch (type) { + switch (socket_type) { case NICE_SOCKET_TYPE_UDP_BSD: return "udp"; case NICE_SOCKET_TYPE_TCP_BSD: return "tcp-bsd"; case NICE_SOCKET_TYPE_TCP_ACTIVE: return "tcp-active"; diff --git a/socket/socket.h b/socket/socket.h index 2b431e42..9df0bb4e 100644 --- a/socket/socket.h +++ b/socket/socket.h @@ -112,7 +112,7 @@ nice_socket_set_rx_enabled (NiceSocket *sock, gboolean enabled); void nice_socket_free (NiceSocket *sock); -const char *socket_type_to_string (NiceSocketType type); +const char *socket_type_to_string (NiceSocketType socket_type); #include "udp-bsd.h" #include "tcp-bsd.h" From b7a0a441ed86b9038774e019b25693446c6bb9d2 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Wed, 19 Oct 2022 13:47:04 +0200 Subject: [PATCH 18/27] MSVC doesn't like variables with the name interface --- agent/agent.h | 2 +- gst/gstnicesrc.c | 40 ++++++++++++++++------------------------ nice/memlist.h | 10 +++++----- socket/socket.c | 26 +++++++++++++------------- socket/udp-bsd.c | 24 ++++++++++++------------ socket/udp-bsd.h | 2 +- 6 files changed, 48 insertions(+), 56 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index 31d23ee6..0ba4d300 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -305,7 +305,7 @@ NICE_EXPORT NiceAgent * nice_agent_new (GMainContext *ctx, NiceCompatibility compat, NiceCompatibility turn_compat); NICE_EXPORT void -nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **interface); +nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **ml_interface); /** * nice_agent_add_local_address: (skip) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 8d361473..1edcb691 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -112,11 +112,11 @@ gst_nice_src_change_state ( static void gst_nice_src_mem_buffer_ref_array_clear(void *element); -NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize size); -void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer); -char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer); -gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer); -void gst_nice_src_buffer_resize(MemlistInterface **interface, +NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **ml_interface, gsize size); +void gst_nice_src_buffer_return(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); +char* gst_nice_src_buffer_contents(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); +gsize gst_nice_src_buffer_size(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); +void gst_nice_src_buffer_resize(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer, gsize new_size); static const MemlistInterface nice_src_mem_interface = { @@ -750,11 +750,7 @@ gst_nice_src_alloc (GstBaseSrc * bsrc, guint64 offset, guint length, GstBuffer ** ret) { GstFlowReturn fret; - GstNiceSrc *src; - GstNiceSrcClass *pclass; - src = GST_NICE_SRC (bsrc); - pclass = GST_NICE_SRC_GET_CLASS (src); fret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, ret); return fret; @@ -765,11 +761,7 @@ gst_nice_src_fill (GstBaseSrc * bsrc, guint64 offset, guint length, GstBuffer * ret) { GstFlowReturn fret; - GstNiceSrc *src; - GstNiceSrcClass *pclass; - src = GST_NICE_SRC (bsrc); - pclass = GST_NICE_SRC_GET_CLASS (src); fret = GST_BASE_SRC_CLASS (parent_class)->fill (bsrc, offset, length, ret); return fret; @@ -983,8 +975,8 @@ gst_nice_src_change_state (GstElement * element, GstStateChange transition) return ret; } -NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interface){ - struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; +NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **ml_interface){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)ml_interface; GstNiceSrcMemoryBufferRef* ref; if (mem_list_interface->temp_refs->len > 0) @@ -1005,10 +997,10 @@ NiceMemoryBufferRef* gst_nice_src_buffer_ref_allocate(MemlistInterface **interfa return ref; } -NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize size){ - struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; +NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **ml_interface, gsize size){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)ml_interface; GstBufferPoolAcquireParams params = { 0 }; - GstNiceSrcMemoryBufferRef *ref = gst_nice_src_buffer_ref_allocate(interface); + GstNiceSrcMemoryBufferRef *ref = gst_nice_src_buffer_ref_allocate(ml_interface); GstBuffer *buffer = NULL; g_assert(mem_list_interface->pool != NULL); @@ -1016,7 +1008,7 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize ¶ms); if(status != GST_FLOW_OK) { - gst_nice_src_buffer_return(interface, ref); + gst_nice_src_buffer_return(ml_interface, ref); return NULL; } g_assert_cmpint(status, ==, GST_FLOW_OK); @@ -1030,8 +1022,8 @@ NiceMemoryBufferRef* gst_nice_src_buffer_get(MemlistInterface **interface, gsize return (NiceMemoryBufferRef*) ref; } -void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ - struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)interface; +void gst_nice_src_buffer_return(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer){ + struct _GstNiceMemlistInterface *mem_list_interface = (struct _GstNiceMemlistInterface *)ml_interface; GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; if(buffer_ref->buffer){ /* Return allocated buffer to the pool after it has been used */ @@ -1044,17 +1036,17 @@ void gst_nice_src_buffer_return(MemlistInterface **interface, NiceMemoryBufferRe } -char* gst_nice_src_buffer_contents(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ +char* gst_nice_src_buffer_contents(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer){ GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; return (char*) buffer_ref->buf_map.data; } -gsize gst_nice_src_buffer_size(MemlistInterface **interface, NiceMemoryBufferRef* buffer){ +gsize gst_nice_src_buffer_size(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer){ GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; return buffer_ref->buf_map.size; } -void gst_nice_src_buffer_resize(MemlistInterface **interface, NiceMemoryBufferRef* buffer, gsize new_size) { +void gst_nice_src_buffer_resize(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer, gsize new_size) { GstNiceSrcMemoryBufferRef *buffer_ref = (GstNiceSrcMemoryBufferRef*)buffer; guint8* data_location; g_assert(new_size <= buffer_ref->buf_map.size); diff --git a/nice/memlist.h b/nice/memlist.h index aa9ac9b4..4cc14329 100644 --- a/nice/memlist.h +++ b/nice/memlist.h @@ -53,15 +53,15 @@ typedef void NiceMemoryBufferRef; /* Libnice expects the buffers received trough the interface to be accessable until they are either returned though nice_return_memory_buffer or by passing them as a result of a read operation. All buffers will be returned when the corresponding agent is destroyed */ -typedef NiceMemoryBufferRef* (*nice_memory_buffer_get)(MemlistInterface **interface, gsize size); +typedef NiceMemoryBufferRef* (*nice_memory_buffer_get)(MemlistInterface **ml_interface, gsize size); /* Return a memory buffer to the provider */ -typedef void (*nice_memory_buffer_return)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +typedef void (*nice_memory_buffer_return)(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); /* Get a pointer to the contents (i.e. bytes) of the memory buffer */ -typedef char* (*nice_memory_buffer_contents)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +typedef char* (*nice_memory_buffer_contents)(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); /* Get the size of the memory buffer */ -typedef gsize (*nice_memory_buffer_size)(MemlistInterface **interface, NiceMemoryBufferRef* buffer); +typedef gsize (*nice_memory_buffer_size)(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer); /* Reduce the size of the memory buffer */ -typedef void (*nice_memory_buffer_resize)(MemlistInterface **interface, NiceMemoryBufferRef* buffer, gsize new_size); +typedef void (*nice_memory_buffer_resize)(MemlistInterface **ml_interface, NiceMemoryBufferRef* buffer, gsize new_size); struct _MemlistInterface { nice_memory_buffer_get buffer_get; diff --git a/socket/socket.c b/socket/socket.c index 65eb4678..26864b9c 100644 --- a/socket/socket.c +++ b/socket/socket.c @@ -110,12 +110,12 @@ nice_socket_buffers_and_interface_unref (NiceSocket *sock) } void -nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface) +nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **ml_interface) { if (sock) { if (sock->type == NICE_SOCKET_TYPE_UDP_BSD) { - nice_udp_socket_interface_set(sock, interface); + nice_udp_socket_interface_set(sock, ml_interface); } } } @@ -123,17 +123,17 @@ nice_socket_buffer_interface_set (NiceSocket *sock, MemlistInterface **interface const char* socket_type_to_string (NiceSocketType socket_type) { switch (socket_type) { - case NICE_SOCKET_TYPE_UDP_BSD: return "udp"; - case NICE_SOCKET_TYPE_TCP_BSD: return "tcp-bsd"; - case NICE_SOCKET_TYPE_TCP_ACTIVE: return "tcp-active"; - case NICE_SOCKET_TYPE_TCP_PASSIVE: return "tcp-passive"; - case NICE_SOCKET_TYPE_TCP_ESTABLISHED: return "tcp-established"; - case NICE_SOCKET_TYPE_TCP_SO: return "tcp-so"; - case NICE_SOCKET_TYPE_PSEUDOSSL: return "pseudossl"; - case NICE_SOCKET_TYPE_HTTP: return "http"; - case NICE_SOCKET_TYPE_SOCKS5: return "socks5"; - case NICE_SOCKET_TYPE_TURN: return "turn"; - case NICE_SOCKET_TYPE_TCP_TURN: return "tcp-turn"; + case NICE_SOCKET_TYPE_UDP_BSD: return "udp"; + case NICE_SOCKET_TYPE_TCP_BSD: return "tcp-bsd"; + case NICE_SOCKET_TYPE_TCP_ACTIVE: return "tcp-active"; + case NICE_SOCKET_TYPE_TCP_PASSIVE: return "tcp-passive"; + case NICE_SOCKET_TYPE_TCP_ESTABLISHED: return "tcp-established"; + case NICE_SOCKET_TYPE_TCP_SO: return "tcp-so"; + case NICE_SOCKET_TYPE_PSEUDOSSL: return "pseudossl"; + case NICE_SOCKET_TYPE_HTTP: return "http"; + case NICE_SOCKET_TYPE_SOCKS5: return "socks5"; + case NICE_SOCKET_TYPE_TURN: return "turn"; + case NICE_SOCKET_TYPE_TCP_TURN: return "tcp-turn"; } return "(invalid)"; } diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index d3993f21..55e2c8eb 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -91,7 +91,7 @@ struct UdpBsdSocketPrivate NiceAddress niceaddr; GSocketAddress *gaddr; #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG - MemlistInterface **interface; + MemlistInterface **ml_interface; /* Alloc buffers outside callback, to avoid reallocing buffers for messages that are not received. Any messages that are passed along are replaced with freshly allocated memory. */ @@ -215,7 +215,7 @@ gint nice_udp_socket_recvmmsg(NiceSocket *sock) { g_assert(sock->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = sock->priv; - MemlistInterface **memory_interface_ptr = priv->interface; + MemlistInterface **memory_interface_ptr = priv->ml_interface; MemlistInterface *memory_interface; if(memory_interface_ptr != NULL) @@ -314,11 +314,11 @@ socket_is_reliable (NiceSocket *sock) /* TODO: We need a way to extract and replenish buffers once they have been received */ -void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **ml_interface){ g_assert(udp_socket->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = udp_socket->priv; - g_assert(priv->interface == NULL); - priv->interface = interface; + g_assert(priv->ml_interface == NULL); + priv->ml_interface = ml_interface; socket_recvmmsg_structures_set_up(udp_socket); } @@ -334,7 +334,7 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, NiceMemoryBufferRef *result = message_data->buffer; message_data->buffer = NULL; /* Replace the entry with a fresh buffer for next recvmmsg call */ - socket_recvmmsg_structures_fill_entry_with_buffer (priv->interface, + socket_recvmmsg_structures_fill_entry_with_buffer (priv->ml_interface, message_data, message_header); return result; } @@ -347,7 +347,7 @@ NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface **memory_interface_ptr = priv->interface; + MemlistInterface **memory_interface_ptr = priv->ml_interface; if(memory_interface_ptr != NULL) { g_assert(priv->message_datas != NULL); @@ -374,7 +374,7 @@ void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket) This may change in the future. However until then do nothing here. */ /* Clear the interface pointer, regardless if it is set or not */ - priv->interface = NULL; + priv->ml_interface = NULL; } @@ -405,7 +405,7 @@ static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface * static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface **memory_interface = priv->interface; + MemlistInterface **memory_interface = priv->ml_interface; gboolean missing_buffers = FALSE; for(int i = 0; i < NICE_UDP_SOCKET_MMSG_TOTAL; i++) @@ -442,7 +442,7 @@ static void socket_recvmmsg_structures_set_up(NiceSocket *udp_socket) void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket, guint iter_start, guint iter_end) { struct UdpBsdSocketPrivate *priv = udp_socket->priv; - MemlistInterface **memory_interface = priv->interface; + MemlistInterface **memory_interface = priv->ml_interface; g_assert(iter_start < iter_end); g_assert(iter_end <= NICE_UDP_SOCKET_MMSG_TOTAL); g_assert(memory_interface != NULL); @@ -495,9 +495,9 @@ void nice_udp_socket_recvmmsg_structures_fill_new_buffers(NiceSocket *udp_socket (void)iter_start; (void)iter_end; } -void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface){ +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **ml_interface){ (void)udp_socket; - (void)interface; + (void)ml_interface; } #endif \ No newline at end of file diff --git a/socket/udp-bsd.h b/socket/udp-bsd.h index 9875a8dd..64a4a47b 100644 --- a/socket/udp-bsd.h +++ b/socket/udp-bsd.h @@ -62,7 +62,7 @@ G_BEGIN_DECLS NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr); -void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **interface); +void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **ml_interface); void nice_udp_socket_buffers_and_interface_unref(NiceSocket *udp_socket); gint nice_udp_socket_recvmmsg(NiceSocket *sock); NiceMemoryBufferRef *nice_udp_socket_packet_retrieve(NiceSocket *udp_socket, From b0ceb35484f9ca7b35ee5f58eb60a0d418f2702b Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Wed, 19 Oct 2022 13:50:37 +0200 Subject: [PATCH 19/27] More interface replacements --- agent/agent.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index cdc0d7e8..c5883262 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -1029,11 +1029,11 @@ nice_agent_set_property (GObject * object, } -void nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **interface){ +void nice_agent_set_mem_list_interface(NiceAgent * agent, MemlistInterface **ml_interface){ /* Clean up and propagate new mem_list_interface */ agent_lock (agent); - mem_list_interface_clean_up_and_replace_locked (agent, interface); - agent->mem_list_interface = interface; + mem_list_interface_clean_up_and_replace_locked (agent, ml_interface); + agent->mem_list_interface = ml_interface; agent_unlock (agent); } From de6bde074537bcbcc0216a407f6562a4967095fc Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Thu, 20 Oct 2022 09:49:20 +0200 Subject: [PATCH 20/27] Use gstbasesrc infrastructure for memory pool setup --- gst/gstnicesrc.c | 162 ++++++++++++----------------------------------- gst/gstnicesrc.h | 7 +- 2 files changed, 41 insertions(+), 128 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 1edcb691..67d671ab 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -81,8 +81,9 @@ gst_nice_src_unlock_stop ( GstBaseSrc *basesrc); static gboolean -gst_nice_src_negotiate ( - GstBaseSrc * src); +gst_nice_src_decide_allocation ( + GstBaseSrc * bsrc, + GstQuery * query); static void gst_nice_src_set_property ( @@ -198,7 +199,10 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop); - gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_nice_src_negotiate); + //gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_nice_src_negotiate); +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG + gstbasesrc_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_nice_src_decide_allocation); +#endif gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_nice_src_handle_event); /* Reimplementation of gstpushsrc in order to support buffer lists */ @@ -434,6 +438,13 @@ gst_nice_src_read_callback (NiceAgent *agent, ", allocate using local allocator instead"); buffer = gst_buffer_new_allocate (NULL, len, NULL); } + + if (gst_buffer_get_size(buffer) != len) + { + gst_buffer_resize(buffer, 0, len); + g_assert(gst_buffer_get_size(buffer) == len); + } + gst_buffer_fill (buffer, 0, buf, len); gst_nice_buffer_address_meta_add(nicesrc, from, buffer); @@ -443,11 +454,6 @@ gst_nice_src_read_callback (NiceAgent *agent, g_main_loop_quit (nicesrc->mainloop); } #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG -/* typedef void (*NiceAgentRecvMultipleFunc) ( - NiceAgent *agent, guint stream_id, guint component_id, - guint num_buffers, - NiceMemoryBufferRef **buffers, const NiceAddress *from, const NiceAddress *to, gpointer user_data); -*/ /* NB: This function does not support pre 1.0 gstreamer */ static void gst_nice_src_read_multiple_callback (NiceAgent *agent, @@ -459,12 +465,6 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, const NiceAddress *to, gpointer data) { - /*(void)agent; - (void)stream_id; - (void)component_id; - (void)data; - (void)from; - (void)to;*/ GstBaseSrc *basesrc = GST_BASE_SRC (data); GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); @@ -545,134 +545,50 @@ gst_nice_src_unlock_stop (GstBaseSrc *src) return TRUE; } -/* Similar to gst_base_src_default_negotiate except that it always queries - * downstream for allowed caps. This is because the default behavior never - * sends a caps-event if the template caps is any. */ +#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG static gboolean -gst_nice_src_negotiate (GstBaseSrc * basesrc) +gst_nice_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) { - GstCaps *caps, *intersect; - GstNiceSrc *src = GST_NICE_SRC_CAST (basesrc); - gboolean result = FALSE; + GstBufferPool *pool; + gboolean update; + GstStructure *config; + GstCaps *caps = NULL; + guint size = BUFFER_SIZE; - caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); - if (!caps) - caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc)); + GstNiceSrc *src = GST_NICE_SRC_CAST (bsrc); - GST_OBJECT_LOCK (src); - intersect = gst_caps_intersect (src->caps, caps); - GST_OBJECT_UNLOCK (src); + if (gst_query_get_n_allocation_pools (query) > 0) { + update = TRUE; + } else { + update = FALSE; + } - gst_caps_take (&caps, intersect); - if (!gst_caps_is_empty (caps)) { - if (gst_caps_is_any (caps)) { - GST_DEBUG_OBJECT (basesrc, "any caps, negotiation not needed"); - result = TRUE; - } else { - GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); - if (bclass->fixate) - caps = bclass->fixate (basesrc, caps); - GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); - if (gst_caps_is_fixed (caps)) { - result = gst_base_src_set_caps (basesrc, caps); - } - } + pool = gst_buffer_pool_new (); -#ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG - gboolean update; - // Start pool setup - if (src->mem_list_interface.pool) { - /* Clean up old pool, unmap all existing memory and allocate new */ - gst_nice_src_clean_up_pool (src); - } + config = gst_buffer_pool_get_config (pool); - GstQuery *query = gst_query_new_allocation (caps, TRUE); - if (!gst_pad_peer_query (GST_BASE_SRC_PAD(basesrc), query)) - GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "didn't get downstream ALLOCATION hints"); + gst_query_parse_allocation (query, &caps, NULL); - if (src->mem_list_interface.allocator != NULL) - gst_object_unref (src->mem_list_interface.allocator); - if (gst_query_get_n_allocation_params (query) > 0) { - gst_query_parse_nth_allocation_param (query, 0, - &src->mem_list_interface.allocator, &src->mem_list_interface.params); - } else { - src->mem_list_interface.allocator = NULL; - gst_allocation_params_init (&src->mem_list_interface.params); - } + gst_buffer_pool_config_set_params (config, caps, size, 0, 0); - if (gst_query_get_n_allocation_pools (query) > 0) { - GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "Got n allocation pools: %d", - gst_query_get_n_allocation_pools (query)); - gst_query_parse_nth_allocation_pool (query, 0, &src->mem_list_interface.pool, NULL, NULL, - NULL); - update = TRUE; - } else { - GST_DEBUG_OBJECT (GST_BASE_SRC_PAD(basesrc), "Creating evsrc buffer pool"); - src->mem_list_interface.pool = gst_buffer_pool_new (); - update = FALSE; - } + gst_buffer_pool_set_config (pool, config); - { - guint size = BUFFER_SIZE, min = 0, max = 0; - GstStructure *config; - config = gst_buffer_pool_get_config (src->mem_list_interface.pool); - /* Ensure we don't pass unfixed caps to the buffer pool config as that will - trigger an assert */ - GstCaps *poolcaps; - if (caps != NULL && gst_caps_is_fixed (caps)) { - poolcaps = caps; - } else { - poolcaps = NULL; - } - gst_buffer_pool_config_set_params (config, poolcaps, (guint) size, min, - max); - gst_buffer_pool_config_set_allocator (config, src->mem_list_interface.allocator, - &src->mem_list_interface.params); - gst_buffer_pool_set_config (src->mem_list_interface.pool, config); - if (update) - { - gst_query_set_nth_allocation_pool (query, 0, src->mem_list_interface.pool, size, 0, 0); - } - else - { - gst_query_add_allocation_pool (query, src->mem_list_interface.pool, size, 0, 0); - } - gst_buffer_pool_set_active (src->mem_list_interface.pool, TRUE); - /* NB: This pool is not used by the basesrc when allocating buffers from it, as it is not possible - to set it when we negotiate caps ourselves (and not overwrite the appropriate functions in gstbasesrc) */ - } - gst_query_unref(query); - // End pool setup + if (update) + gst_query_set_nth_allocation_pool (query, 0, pool, size, 0, 0); + else + gst_query_add_allocation_pool (query, pool, size, 0, 0); - /* Now that we have set up a memory pool and the rest of the pipeline, - we can set the mem list interface in the agent, - which will retrieve and initialise memory buffers */ - if (src->mem_list_interface_set == FALSE) - { - nice_agent_set_mem_list_interface(src->agent, (MemlistInterface**)&src->mem_list_interface); - src->mem_list_interface_set = TRUE; - } -#endif + src->mem_list_interface.pool = pool; - gst_caps_unref (caps); - } else { - GST_DEBUG_OBJECT (basesrc, "no common caps"); - } - return result; + return TRUE; } -#if NICE_UDP_SOCKET_HAVE_RECVMMSG static void gst_nice_src_clean_up_pool(GstNiceSrc * src) { - if (src->mem_list_interface.allocator != NULL) { - gst_object_unref (src->mem_list_interface.allocator); - src->mem_list_interface.allocator = NULL; - } - if (src->mem_list_interface.pool != NULL) { /* The entries that already exists will be with the old pool until they die as we have no way of moving them to the new pool. */ - gst_buffer_pool_set_active (src->mem_list_interface.pool, FALSE); + //gst_buffer_pool_set_active (src->mem_list_interface.pool, FALSE); gst_object_unref (src->mem_list_interface.pool); src->mem_list_interface.pool = NULL; } diff --git a/gst/gstnicesrc.h b/gst/gstnicesrc.h index 074ce1bb..a8482b01 100644 --- a/gst/gstnicesrc.h +++ b/gst/gstnicesrc.h @@ -76,13 +76,10 @@ struct _GstNiceMemlistInterface{ /* When embedded in GstNiceSrc this will be a self referencing pointer, that is not refcounted */ GstNiceSrc *gst_src; - /* Pointers to GstNiceSrcMemoryBufferRefs that have been returned that are - waiting to be given out again. It is assumed that the buffer and mapping + /* Pointers to GstNiceSrcMemoryBufferRefs that have been returned that are + waiting to be given out again. It is assumed that the buffer and mapping refed to by the reference is in an unintitialised state */ GArray *temp_refs; - /* Buffer variables needed for allocating and releasing buffers trough a pool */ - GstAllocator *allocator; - GstAllocationParams params; GstBufferPool *pool; }; From b61f952204b5885014a8281315397d46666a6bc9 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 24 Oct 2022 10:54:56 +0200 Subject: [PATCH 21/27] Set memory list --- gst/gstnicesrc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 67d671ab..1dcb0a07 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -580,6 +580,14 @@ gst_nice_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) src->mem_list_interface.pool = pool; + if (src->agent){ + if (src->mem_list_interface_set == FALSE) + { + nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + src->mem_list_interface_set = TRUE; + } + } + return TRUE; } @@ -619,7 +627,6 @@ gst_nice_src_query (GstBaseSrc * src, GstQuery * query) return ret; } - static GstFlowReturn gst_nice_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) From 3ec042f10b4dadb212fb219a0a8109a7871582cd Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 24 Oct 2022 13:12:14 +0200 Subject: [PATCH 22/27] Don't try to receve multiple buffers if we con't have the callbacks for it --- agent/agent.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/agent/agent.c b/agent/agent.c index c5883262..2a924f0d 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -3040,8 +3040,10 @@ nice_agent_g_source_cb (GSocket * gsocket, } #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG - if (component->g_source_io_multiple_cb && ctx->socket->type == NICE_SOCKET_TYPE_UDP_BSD) { - NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; + if (component->g_source_io_multiple_cb + && ctx->socket->type == NICE_SOCKET_TYPE_UDP_BSD + && agent->mem_list_interface != NULL) { + NiceMemoryBufferRef *buffers[NICE_UDP_SOCKET_MMSG_TOTAL]; NiceAddress from_addresses[NICE_UDP_SOCKET_MMSG_TOTAL]; len = _nice_agent_recv_multiple(agent, stream, component, ctx->socket, From 9ac3ce1742c5dd0eea129327c7c486778e0fc3ff Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Mon, 24 Oct 2022 14:15:59 +0200 Subject: [PATCH 23/27] Restore caps negotiation, fixes pexcelent test --- gst/gstnicesrc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 1dcb0a07..7f7ecbde 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -85,6 +85,10 @@ gst_nice_src_decide_allocation ( GstBaseSrc * bsrc, GstQuery * query); +static gboolean +gst_nice_src_negotiate ( + GstBaseSrc * basesrc); + static void gst_nice_src_set_property ( GObject *object, @@ -199,7 +203,7 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop); - //gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_nice_src_negotiate); + gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_nice_src_negotiate); #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG gstbasesrc_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_nice_src_decide_allocation); #endif @@ -545,6 +549,46 @@ gst_nice_src_unlock_stop (GstBaseSrc *src) return TRUE; } +/* Similar to gst_base_src_default_negotiate except that it always queries + * downstream for allowed caps. This is because the default behavior never + * sends a caps-event if the template caps is any. */ +static gboolean +gst_nice_src_negotiate (GstBaseSrc * basesrc) +{ + GstCaps *caps, *intersect; + GstNiceSrc *src = GST_NICE_SRC_CAST (basesrc); + gboolean result = FALSE; + + caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); + if (!caps) + caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc)); + + GST_OBJECT_LOCK (src); + intersect = gst_caps_intersect (src->caps, caps); + GST_OBJECT_UNLOCK (src); + + gst_caps_take (&caps, intersect); + + if (!gst_caps_is_empty (caps)) { + if (gst_caps_is_any (caps)) { + GST_DEBUG_OBJECT (basesrc, "any caps, negotiation not needed"); + result = TRUE; + } else { + GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); + if (bclass->fixate) + caps = bclass->fixate (basesrc, caps); + GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); + if (gst_caps_is_fixed (caps)) { + result = gst_base_src_set_caps (basesrc, caps); + } + } + gst_caps_unref (caps); + } else { + GST_DEBUG_OBJECT (basesrc, "no common caps"); + } + return result; +} + #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG static gboolean gst_nice_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) @@ -583,7 +627,7 @@ gst_nice_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) if (src->agent){ if (src->mem_list_interface_set == FALSE) { - nice_agent_set_mem_list_interface(src->agent, &src->mem_list_interface); + nice_agent_set_mem_list_interface(src->agent, (MemlistInterface**)&src->mem_list_interface); src->mem_list_interface_set = TRUE; } } @@ -626,7 +670,32 @@ gst_nice_src_query (GstBaseSrc * src, GstQuery * query) } return ret; } +static void gst_nice_src_set_timestamp(GstBaseSrc * basesrc, GstBuffer *buffer) +{ + GstClock *clock; + GstClockTime running_time, now; + GstClockTime base_time = GST_ELEMENT_CAST (basesrc)->base_time; + + /* get clock, if no clock, we can't sync or do timestamps */ + if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL) + { + return; + } + else + { + gst_object_ref (clock); + } + + now = gst_clock_get_time (clock); + running_time = now - base_time; + + GST_BUFFER_DTS (buffer) = running_time; + GST_LOG_OBJECT (basesrc, "created DTS %" GST_TIME_FORMAT, + GST_TIME_ARGS (running_time)); + + gst_object_unref(clock); +} static GstFlowReturn gst_nice_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** ret) @@ -651,12 +720,19 @@ gst_nice_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, if (bufptr != NULL) { if (GST_IS_BUFFER_LIST(bufptr)){ *ret = NULL; + guint bl_len = gst_buffer_list_length(bufptr); + for(int i = 0; i < bl_len; i++){ + GstBuffer *buf = gst_buffer_list_get(bufptr, i); + gst_nice_src_set_timestamp(basesrc, buf); + } gst_base_src_submit_buffer_list (basesrc, bufptr); GST_LOG_OBJECT (nicesrc, "Got buffer list, pushing"); } else { *ret = bufptr; + gst_nice_src_set_timestamp(basesrc, bufptr); + GST_LOG_OBJECT (nicesrc, "Got buffer, pushing"); } return GST_FLOW_OK; From 6d76ff75962e3d0dd3ab95bc1c3b7d07e0cb2c5b Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Tue, 25 Oct 2022 10:34:05 +0200 Subject: [PATCH 24/27] Don't leak pools if allocated multiple times --- gst/gstnicesrc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 7f7ecbde..46f30d83 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -560,7 +560,7 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) gboolean result = FALSE; caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (basesrc)); - if (!caps) + if (caps == NULL) caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (basesrc)); GST_OBJECT_LOCK (src); @@ -575,17 +575,22 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) result = TRUE; } else { GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc); - if (bclass->fixate) + if (bclass->fixate){ + GstCaps *oldcaps = caps; caps = bclass->fixate (basesrc, caps); + //gst_caps_unref(oldcaps); + } GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); if (gst_caps_is_fixed (caps)) { result = gst_base_src_set_caps (basesrc, caps); } } - gst_caps_unref (caps); } else { GST_DEBUG_OBJECT (basesrc, "no common caps"); } + if (caps != NULL){ + gst_caps_unref (caps); + } return result; } @@ -622,6 +627,8 @@ gst_nice_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) else gst_query_add_allocation_pool (query, pool, size, 0, 0); + gst_nice_src_clean_up_pool(src); + src->mem_list_interface.pool = pool; if (src->agent){ From 6104a73e2db581e66b2e64964885f267531c6df0 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 18 Nov 2022 08:04:58 +0100 Subject: [PATCH 25/27] Removed debug code --- socket/udp-bsd.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 55e2c8eb..26ee2d1c 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -386,11 +386,6 @@ static void socket_recvmmsg_structures_fill_entry_with_buffer(MemlistInterface * { message_data->buffer = memory_interface->buffer_get(memory_interface_ptr, NICE_UDP_SOCKET_BUFFER_ALLOC_SIZE); } -#if 0 - else{ - uint64_t bufval = *((uint64_t*)message_data->buffer); /* Breakpoint */ - } -#endif if (message_data->buffer == NULL){ return; } From ea255cdfd7c655a823533a10f455148e60bd84f7 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 18 Nov 2022 08:11:21 +0100 Subject: [PATCH 26/27] Revert changes introduced by gst-indent, they make the review unneccesarily noisy --- agent/agent-priv.h | 2 +- agent/agent.c | 125 +++++++++++++++++++++------------------------ 2 files changed, 60 insertions(+), 67 deletions(-) diff --git a/agent/agent-priv.h b/agent/agent-priv.h index ae592e39..7dee4153 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -128,7 +128,7 @@ struct _NiceAgent gchar *software_attribute; /* SOFTWARE attribute */ gboolean reliable; /* property: reliable */ - MemlistInterface **mem_list_interface; /* property: mem_list_interface */ + MemlistInterface **mem_list_interface; /* mem_list_interface: used for recvmmsg buffer access */ /* XXX: add pointer to internal data struct for ABI-safe extensions */ }; diff --git a/agent/agent.c b/agent/agent.c index 2a924f0d..bb9b29f7 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -75,7 +75,7 @@ * will it work tcp relaying?? */ #define MAX_BUFFER_SIZE 65536 -#define DEFAULT_STUN_PORT 3478 +#define DEFAULT_STUN_PORT 3478 #define DEFAULT_UPNP_TIMEOUT 200 #define MAX_TCP_MTU 1400 /* Use 1400 because of VPNs and we assume IEE 802.3 */ @@ -108,8 +108,7 @@ enum PROP_CONNCHECK_RETRANSMISSIONS, PROP_AGGRESSIVE_MODE, PROP_REGULAR_NOMINATION_TIMEOUT, - PROP_TIE_BREAKER, - PROP_MEM_LIST_INTERFACE + PROP_TIE_BREAKER }; @@ -572,12 +571,6 @@ nice_agent_class_init (NiceAgentClass * klass) 0, /* Not construct time so ignored */ G_PARAM_READWRITE)); - /*g_object_class_install_property (gobject_class, PROP_MEM_LIST_INTERFACE, - g_param_spec_pointer ("mem-list-interface", - "Memory list interface", - "Interface for allocating and releasing memory buffers (should be a double ptr)", - G_PARAM_CONSTRUCT_ONLY));*/ - /* install signals */ /** @@ -1987,31 +1980,28 @@ nice_agent_add_stream_local_address_from_string (NiceAgent * agent, * having a specific remote candidate, and eventually update the * priority of the selected pair as well. */ -static void -priv_update_pair_foundations (NiceAgent * agent, - guint stream_id, guint component_id, NiceCandidate * remote) +static void priv_update_pair_foundations (NiceAgent *agent, + guint stream_id, guint component_id, NiceCandidate *remote) { Stream *stream; Component *component; if (agent_find_component (agent, stream_id, component_id, &stream, - &component)) { + &component)) { GSList *i; for (i = stream->conncheck_list; i; i = i->next) { CandidateCheckPair *pair = i->data; if (pair->remote == remote) { - gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION + 1]; + gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION+1]; g_snprintf (foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s", pair->local->foundation, pair->remote->foundation); - if (strncmp (pair->foundation, foundation, - NICE_CANDIDATE_PAIR_MAX_FOUNDATION)) { + if (strncmp (pair->foundation, foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION)) { - g_strlcpy (pair->foundation, foundation, - NICE_CANDIDATE_PAIR_MAX_FOUNDATION); + g_strlcpy (pair->foundation, foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION); GST_DEBUG_OBJECT (agent, "%u/%u: Updating pair %p foundation to '%s'", stream_id, component_id, pair, pair->foundation); @@ -2025,13 +2015,12 @@ priv_update_pair_foundations (NiceAgent * agent, * an update of its priority. stun_priority doesn't change * because only the remote candidate foundation is modified. */ - GST_DEBUG_OBJECT (agent, - "%u/%u : pair %p is the selected pair, updating " + GST_DEBUG_OBJECT (agent, "%u/%u : pair %p is the selected pair, updating " "its priority.", stream_id, component_id, pair); component->selected_pair.priority = pair->priority; agent_signal_new_selected_pair (agent, pair->stream_id, - component->id, pair->local, pair->remote); + component->id, pair->local, pair->remote); } } } @@ -2045,8 +2034,10 @@ priv_update_pair_foundations (NiceAgent * agent, * pair */ static void -priv_check_for_new_selected_pair (NiceAgent * agent, - guint stream_id, guint component_id) +priv_check_for_new_selected_pair ( + NiceAgent *agent, + guint stream_id, + guint component_id) { Stream *stream; Component *component; @@ -2054,17 +2045,17 @@ priv_check_for_new_selected_pair (NiceAgent * agent, GSList *i; if (agent_find_component (agent, stream_id, component_id, &stream, - &component)) { + &component)) { for (i = stream->conncheck_list; i; i = i->next) { pair = i->data; if (pair->component_id == component_id && pair->state == NICE_CHECK_SUCCEEDED && - pair->valid_pair != NULL && pair->valid_pair->nominated) { + pair->valid_pair != NULL && + pair->valid_pair->nominated) { if (pair->priority > component->selected_pair.priority) { - GST_INFO_OBJECT (agent, - "%u/%u: New trickle candidate has promoted %p as the selected pair", + GST_INFO_OBJECT (agent, "%u/%u: New trickle candidate has promoted %p as the selected pair", stream_id, component_id, pair); conn_check_update_selected_pair (agent, component, pair->valid_pair); } @@ -2090,8 +2081,7 @@ priv_add_remote_candidate (NiceAgent * agent, Stream *stream; NiceCandidate *candidate; - if (!agent_find_component (agent, stream_id, component_id, &stream, - &component)) + if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) return FALSE; /* step: check whether the candidate already exists */ @@ -2101,9 +2091,8 @@ priv_add_remote_candidate (NiceAgent * agent, if (stream->trickle_ice) { if (candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) { - GST_DEBUG_OBJECT (agent, - "%u/%u: Updating existing prflx candidate to %s", stream_id, - component_id, candidate_type_to_string (type)); + GST_DEBUG_OBJECT (agent, "%u/%u: Updating existing prflx candidate to %s", + stream_id, component_id, candidate_type_to_string(type)); candidate->type = type; } @@ -2111,10 +2100,11 @@ priv_add_remote_candidate (NiceAgent * agent, if (candidate && candidate->type == type) { gchar tmpbuf[INET6_ADDRSTRLEN]; nice_address_to_string (addr, tmpbuf); - GST_DEBUG_OBJECT (agent, - "%u/%u: Updating existing remote candidate with addr [%s]:%u" - " U/P '%s'/'%s' prio: %08x", stream_id, component_id, tmpbuf, - nice_address_get_port (addr), username, password, priority); + GST_DEBUG_OBJECT (agent, "%u/%u: Updating existing remote candidate with addr [%s]:%u" + " U/P '%s'/'%s' prio: %08x", + stream_id, component_id, + tmpbuf, nice_address_get_port (addr), + username, password, priority); updated = TRUE; @@ -2122,26 +2112,26 @@ priv_add_remote_candidate (NiceAgent * agent, candidate->base_addr = *base_addr; candidate->priority = priority; if (foundation) - g_strlcpy (candidate->foundation, foundation, + g_strlcpy(candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION); if (username) { if (candidate->username == NULL) candidate->username = g_strdup (username); else if (g_strcmp0 (username, candidate->username)) - GST_WARNING_OBJECT (agent, - "%u/%u: Candidate username '%s' is not allowed " - "to change to '%s' now (ICE restart only).", stream_id, - component_id, candidate->username, username); + GST_WARNING_OBJECT (agent, "%u/%u: Candidate username '%s' is not allowed " + "to change to '%s' now (ICE restart only).", + stream_id, component_id, + candidate->username, username); } if (password) { if (candidate->password == NULL) candidate->password = g_strdup (password); else if (g_strcmp0 (password, candidate->password)) - GST_WARNING_OBJECT (agent, - "%u/%u: Candidate password '%s' is not allowed " - "to change to '%s' now (ICE restart only).", stream_id, - component_id, candidate->password, password); + GST_WARNING_OBJECT (agent, "%u/%u: Candidate password '%s' is not allowed " + "to change to '%s' now (ICE restart only).", + stream_id, component_id, + candidate->password, password); } /* since the type of the existing candidate may have changed, @@ -2149,8 +2139,7 @@ priv_add_remote_candidate (NiceAgent * agent, * to be recomputed... */ conn_check_recalculate_pair_priorities (agent); - priv_update_pair_foundations (agent, stream_id, component_id, - candidate); + priv_update_pair_foundations (agent, stream_id, component_id, candidate); /* ... and maybe we now have another nominated pair with a higher * priority as the result of this priorities update. @@ -2164,9 +2153,9 @@ priv_add_remote_candidate (NiceAgent * agent, nice_address_to_string (addr, tmpbuf); GST_DEBUG_OBJECT (agent, "%u/%u: Not updating existing remote candidate with addr [%s]:%u" - " U/P '%s'/'%s' prio: %u type:%s transport:%d", stream_id, - component_id, tmpbuf, nice_address_get_port (addr), username, - password, priority, candidate_type_to_string (type), transport); + " U/P '%s'/'%s' prio: %u type:%s transport:%d", stream_id, component_id, + tmpbuf, nice_address_get_port (addr), username, password, priority, + candidate_type_to_string(type), transport); } } } else { @@ -2680,7 +2669,7 @@ nice_agent_get_remote_candidates (NiceAgent * agent, } gboolean -nice_agent_restart (NiceAgent * agent) +nice_agent_restart (NiceAgent *agent) { GSList *i; @@ -2702,7 +2691,8 @@ nice_agent_restart (NiceAgent * agent) } gboolean -nice_agent_restart_stream (NiceAgent * agent, guint stream_id) +nice_agent_restart_stream (NiceAgent *agent, + guint stream_id) { gboolean res = FALSE; Stream *stream; @@ -2723,7 +2713,7 @@ nice_agent_restart_stream (NiceAgent * agent, guint stream_id) stream_restart (agent, stream, agent->rng); res = TRUE; -done: + done: agent_unlock (agent); return res; } @@ -3196,7 +3186,8 @@ nice_agent_attach_recv (NiceAgent * agent, guint component_id, GMainContext * ctx, NiceAgentRecvFunc func, - NiceAgentRecvMultipleFunc multiple_func, gpointer data) + NiceAgentRecvMultipleFunc multiple_func, + gpointer data) { Component *component = NULL; Stream *stream = NULL; @@ -3357,13 +3348,13 @@ _priv_set_socket_tos (NiceAgent * agent, NiceSocket * sock, gint tos) if (sock->fileno && setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IP, IP_TOS, (const char *) &tos, sizeof (tos)) < 0) { - GST_WARNING_OBJECT (agent, "Could not set socket ToS %s", g_strerror (errno)); + GST_WARNING_OBJECT (agent, "Could not set socket ToS", g_strerror (errno)); } #ifdef IPV6_TCLASS if (sock->fileno && setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IPV6, IPV6_TCLASS, (const char *) &tos, sizeof (tos)) < 0) { - GST_DEBUG_OBJECT (agent, "Could not set IPV6 socket ToS %s", + GST_DEBUG_OBJECT (agent, "Could not set IPV6 socket ToS", g_strerror (errno)); } #endif @@ -3419,7 +3410,8 @@ nice_agent_set_stream_max_tcp_queue_size (NiceAgent * agent, void nice_agent_set_stream_trickle_ice (NiceAgent * agent, - guint stream_id, gboolean trickle_ice) + guint stream_id, + gboolean trickle_ice) { Stream *stream; @@ -3431,7 +3423,8 @@ nice_agent_set_stream_trickle_ice (NiceAgent * agent, } GST_DEBUG_OBJECT (agent, "%u/*: setting trickle_ice to %s", - stream_id, trickle_ice ? "TRUE" : "FALSE"); + stream_id, + trickle_ice ? "TRUE" : "FALSE"); stream->trickle_ice = trickle_ice; done: @@ -3439,8 +3432,10 @@ nice_agent_set_stream_trickle_ice (NiceAgent * agent, } NICE_EXPORT void -nice_agent_end_of_candidates (NiceAgent * agent, - guint stream_id, guint component_id) +nice_agent_end_of_candidates ( + NiceAgent *agent, + guint stream_id, + guint component_id) { Component *component; Stream *stream; @@ -3449,14 +3444,11 @@ nice_agent_end_of_candidates (NiceAgent * agent, if (agent_find_component (agent, stream_id, component_id, &stream, &component)) { - GST_DEBUG_OBJECT (agent, "%u/%u: end-of-candidates", stream_id, - component_id); + GST_DEBUG_OBJECT (agent, "%u/%u: end-of-candidates", stream_id, component_id); component->peer_gathering_done = TRUE; conn_check_end_of_candidates (agent, stream, component); } else { - GST_WARNING_OBJECT (agent, - "%u/%u: end-of-candidates unknown stream/component", stream_id, - component_id); + GST_WARNING_OBJECT (agent, "%u/%u: end-of-candidates unknown stream/component", stream_id, component_id); } agent_unlock (agent); @@ -3530,7 +3522,8 @@ nice_agent_set_rx_enabled (NiceAgent * agent, agent_unlock (agent); } -NICEAPI_EXPORT const char * +NICEAPI_EXPORT +const char * nice_component_state_to_string (NiceComponentState state) { return component_state_to_string (state); From 70e898428bba90c663bf986fa1c5599bee6ef2e3 Mon Sep 17 00:00:00 2001 From: Frederik Vestre Date: Fri, 18 Nov 2022 08:30:07 +0100 Subject: [PATCH 27/27] Comment cleanup --- gst/gstnicesrc.c | 5 ----- socket/udp-bsd.c | 3 --- 2 files changed, 8 deletions(-) diff --git a/gst/gstnicesrc.c b/gst/gstnicesrc.c index 46f30d83..618766d0 100644 --- a/gst/gstnicesrc.c +++ b/gst/gstnicesrc.c @@ -197,9 +197,6 @@ gst_nice_src_class_init (GstNiceSrcClass *klass) GST_DEBUG_CATEGORY_INIT (nicesrc_debug, "nicesrc", 0, "libnice source"); - //gstpushsrc_class = (GstPushSrcClass *) klass; - //gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create); - gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock); gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop); @@ -484,7 +481,6 @@ gst_nice_src_read_multiple_callback (NiceAgent *agent, } GST_LOG_OBJECT (agent, "Got multiple buffers (%d), getting out of the main loop", num_buffers); - //GST_ERROR_OBJECT (agent, "Pushing multiple buffers are not implemented for gstnicesrc yet. Dropping buffer."); g_queue_push_tail (nicesrc->outbufs, outlist); @@ -578,7 +574,6 @@ gst_nice_src_negotiate (GstBaseSrc * basesrc) if (bclass->fixate){ GstCaps *oldcaps = caps; caps = bclass->fixate (basesrc, caps); - //gst_caps_unref(oldcaps); } GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); if (gst_caps_is_fixed (caps)) { diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c index 26ee2d1c..6435b8fe 100644 --- a/socket/udp-bsd.c +++ b/socket/udp-bsd.c @@ -235,7 +235,6 @@ gint nice_udp_socket_recvmmsg(NiceSocket *sock) } } - //g_assert(priv->message_headers != NULL); /* What do we do here if we haven't been able to initiate enough buffers to put data in?*/ int socket_fd = g_socket_get_fd(sock->fileno); gssize result = @@ -312,8 +311,6 @@ socket_is_reliable (NiceSocket *sock) #ifdef NICE_UDP_SOCKET_HAVE_RECVMMSG -/* TODO: We need a way to extract and replenish buffers once they have been received */ - void nice_udp_socket_interface_set(NiceSocket *udp_socket, MemlistInterface **ml_interface){ g_assert(udp_socket->type == NICE_SOCKET_TYPE_UDP_BSD); struct UdpBsdSocketPrivate *priv = udp_socket->priv;