PipeWire  0.3.66
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 
20 struct 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 
61 static 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 
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);
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 
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 
182 static inline struct spa_buffer *
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 
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);
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 
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];
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 
260 static inline int
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 
295 static 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;
304  void *skel;
305 
307 
308  buffers = (struct spa_buffer **)calloc(1, info.max_align +
309  n_buffers * (sizeof(struct spa_buffer *) + info.skel_size));
310  if (buffers == NULL)
311  return NULL;
312 
313  skel = SPA_PTROFF(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
314  skel = SPA_PTR_ALIGN(skel, info.max_align, void);
315 
316  spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL);
317 
318  return buffers;
319 }
320 
325 #ifdef __cplusplus
326 } /* extern "C" */
327 #endif
328 
329 #endif /* SPA_BUFFER_ALLOC_H */
spa/buffer/buffer.h
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
#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
Definition: alloc.h:33
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META
add metadata data in the skeleton
Definition: alloc.h:27
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
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
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
add chunk data in the skeleton
Definition: alloc.h:29
#define SPA_BUFFER_ALLOC_FLAG_NO_DATA
don't set data pointers
Definition: alloc.h:35
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
add buffer data to the skeleton
Definition: alloc.h:31
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
#define SPA_ROUND_UP_N(num, align)
Definition: defs.h:320
#define SPA_PTR_ALIGN(p, align, type)
Definition: defs.h:335
#define SPA_FLAG_IS_SET(field, flag)
Definition: defs.h:76
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:194
#define SPA_MAX(a, b)
Definition: defs.h:157
information about the buffer layout
Definition: alloc.h:25
size_t mem_size
size of the total memory if not inlined
Definition: alloc.h:47
size_t data_size
size of the data if not inlined
Definition: alloc.h:46
uint32_t n_metas
Definition: alloc.h:38
uint32_t max_align
max of all alignments
Definition: alloc.h:37
size_t meta_size
size of the meta if not inlined
Definition: alloc.h:44
size_t chunk_size
size of the chunk if not inlined
Definition: alloc.h:45
size_t skel_size
size of the struct spa_buffer and inlined meta/chunk/data
Definition: alloc.h:43
struct spa_data * datas
Definition: alloc.h:41
uint32_t * data_aligns
Definition: alloc.h:42
uint32_t n_datas
Definition: alloc.h:39
struct spa_meta * metas
Definition: alloc.h:40
uint32_t flags
Definition: alloc.h:36
A Buffer.
Definition: buffer/buffer.h:90
uint32_t n_metas
number of metadata
Definition: buffer/buffer.h:91
struct spa_meta * metas
array of metadata
Definition: buffer/buffer.h:93
struct spa_data * datas
array of data members
Definition: buffer/buffer.h:94
uint32_t n_datas
number of data members
Definition: buffer/buffer.h:92
Chunk of memory, can change for each buffer.
Definition: buffer/buffer.h:43
uint32_t size
size of valid data.
Definition: buffer/buffer.h:47
Data for a buffer this stays constant for a buffer.
Definition: buffer/buffer.h:62
struct spa_chunk * chunk
valid chunk of memory
Definition: buffer/buffer.h:86
void * data
optional data pointer
Definition: buffer/buffer.h:85
uint32_t maxsize
max size of data
Definition: buffer/buffer.h:84
A metadata element.
Definition: meta.h:47
uint32_t size
size of metadata
Definition: meta.h:49
void * data
pointer to metadata
Definition: meta.h:50