/* * Chain list function for testing buffer lists */ static GstFlowReturn rtp_pipeline_chain_list (GstPad * pad, GstBufferList * list) { GstBufferListIterator *it; fail_if (!list); it = gst_buffer_list_iterate (list); /* * Count the size of the payload in the buffer list. */ /* Loop through all groups */ while (gst_buffer_list_iterator_next_group (it)) { GstBuffer *paybuf; /* Skip the first buffer in the group, its the RTP header */ fail_if (!gst_buffer_list_iterator_next (it)); /* Loop through all payload buffers in the current group */ while ((paybuf = gst_buffer_list_iterator_next (it))) { chain_list_bytes_received += GST_BUFFER_SIZE (paybuf); } } gst_buffer_list_iterator_free (it); gst_buffer_list_unref (list); return GST_FLOW_OK; }
/** * gst_rtp_buffer_list_get_payload_len: * @list: the buffer list * * Get the length of the payload of the RTP packet in @list. * * Returns: The length of the payload in @list. * * Since: 0.10.24 */ guint gst_rtp_buffer_list_get_payload_len (GstBufferList * list) { guint len; GstBufferListIterator *it; it = gst_buffer_list_iterate (list); len = 0; while (gst_buffer_list_iterator_next_group (it)) { guint i; GstBuffer *buf; i = 0; while ((buf = gst_buffer_list_iterator_next (it))) { /* skip the RTP header */ if (!i++) continue; /* take the size of the current buffer */ len += GST_BUFFER_SIZE (buf); } } gst_buffer_list_iterator_free (it); return len; }
/* * Render function for testing udpsink with buffer lists */ static GstFlowReturn udpsink_render (GstBaseSink * sink, GstBufferList * list) { GstBufferListIterator *it; fail_if (!list); /* * Count the size of the rtp header and the payload in the buffer list. */ it = gst_buffer_list_iterate (list); /* Loop through all groups */ while (gst_buffer_list_iterator_next_group (it)) { GstBuffer *buf; /* Loop through all buffers in the current group */ while ((buf = gst_buffer_list_iterator_next (it))) { guint size; size = GST_BUFFER_SIZE (buf); GST_DEBUG ("rendered %u bytes", size); render_list_bytes_received += size; } } gst_buffer_list_iterator_free (it); return GST_FLOW_OK; }
/** * gst_rtp_buffer_list_validate: * @list: the buffer list to validate * * Check if all RTP packets in the @list are valid using validate_data(). * Use this function to validate an list before using the other functions in * this module. * * Returns: TRUE if @list consists only of valid RTP packets. * * Since: 0.10.24 */ gboolean gst_rtp_buffer_list_validate (GstBufferList * list) { guint16 prev_seqnum = 0; GstBufferListIterator *it; guint i = 0; g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); it = gst_buffer_list_iterate (list); g_return_val_if_fail (it != NULL, FALSE); /* iterate through all the RTP packets in the list */ while (gst_buffer_list_iterator_next_group (it)) { GstBuffer *rtpbuf; GstBuffer *paybuf; guint8 *packet_header; guint8 *packet_payload; guint payload_size; guint packet_size; /* each group should consists of 2 buffers: one containing the RTP header * and the other one the payload, FIXME, relax the requirement of only one * payload buffer. */ if (gst_buffer_list_iterator_n_buffers (it) != 2) goto invalid_list; /* get the RTP header */ rtpbuf = gst_buffer_list_iterator_next (it); packet_header = GST_BUFFER_DATA (rtpbuf); if (packet_header == NULL) goto invalid_list; /* get the payload */ paybuf = gst_buffer_list_iterator_next (it); packet_payload = GST_BUFFER_DATA (paybuf); if (packet_payload == NULL) { goto invalid_list; } payload_size = GST_BUFFER_SIZE (paybuf); if (payload_size == 0) { goto invalid_list; } /* the size of the RTP packet within the current group */ packet_size = GST_BUFFER_SIZE (rtpbuf) + payload_size; /* check the sequence number */ if (G_UNLIKELY (i == 0)) { prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header)); i++; } else { if (++prev_seqnum != g_ntohs (GST_RTP_HEADER_SEQ (packet_header))) goto invalid_list; } /* validate packet */ if (!validate_data (packet_header, packet_size, packet_payload, payload_size)) { goto invalid_list; } } gst_buffer_list_iterator_free (it); return TRUE; /* ERRORS */ invalid_list: { gst_buffer_list_iterator_free (it); return FALSE; } }
BufferPtr BufferListIterator::next() { return BufferPtr::wrap(gst_buffer_list_iterator_next(m_it)); }
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); it = gst_buffer_list_iterate (list); g_return_val_if_fail (it != 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))) { if (GST_BUFFER_SIZE (buf) > UDP_MAX_SIZE) { GST_WARNING ("Attempting to send a UDP packet larger than maximum " "size (%d > %d)", GST_BUFFER_SIZE (buf), UDP_MAX_SIZE); } 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; gint count; client = (GstUDPClient *) clients->data; no_clients++; GST_LOG_OBJECT (sink, "sending %d bytes to client %p", size, client); count = sink->send_duplicates ? client->refcount : 1; while (count--) { while (TRUE) { msg.msg_name = (void *) &client->theiraddr; msg.msg_namelen = sizeof (client->theiraddr); ret = sendmsg (*client->sock, &msg, 0); if (ret < 0) { if (!socket_error_is_ignorable ()) { 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; }