/** * gst_buffer_list_insert: * @list: a #GstBufferList * @idx: the index * @buffer: (transfer full): a #GstBuffer * * Insert @buffer at @idx in @list. Other buffers are moved to make room for * this new buffer. * * A -1 value for @idx will append the buffer at the end. */ void gst_buffer_list_insert (GstBufferList * list, gint idx, GstBuffer * buffer) { guint want_alloc; g_return_if_fail (GST_IS_BUFFER_LIST (list)); g_return_if_fail (buffer != NULL); g_return_if_fail (gst_buffer_list_is_writable (list)); if (idx == -1 && list->n_buffers < list->n_allocated) { list->buffers[list->n_buffers++] = buffer; return; } if (idx == -1 || idx > list->n_buffers) idx = list->n_buffers; want_alloc = list->n_buffers + 1; if (want_alloc > list->n_allocated) { want_alloc = MAX (GST_ROUND_UP_16 (want_alloc), list->n_allocated * 2); if (GST_BUFFER_LIST_IS_USING_DYNAMIC_ARRAY (list)) { list->buffers = g_renew (GstBuffer *, list->buffers, want_alloc); } else {
/** * gst_buffer_list_length: * @list: a #GstBufferList * * Returns the number of buffers in @list. * * Returns: the number of buffers in the buffer list */ guint gst_buffer_list_length (GstBufferList * list) { g_return_val_if_fail (GST_IS_BUFFER_LIST (list), 0); return list->n_buffers; }
/** * gst_buffer_list_get: * @list: a #GstBufferList * @idx: the index * * Get the buffer at @idx. * * Returns: (transfer none) (nullable): the buffer at @idx in @group * or %NULL when there is no buffer. The buffer remains valid as * long as @list is valid and buffer is not removed from the list. */ GstBuffer * gst_buffer_list_get (GstBufferList * list, guint idx) { g_return_val_if_fail (GST_IS_BUFFER_LIST (list), NULL); g_return_val_if_fail (idx < list->n_buffers, NULL); return list->buffers[idx]; }
/** * gst_proxy_pad_chain_list_default: * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. * @parent: the parent of @pad or NULL * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR * if not. * * Invoke the default chain list function of the proxy pad. * * Returns: a #GstFlowReturn from the pad. */ GstFlowReturn gst_proxy_pad_chain_list_default (GstPad * pad, GstObject * parent, GstBufferList * list) { GstFlowReturn res; GstPad *internal; g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR); internal = GST_PROXY_PAD_INTERNAL (pad); res = gst_pad_push_list (internal, list); return res; }
/** * gst_buffer_list_foreach: * @list: a #GstBufferList * @func: (scope call): a #GstBufferListFunc to call * @user_data: (closure): user data passed to @func * * Call @func with @data for each buffer in @list. * * @func can modify the passed buffer pointer or its contents. The return value * of @func define if this function returns or if the remaining buffers in * the list should be skipped. * * Returns: %TRUE when @func returned %TRUE for each buffer in @list or when * @list is empty. */ gboolean gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func, gpointer user_data) { guint i, len; gboolean ret = TRUE; g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); g_return_val_if_fail (func != NULL, FALSE); len = list->n_buffers; for (i = 0; i < len;) { GstBuffer *buf, *buf_ret; buf = buf_ret = list->buffers[i]; ret = func (&buf_ret, i, user_data); /* Check if the function changed the buffer */ if (buf != buf_ret) { if (buf_ret == NULL) { gst_buffer_list_remove_range_internal (list, i, 1, FALSE); --len; } else { list->buffers[i] = buf_ret; } } if (!ret) break; /* If the buffer was not removed by func go to the next buffer */ if (buf_ret != NULL) i++; } 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; } }