PipeWire  1.4.2
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
9 extern "C" {
10 #endif
11 
12 #include <spa/buffer/buffer.h>
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 
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 
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 dummy |
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 
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);
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 
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 
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 
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);
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 
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];
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 
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 
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;
312  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
313  void *skel;
314 
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 
334 #ifdef __cplusplus
335 } /* extern "C" */
336 #endif
337 
338 #endif /* SPA_BUFFER_ALLOC_H */
#define SPA_API_BUFFER_ALLOC
Definition: alloc.h:25
spa/buffer/buffer.h
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_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
#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
Definition: alloc.h:43
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
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META
add metadata data in the skeleton
Definition: alloc.h:37
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
add chunk data in the skeleton
Definition: alloc.h:39
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
#define SPA_BUFFER_ALLOC_FLAG_NO_DATA
don't set data pointers
Definition: alloc.h:45
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
add buffer data to the skeleton
Definition: alloc.h:41
#define SPA_ROUND_UP_N(num, align)
Definition: defs.h:360
#define SPA_PTR_ALIGN(p, align, type)
Definition: defs.h:382
#define SPA_FLAG_IS_SET(field, flag)
Definition: defs.h:90
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:222
#define SPA_MAX(a, b)
Definition: defs.h:171
information about the buffer layout
Definition: alloc.h:35
size_t mem_size
size of the total memory if not inlined
Definition: alloc.h:57
size_t data_size
size of the data if not inlined
Definition: alloc.h:56
uint32_t n_metas
Definition: alloc.h:48
uint32_t max_align
max of all alignments
Definition: alloc.h:47
size_t meta_size
size of the meta if not inlined
Definition: alloc.h:54
size_t chunk_size
size of the chunk if not inlined
Definition: alloc.h:55
size_t skel_size
size of the struct spa_buffer and inlined meta/chunk/data
Definition: alloc.h:53
struct spa_data * datas
Definition: alloc.h:51
uint32_t * data_aligns
Definition: alloc.h:52
uint32_t n_datas
Definition: alloc.h:49
struct spa_meta * metas
Definition: alloc.h:50
uint32_t flags
Definition: alloc.h:46
A Buffer.
Definition: buffer.h:110
uint32_t n_metas
number of metadata
Definition: buffer.h:111
struct spa_meta * metas
array of metadata
Definition: buffer.h:113
struct spa_data * datas
array of data members
Definition: buffer.h:114
uint32_t n_datas
number of data members
Definition: buffer.h:112
Chunk of memory, can change for each buffer.
Definition: buffer.h:59
uint32_t size
size of valid data.
Definition: buffer.h:63
Data for a buffer this stays constant for a buffer.
Definition: buffer.h:78
struct spa_chunk * chunk
valid chunk of memory
Definition: buffer.h:106
void * data
optional data pointer
Definition: buffer.h:105
uint32_t maxsize
max size of data
Definition: buffer.h:104
A metadata element.
Definition: meta.h:58
uint32_t size
size of metadata
Definition: meta.h:60
void * data
pointer to metadata
Definition: meta.h:61