static GstBufferList * _create_buffer_list (guint * data_size) { GstBufferList *list; GstBufferListIterator *it; GstBuffer *rtp_buffer; GstBuffer *data_buffer; list = gst_buffer_list_new (); it = gst_buffer_list_iterate (list); /*** First group, i.e. first packet. **/ /* Create the RTP header buffer */ rtp_buffer = gst_buffer_new (); GST_BUFFER_MALLOCDATA (rtp_buffer) = g_malloc (RTP_HEADER_SIZE); GST_BUFFER_DATA (rtp_buffer) = GST_BUFFER_MALLOCDATA (rtp_buffer); GST_BUFFER_SIZE (rtp_buffer) = RTP_HEADER_SIZE; memset (GST_BUFFER_DATA (rtp_buffer), 0, RTP_HEADER_SIZE); /* Create the buffer that holds the payload */ data_buffer = gst_buffer_new (); GST_BUFFER_MALLOCDATA (data_buffer) = g_malloc (RTP_PAYLOAD_SIZE); GST_BUFFER_DATA (data_buffer) = GST_BUFFER_MALLOCDATA (data_buffer); GST_BUFFER_SIZE (data_buffer) = RTP_PAYLOAD_SIZE; memset (GST_BUFFER_DATA (data_buffer), 0, RTP_PAYLOAD_SIZE); /* Create a new group to hold the rtp header and the payload */ gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add (it, rtp_buffer); gst_buffer_list_iterator_add (it, data_buffer); /*** Second group, i.e. second packet. ***/ /* Create the RTP header buffer */ rtp_buffer = gst_buffer_new (); GST_BUFFER_MALLOCDATA (rtp_buffer) = g_malloc (RTP_HEADER_SIZE); GST_BUFFER_DATA (rtp_buffer) = GST_BUFFER_MALLOCDATA (rtp_buffer); GST_BUFFER_SIZE (rtp_buffer) = RTP_HEADER_SIZE; memset (GST_BUFFER_DATA (rtp_buffer), 0, RTP_HEADER_SIZE); /* Create the buffer that holds the payload */ data_buffer = gst_buffer_new (); GST_BUFFER_MALLOCDATA (data_buffer) = g_malloc (RTP_PAYLOAD_SIZE); GST_BUFFER_DATA (data_buffer) = GST_BUFFER_MALLOCDATA (data_buffer); GST_BUFFER_SIZE (data_buffer) = RTP_PAYLOAD_SIZE; memset (GST_BUFFER_DATA (data_buffer), 0, RTP_PAYLOAD_SIZE); /* Create a new group to hold the rtp header and the payload */ gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add (it, rtp_buffer); gst_buffer_list_iterator_add (it, data_buffer); /* Calculate the size of the data */ *data_size = 2 * RTP_HEADER_SIZE + 2 * RTP_PAYLOAD_SIZE; gst_buffer_list_iterator_free (it); return list; }
/** * 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; }
static void copyGstreamerBuffersToAudioChannel(GstBufferList* buffers, AudioChannel* audioChannel) { #ifdef GST_API_VERSION_1 gsize offset = 0; for (unsigned i = 0; i < gst_buffer_list_length(buffers); i++) { GstBuffer* buffer = gst_buffer_list_get(buffers, i); if (!buffer) continue; GstMapInfo info; gst_buffer_map(buffer, &info, GST_MAP_READ); memcpy(audioChannel->mutableData() + offset, reinterpret_cast<float*>(info.data), info.size); offset += info.size / sizeof(float); gst_buffer_unmap(buffer, &info); } #else GstBufferListIterator* iter = gst_buffer_list_iterate(buffers); gst_buffer_list_iterator_next_group(iter); GstBuffer* buffer = gst_buffer_list_iterator_merge_group(iter); if (buffer) { memcpy(audioChannel->mutableData(), reinterpret_cast<float*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer)); gst_buffer_unref(buffer); } gst_buffer_list_iterator_free(iter); #endif }
/* * 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; }
/* * 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; }
PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono) { m_sampleRate = sampleRate; m_frontLeftBuffers = gst_buffer_list_new(); m_frontRightBuffers = gst_buffer_list_new(); #ifndef GST_API_VERSION_1 m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers); gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator); m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers); gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator); #endif GRefPtr<GMainContext> context = adoptGRef(g_main_context_new()); g_main_context_push_thread_default(context.get()); m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE)); // Start the pipeline processing just after the loop is started. GRefPtr<GSource> timeoutSource = adoptGRef(g_timeout_source_new(0)); g_source_attach(timeoutSource.get(), context.get()); g_source_set_callback(timeoutSource.get(), reinterpret_cast<GSourceFunc>(enteredMainLoopCallback), this, 0); g_main_loop_run(m_loop.get()); g_main_context_pop_thread_default(context.get()); if (m_errorOccurred) return nullptr; unsigned channels = mixToMono ? 1 : 2; OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(channels, m_channelSize, true)); audioBus->setSampleRate(m_sampleRate); copyGstreamerBuffersToAudioChannel(m_frontLeftBuffers, audioBus->channel(0)); if (!mixToMono) copyGstreamerBuffersToAudioChannel(m_frontRightBuffers, audioBus->channel(1)); return audioBus.release(); }
static void add_buffer_to_goplist (MpegPsMux * mux, GstBuffer * buf) { GstBufferListIterator *it; if (mux->gop_list == NULL) mux->gop_list = gst_buffer_list_new (); it = gst_buffer_list_iterate (mux->gop_list); /* move iterator to end */ while (gst_buffer_list_iterator_next_group (it)) { /* .. */ } gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add (it, buf); gst_buffer_list_iterator_free (it); }
static void gst_fragment_init (GstFragment * fragment) { GstFragmentPrivate *priv; fragment->priv = priv = GST_FRAGMENT_GET_PRIVATE (fragment); g_mutex_init (&fragment->priv->lock); priv->buffer_list = gst_buffer_list_new (); priv->size = 0; priv->buffer_iterator = gst_buffer_list_iterate (priv->buffer_list); gst_buffer_list_iterator_add_group (priv->buffer_iterator); fragment->download_start_time = g_get_real_time (); fragment->start_time = 0; fragment->stop_time = 0; fragment->index = 0; fragment->name = g_strdup (""); fragment->completed = FALSE; fragment->discontinuous = FALSE; }
static GstFlowReturn gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload) { GstRtpJ2KDepay *rtpj2kdepay; guint8 end[2]; guint8 *data; guint avail; GstFlowReturn ret = GST_FLOW_OK; rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload); /* flush pending tile */ gst_rtp_j2k_depay_flush_tile (depayload); /* last buffer take all data out of the adapter */ avail = gst_adapter_available (rtpj2kdepay->f_adapter); if (avail == 0) goto done; if (avail > 2) { GstBuffer *outbuf; /* take the last bytes of the JPEG 2000 data to see if there is an EOC * marker */ gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2); if (end[0] != 0xff && end[1] != 0xd9) { GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one"); /* no EOI marker, add one */ outbuf = gst_buffer_new_and_alloc (2); data = GST_BUFFER_DATA (outbuf); data[0] = 0xff; data[1] = 0xd9; gst_adapter_push (rtpj2kdepay->f_adapter, outbuf); avail += 2; } if (rtpj2kdepay->buffer_list) { GList *list; GstBufferList *buflist; GstBufferListIterator *it; GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail); list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail); buflist = gst_buffer_list_new (); it = gst_buffer_list_iterate (buflist); gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add_list (it, list); gst_buffer_list_iterator_free (it); ret = gst_base_rtp_depayload_push_list (depayload, buflist); } else { GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail); outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail); ret = gst_base_rtp_depayload_push (depayload, outbuf); } } else { GST_WARNING_OBJECT (rtpj2kdepay, "empty packet"); gst_adapter_clear (rtpj2kdepay->f_adapter); } /* we accept any mh_id now */ rtpj2kdepay->last_mh_id = -1; /* reset state */ rtpj2kdepay->next_frag = 0; rtpj2kdepay->have_sync = FALSE; done: /* we can't keep headers with mh_id of 0 */ store_mheader (rtpj2kdepay, 0, NULL); return ret; }
/** * 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; } }
static GstFlowReturn gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload * baseaudiopayload, GstBuffer * buffer) { GstBaseRTPPayload *basepayload; GstBaseRTPAudioPayloadPrivate *priv; GstBuffer *outbuf; GstClockTime timestamp; guint8 *payload; guint payload_len; GstFlowReturn ret; priv = baseaudiopayload->priv; basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload); payload_len = GST_BUFFER_SIZE (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT, payload_len, GST_TIME_ARGS (timestamp)); if (priv->buffer_list) { /* create just the RTP header buffer */ outbuf = gst_rtp_buffer_new_allocate (0, 0, 0); } else { /* create buffer to hold the payload */ outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); } /* set metadata */ gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len, timestamp); if (priv->buffer_list) { GstBufferList *list; GstBufferListIterator *it; list = gst_buffer_list_new (); it = gst_buffer_list_iterate (list); /* add both buffers to the buffer list */ gst_buffer_list_iterator_add_group (it); gst_buffer_list_iterator_add (it, outbuf); gst_buffer_list_iterator_add (it, buffer); gst_buffer_list_iterator_free (it); GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list); ret = gst_basertppayload_push_list (basepayload, list); } else { /* copy payload */ payload = gst_rtp_buffer_get_payload (outbuf); memcpy (payload, GST_BUFFER_DATA (buffer), payload_len); gst_buffer_unref (buffer); GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf); ret = gst_basertppayload_push (basepayload, outbuf); } return ret; }
BufferListIterator::BufferListIterator(const BufferListPtr & list) { m_it = gst_buffer_list_iterate(list); }
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; }