1 /*****************************************************************************
2 * block.c: Data blocks management functions
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: block.c,v 1.3 2003/10/08 21:01:07 gbazin Exp $
7 * Authors: Laurent Aimar <fenrir@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include "vlc_block.h"
38 uint8_t *p_allocated_buffer;
39 int i_allocated_buffer;
41 vlc_bool_t b_modify; /* has it been put in modified state */
42 int i_duplicated; /* how many times has the content been
47 static void BlockRelease( block_t *p_block )
49 vlc_mutex_lock( &p_block->p_sys->lock );
51 p_block->p_sys->i_duplicated--;
52 if( p_block->p_sys->i_duplicated < 0 )
54 vlc_mutex_unlock( &p_block->p_sys->lock );
55 free( p_block->p_sys->p_allocated_buffer );
56 free( p_block->p_sys );
62 vlc_mutex_unlock( &p_block->p_sys->lock );
66 static block_t *__BlockDupContent( block_t *p_block )
70 p_dup = block_New( p_block->p_manager, p_block->i_buffer );
71 memcpy( p_dup->p_buffer, p_block->p_buffer, p_block->i_buffer );
72 p_dup->b_frame_display = p_block->b_frame_display;
73 p_dup->b_frame_start = p_block->b_frame_start;
74 p_dup->i_pts = p_block->i_pts;
75 p_dup->i_dts = p_block->i_dts;
80 static block_t *BlockModify( block_t *p_block, vlc_bool_t b_will_modify )
82 block_t *p_mod = p_block; /* by default */
84 vlc_mutex_lock( &p_block->p_sys->lock );
86 if( p_block->p_sys->b_modify == b_will_modify )
88 vlc_mutex_unlock( &p_block->p_sys->lock );
92 if( p_block->p_sys->i_duplicated == 0 )
94 p_block->p_sys->b_modify = b_will_modify;
95 vlc_mutex_unlock( &p_block->p_sys->lock );
99 /* FIXME we could avoid that
100 * we just need to create a new p_sys with new mem FIXME */
101 p_mod = __BlockDupContent( p_block );
102 vlc_mutex_unlock( &p_block->p_sys->lock );
104 BlockRelease( p_block );
109 static block_t *BlockDuplicate( block_t *p_block )
113 vlc_mutex_lock( &p_block->p_sys->lock );
114 if( !p_block->p_sys->b_modify )
116 p_block->p_sys->i_duplicated++;
117 vlc_mutex_unlock( &p_block->p_sys->lock );
118 p_dup = block_NewEmpty();
119 memcpy( p_dup, p_block, sizeof( block_t ) );
120 p_dup->p_next = NULL;
123 p_dup = __BlockDupContent( p_block );
124 vlc_mutex_unlock( &p_block->p_sys->lock );
129 static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
132 vlc_mutex_lock( &p_block->p_sys->lock );
133 if( i_prebody < 0 || p_block->p_buffer - i_prebody >
134 p_block->p_sys->p_allocated_buffer )
136 p_block->p_buffer -= i_prebody;
137 p_block->i_buffer += i_prebody;
141 p_block->p_buffer + i_body < p_block->p_sys->p_allocated_buffer +
142 p_block->p_sys->i_allocated_buffer )
144 p_block->i_buffer = i_body;
147 vlc_mutex_unlock( &p_block->p_sys->lock );
151 block_t *p_rea = block_New( p_block->p_manager, i_prebody + i_body );
153 memcpy( &p_rea->p_buffer[i_prebody], p_block->p_buffer,
162 block_t *p_rea = BlockModify( p_block, VLC_TRUE );
164 i_start = p_rea->p_buffer - p_rea->p_sys->p_allocated_buffer;
166 p_rea->p_sys->i_allocated_buffer += i_body - p_rea->i_buffer;
167 p_rea->p_sys->p_allocated_buffer =
168 realloc( p_rea->p_sys->p_allocated_buffer,
169 p_rea->p_sys->i_allocated_buffer );
171 p_rea->p_buffer = &p_rea->p_sys->p_allocated_buffer[i_start];
172 p_rea->i_buffer = i_body;
180 /*****************************************************************************
181 * Standard block management
183 *****************************************************************************/
184 /* to be used by other block management */
185 block_t *block_NewEmpty( void )
189 p_block = malloc( sizeof( block_t ) );
190 p_block->p_next = NULL;
191 p_block->b_frame_display= VLC_TRUE;
192 p_block->b_frame_start = VLC_FALSE;
196 p_block->i_buffer = 0;
197 p_block->p_buffer = NULL;
199 p_block->pf_release = NULL;
200 p_block->pf_duplicate = NULL;
201 p_block->pf_modify = NULL;
202 p_block->pf_realloc = NULL;
204 p_block->p_sys = NULL;
208 block_t *__block_New( vlc_object_t *p_obj, int i_size )
213 p_block = block_NewEmpty();
215 p_block->i_buffer = i_size;
218 p_block->p_buffer = malloc( i_size );
221 p_block->pf_release = BlockRelease;
222 p_block->pf_duplicate = BlockDuplicate;
223 p_block->pf_modify = BlockModify;
224 p_block->pf_realloc = BlockRealloc;
226 /* that should be ok (no comunication between multiple p_vlc) */
227 p_block->p_manager = VLC_OBJECT( p_obj->p_vlc );
229 p_block->p_sys = p_sys = malloc( sizeof( block_sys_t ) );
230 vlc_mutex_init( p_obj, &p_sys->lock );
231 p_sys->p_allocated_buffer = p_block->p_buffer;
232 p_sys->i_allocated_buffer = p_block->i_buffer;
233 p_sys->i_duplicated = 0;
234 p_sys->b_modify = VLC_TRUE;
239 void block_ChainAppend( block_t **pp_list, block_t *p_block )
242 if( *pp_list == NULL )
248 block_t *p = *pp_list;
258 void block_ChainRelease( block_t *p_block )
263 p_next = p_block->p_next;
264 p_block->pf_release( p_block );
269 int block_ChainExtract( block_t *p_list, void *p_data, int i_max )
275 for( b = p_list; b != NULL; b = b->p_next )
279 i_copy = __MIN( i_max, b->i_buffer );
282 memcpy( p, b->p_buffer, i_copy );
296 block_t *block_ChainGather( block_t *p_list )
301 if( p_list->p_next == NULL )
303 /* only one, so no need */
307 for( b = p_list; b != NULL; b = b->p_next )
309 i_total += b->i_buffer;
312 g = block_New( p_list->p_manager, i_total );
313 block_ChainExtract( p_list, g->p_buffer, g->i_buffer );
315 g->b_frame_display = p_list->b_frame_display;
316 g->b_frame_start = p_list->b_frame_start;
317 g->i_pts = p_list->i_pts;
318 g->i_dts = p_list->i_dts;
321 block_ChainRelease( p_list );
325 /*****************************************************************************
326 * block_fifo_t management
327 *****************************************************************************/
328 block_fifo_t *__block_FifoNew( vlc_object_t *p_obj )
330 block_fifo_t *p_fifo;
332 p_fifo = malloc( sizeof( vlc_object_t ) );
333 vlc_mutex_init( p_obj, &p_fifo->lock );
334 vlc_cond_init( p_obj, &p_fifo->wait );
336 p_fifo->p_first = NULL;
337 p_fifo->pp_last = &p_fifo->p_first;
342 void block_FifoRelease( block_fifo_t *p_fifo )
344 block_FifoEmpty( p_fifo );
345 vlc_cond_destroy( &p_fifo->wait );
346 vlc_mutex_destroy( &p_fifo->lock );
350 void block_FifoEmpty( block_fifo_t *p_fifo )
354 vlc_mutex_lock( &p_fifo->lock );
355 for( b = p_fifo->p_first; b != NULL; )
365 p_fifo->p_first = NULL;
366 p_fifo->pp_last = &p_fifo->p_first;
367 vlc_mutex_unlock( &p_fifo->lock );
370 int block_FifoPut( block_fifo_t *p_fifo, block_t *p_block )
373 vlc_mutex_lock( &p_fifo->lock );
377 i_size += p_block->i_buffer;
379 *p_fifo->pp_last = p_block;
380 p_fifo->pp_last = &p_block->p_next;
383 p_block = p_block->p_next;
387 /* warn there is data in this fifo */
388 vlc_cond_signal( &p_fifo->wait );
389 vlc_mutex_unlock( &p_fifo->lock );
394 block_t *block_FifoGet( block_fifo_t *p_fifo )
398 vlc_mutex_lock( &p_fifo->lock );
400 if( p_fifo->p_first == NULL )
402 vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
407 p_fifo->p_first = b->p_next;
410 if( p_fifo->p_first == NULL )
412 p_fifo->pp_last = &p_fifo->p_first;
415 vlc_mutex_unlock( &p_fifo->lock );
421 block_t *block_FifoShow( block_fifo_t *p_fifo )
425 vlc_mutex_lock( &p_fifo->lock );
427 if( p_fifo->p_first == NULL )
429 vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
434 vlc_mutex_unlock( &p_fifo->lock );
440 block_t *block_FifoGetFrame( block_fifo_t *p_fifo )
447 block_ChainAppend( &b, block_FifoGet( p_fifo ) );
448 p_next = block_FifoShow( p_fifo );
449 if( p_next == NULL || p_next->b_frame_start )