87
101
/* We do only one malloc
88
102
* TODO: bench if doing 2 malloc but keeping a pool of buffer is better
91
* 2 * BLOCK_PADDING_SIZE -> pre + post padding
103
* 2 * BLOCK_PADDING -> pre + post padding
93
const size_t i_alloc = i_size + 2 * BLOCK_PADDING_SIZE + BLOCK_ALIGN;
94
block_sys_t *p_sys = malloc( sizeof( *p_sys ) + i_alloc );
108
#define ALIGN(x) (((x) + BLOCK_ALIGN - 1) & ~(BLOCK_ALIGN - 1))
109
#if 0 /*def HAVE_POSIX_MEMALIGN */
110
/* posix_memalign(,16,) is much slower than malloc() on glibc.
111
* -- Courmisch, September 2009, glibc 2.5 & 2.9 */
112
const size_t i_alloc = ALIGN(sizeof(*p_sys)) + (2 * BLOCK_PADDING)
116
if( posix_memalign( &ptr, BLOCK_ALIGN, i_alloc ) )
120
buf = p_sys->p_allocated_buffer + (-sizeof(*p_sys) & (BLOCK_ALIGN - 1));
123
const size_t i_alloc = sizeof(*p_sys) + BLOCK_ALIGN + (2 * BLOCK_PADDING)
125
p_sys = malloc( i_alloc );
96
126
if( p_sys == NULL )
129
buf = (void *)ALIGN((uintptr_t)p_sys->p_allocated_buffer);
132
buf += BLOCK_PADDING;
134
block_Init( &p_sys->self, buf, i_size );
135
p_sys->self.pf_release = BlockRelease;
99
136
/* Fill opaque data */
100
p_sys->i_allocated_buffer = i_alloc;
102
block_Init( &p_sys->self, p_sys->p_allocated_buffer + BLOCK_PADDING_SIZE
104
- ((uintptr_t)p_sys->p_allocated_buffer % BLOCK_ALIGN),
106
p_sys->self.pf_release = BlockRelease;
137
p_sys->i_allocated_buffer = i_alloc - sizeof(*p_sys);
108
139
return &p_sys->self;
132
164
p_sys = (block_sys_t *)p_block;
135
/* Adjust reserved header if there is enough room */
136
if( p_block->p_buffer - i_prebody > p_sys->p_allocated_buffer &&
137
p_block->p_buffer - i_prebody < p_sys->p_allocated_buffer +
138
p_sys->i_allocated_buffer )
140
p_block->p_buffer -= i_prebody;
141
p_block->i_buffer += i_prebody;
145
/* Adjust payload size if there is enough room */
146
if( p_block->p_buffer + i_body < p_sys->p_allocated_buffer +
147
p_sys->i_allocated_buffer )
149
p_block->i_buffer = i_buffer_size;
153
/* Not enough room, reallocate the buffer */
154
if( i_body > 0 || i_prebody > 0 )
156
/* FIXME: this is really dumb, we should use realloc() */
157
block_t *p_rea = block_New( NULL, i_buffer_size );
167
uint8_t *p_start = p_sys->p_allocated_buffer;
168
uint8_t *p_end = p_sys->p_allocated_buffer + p_sys->i_allocated_buffer;
170
assert( p_block->p_buffer + p_block->i_buffer <= p_end );
171
assert( p_block->p_buffer >= p_start );
173
/* Corner case: the current payload is discarded completely */
174
if( i_prebody <= 0 && p_block->i_buffer <= (size_t)-i_prebody )
175
p_block->i_buffer = 0; /* discard current payload */
176
if( p_block->i_buffer == 0 )
178
size_t available = p_end - p_start;
180
if( requested <= available )
181
{ /* Enough room: recycle buffer */
182
size_t extra = available - requested;
184
p_block->p_buffer = p_start + (extra / 2);
185
p_block->i_buffer = requested;
188
/* Not enough room: allocate a new buffer */
189
block_t *p_rea = block_Alloc( requested );
161
p_rea->i_dts = p_block->i_dts;
162
p_rea->i_pts = p_block->i_pts;
163
p_rea->i_flags = p_block->i_flags;
164
p_rea->i_length = p_block->i_length;
165
p_rea->i_rate = p_block->i_rate;
166
p_rea->i_samples = p_block->i_samples;
168
memcpy( p_rea->p_buffer + i_prebody, p_block->p_buffer,
169
__MIN( p_block->i_buffer, p_rea->i_buffer - i_prebody ) );
191
BlockMetaCopy( p_rea, p_block );
172
192
block_Release( p_block );
196
/* First, shrink payload */
198
/* Pull payload start */
201
assert( p_block->i_buffer >= (size_t)-i_prebody );
202
p_block->p_buffer -= i_prebody;
203
p_block->i_buffer += i_prebody;
208
/* Trim payload end */
209
if( p_block->i_buffer > i_body )
210
p_block->i_buffer = i_body;
212
/* Second, reallocate the buffer if we lack space. This is done now to
213
* minimize the payload size for memory copy. */
214
assert( i_prebody >= 0 );
215
if( (size_t)(p_block->p_buffer - p_start) < (size_t)i_prebody
216
|| (size_t)(p_end - p_block->p_buffer) < i_body )
218
block_t *p_rea = block_Alloc( requested );
221
BlockMetaCopy( p_rea, p_block );
222
p_rea->p_buffer += i_prebody;
223
p_rea->i_buffer -= i_prebody;
224
memcpy( p_rea->p_buffer, p_block->p_buffer, p_block->i_buffer );
226
block_Release( p_block );
177
232
/* We have a very large reserved footer now? Release some of it.
178
* XXX it may not keep the algniment of p_buffer */
179
if( (p_sys->p_allocated_buffer + p_sys->i_allocated_buffer) -
180
(p_block->p_buffer + p_block->i_buffer) > BLOCK_WASTE_SIZE )
233
* XXX it might not preserve the alignment of p_buffer */
234
if( p_end - (p_block->p_buffer + i_body) > BLOCK_WASTE_SIZE )
182
const ptrdiff_t i_prebody = p_block->p_buffer - p_sys->p_allocated_buffer;
183
const size_t i_new = i_prebody + p_block->i_buffer + 1 * BLOCK_PADDING_SIZE;
184
block_sys_t *p_new = realloc( p_sys, sizeof (*p_sys) + i_new );
236
block_t *p_rea = block_Alloc( requested );
189
p_sys->i_allocated_buffer = i_new;
190
p_block = &p_sys->self;
191
p_block->p_buffer = &p_sys->p_allocated_buffer[i_prebody];
239
BlockMetaCopy( p_rea, p_block );
240
p_rea->p_buffer += i_prebody;
241
p_rea->i_buffer -= i_prebody;
242
memcpy( p_rea->p_buffer, p_block->p_buffer, p_block->i_buffer );
243
block_Release( p_block );
248
/* NOTE: p_start and p_end are corrupted from this point */
250
/* Third, expand payload */
252
/* Push payload start */
255
p_block->p_buffer -= i_prebody;
256
p_block->i_buffer += i_prebody;
261
/* Expand payload to requested size */
262
p_block->i_buffer = i_body;
274
static void block_heap_Release (block_t *self)
276
block_heap_t *block = (block_heap_t *)self;
283
* Creates a block from a heap allocation.
284
* This is provided by LibVLC so that manually heap-allocated blocks can safely
285
* be deallocated even after the origin plugin has been unloaded from memory.
287
* When block_Release() is called, VLC will free() the specified pointer.
289
* @param ptr base address of the heap allocation (will be free()'d)
290
* @param addr base address of the useful buffer data
291
* @param length bytes length of the useful buffer datan
292
* @return NULL in case of error (ptr free()'d in that case), or a valid
295
block_t *block_heap_Alloc (void *ptr, void *addr, size_t length)
297
block_heap_t *block = malloc (sizeof (*block));
304
block_Init (&block->self, (uint8_t *)addr, length);
305
block->self.pf_release = block_heap_Release;
198
311
# include <sys/mman.h>
449
566
* Immediately queue one block at the end of a FIFO.
450
567
* @param fifo queue
451
568
* @param block head of a block list to queue (may be NULL)
569
* @return total number of bytes appended to the queue
453
571
size_t block_FifoPut( block_fifo_t *p_fifo, block_t *p_block )
456
vlc_mutex_lock( &p_fifo->lock );
573
size_t i_size = 0, i_depth = 0;
458
while (p_block != NULL)
578
for (p_last = p_block; ; p_last = p_last->p_next)
460
i_size += p_block->i_buffer;
462
*p_fifo->pp_last = p_block;
463
p_fifo->pp_last = &p_block->p_next;
465
p_fifo->i_size += p_block->i_buffer;
467
p_block = p_block->p_next;
580
i_size += p_last->i_buffer;
470
/* We queued one block: wake up one read-waiting thread */
586
vlc_mutex_lock (&p_fifo->lock);
587
*p_fifo->pp_last = p_block;
588
p_fifo->pp_last = &p_last->p_next;
589
p_fifo->i_depth += i_depth;
590
p_fifo->i_size += i_size;
591
/* We queued at least one block: wake up one read-waiting thread */
471
592
vlc_cond_signal( &p_fifo->wait );
472
593
vlc_mutex_unlock( &p_fifo->lock );