mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	buffer-alloc: add helpers for buffer allocation
Add some helpers to calculate buffers memory sizes and construct buffer structures in memory.
This commit is contained in:
		
							parent
							
								
									b171361204
								
							
						
					
					
						commit
						19067dde17
					
				
					 1 changed files with 195 additions and 0 deletions
				
			
		
							
								
								
									
										195
									
								
								spa/include/spa/buffer/alloc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								spa/include/spa/buffer/alloc.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,195 @@
 | 
			
		|||
/* Simple Plugin API
 | 
			
		||||
 * Copyright (C) 2018 Wim Taymans <wim.taymans@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this library; if not, write to the
 | 
			
		||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
			
		||||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPA_BUFFER_ALLOC_H__
 | 
			
		||||
#define __SPA_BUFFER_ALLOC_H__
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <spa/buffer/buffer.h>
 | 
			
		||||
 | 
			
		||||
struct spa_buffer_alloc_info {
 | 
			
		||||
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META	(1<<0)	/**< add metadata data in the skeleton */
 | 
			
		||||
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK	(1<<1)	/**< add chunk data in the skeleton */
 | 
			
		||||
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA	(1<<2)	/**< add buffer data to the skeleton */
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint32_t n_metas;
 | 
			
		||||
	uint32_t *meta_sizes;
 | 
			
		||||
	uint32_t n_datas;
 | 
			
		||||
	uint32_t *data_sizes;
 | 
			
		||||
	uint32_t *data_aligns;
 | 
			
		||||
	size_t skel_size;	/**< size of the struct spa_buffer */
 | 
			
		||||
	size_t data_size;	/**< size of the metadata/chunk/data if not inlined */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info,
 | 
			
		||||
					     uint32_t n_metas, uint32_t meta_sizes[n_metas],
 | 
			
		||||
					     uint32_t n_datas, uint32_t data_sizes[n_datas],
 | 
			
		||||
					     uint32_t data_aligns[n_datas])
 | 
			
		||||
{
 | 
			
		||||
	size_t size;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	info->n_metas = n_metas;
 | 
			
		||||
	info->meta_sizes = meta_sizes;
 | 
			
		||||
	info->n_datas = n_datas;
 | 
			
		||||
	info->data_sizes = data_sizes;
 | 
			
		||||
	info->data_aligns = data_aligns;
 | 
			
		||||
 | 
			
		||||
	info->skel_size = sizeof(struct spa_buffer);
 | 
			
		||||
        info->skel_size += n_metas * sizeof(struct spa_meta);
 | 
			
		||||
        info->skel_size += n_datas * sizeof(struct spa_data);
 | 
			
		||||
 | 
			
		||||
	for (i = 0, size = 0; i < n_metas; i++)
 | 
			
		||||
		size += meta_sizes[i];
 | 
			
		||||
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
 | 
			
		||||
		info->skel_size += size;
 | 
			
		||||
	else
 | 
			
		||||
		info->data_size += size;
 | 
			
		||||
 | 
			
		||||
	size = n_datas * sizeof(struct spa_chunk);
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK))
 | 
			
		||||
	        info->skel_size += size;
 | 
			
		||||
	else
 | 
			
		||||
	        info->data_size += size;
 | 
			
		||||
 | 
			
		||||
	for (i = 0, size = 0; i < n_datas; i++)
 | 
			
		||||
		size += data_sizes[i];
 | 
			
		||||
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
 | 
			
		||||
		info->skel_size += size;
 | 
			
		||||
	else
 | 
			
		||||
		info->data_size += size;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct spa_buffer *
 | 
			
		||||
spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info,
 | 
			
		||||
			void *skel_mem, void *data_mem, uint32_t id, uint32_t mem_type)
 | 
			
		||||
{
 | 
			
		||||
	struct spa_buffer *b = skel_mem;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	int i;
 | 
			
		||||
	void **dp, *skel, *data;
 | 
			
		||||
	struct spa_chunk *cp;
 | 
			
		||||
 | 
			
		||||
	b->id = id;
 | 
			
		||||
	b->n_metas = info->n_metas;
 | 
			
		||||
	b->metas = SPA_MEMBER(b, sizeof(struct spa_buffer), struct spa_meta);
 | 
			
		||||
	b->n_datas = info->n_datas;
 | 
			
		||||
	b->datas = SPA_MEMBER(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data);
 | 
			
		||||
 | 
			
		||||
	skel = SPA_MEMBER(b->datas, info->n_datas * sizeof(struct spa_data), void);
 | 
			
		||||
	data = data_mem;
 | 
			
		||||
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
 | 
			
		||||
		dp = &skel;
 | 
			
		||||
	else
 | 
			
		||||
		dp = &data;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < info->n_metas; i++) {
 | 
			
		||||
		struct spa_meta *m = &b->metas[i];
 | 
			
		||||
		m->size = info->meta_sizes[i];
 | 
			
		||||
		m->data = *dp;
 | 
			
		||||
		*dp += m->size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size = info->n_datas * sizeof(struct spa_chunk);
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) {
 | 
			
		||||
		cp = skel;
 | 
			
		||||
		skel += size;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		cp = data;
 | 
			
		||||
		data += size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (SPA_FLAG_CHECK(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
 | 
			
		||||
		dp = &skel;
 | 
			
		||||
	else
 | 
			
		||||
		dp = &data;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < info->n_datas; i++) {
 | 
			
		||||
		struct spa_data *d = &b->datas[i];
 | 
			
		||||
 | 
			
		||||
		d->chunk = &cp[i];
 | 
			
		||||
		d->type = mem_type;
 | 
			
		||||
		if (info->data_sizes[i] > 0) {
 | 
			
		||||
			d->data = *dp;
 | 
			
		||||
			d->maxsize = info->data_sizes[i];
 | 
			
		||||
			*dp += d->maxsize;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info,
 | 
			
		||||
			      uint32_t n_buffers, struct spa_buffer *buffers[n_buffers],
 | 
			
		||||
			      void *skel_mem, void *data_mem, uint32_t mem_type)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	for (i = 0; i < n_buffers; i++) {
 | 
			
		||||
		buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem, i, mem_type);
 | 
			
		||||
                skel_mem = SPA_MEMBER(skel_mem, info->skel_size, void);
 | 
			
		||||
                data_mem = SPA_MEMBER(data_mem, info->data_size, void);
 | 
			
		||||
        }
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct spa_buffer **
 | 
			
		||||
spa_buffer_alloc_array(uint32_t n_buffers, uint32_t mem_type,
 | 
			
		||||
		       uint32_t n_metas, uint32_t meta_sizes[n_metas],
 | 
			
		||||
		       uint32_t n_datas, uint32_t data_sizes[n_datas],
 | 
			
		||||
		       uint32_t data_aligns[n_datas])
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
        size_t size;
 | 
			
		||||
        struct spa_buffer **buffers;
 | 
			
		||||
        struct spa_buffer_alloc_info info = { 0, };
 | 
			
		||||
        void *skel;
 | 
			
		||||
 | 
			
		||||
        info.flags = SPA_BUFFER_ALLOC_FLAG_INLINE_META |
 | 
			
		||||
                     SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK |
 | 
			
		||||
                     SPA_BUFFER_ALLOC_FLAG_INLINE_DATA;
 | 
			
		||||
 | 
			
		||||
        spa_buffer_alloc_fill_info(&info, n_metas, meta_sizes, n_datas, data_sizes, data_aligns);
 | 
			
		||||
 | 
			
		||||
        info.skel_size = SPA_ROUND_UP_N(info.skel_size, 16);
 | 
			
		||||
 | 
			
		||||
        size = sizeof(struct spa_buffer *) + info.skel_size;
 | 
			
		||||
        buffers = calloc(n_buffers, size);
 | 
			
		||||
 | 
			
		||||
        skel = SPA_MEMBER(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
 | 
			
		||||
 | 
			
		||||
        spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL, mem_type);
 | 
			
		||||
 | 
			
		||||
        return buffers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __SPA_BUFFER_ALLOC_H__ */
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue