1 /*****************************************************************************
2 * input_ext-plugins.h: structures of the input not exported to other modules,
3 * but exported to plug-ins
4 *****************************************************************************
5 * Copyright (C) 1999-2001 VideoLAN
6 * $Id: input_ext-plugins.h,v 1.16 2002/01/21 23:57:46 massiot Exp $
8 * Authors: Christophe Massiot <massiot@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
26 * Communication plugin -> input
29 /* FIXME: you've gotta move this move this, you've gotta move this move this */
30 #define PADDING_PACKET_SIZE 188 /* Size of the NULL packet inserted in case
31 * of data loss (this should be < 188). */
32 #define PADDING_PACKET_NUMBER 10 /* Number of padding packets top insert to
33 * escape a decoder. */
36 /*****************************************************************************
37 * Prototypes from input_programs.c
38 *****************************************************************************/
40 int input_InitStream( struct input_thread_s *, size_t );
41 void input_EndStream ( struct input_thread_s * );
42 struct pgrm_descriptor_s * input_FindProgram( struct input_thread_s *, u16 );
43 struct pgrm_descriptor_s * input_AddProgram ( struct input_thread_s *,
45 void input_DelProgram( struct input_thread_s *, struct pgrm_descriptor_s * );
46 int input_SetProgram( struct input_thread_s *, struct pgrm_descriptor_s * );
47 struct input_area_s * input_AddArea( struct input_thread_s * );
48 void input_DelArea ( struct input_thread_s *, struct input_area_s * );
49 struct es_descriptor_s * input_FindES( struct input_thread_s *, u16 );
50 struct es_descriptor_s * input_AddES ( struct input_thread_s *,
51 struct pgrm_descriptor_s *, u16,
53 void input_DelES ( struct input_thread_s *, struct es_descriptor_s * );
54 int input_SelectES ( struct input_thread_s *, struct es_descriptor_s * );
55 int input_UnselectES( struct input_thread_s *, struct es_descriptor_s * );
57 # define input_InitStream p_symbols->input_InitStream
58 # define input_EndStream p_symbols->input_EndStream
59 # define input_SetProgram p_symbols->input_SetProgram
60 # define input_FindES p_symbols->input_FindES
61 # define input_AddES p_symbols->input_AddES
62 # define input_DelES p_symbols->input_DelES
63 # define input_SelectES p_symbols->input_SelectES
64 # define input_UnselectES p_symbols->input_UnselectES
65 # define input_AddProgram p_symbols->input_AddProgram
66 # define input_DelProgram p_symbols->input_DelProgram
67 # define input_AddArea p_symbols->input_AddArea
68 # define input_DelArea p_symbols->input_DelArea
71 /*****************************************************************************
72 * Prototypes from input_dec.c
73 *****************************************************************************/
75 //decoder_capabilities_s * input_ProbeDecoder( void );
76 vlc_thread_t input_RunDecoder( struct input_thread_s *,
77 struct es_descriptor_s * );
78 void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * );
79 void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * );
80 void input_EscapeDiscontinuity( struct input_thread_s *,
81 struct pgrm_descriptor_s * );
82 void input_EscapeAudioDiscontinuity( struct input_thread_s * );
84 # define input_DecodePES p_symbols->input_DecodePES
87 /*****************************************************************************
88 * Prototypes from input_clock.c
89 *****************************************************************************/
91 void input_ClockInit( struct pgrm_descriptor_s * );
92 int input_ClockManageControl( struct input_thread_s *,
93 struct pgrm_descriptor_s *, mtime_t );
94 void input_ClockManageRef( struct input_thread_s *,
95 struct pgrm_descriptor_s *, mtime_t );
96 mtime_t input_ClockGetTS( struct input_thread_s *,
97 struct pgrm_descriptor_s *, mtime_t );
99 # define input_ClockManageControl p_symbols->input_ClockManageControl
102 /*****************************************************************************
103 * Create a NULL packet for padding in case of a data loss
104 *****************************************************************************/
105 static __inline__ void input_NullPacket( input_thread_t * p_input,
106 es_descriptor_t * p_es )
108 data_packet_t * p_pad_data;
109 pes_packet_t * p_pes;
111 if( (p_pad_data = p_input->pf_new_packet(
112 p_input->p_method_data,
113 PADDING_PACKET_SIZE )) == NULL )
115 intf_ErrMsg("Out of memory");
116 p_input->b_error = 1;
120 memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
121 p_pad_data->b_discard_payload = 1;
126 p_pes->b_discontinuity = 1;
127 p_pes->p_last->p_next = p_pad_data;
128 p_pes->p_last = p_pad_data;
133 if( (p_pes = p_input->pf_new_pes( p_input->p_method_data )) == NULL )
135 intf_ErrMsg("Out of memory");
136 p_input->b_error = 1;
140 p_pes->i_rate = p_input->stream.control.i_rate;
141 p_pes->p_first = p_pes->p_last = p_pad_data;
142 p_pes->i_nb_data = 1;
143 p_pes->b_discontinuity = 1;
144 input_DecodePES( p_es->p_decoder_fifo, p_pes );
150 * Optional Next Generation buffer manager
152 * Either buffers can only be used in one data packet (PS case), or buffers
153 * contain several data packets (DVD case). In the first case, buffers are
154 * embedded into data packets, otherwise they are allocated separately and
155 * shared with a refcount. --Meuuh
158 /* Number of buffers for the calculation of the mean */
159 #define INPUT_BRESENHAM_NB 50
162 #define BUFFERS_NOFLAGS 0
163 #define BUFFERS_UNIQUE_SIZE 1 /* Only with NB_LIFO == 1 */
165 /*****************************************************************************
166 * _input_buffers_t: defines a LIFO per data type to keep
167 *****************************************************************************/
168 #define PACKETS_LIFO( TYPE, NAME ) \
172 unsigned int i_depth; \
175 #define BUFFERS_LIFO( TYPE, NAME ) \
178 TYPE * p_stack; /* First item in the LIFO */ \
179 unsigned int i_depth; /* Number of items in the LIFO */ \
180 unsigned int i_average_size; /* Average size of the items (Bresenham) */\
183 #define DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO ) \
184 typedef struct _input_buffers_s \
187 PACKETS_LIFO( pes_packet_t, pes ) \
188 BUFFERS_LIFO( _data_packet_t, data[NB_LIFO] ) \
189 size_t i_allocated; \
192 #define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \
193 typedef struct _input_buffers_s \
196 PACKETS_LIFO( pes_packet_t, pes ) \
197 PACKETS_LIFO( _data_packet_t, data ) \
198 BUFFERS_LIFO( _data_buffer_t, buffers[NB_LIFO] ) \
199 size_t i_allocated; \
202 /* Data buffer, used in case the buffer can be shared between several data
204 typedef struct _data_buffer_s
206 struct _data_buffer_s * p_next;
208 /* number of data packets this buffer is referenced from - when it falls
209 * down to 0, the buffer is freed */
212 struct /* for compatibility with _data_packet_t */
214 /* size of the current buffer (starting right thereafter) */
219 /* We overload the data_packet_t type to add private members */
220 typedef struct _data_packet_s
222 struct _data_packet_s * p_next;
228 struct _data_buffer_s * p_buffer; /* in case of shared buffers */
229 /* size of the embedded buffer (starting right thereafter) */
235 /*****************************************************************************
236 * input_BuffersInit: initialize the cache structures, return a pointer to it
237 *****************************************************************************/
238 #define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ) \
239 static void * input_BuffersInit( void ) \
241 _input_buffers_t * p_buffers = malloc( sizeof( _input_buffers_t ) ); \
243 if( p_buffers == NULL ) \
248 memset( p_buffers, 0, sizeof( _input_buffers_t ) ); \
249 vlc_mutex_init( &p_buffers->lock ); \
251 return (void *)p_buffers; \
254 /*****************************************************************************
255 * input_BuffersEnd: free all cached structures
256 *****************************************************************************/
257 #define BUFFERS_END_STAT_BUFFERS_LOOP( STRUCT ) \
258 for( i = 0; i < NB_LIFO; i++ ) \
260 if( FLAGS & BUFFERS_UNIQUE_SIZE ) \
263 "input buffers stats: " #STRUCT "[%d]: %d packets", \
264 i, p_buffers->STRUCT[i].i_depth ); \
269 "input buffers stats: " #STRUCT "[%d]: %d bytes, %d packets", \
270 i, p_buffers->STRUCT[i].i_average_size, \
271 p_buffers->STRUCT[i].i_depth ); \
275 #define BUFFERS_END_STAT( FLAGS, NB_LIFO ) \
276 BUFFERS_END_STAT_BUFFERS_LOOP( data );
278 #define BUFFERS_END_STAT_SHARED( FLAGS, NB_LIFO ) \
279 intf_StatMsg( "input buffers stats: data: %d packets", \
280 p_buffers->data.i_depth ); \
281 BUFFERS_END_STAT_BUFFERS_LOOP( buffers );
284 #define BUFFERS_END_BUFFERS_LOOP \
285 while( p_buf != NULL ) \
287 p_next = p_buf->p_next; \
288 p_buffers->i_allocated -= p_buf->_private.i_size; \
293 #define BUFFERS_END_PACKETS_LOOP \
294 while( p_packet != NULL ) \
296 p_next = p_packet->p_next; \
301 #define BUFFERS_END_LOOP( FLAGS, NB_LIFO ) \
302 for( i = 0; i < NB_LIFO; i++ ) \
304 _data_packet_t * p_next; \
305 _data_packet_t * p_buf = p_buffers->data[i].p_stack; \
306 BUFFERS_END_BUFFERS_LOOP; \
309 #define BUFFERS_END_LOOP_SHARED( FLAGS, NB_LIFO ) \
311 /* Free data packets */ \
312 _data_packet_t * p_next; \
313 _data_packet_t * p_packet = p_buffers->data.p_stack; \
314 BUFFERS_END_PACKETS_LOOP; \
317 for( i = 0; i < NB_LIFO; i++ ) \
319 _data_buffer_t * p_next; \
320 _data_buffer_t * p_buf = p_buffers->buffers[i].p_stack; \
321 BUFFERS_END_BUFFERS_LOOP; \
324 #define BUFFERS_END( FLAGS, NB_LIFO, STAT_LOOP, LOOP ) \
325 static void input_BuffersEnd( void * _p_buffers ) \
327 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
329 if( _p_buffers != NULL ) \
333 if( p_main->b_stats ) \
336 intf_StatMsg( "input buffers stats: pes: %d packets", \
337 p_buffers->pes.i_depth ); \
338 STAT_LOOP( FLAGS, NB_LIFO ); \
343 pes_packet_t * p_next, * p_packet = p_buffers->pes.p_stack; \
344 BUFFERS_END_PACKETS_LOOP; \
347 LOOP( FLAGS, NB_LIFO ); \
349 if( p_buffers->i_allocated ) \
351 intf_ErrMsg( "input buffers error: %d bytes have not been" \
352 " freed, expect memory leak", \
353 p_buffers->i_allocated ); \
356 vlc_mutex_destroy( &p_buffers->lock ); \
357 free( _p_buffers ); \
361 #define DECLARE_BUFFERS_END( FLAGS, NB_LIFO ) \
362 BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT, BUFFERS_END_LOOP );
364 #define DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO ) \
365 BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT_SHARED, \
366 BUFFERS_END_LOOP_SHARED );
368 /*****************************************************************************
369 * input_NewPacket: return a pointer to a data packet of the appropriate size
370 *****************************************************************************/
371 #define BUFFERS_NEWPACKET_EXTRA_DECLARATION( FLAGS, NB_LIFO ) \
372 _data_packet_t ** pp_data = &p_buf;
374 #define BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED( FLAGS, NB_LIFO ) \
375 _data_packet_t * p_data; \
376 _data_packet_t ** pp_data = &p_data;
378 #define BUFFERS_NEWPACKET_EXTRA( FLAGS, NB_LIFO )
380 #define BUFFERS_NEWPACKET_EXTRA_SHARED( FLAGS, NB_LIFO ) \
381 /* Find a data packet */ \
382 if( p_buffers->data.p_stack != NULL ) \
384 p_data = p_buffers->data.p_stack; \
385 p_buffers->data.p_stack = p_data->p_next; \
386 p_buffers->data.i_depth--; \
390 p_data = malloc( sizeof( _data_packet_t ) ); \
391 if( p_data == NULL ) \
393 intf_ErrMsg( "Out of memory" ); \
394 vlc_mutex_unlock( &p_buffers->lock ); \
401 /* Warning : in that case, the data packet is left partly \
402 * uninitialized ; theorically only input_ShareBuffer may call \
404 p_data->p_next = NULL; \
405 p_data->b_discard_payload = 0; \
406 return( (data_packet_t *)p_data ); \
409 #define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO, TYPE ) \
410 (*pp_data)->p_demux_start = (byte_t *)*pp_data + sizeof( TYPE );
412 #define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO, TYPE ) \
413 (*pp_data)->_private.p_buffer = p_buf; \
414 (*pp_data)->p_demux_start = (byte_t *)(*pp_data)->_private.p_buffer \
416 /* Initialize refcount */ \
417 p_buf->i_refcount = 1;
419 #define BUFFERS_NEWPACKET( FLAGS, NB_LIFO, TYPE, NAME, EXTRA_DECLARATION, \
421 /* This one doesn't take p_buffers->lock. */ \
422 static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers, \
425 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
428 EXTRA_DECLARATION( FLAGS, NB_LIFO ); \
431 if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION ) \
433 intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)", \
434 p_buffers->i_allocated ); \
438 EXTRA( FLAGS, NB_LIFO ); \
440 for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
442 if( i_size <= (2 * p_buffers->NAME[i_select].i_average_size \
443 + p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
449 if( p_buffers->NAME[i_select].p_stack != NULL ) \
451 /* Take the packet from the cache */ \
452 p_buf = p_buffers->NAME[i_select].p_stack; \
453 p_buffers->NAME[i_select].p_stack = p_buf->p_next; \
454 p_buffers->NAME[i_select].i_depth--; \
456 /* Reallocate the packet if it is too small or too large */ \
457 if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && \
458 (p_buf->_private.i_size < i_size \
459 || p_buf->_private.i_size > 3 * i_size) ) \
461 p_buffers->i_allocated -= p_buf->_private.i_size; \
462 p_buf = realloc( p_buf, sizeof( TYPE ) + i_size ); \
463 if( p_buf == NULL ) \
465 intf_ErrMsg( "Out of memory" ); \
468 p_buf->_private.i_size = i_size; \
469 p_buffers->i_allocated += i_size; \
474 /* Allocate a new packet */ \
475 p_buf = malloc( sizeof( TYPE ) + i_size ); \
476 if( p_buf == NULL ) \
478 intf_ErrMsg( "Out of memory" ); \
481 p_buf->_private.i_size = i_size; \
482 p_buffers->i_allocated += i_size; \
485 /* Initialize data */ \
486 END( FLAGS, NB_LIFO, TYPE ); \
487 (*pp_data)->p_next = NULL; \
488 (*pp_data)->b_discard_payload = 0; \
489 (*pp_data)->p_payload_start = (*pp_data)->p_demux_start; \
490 (*pp_data)->p_payload_end = (*pp_data)->p_payload_start + i_size; \
492 return( (data_packet_t *)*pp_data ); \
495 static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
497 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
498 data_packet_t * p_data; \
501 if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && i_size > INPUT_MAX_PACKET_SIZE ) \
503 intf_ErrMsg( "Packet too big (%d)", i_size ); \
507 vlc_mutex_lock( &p_buffers->lock ); \
508 p_data = _input_NewPacket( _p_buffers, i_size ); \
509 vlc_mutex_unlock( &p_buffers->lock ); \
513 #define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \
514 BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_packet_t, data, \
515 BUFFERS_NEWPACKET_EXTRA_DECLARATION, BUFFERS_NEWPACKET_EXTRA, \
516 BUFFERS_NEWPACKET_END )
518 #define DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO ) \
519 BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_buffer_t, buffers, \
520 BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED, \
521 BUFFERS_NEWPACKET_EXTRA_SHARED, BUFFERS_NEWPACKET_END_SHARED )
523 /*****************************************************************************
524 * input_DeletePacket: put a packet back into the cache
525 *****************************************************************************/
526 #define BUFFERS_DELETEPACKET_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
527 _data_packet_t * p_buf = p_data;
529 #define BUFFERS_DELETEPACKET_EXTRA_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE )\
530 _data_buffer_t * p_buf = (_data_buffer_t *)p_data->_private.p_buffer; \
532 /* Get rid of the data packet */ \
533 if( p_buffers->data.i_depth < DATA_CACHE_SIZE ) \
535 /* Cache not full : store the packet in it */ \
536 p_data->p_next = p_buffers->data.p_stack; \
537 p_buffers->data.p_stack = p_data; \
538 p_buffers->data.i_depth++; \
545 /* Decrement refcount */ \
546 p_buf->i_refcount--; \
547 if( p_buf->i_refcount > 0 ) \
552 #define BUFFERS_DELETEPACKETSTACK_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
553 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
554 _data_packet_t * p_first = (_data_packet_t *)_p_first; \
555 _data_packet_t ** pp_last = (_data_packet_t **)_pp_last; \
557 /* Small hopeless optimization */ \
558 if( (FLAGS & BUFFERS_UNIQUE_SIZE) \
559 && p_buffers->data[0].i_depth < DATA_CACHE_SIZE ) \
561 p_buffers->data[0].i_depth += i_nb; \
562 *pp_last = p_buffers->data[0].p_stack; \
563 p_buffers->data[0].p_stack = p_first; \
565 else /* No semicolon after this or you will die */
567 #define BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED( FLAGS, NB_LIFO, \
570 #define BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, TYPE, \
571 NAME, EXTRA, EXTRA_STACK ) \
572 /* This one doesn't take p_buffers->lock. */ \
573 static __inline__ void _input_DeletePacket( void * _p_buffers, \
574 data_packet_t * _p_data ) \
576 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
577 _data_packet_t * p_data = (_data_packet_t *)_p_data; \
580 while( p_data != NULL ) \
582 _data_packet_t * p_next = p_data->p_next; \
584 EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ); \
586 for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
588 if( p_buf->_private.i_size <= \
589 (2 * p_buffers->NAME[i_select].i_average_size \
590 + p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
596 if( p_buffers->NAME[i_select].i_depth < DATA_CACHE_SIZE ) \
598 /* Cache not full : store the packet in it */ \
599 p_buf->p_next = p_buffers->NAME[i_select].p_stack; \
600 p_buffers->NAME[i_select].p_stack = p_buf; \
601 p_buffers->NAME[i_select].i_depth++; \
603 if( !(FLAGS & BUFFERS_UNIQUE_SIZE) ) \
605 /* Update Bresenham mean (very approximative) */ \
606 p_buffers->NAME[i_select].i_average_size = \
607 ( p_buf->_private.i_size \
608 + p_buffers->NAME[i_select].i_average_size \
609 * (INPUT_BRESENHAM_NB - 1) ) \
610 / INPUT_BRESENHAM_NB; \
615 p_buffers->i_allocated -= p_buf->_private.i_size; \
623 static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
625 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
627 vlc_mutex_lock( &p_buffers->lock ); \
628 _input_DeletePacket( _p_buffers, p_data ); \
629 vlc_mutex_unlock( &p_buffers->lock ); \
632 /* Delete a chained list of i_nb data packets. -- needed by DeletePES */ \
633 static __inline__ void _input_DeletePacketStack( void * _p_buffers, \
634 data_packet_t * _p_first, \
635 data_packet_t ** _pp_last, \
636 unsigned int i_nb ) \
638 /* Do not add code before, EXTRA_STACK makes its own declarations. */ \
639 EXTRA_STACK( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
640 /* No semicolon - PLEASE */ \
642 _input_DeletePacket( _p_buffers, _p_first ); \
646 #define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
647 BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_packet_t, \
648 data, BUFFERS_DELETEPACKET_EXTRA, \
649 BUFFERS_DELETEPACKETSTACK_EXTRA )
651 #define DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, \
653 BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_buffer_t, \
654 buffers, BUFFERS_DELETEPACKET_EXTRA_SHARED, \
655 BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED )
657 /*****************************************************************************
658 * input_DeletePacketStack: optimize deleting of a stack of packets when
659 * knowing much information
660 *****************************************************************************/
661 /* AFAIK, this isn't used by anyone - it is here for completion.
662 * _input_DeletePacketStack is declared in DeletePacket because it is needed
664 #define DECLARE_BUFFERS_DELETEPACKETSTACK( FLAGS, NB_LIFO ) \
665 static void input_DeletePacketStack( void * _p_buffers, \
666 data_packet_t * p_first, \
667 data_packet_t ** pp_last, \
668 unsigned int i_nb ) \
670 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
672 vlc_mutex_lock( &p_buffers->lock ); \
673 _input_DeletePacketStack( _p_buffers, p_first, pp_last, i_nb ); \
674 vlc_mutex_unlock( &p_buffers->lock ); \
677 /*****************************************************************************
678 * input_NewPES: return a pointer to a new PES packet
679 *****************************************************************************/
680 #define DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ) \
681 static pes_packet_t * input_NewPES( void * _p_buffers ) \
683 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
684 pes_packet_t * p_pes; \
686 vlc_mutex_lock( &p_buffers->lock ); \
688 if( p_buffers->pes.p_stack != NULL ) \
690 p_pes = p_buffers->pes.p_stack; \
691 p_buffers->pes.p_stack = p_pes->p_next; \
692 p_buffers->pes.i_depth--; \
696 p_pes = malloc( sizeof( pes_packet_t ) ); \
697 if( p_pes == NULL ) \
699 intf_ErrMsg( "Out of memory" ); \
700 vlc_mutex_unlock( &p_buffers->lock ); \
705 vlc_mutex_unlock( &p_buffers->lock ); \
707 /* Initialize data */ \
708 p_pes->p_next = NULL; \
709 p_pes->b_data_alignment = p_pes->b_discontinuity = \
710 p_pes->i_pts = p_pes->i_dts = 0; \
711 p_pes->i_pes_size = 0; \
712 p_pes->p_first = p_pes->p_last = NULL; \
713 p_pes->i_nb_data = 0; \
718 /*****************************************************************************
719 * input_DeletePES: put a pes and all data packets back into the cache
720 *****************************************************************************/
721 #define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE ) \
722 static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \
724 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
726 vlc_mutex_lock( &p_buffers->lock ); \
728 while( p_pes != NULL ) \
730 pes_packet_t * p_next = p_pes->p_next; \
732 /* Delete all data packets */ \
733 if( p_pes->p_first != NULL ) \
735 _input_DeletePacketStack( _p_buffers, p_pes->p_first, \
736 &p_pes->p_last->p_next, \
737 p_pes->i_nb_data ); \
740 if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \
742 /* Cache not full : store the packet in it */ \
743 p_pes->p_next = p_buffers->pes.p_stack; \
744 p_buffers->pes.p_stack = p_pes; \
745 p_buffers->pes.i_depth++; \
755 vlc_mutex_unlock( &p_buffers->lock ); \
758 /*****************************************************************************
759 * input_BuffersToIO: return an IO vector (only with BUFFERS_UNIQUE_SIZE)
760 *****************************************************************************/
761 #define DECLARE_BUFFERS_TOIO( FLAGS, BUFFER_SIZE ) \
762 static data_packet_t * input_BuffersToIO( void * _p_buffers, \
763 struct iovec * p_iovec, int i_nb )\
765 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
766 data_packet_t * p_data = NULL; \
769 vlc_mutex_lock( &p_buffers->lock ); \
771 for( i = i_nb - 1; i >= 0; i-- ) \
773 data_packet_t * p_next = _input_NewPacket( _p_buffers, \
774 BUFFER_SIZE /* UNIQUE_SIZE */ ); \
775 if( p_next == NULL ) \
777 _input_DeletePacket( _p_buffers, p_data ); \
781 p_iovec[i].iov_base = p_next->p_demux_start; \
782 p_iovec[i].iov_len = BUFFER_SIZE; \
783 p_next->p_next = p_data; \
787 vlc_mutex_unlock( &p_buffers->lock ); \
792 /*****************************************************************************
793 * input_ShareBuffer: return a new data_packet to the same buffer
794 *****************************************************************************/
795 #define DECLARE_BUFFERS_SHAREBUFFER( FLAGS ) \
796 static data_packet_t * input_ShareBuffer( void * _p_buffers, \
797 data_packet_t * _p_shared_data ) \
799 _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
800 _data_packet_t * p_shared_data = (_data_packet_t *)_p_shared_data; \
801 _data_packet_t * p_data; \
802 _data_buffer_t * p_buf = p_shared_data->_private.p_buffer; \
804 vlc_mutex_lock( &p_buffers->lock ); \
806 /* Get new data_packet_t, without a buffer through a special backdoor \
807 * in _input_NewPacket. */ \
808 p_data = (_data_packet_t *)_input_NewPacket( _p_buffers, 0 ); \
810 /* Finish initialization of p_data */ \
811 p_data->_private.p_buffer = p_shared_data->_private.p_buffer; \
812 p_data->p_demux_start = p_data->p_payload_start \
813 = (byte_t *)p_shared_data->_private.p_buffer \
814 + sizeof( _data_buffer_t ); \
815 p_data->p_payload_end = p_data->p_demux_start + p_buf->_private.i_size; \
817 /* Update refcount */ \
818 p_buf->i_refcount++; \
820 vlc_mutex_unlock( &p_buffers->lock ); \
822 return( (data_packet_t *)p_data ); \
827 * Optional MPEG demultiplexing
830 /*****************************************************************************
832 *****************************************************************************/
833 #define TS_PACKET_SIZE 188 /* Size of a TS packet */
834 #define PSI_SECTION_SIZE 4096 /* Maximum size of a PSI section */
836 #define PAT_UNINITIALIZED (1 << 6)
837 #define PMT_UNINITIALIZED (1 << 6)
839 #define PSI_IS_PAT 0x00
840 #define PSI_IS_PMT 0x01
841 #define UNKNOWN_PSI 0xff
843 /*****************************************************************************
845 *****************************************************************************
846 * Describes a PSI section. Beware, it doesn't contain pointers to the TS
847 * packets that contain it as for a PES, but the data themselves
848 *****************************************************************************/
849 typedef struct psi_section_s
851 byte_t buffer[PSI_SECTION_SIZE];
854 u8 i_last_section_number;
856 u16 i_section_length;
857 u16 i_read_in_section;
859 /* the PSI is complete */
860 boolean_t b_is_complete;
862 /* packet missed up ? */
866 boolean_t b_section_complete;
868 /* where are we currently ? */
873 /*****************************************************************************
874 * es_ts_data_t: extension of es_descriptor_t
875 *****************************************************************************/
876 typedef struct es_ts_data_s
878 boolean_t b_psi; /* Does the stream have to be handled by
879 * the PSI decoder ? */
881 int i_psi_type; /* There are different types of PSI */
883 psi_section_t * p_psi_section; /* PSI packets */
886 int i_continuity_counter;
889 /*****************************************************************************
890 * pgrm_ts_data_t: extension of pgrm_descriptor_t
891 *****************************************************************************/
892 typedef struct pgrm_ts_data_s
894 u16 i_pcr_pid; /* PCR ES, for TS streams */
898 /*****************************************************************************
899 * stream_ts_data_t: extension of stream_descriptor_t
900 *****************************************************************************/
901 typedef struct stream_ts_data_s
903 int i_pat_version; /* Current version of the PAT */
906 /*****************************************************************************
907 * stream_ps_data_t: extension of stream_descriptor_t
908 *****************************************************************************/
909 typedef struct stream_ps_data_s
911 boolean_t b_has_PSM; /* very rare, in fact */
916 /* PSM version is 5 bits, so -1 is not a valid value */
917 #define EMPTY_PSM_VERSION -1
920 /*****************************************************************************
922 *****************************************************************************/
924 void input_ParsePES ( struct input_thread_s *, struct es_descriptor_s * );
925 void input_GatherPES ( struct input_thread_s *, struct data_packet_s *,
926 struct es_descriptor_s *, boolean_t, boolean_t );
927 es_descriptor_t * input_ParsePS( struct input_thread_s *,
928 struct data_packet_s * );
929 void input_DemuxPS ( struct input_thread_s *, struct data_packet_s * );
930 void input_DemuxTS ( struct input_thread_s *, struct data_packet_s * );
931 void input_DemuxPSI ( struct input_thread_s *, struct data_packet_s *,
932 struct es_descriptor_s *, boolean_t, boolean_t );
934 # define input_ParsePES p_symbols->input_ParsePES
935 # define input_GatherPES p_symbols->input_GatherPES
936 # define input_ParsePS p_symbols->input_ParsePS
937 # define input_DemuxPS p_symbols->input_DemuxPS
938 # define input_DemuxTS p_symbols->input_DemuxTS
939 # define input_DemuxPSI p_symbols->input_DemuxPSI