PipeWire: spa/buffer/alloc.h Source File

PipeWire 1.2.3

Loading...
Searching...
No Matches
alloc.h
Go to the documentation of this file.
1/* Simple Plugin API */
2/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
3/* SPDX-License-Identifier: MIT */
4
5#ifndef SPA_BUFFER_ALLOC_H
6#define SPA_BUFFER_ALLOC_H
7
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12#include <spa/buffer/buffer.h>
13
20struct spa_buffer_alloc_info {
21#define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0)
22#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1)
23#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2)
24#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111
25#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3)
26 uint32_t flags;
27 uint32_t max_align;
28 uint32_t n_metas;
29 uint32_t n_datas;
30 struct spa_meta *metas;
31 struct spa_data *datas;
32 uint32_t *data_aligns;
33 size_t skel_size;
34 size_t meta_size;
35 size_t chunk_size;
36 size_t data_size;
37 size_t mem_size;
38};
39
61static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info,
62 uint32_t n_metas, struct spa_meta metas[],
63 uint32_t n_datas, struct spa_data datas[],
64 uint32_t data_aligns[])
65{
66 size_t size, *target;
67 uint32_t i;
68
69 info->n_metas = n_metas;
70 info->metas = metas;
71 info->n_datas = n_datas;
72 info->datas = datas;
73 info->data_aligns = data_aligns;
74 info->max_align = 16;
75 info->mem_size = 0;
76 /*
77 * The buffer skeleton is placed in memory like below and can
78 * be accessed as a regular structure.
79 *
80 * +==============================+
81 * | struct spa_buffer |
82 * | uint32_t n_metas | number of metas
83 * | uint32_t n_datas | number of datas
84 * +-| struct spa_meta *metas | pointer to array of metas
85 * +|-| struct spa_data *datas | pointer to array of datas
86 * || +------------------------------+
87 * |+>| struct spa_meta |
88 * | | uint32_t type | metadata
89 * | | uint32_t size | size of metadata
90 * +|--| void *data | pointer to metadata
91 * || | ... <n_metas> | more spa_meta follow
92 * || +------------------------------+
93 * |+->| struct spa_data |
94 * | | uint32_t type | memory type
95 * | | uint32_t flags |
96 * | | int fd | fd of shared memory block
97 * | | uint32_t mapoffset | offset in shared memory of data
98 * | | uint32_t maxsize | size of data block
99 * | +-| void *data | pointer to data
100 * |+|-| struct spa_chunk *chunk | pointer to chunk
101 * ||| | ... <n_datas> | more spa_data follow
102 * ||| +==============================+
103 * VVV
104 *
105 * metadata, chunk and memory can either be placed right
106 * after the skeleton (inlined) or in a separate piece of memory.
107 *
108 * vvv
109 * ||| +==============================+
110 * +-->| meta data memory | metadata memory, 8 byte aligned
111 * || | ... <n_metas> |
112 * || +------------------------------+
113 * +->| struct spa_chunk | memory for n_datas chunks
114 * | | uint32_t offset |
115 * | | uint32_t size |
116 * | | int32_t stride |
117 * | | int32_t dummy |
118 * | | ... <n_datas> chunks |
119 * | +------------------------------+
120 * +>| data | memory for n_datas data, aligned
121 * | ... <n_datas> blocks | according to alignments
122 * +==============================+
123 */
124 info->skel_size = sizeof(struct spa_buffer);
125 info->skel_size += n_metas * sizeof(struct spa_meta);
126 info->skel_size += n_datas * sizeof(struct spa_data);
127
128 for (i = 0, size = 0; i < n_metas; i++)
129 size += SPA_ROUND_UP_N(metas[i].size, 8);
130 info->meta_size = size;
131
132 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
133 target = &info->skel_size;
134 else
135 target = &info->mem_size;
136 *target += info->meta_size;
137
138 info->chunk_size = n_datas * sizeof(struct spa_chunk);
139 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK))
140 target = &info->skel_size;
141 else
142 target = &info->mem_size;
143 *target += info->chunk_size;
144
145 for (i = 0, size = 0; i < n_datas; i++) {
146 int64_t align = data_aligns[i];
147 info->max_align = SPA_MAX(info->max_align, data_aligns[i]);
148 size = SPA_ROUND_UP_N(size, align);
149 size += datas[i].maxsize;
150 }
151 info->data_size = size;
152
153 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) &&
154 SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
155 target = &info->skel_size;
156 else
157 target = &info->mem_size;
158
159 *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1);
160 *target += info->data_size;
161 *target = SPA_ROUND_UP_N(*target, info->max_align);
162
163 return 0;
164}
165
182static inline struct spa_buffer *
183 spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info,
184 void *skel_mem, void *data_mem)
185{
186 struct spa_buffer *b = (struct spa_buffer*)skel_mem;
187 size_t size;
188 uint32_t i;
189 void **dp, *skel, *data;
190 struct spa_chunk *cp;
191
192 b->n_metas = info->n_metas;
193 b->metas = SPA_PTROFF(b, sizeof(struct spa_buffer), struct spa_meta);
194 b->n_datas = info->n_datas;
195 b->datas = SPA_PTROFF(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data);
196
197 skel = SPA_PTROFF(b->datas, info->n_datas * sizeof(struct spa_data), void);
198 data = data_mem;
199
200 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
201 dp = &skel;
202 else
203 dp = &data;
204
205 for (i = 0; i < info->n_metas; i++) {
206 struct spa_meta *m = &b->metas[i];
207 *m = info->metas[i];
208 m->data = *dp;
209 *dp = SPA_PTROFF(*dp, SPA_ROUND_UP_N(m->size, 8), void);
210 }
211
212 size = info->n_datas * sizeof(struct spa_chunk);
213 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) {
214 cp = (struct spa_chunk*)skel;
215 skel = SPA_PTROFF(skel, size, void);
216 }
217 else {
218 cp = (struct spa_chunk*)data;
219 data = SPA_PTROFF(data, size, void);
220 }
221
222 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
223 dp = &skel;
224 else
225 dp = &data;
226
227 for (i = 0; i < info->n_datas; i++) {
228 struct spa_data *d = &b->datas[i];
229
230 *d = info->datas[i];
231 d->chunk = &cp[i];
232 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) {
233 *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void);
234 d->data = *dp;
235 *dp = SPA_PTROFF(*dp, d->maxsize, void);
236 }
237 }
238 return b;
239}
240
260static inline int
261 spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info,
262 uint32_t n_buffers, struct spa_buffer *buffers[],
263 void *skel_mem, void *data_mem)
264{
265 uint32_t i;
266 for (i = 0; i < n_buffers; i++) {
267 buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem);
268 skel_mem = SPA_PTROFF(skel_mem, info->skel_size, void);
269 data_mem = SPA_PTROFF(data_mem, info->mem_size, void);
270 }
271 return 0;
272}
273
295static inline struct spa_buffer **
296 spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags,
297 uint32_t n_metas, struct spa_meta metas[],
298 uint32_t n_datas, struct spa_data datas[],
299 uint32_t data_aligns[])
300{
301
302 struct spa_buffer **buffers;
303 struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL,
304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
305 void *skel;
306
307 spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns);
308
309 buffers = (struct spa_buffer **)calloc(1, info.max_align +
310 n_buffers * (sizeof(struct spa_buffer *) + info.skel_size));
311 if (buffers == NULL)
312 return NULL;
313
314 skel = SPA_PTROFF(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
315 skel = SPA_PTR_ALIGN(skel, info.max_align, void);
316
317 spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL);
318
319 return buffers;
320}
321
326#ifdef __cplusplus
327} /* extern "C" */
328#endif
329
330#endif /* SPA_BUFFER_ALLOC_H */
buffer.h
spa/buffer/buffer.h
spa_buffer_alloc_array
static struct spa_buffer ** spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags, uint32_t n_metas, struct spa_meta metas[], uint32_t n_datas, struct spa_data datas[], uint32_t data_aligns[])
Allocate an array of buffers.
Definition alloc.h:306
SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
Definition alloc.h:33
spa_buffer_alloc_layout
static struct spa_buffer * spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, void *skel_mem, void *data_mem)
Fill skeleton and data according to the allocation info.
Definition alloc.h:193
SPA_BUFFER_ALLOC_FLAG_INLINE_META
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META
add metadata data in the skeleton
Definition alloc.h:27
spa_buffer_alloc_fill_info
static int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, uint32_t n_metas, struct spa_meta metas[], uint32_t n_datas, struct spa_data datas[], uint32_t data_aligns[])
Fill buffer allocation information.
Definition alloc.h:71
spa_buffer_alloc_layout_array
static int spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, uint32_t n_buffers, struct spa_buffer *buffers[], void *skel_mem, void *data_mem)
Layout an array of buffers.
Definition alloc.h:271
SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
add chunk data in the skeleton
Definition alloc.h:29
SPA_BUFFER_ALLOC_FLAG_NO_DATA
#define SPA_BUFFER_ALLOC_FLAG_NO_DATA
don't set data pointers
Definition alloc.h:35
SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
add buffer data to the skeleton
Definition alloc.h:31
SPA_ROUND_UP_N
#define SPA_ROUND_UP_N(num, align)
Definition defs.h:342
SPA_PTR_ALIGN
#define SPA_PTR_ALIGN(p, align, type)
Definition defs.h:357
SPA_FLAG_IS_SET
#define SPA_FLAG_IS_SET(field, flag)
Definition defs.h:90
SPA_PTROFF
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition defs.h:222
SPA_MAX
#define SPA_MAX(a, b)
Definition defs.h:171
spa_buffer_alloc_info
information about the buffer layout
Definition alloc.h:25
spa_buffer_alloc_info::mem_size
size_t mem_size
size of the total memory if not inlined
Definition alloc.h:47
spa_buffer_alloc_info::data_size
size_t data_size
size of the data if not inlined
Definition alloc.h:46
spa_buffer_alloc_info::n_metas
uint32_t n_metas
Definition alloc.h:38
spa_buffer_alloc_info::max_align
uint32_t max_align
max of all alignments
Definition alloc.h:37
spa_buffer_alloc_info::meta_size
size_t meta_size
size of the meta if not inlined
Definition alloc.h:44
spa_buffer_alloc_info::chunk_size
size_t chunk_size
size of the chunk if not inlined
Definition alloc.h:45
spa_buffer_alloc_info::skel_size
size_t skel_size
size of the struct spa_buffer and inlined meta/chunk/data
Definition alloc.h:43
spa_buffer_alloc_info::datas
struct spa_data * datas
Definition alloc.h:41
spa_buffer_alloc_info::data_aligns
uint32_t * data_aligns
Definition alloc.h:42
spa_buffer_alloc_info::n_datas
uint32_t n_datas
Definition alloc.h:39
spa_buffer_alloc_info::metas
struct spa_meta * metas
Definition alloc.h:40
spa_buffer_alloc_info::flags
uint32_t flags
Definition alloc.h:36
spa_buffer
A Buffer.
Definition buffer.h:100
spa_buffer::n_metas
uint32_t n_metas
number of metadata
Definition buffer.h:101
spa_buffer::metas
struct spa_meta * metas
array of metadata
Definition buffer.h:103
spa_buffer::datas
struct spa_data * datas
array of data members
Definition buffer.h:104
spa_buffer::n_datas
uint32_t n_datas
number of data members
Definition buffer.h:102
spa_chunk
Chunk of memory, can change for each buffer.
Definition buffer.h:49
spa_chunk::size
uint32_t size
size of valid data.
Definition buffer.h:53
spa_data
Data for a buffer this stays constant for a buffer.
Definition buffer.h:68
spa_data::chunk
struct spa_chunk * chunk
valid chunk of memory
Definition buffer.h:96
spa_data::data
void * data
optional data pointer
Definition buffer.h:95
spa_data::maxsize
uint32_t maxsize
max size of data
Definition buffer.h:94
spa_meta
A metadata element.
Definition meta.h:48
spa_meta::size
uint32_t size
size of metadata
Definition meta.h:50
spa_meta::data
void * data
pointer to metadata
Definition meta.h:51