summaryrefslogtreecommitdiffstats
path: root/gst/udp/gstmultiudpsink.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/udp/gstmultiudpsink.c')
-rw-r--r--gst/udp/gstmultiudpsink.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c
index f097333b..ac4c130c 100644
--- a/gst/udp/gstmultiudpsink.c
+++ b/gst/udp/gstmultiudpsink.c
@@ -117,6 +117,8 @@ static void gst_multiudpsink_finalize (GObject * object);
static GstFlowReturn gst_multiudpsink_render (GstBaseSink * sink,
GstBuffer * buffer);
+static GstFlowReturn gst_multiudpsink_render_list (GstBaseSink * bsink,
+ GstBufferList * list);
static GstStateChangeReturn gst_multiudpsink_change_state (GstElement *
element, GstStateChange transition);
@@ -318,6 +320,7 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
gstelement_class->change_state = gst_multiudpsink_change_state;
gstbasesink_class->render = gst_multiudpsink_render;
+ gstbasesink_class->render_list = gst_multiudpsink_render_list;
klass->add = gst_multiudpsink_add;
klass->remove = gst_multiudpsink_remove;
klass->clear = gst_multiudpsink_clear;
@@ -427,6 +430,93 @@ gst_multiudpsink_render (GstBaseSink * bsink, GstBuffer * buffer)
return GST_FLOW_OK;
}
+static GstFlowReturn
+gst_multiudpsink_render_list (GstBaseSink * bsink, GstBufferList * list)
+{
+ GstMultiUDPSink *sink;
+ GList *clients;
+ gint ret, size = 0, num = 0, no_clients = 0;
+ struct iovec *iov;
+ struct msghdr msg = { 0 };
+
+ GstBufferListIterator *it;
+ guint gsize;
+ GstBuffer *buf;
+
+ sink = GST_MULTIUDPSINK (bsink);
+
+ g_return_val_if_fail (list != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail ((it = gst_buffer_list_iterate (list)) != NULL,
+ GST_FLOW_ERROR);
+
+ while (gst_buffer_list_iterator_next_group (it)) {
+ msg.msg_iovlen = 0;
+ size = 0;
+
+ if ((gsize = gst_buffer_list_iterator_n_buffers (it)) == 0) {
+ goto invalid_list;
+ }
+
+ iov = (struct iovec *) g_malloc (gsize * sizeof (struct iovec));
+ msg.msg_iov = iov;
+
+ while ((buf = gst_buffer_list_iterator_next (it))) {
+ msg.msg_iov[msg.msg_iovlen].iov_len = GST_BUFFER_SIZE (buf);
+ msg.msg_iov[msg.msg_iovlen].iov_base = GST_BUFFER_DATA (buf);
+ msg.msg_iovlen++;
+ size += GST_BUFFER_SIZE (buf);
+ }
+
+ sink->bytes_to_serve += size;
+
+ /* grab lock while iterating and sending to clients, this should be
+ * fast as UDP never blocks */
+ g_mutex_lock (sink->client_lock);
+ GST_LOG_OBJECT (bsink, "about to send %d bytes", size);
+
+ for (clients = sink->clients; clients; clients = g_list_next (clients)) {
+ GstUDPClient *client;
+
+ client = (GstUDPClient *) clients->data;
+ no_clients++;
+ GST_LOG_OBJECT (sink, "sending %d bytes to client %p", size, client);
+
+ while (TRUE) {
+ msg.msg_name = (void *) &client->theiraddr;
+ msg.msg_namelen = sizeof (client->theiraddr);
+ ret = sendmsg (*client->sock, &msg, 0);
+
+ if (ret < 0) {
+ if (errno != EINTR && errno != EAGAIN) {
+ break;
+ }
+ } else {
+ num++;
+ client->bytes_sent += ret;
+ client->packets_sent++;
+ sink->bytes_served += ret;
+ break;
+ }
+ }
+ }
+ g_mutex_unlock (sink->client_lock);
+
+ g_free (iov);
+ msg.msg_iov = NULL;
+
+ GST_LOG_OBJECT (sink, "sent %d bytes to %d (of %d) clients", size, num,
+ no_clients);
+ }
+
+ gst_buffer_list_iterator_free (it);
+
+ return GST_FLOW_OK;
+
+invalid_list:
+ gst_buffer_list_iterator_free (it);
+ return GST_FLOW_ERROR;
+}
+
static void
gst_multiudpsink_set_clients_string (GstMultiUDPSink * sink,
const gchar * string)