PipeWire 1.6.8

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#include <spa/buffer/buffer.h>
9
10#ifdef __cplusplus
11 extern "C" {
12#endif
13
14#ifndef SPA_API_BUFFER_ALLOC
15 #ifdef SPA_API_IMPL
16 #define SPA_API_BUFFER_ALLOC SPA_API_IMPL
17 #else
18 #define SPA_API_BUFFER_ALLOC static inline
19 #endif
20#endif
21
26
28 struct spa_buffer_alloc_info {
29#define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0)
30#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1)
31#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2)
32#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111
33#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3)
34 uint32_t flags;
35 uint32_t max_align;
36 uint32_t n_metas;
37 uint32_t n_datas;
38 struct spa_meta *metas;
39 struct spa_data *datas;
40 uint32_t *data_aligns;
41 size_t skel_size;
42 size_t meta_size;
43 size_t chunk_size;
44 size_t data_size;
45 size_t mem_size;
46};
47
59
69 SPA_API_BUFFER_ALLOC int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info,
70 uint32_t n_metas, struct spa_meta metas[],
71 uint32_t n_datas, struct spa_data datas[],
72 uint32_t data_aligns[])
73{
74 size_t size, *target;
75 uint32_t i;
76
77 info->n_metas = n_metas;
78 info->metas = metas;
79 info->n_datas = n_datas;
80 info->datas = datas;
81 info->data_aligns = data_aligns;
82 info->max_align = 16;
83 info->mem_size = 0;
84 /*
85 * The buffer skeleton is placed in memory like below and can
86 * be accessed as a regular structure.
87 *
88 * +==============================+
89 * | struct spa_buffer |
90 * | uint32_t n_metas | number of metas
91 * | uint32_t n_datas | number of datas
92 * +-| struct spa_meta *metas | pointer to array of metas
93 * +|-| struct spa_data *datas | pointer to array of datas
94 * || +------------------------------+
95 * |+>| struct spa_meta |
96 * | | uint32_t type | metadata
97 * | | uint32_t size | size of metadata
98 * +|--| void *data | pointer to metadata
99 * || | ... <n_metas> | more spa_meta follow
100 * || +------------------------------+
101 * |+->| struct spa_data |
102 * | | uint32_t type | memory type
103 * | | uint32_t flags |
104 * | | int fd | fd of shared memory block
105 * | | uint32_t mapoffset | offset in shared memory of data
106 * | | uint32_t maxsize | size of data block
107 * | +-| void *data | pointer to data
108 * |+|-| struct spa_chunk *chunk | pointer to chunk
109 * ||| | ... <n_datas> | more spa_data follow
110 * ||| +==============================+
111 * VVV
112 *
113 * metadata, chunk and memory can either be placed right
114 * after the skeleton (inlined) or in a separate piece of memory.
115 *
116 * vvv
117 * ||| +==============================+
118 * +-->| meta data memory | metadata memory, 8 byte aligned
119 * || | ... <n_metas> |
120 * || +------------------------------+
121 * +->| struct spa_chunk | memory for n_datas chunks
122 * | | uint32_t offset |
123 * | | uint32_t size |
124 * | | int32_t stride |
125 * | | int32_t flags |
126 * | | ... <n_datas> chunks |
127 * | +------------------------------+
128 * +>| data | memory for n_datas data, aligned
129 * | ... <n_datas> blocks | according to alignments
130 * +==============================+
131 */
132 info->skel_size = sizeof(struct spa_buffer);
133 info->skel_size += n_metas * sizeof(struct spa_meta);
134 info->skel_size += n_datas * sizeof(struct spa_data);
135
136 for (i = 0, size = 0; i < n_metas; i++)
137 size += SPA_ROUND_UP_N(metas[i].size, 8);
138 info->meta_size = size;
139
140 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
141 target = &info->skel_size;
142 else
143 target = &info->mem_size;
144 *target += info->meta_size;
145
146 info->chunk_size = n_datas * sizeof(struct spa_chunk);
147 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK))
148 target = &info->skel_size;
149 else
150 target = &info->mem_size;
151 *target += info->chunk_size;
152
153 for (i = 0, size = 0; i < n_datas; i++) {
154 int64_t align = data_aligns[i];
155 info->max_align = SPA_MAX(info->max_align, data_aligns[i]);
156 size = SPA_ROUND_UP_N(size, align);
157 size += datas[i].maxsize;
158 }
159 info->data_size = size;
160
161 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) &&
162 SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
163 target = &info->skel_size;
164 else
165 target = &info->mem_size;
166
167 *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1);
168 *target += info->data_size;
169 *target = SPA_ROUND_UP_N(*target, info->max_align);
170
171 return 0;
172}
173
185
190 SPA_API_BUFFER_ALLOC struct spa_buffer *
191 spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info,
192 void *skel_mem, void *data_mem)
193{
194 struct spa_buffer *b = (struct spa_buffer*)skel_mem;
195 size_t size;
196 uint32_t i;
197 void **dp, *skel, *data;
198 struct spa_chunk *cp;
199
200 b->n_metas = info->n_metas;
201 b->metas = SPA_PTROFF(b, sizeof(struct spa_buffer), struct spa_meta);
202 b->n_datas = info->n_datas;
203 b->datas = SPA_PTROFF(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data);
204
205 skel = SPA_PTROFF(b->datas, info->n_datas * sizeof(struct spa_data), void);
206 data = data_mem;
207
208 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
209 dp = &skel;
210 else
211 dp = &data;
212
213 for (i = 0; i < info->n_metas; i++) {
214 struct spa_meta *m = &b->metas[i];
215 *m = info->metas[i];
216 m->data = *dp;
217 *dp = SPA_PTROFF(*dp, SPA_ROUND_UP_N(m->size, 8), void);
218 }
219
220 size = info->n_datas * sizeof(struct spa_chunk);
221 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) {
222 cp = (struct spa_chunk*)skel;
223 skel = SPA_PTROFF(skel, size, void);
224 }
225 else {
226 cp = (struct spa_chunk*)data;
227 data = SPA_PTROFF(data, size, void);
228 }
229
230 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
231 dp = &skel;
232 else
233 dp = &data;
234
235 for (i = 0; i < info->n_datas; i++) {
236 struct spa_data *d = &b->datas[i];
237
238 *d = info->datas[i];
239 d->chunk = &cp[i];
240 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) {
241 *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void);
242 d->data = *dp;
243 *dp = SPA_PTROFF(*dp, d->maxsize, void);
244 }
245 }
246 return b;
247}
248
260
268 SPA_API_BUFFER_ALLOC int
269 spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info,
270 uint32_t n_buffers, struct spa_buffer *buffers[],
271 void *skel_mem, void *data_mem)
272{
273 uint32_t i;
274 for (i = 0; i < n_buffers; i++) {
275 buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem);
276 skel_mem = SPA_PTROFF(skel_mem, info->skel_size, void);
277 data_mem = SPA_PTROFF(data_mem, info->mem_size, void);
278 }
279 return 0;
280}
281
293
303 SPA_API_BUFFER_ALLOC struct spa_buffer **
304 spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags,
305 uint32_t n_metas, struct spa_meta metas[],
306 uint32_t n_datas, struct spa_data datas[],
307 uint32_t data_aligns[])
308{
309
310 struct spa_buffer **buffers;
311 struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL,
312 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
313 void *skel;
314
315 spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns);
316
317 buffers = (struct spa_buffer **)calloc(1, info.max_align +
318 n_buffers * (sizeof(struct spa_buffer *) + info.skel_size));
319 if (buffers == NULL)
320 return NULL;
321
322 skel = SPA_PTROFF(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
323 skel = SPA_PTR_ALIGN(skel, info.max_align, void);
324
325 spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL);
326
327 return buffers;
328}
329
333
334#ifdef __cplusplus
335} /* extern "C" */
336#endif
337
338#endif /* SPA_BUFFER_ALLOC_H */
SPA_API_BUFFER_ALLOC
#define SPA_API_BUFFER_ALLOC
Definition alloc.h:25
buffer.h
spa/buffer/buffer.h
spa_buffer_alloc_array
SPA_API_BUFFER_ALLOC 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:316
spa_buffer_alloc_layout
SPA_API_BUFFER_ALLOC 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:203
SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
Definition alloc.h:43
spa_buffer_alloc_fill_info
SPA_API_BUFFER_ALLOC 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:81
SPA_BUFFER_ALLOC_FLAG_INLINE_META
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META
add metadata data in the skeleton
Definition alloc.h:37
SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
add chunk data in the skeleton
Definition alloc.h:39
spa_buffer_alloc_layout_array
SPA_API_BUFFER_ALLOC 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:281
SPA_BUFFER_ALLOC_FLAG_NO_DATA
#define SPA_BUFFER_ALLOC_FLAG_NO_DATA
don't set data pointers
Definition alloc.h:45
SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
add buffer data to the skeleton
Definition alloc.h:41
SPA_ROUND_UP_N
#define SPA_ROUND_UP_N(num, align)
Definition defs.h:364
SPA_PTR_ALIGN
#define SPA_PTR_ALIGN(p, align, type)
Definition defs.h:386
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:35
spa_buffer_alloc_info::mem_size
size_t mem_size
size of the total memory if not inlined
Definition alloc.h:57
spa_buffer_alloc_info::data_size
size_t data_size
size of the data if not inlined
Definition alloc.h:56
spa_buffer_alloc_info::n_metas
uint32_t n_metas
Definition alloc.h:48
spa_buffer_alloc_info::max_align
uint32_t max_align
max of all alignments
Definition alloc.h:47
spa_buffer_alloc_info::meta_size
size_t meta_size
size of the meta if not inlined
Definition alloc.h:54
spa_buffer_alloc_info::chunk_size
size_t chunk_size
size of the chunk if not inlined
Definition alloc.h:55
spa_buffer_alloc_info::skel_size
size_t skel_size
size of the struct spa_buffer and inlined meta/chunk/data
Definition alloc.h:53
spa_buffer_alloc_info::datas
struct spa_data * datas
Definition alloc.h:51
spa_buffer_alloc_info::data_aligns
uint32_t * data_aligns
Definition alloc.h:52
spa_buffer_alloc_info::n_datas
uint32_t n_datas
Definition alloc.h:49
spa_buffer_alloc_info::metas
struct spa_meta * metas
Definition alloc.h:50
spa_buffer_alloc_info::flags
uint32_t flags
Definition alloc.h:46
spa_buffer
A Buffer.
Definition buffer.h:110
spa_buffer::n_metas
uint32_t n_metas
number of metadata
Definition buffer.h:111
spa_buffer::metas
struct spa_meta * metas
array of metadata
Definition buffer.h:113
spa_buffer::datas
struct spa_data * datas
array of data members
Definition buffer.h:114
spa_buffer::n_datas
uint32_t n_datas
number of data members
Definition buffer.h:112
spa_chunk
Chunk of memory, can change for each buffer.
Definition buffer.h:59
spa_chunk::size
uint32_t size
size of valid data.
Definition buffer.h:63
spa_data
Data for a buffer this stays constant for a buffer.
Definition buffer.h:78
spa_data::chunk
struct spa_chunk * chunk
valid chunk of memory
Definition buffer.h:106
spa_data::data
void * data
optional data pointer
Definition buffer.h:105
spa_data::maxsize
uint32_t maxsize
max size of data
Definition buffer.h:104
spa_meta
A metadata element.
Definition meta.h:66
spa_meta::size
uint32_t size
size of metadata
Definition meta.h:68
spa_meta::data
void * data
pointer to metadata
Definition meta.h:69