* Now the MacOS mozilla plugin is an independant bundle ( searchs no more
[vlc.git] / src / misc / block.c
blob2e7db1dce3fdc94761bd023cbc80d557dac4605e
1 /*****************************************************************************
2 * block.c
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: block.c,v 1.1 2003/08/23 22:49:50 fenrir 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 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #include <stdlib.h>
28 #include <stdarg.h>
30 #include <vlc/vlc.h>
31 #include "vlc_block.h"
33 /* private */
34 struct block_sys_t
36 vlc_mutex_t lock;
38 uint8_t *p_allocated_buffer;
39 int i_allocated_buffer;
41 vlc_bool_t b_modify; /* has it be put in modify state */
42 int i_duplicated; /* how many times it has been duplicated (only content) */
46 static void BlockRelease( block_t *p_block )
48 vlc_mutex_lock( &p_block->p_sys->lock );
50 p_block->p_sys->i_duplicated--;
51 if( p_block->p_sys->i_duplicated < 0 )
53 vlc_mutex_unlock( &p_block->p_sys->lock );
54 free( p_block->p_sys->p_allocated_buffer );
55 free( p_block->p_sys );
56 free( p_block );
58 return;
61 vlc_mutex_unlock( &p_block->p_sys->lock );
62 free( p_block );
65 static block_t *__BlockDupContent( block_t *p_block )
67 block_t *p_dup;
69 p_dup = block_New( p_block->p_manager, p_block->i_buffer );
70 memcpy( p_dup->p_buffer, p_block->p_buffer, p_block->i_buffer );
71 p_dup->b_frame_display = p_block->b_frame_display;
72 p_dup->b_frame_start = p_block->b_frame_start;
73 p_dup->i_pts = p_block->i_pts;
74 p_dup->i_dts = p_block->i_dts;
76 return p_dup;
79 static block_t *BlockModify( block_t *p_block, vlc_bool_t b_will_modify )
81 block_t *p_mod = p_block; /* by default */
83 vlc_mutex_lock( &p_block->p_sys->lock );
85 if( p_block->p_sys->b_modify == b_will_modify )
87 vlc_mutex_unlock( &p_block->p_sys->lock );
88 return p_block;
91 if( p_block->p_sys->i_duplicated == 0 )
93 p_block->p_sys->b_modify = b_will_modify;
94 vlc_mutex_unlock( &p_block->p_sys->lock );
95 return p_block;
98 /* FIXME we could avoid that
99 * we just need to create a new p_sys with new mem FIXME */
100 p_mod = __BlockDupContent( p_block );
101 vlc_mutex_unlock( &p_block->p_sys->lock );
103 BlockRelease( p_block );
105 return p_mod;
107 static block_t *BlockDuplicate( block_t *p_block )
109 block_t *p_dup;
111 vlc_mutex_lock( &p_block->p_sys->lock );
112 if( !p_block->p_sys->b_modify )
114 p_block->p_sys->i_duplicated++;
115 vlc_mutex_unlock( &p_block->p_sys->lock );
116 p_dup = block_NewEmpty();
117 memcpy( p_dup, p_block, sizeof( block_t ) );
118 p_dup->p_next = NULL;
119 return p_dup;
121 p_dup = __BlockDupContent( p_block );
122 vlc_mutex_unlock( &p_block->p_sys->lock );
124 return p_dup;
127 static block_t *BlockRealloc( block_t *p_block, int i_prebody, int i_body )
130 vlc_mutex_lock( &p_block->p_sys->lock );
131 if( i_prebody < 0 ||
132 ( p_block->p_buffer - i_prebody > p_block->p_sys->p_allocated_buffer ) )
134 p_block->p_buffer -= i_prebody;
135 p_block->i_buffer += i_prebody;
136 i_prebody = 0;
138 if( i_body < 0 ||
139 ( p_block->p_buffer + i_body < p_block->p_sys->p_allocated_buffer + p_block->p_sys->i_allocated_buffer ) )
141 p_block->i_buffer = i_body;
142 i_body = 0;
144 vlc_mutex_unlock( &p_block->p_sys->lock );
146 if( i_prebody > 0 )
148 block_t *p_rea = block_New( p_block->p_manager, i_prebody + i_body );
150 memcpy( &p_rea->p_buffer[i_prebody], p_block->p_buffer, p_block->i_buffer );
152 return p_rea;
155 if( i_body > 0 )
157 int i_start;
158 block_t *p_rea = BlockModify( p_block, VLC_TRUE );
160 i_start = p_rea->p_buffer - p_rea->p_sys->p_allocated_buffer;
162 p_rea->p_sys->i_allocated_buffer += i_body - p_rea->i_buffer;
163 p_rea->p_sys->p_allocated_buffer = realloc( p_rea->p_sys->p_allocated_buffer, p_rea->p_sys->i_allocated_buffer );
165 p_rea->p_buffer = &p_rea->p_sys->p_allocated_buffer[i_start];
166 p_rea->i_buffer = i_body;
168 return p_rea;
171 return p_block;
173 /*****************************************************************************
174 * Standard block management
176 *****************************************************************************/
177 /* to be used by other block managment */
178 block_t *block_NewEmpty( void )
180 block_t *p_block;
182 p_block = malloc( sizeof( block_t ) );
183 p_block->p_next = NULL;
184 p_block->b_frame_display= VLC_TRUE;
185 p_block->b_frame_start = VLC_FALSE;
186 p_block->i_pts = 0;
187 p_block->i_dts = 0;
189 p_block->i_buffer = 0;
190 p_block->p_buffer = NULL;
192 p_block->pf_release = NULL;
193 p_block->pf_duplicate = NULL;
194 p_block->pf_modify = NULL;
195 p_block->pf_realloc = NULL;
197 p_block->p_sys = NULL;
198 return p_block;
201 block_t *__block_New( vlc_object_t *p_obj, int i_size )
203 block_t *p_block;
204 block_sys_t *p_sys;
207 p_block = block_NewEmpty();
209 p_block->i_buffer = i_size;
210 if( i_size > 0 )
212 p_block->p_buffer = malloc( i_size );
215 p_block->pf_release = BlockRelease;
216 p_block->pf_duplicate = BlockDuplicate;
217 p_block->pf_modify = BlockModify;
218 p_block->pf_realloc = BlockRealloc;
220 /* that should be ok (no comunication between multiple p_vlc) */
221 p_block->p_manager = p_obj->p_vlc;
223 p_block->p_sys = p_sys = malloc( sizeof( block_sys_t ) );
224 vlc_mutex_init( p_obj, &p_sys->lock );
225 p_sys->p_allocated_buffer = p_block->p_buffer;
226 p_sys->i_allocated_buffer = p_block->i_buffer;
227 p_sys->i_duplicated = 0;
228 p_sys->b_modify = VLC_TRUE;
230 return p_block;
233 void block_ChainAppend( block_t **pp_list, block_t *p_block )
236 if( *pp_list == NULL )
238 *pp_list = p_block;
240 else
242 block_t *p = *pp_list;
244 while( p->p_next )
246 p = p->p_next;
248 p->p_next = p_block;
252 void block_ChainRelease( block_t *p_block )
254 while( p_block )
256 block_t *p_next;
257 p_next = p_block->p_next;
258 p_block->pf_release( p_block );
259 p_block = p_next;
263 int block_ChainExtract( block_t *p_list, void *p_data, int i_max )
265 block_t *b;
266 int i_total = 0;
267 uint8_t *p = p_data;
269 for( b = p_list; b != NULL; b = b->p_next )
271 int i_copy;
273 i_copy = __MIN( i_max, b->i_buffer );
274 if( i_copy > 0 )
276 memcpy( p, b->p_buffer, i_copy );
277 i_max -= i_copy;
278 i_total += i_copy;
279 p += i_copy;
281 if( i_max == 0 )
283 return i_total;
287 return i_total;
290 block_t *block_ChainGather( block_t *p_list )
292 int i_total = 0;
293 block_t *b, *g;
295 if( p_list->p_next == NULL )
297 /* only one, so no need */
298 return p_list;
301 for( b = p_list; b != NULL; b = b->p_next )
303 i_total += b->i_buffer;
306 g = block_New( p_list->p_manager, i_total );
307 block_ChainExtract( p_list, g->p_buffer, g->i_buffer );
309 g->b_frame_display = p_list->b_frame_display;
310 g->b_frame_start = p_list->b_frame_start;
311 g->i_pts = p_list->i_pts;
312 g->i_dts = p_list->i_dts;
314 /* free p_list */
315 block_ChainRelease( p_list );
316 return g;
320 /*****************************************************************************
321 * block_fifo_t managment
322 *****************************************************************************/
323 block_fifo_t * __block_FifoNew ( vlc_object_t *p_obj )
325 block_fifo_t *p_fifo;
327 p_fifo = malloc( sizeof( vlc_object_t ) );
328 vlc_mutex_init( p_obj, &p_fifo->lock );
329 vlc_cond_init( p_obj, &p_fifo->wait );
330 p_fifo->i_depth = 0;
331 p_fifo->p_first = NULL;
332 p_fifo->pp_last = &p_fifo->p_first;
334 return p_fifo;
337 void block_FifoRelease( block_fifo_t *p_fifo )
339 block_FifoEmpty( p_fifo );
340 vlc_cond_destroy( &p_fifo->wait );
341 vlc_mutex_destroy( &p_fifo->lock );
342 free( p_fifo );
345 void block_FifoEmpty( block_fifo_t *p_fifo )
347 block_t *b;
349 vlc_mutex_lock( &p_fifo->lock );
350 for( b = p_fifo->p_first; b != NULL; )
352 block_t *p_next;
354 p_next = b->p_next;
355 block_Release( b );
356 b = p_next;
359 p_fifo->i_depth = 0;
360 p_fifo->p_first = NULL;
361 p_fifo->pp_last = &p_fifo->p_first;
362 vlc_mutex_unlock( &p_fifo->lock );
365 int block_FifoPut ( block_fifo_t *p_fifo, block_t *p_block )
367 int i_size = 0;
368 vlc_mutex_lock( &p_fifo->lock );
372 i_size += p_block->i_buffer;
374 *p_fifo->pp_last = p_block;
375 p_fifo->pp_last = &p_block->p_next;
376 p_fifo->i_depth++;
378 p_block = p_block->p_next;
380 } while( p_block );
382 /* warm there is data in this fifo */
383 vlc_cond_signal( &p_fifo->wait );
384 vlc_mutex_unlock( &p_fifo->lock );
386 return i_size;
389 block_t * block_FifoGet ( block_fifo_t *p_fifo )
391 block_t *b;
393 vlc_mutex_lock( &p_fifo->lock );
395 if( p_fifo->p_first == NULL )
397 vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
400 b = p_fifo->p_first;
402 p_fifo->p_first = b->p_next;
403 p_fifo->i_depth--;
405 if( p_fifo->p_first == NULL )
407 p_fifo->pp_last = &p_fifo->p_first;
410 vlc_mutex_unlock( &p_fifo->lock );
412 b->p_next = NULL;
413 return( b );
416 block_t * block_FifoShow ( block_fifo_t *p_fifo )
418 block_t *b;
420 vlc_mutex_lock( &p_fifo->lock );
422 if( p_fifo->p_first == NULL )
424 vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
427 b = p_fifo->p_first;
429 vlc_mutex_unlock( &p_fifo->lock );
431 return( b );
435 block_t * block_FifoGetFrame( block_fifo_t *p_fifo )
437 block_t *b = NULL;
439 for( ;; )
441 block_t *p_next;
442 block_ChainAppend( &b, block_FifoGet( p_fifo ) );
443 p_next = block_FifoShow( p_fifo );
444 if( p_next == NULL || p_next->b_frame_start )
446 break;
450 return b;