]> git.sesse.net Git - vlc/blob - include/input_ext-plugins.h
Some heavy changes today:
[vlc] / include / input_ext-plugins.h
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.15 2001/12/30 07:09:54 sam Exp $
7  *
8  * Authors: Christophe Massiot <massiot@via.ecp.fr>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*
26  * Communication plugin -> input
27  */
28
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.                        */
34 #define NO_SEEK             -1
35
36 /*****************************************************************************
37  * Prototypes from input_ext-dec.c
38  *****************************************************************************/
39 #ifndef PLUGIN
40 void InitBitstream  ( struct bit_stream_s *, struct decoder_fifo_s *,
41                       void (* pf_bitstream_callback)( struct bit_stream_s *,
42                                                       boolean_t ),
43                       void * p_callback_arg );
44 void NextDataPacket ( struct bit_stream_s * );
45 #else
46 #   define InitBitstream p_symbols->InitBitstream
47 #endif
48
49 /*****************************************************************************
50  * Prototypes from input_programs.c
51  *****************************************************************************/
52 #ifndef PLUGIN
53 int  input_InitStream( struct input_thread_s *, size_t );
54 void input_EndStream ( struct input_thread_s * );
55 struct pgrm_descriptor_s * input_FindProgram( struct input_thread_s *, u16 );
56 struct pgrm_descriptor_s * input_AddProgram ( struct input_thread_s *,
57                                               u16, size_t );
58 void input_DelProgram( struct input_thread_s *, struct pgrm_descriptor_s * );
59 int input_SetProgram( struct input_thread_s *, struct pgrm_descriptor_s * );
60 struct input_area_s * input_AddArea( struct input_thread_s * );
61 void input_DelArea   ( struct input_thread_s *, struct input_area_s * );
62 struct es_descriptor_s * input_FindES( struct input_thread_s *, u16 );
63 struct es_descriptor_s * input_AddES ( struct input_thread_s *,
64                                        struct pgrm_descriptor_s *, u16,
65                                        size_t );
66 void input_DelES     ( struct input_thread_s *, struct es_descriptor_s * );
67 int  input_SelectES  ( struct input_thread_s *, struct es_descriptor_s * );
68 int  input_UnselectES( struct input_thread_s *, struct es_descriptor_s * );
69 #else
70 #   define input_InitStream p_symbols->input_InitStream
71 #   define input_EndStream p_symbols->input_EndStream
72 #   define input_SetProgram p_symbols->input_SetProgram
73 #   define input_FindES p_symbols->input_FindES
74 #   define input_AddES p_symbols->input_AddES
75 #   define input_DelES p_symbols->input_DelES
76 #   define input_SelectES p_symbols->input_SelectES
77 #   define input_UnselectES p_symbols->input_UnselectES
78 #   define input_AddProgram p_symbols->input_AddProgram
79 #   define input_DelProgram p_symbols->input_DelProgram
80 #   define input_AddArea p_symbols->input_AddArea
81 #   define input_DelArea p_symbols->input_DelArea
82 #endif
83
84 /*****************************************************************************
85  * Prototypes from input_dec.c
86  *****************************************************************************/
87 #ifndef PLUGIN
88 //decoder_capabilities_s * input_ProbeDecoder( void );
89 vlc_thread_t input_RunDecoder( struct input_thread_s *,
90                                struct es_descriptor_s * );
91 void input_EndDecoder( struct input_thread_s *, struct es_descriptor_s * );
92 void input_DecodePES ( struct decoder_fifo_s *, struct pes_packet_s * );
93 void input_EscapeDiscontinuity( struct input_thread_s *,
94                                 struct pgrm_descriptor_s * );
95 void input_EscapeAudioDiscontinuity( struct input_thread_s * );
96 #else
97 #   define input_DecodePES p_symbols->input_DecodePES
98 #endif
99
100 /*****************************************************************************
101  * Prototypes from input_clock.c
102  *****************************************************************************/
103 #ifndef PLUGIN
104 void input_ClockInit( struct pgrm_descriptor_s * );
105 int  input_ClockManageControl( struct input_thread_s *,
106                                struct pgrm_descriptor_s *, mtime_t );
107 void input_ClockManageRef( struct input_thread_s *,
108                            struct pgrm_descriptor_s *, mtime_t );
109 mtime_t input_ClockGetTS( struct input_thread_s *,
110                           struct pgrm_descriptor_s *, mtime_t );
111 #else
112 #   define input_ClockManageControl p_symbols->input_ClockManageControl
113 #endif
114
115 /*****************************************************************************
116  * Create a NULL packet for padding in case of a data loss
117  *****************************************************************************/
118 static __inline__ void input_NullPacket( input_thread_t * p_input,
119                                          es_descriptor_t * p_es )
120 {
121     data_packet_t *             p_pad_data;
122     pes_packet_t *              p_pes;
123
124     if( (p_pad_data = p_input->pf_new_packet(
125                     p_input->p_method_data,
126                     PADDING_PACKET_SIZE )) == NULL )
127     {
128         intf_ErrMsg("Out of memory");
129         p_input->b_error = 1;
130         return;
131     }
132
133     memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
134     p_pad_data->b_discard_payload = 1;
135     p_pes = p_es->p_pes;
136
137     if( p_pes != NULL )
138     {
139         p_pes->b_discontinuity = 1;
140         p_pes->p_last->p_next = p_pad_data;
141         p_pes->p_last = p_pad_data;
142         p_pes->i_nb_data++;
143     }
144     else
145     {
146         if( (p_pes = p_input->pf_new_pes( p_input->p_method_data )) == NULL )
147         {
148             intf_ErrMsg("Out of memory");
149             p_input->b_error = 1;
150             return;
151         }
152
153         p_pes->i_rate = p_input->stream.control.i_rate;
154         p_pes->p_first = p_pes->p_last = p_pad_data;
155         p_pes->i_nb_data = 1;
156         p_pes->b_discontinuity = 1;
157         input_DecodePES( p_es->p_decoder_fifo, p_pes );
158     }
159 }
160
161
162 /*
163  * Optional Next Generation buffer manager
164  *
165  * Either buffers can only be used in one data packet (PS case), or buffers
166  * contain several data packets (DVD case). In the first case, buffers are
167  * embedded into data packets, otherwise they are allocated separately and
168  * shared with a refcount. --Meuuh
169  */
170
171 /* Number of buffers for the calculation of the mean */
172 #define INPUT_BRESENHAM_NB      50
173
174 /* Flags */
175 #define BUFFERS_NOFLAGS         0
176 #define BUFFERS_UNIQUE_SIZE     1 /* Only with NB_LIFO == 1 */
177
178 /*****************************************************************************
179  * _input_buffers_t: defines a LIFO per data type to keep
180  *****************************************************************************/
181 #define PACKETS_LIFO( TYPE, NAME )                                          \
182 struct                                                                      \
183 {                                                                           \
184     TYPE * p_stack;                                                         \
185     unsigned int i_depth;                                                   \
186 } NAME;
187
188 #define BUFFERS_LIFO( TYPE, NAME )                                          \
189 struct                                                                      \
190 {                                                                           \
191     TYPE * p_stack; /* First item in the LIFO */                            \
192     unsigned int i_depth; /* Number of items in the LIFO */                 \
193     unsigned int i_average_size; /* Average size of the items (Bresenham) */\
194 } NAME;
195
196 #define DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO )                          \
197 typedef struct _input_buffers_s                                             \
198 {                                                                           \
199     vlc_mutex_t lock;                                                       \
200     PACKETS_LIFO( pes_packet_t, pes )                                       \
201     BUFFERS_LIFO( _data_packet_t, data[NB_LIFO] )                           \
202     size_t i_allocated;                                                     \
203 } _input_buffers_t;
204
205 #define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO )                            \
206 typedef struct _input_buffers_s                                             \
207 {                                                                           \
208     vlc_mutex_t lock;                                                       \
209     PACKETS_LIFO( pes_packet_t, pes )                                       \
210     PACKETS_LIFO( _data_packet_t, data )                                    \
211     BUFFERS_LIFO( _data_buffer_t, buffers[NB_LIFO] )                        \
212     size_t i_allocated;                                                     \
213 } _input_buffers_t;
214
215 /* Data buffer, used in case the buffer can be shared between several data
216  * packets */
217 typedef struct _data_buffer_s
218 {
219     struct _data_buffer_s * p_next;
220
221     /* number of data packets this buffer is referenced from - when it falls
222      * down to 0, the buffer is freed */
223     int i_refcount;
224
225     struct /* for compatibility with _data_packet_t */
226     {
227         /* size of the current buffer (starting right thereafter) */
228         unsigned int i_size;
229     } _private;
230 } _data_buffer_t;
231
232 /* We overload the data_packet_t type to add private members */
233 typedef struct _data_packet_s
234 {
235     struct _data_packet_s * p_next;
236
237     DATA_PACKET
238
239     union
240     {
241         struct _data_buffer_s * p_buffer; /* in case of shared buffers */
242         /* size of the embedded buffer (starting right thereafter) */
243         unsigned int i_size;
244     } _private;
245 } _data_packet_t;
246
247
248 /*****************************************************************************
249  * input_BuffersInit: initialize the cache structures, return a pointer to it
250  *****************************************************************************/
251 #define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO )                              \
252 static void * input_BuffersInit( void )                                     \
253 {                                                                           \
254     _input_buffers_t * p_buffers = malloc( sizeof( _input_buffers_t ) );    \
255                                                                             \
256     if( p_buffers == NULL )                                                 \
257     {                                                                       \
258         return( NULL );                                                     \
259     }                                                                       \
260                                                                             \
261     memset( p_buffers, 0, sizeof( _input_buffers_t ) );                     \
262     vlc_mutex_init( &p_buffers->lock );                                     \
263                                                                             \
264     return (void *)p_buffers;                                               \
265 }
266
267 /*****************************************************************************
268  * input_BuffersEnd: free all cached structures
269  *****************************************************************************/
270 #define BUFFERS_END_STAT_BUFFERS_LOOP( STRUCT )                             \
271     for( i = 0; i < NB_LIFO; i++ )                                          \
272     {                                                                       \
273         if( FLAGS & BUFFERS_UNIQUE_SIZE )                                   \
274         {                                                                   \
275             intf_StatMsg(                                                   \
276               "input buffers stats: " #STRUCT "[%d]: %d packets",           \
277               i, p_buffers->STRUCT[i].i_depth );                            \
278         }                                                                   \
279         else                                                                \
280         {                                                                   \
281             intf_StatMsg(                                                   \
282               "input buffers stats: " #STRUCT "[%d]: %d bytes, %d packets", \
283               i, p_buffers->STRUCT[i].i_average_size,                       \
284               p_buffers->STRUCT[i].i_depth );                               \
285         }                                                                   \
286     }
287
288 #define BUFFERS_END_STAT( FLAGS, NB_LIFO )                                  \
289     BUFFERS_END_STAT_BUFFERS_LOOP( data );
290
291 #define BUFFERS_END_STAT_SHARED( FLAGS, NB_LIFO )                           \
292     intf_StatMsg( "input buffers stats: data: %d packets",                  \
293                   p_buffers->data.i_depth );                                \
294     BUFFERS_END_STAT_BUFFERS_LOOP( buffers );
295
296
297 #define BUFFERS_END_BUFFERS_LOOP                                            \
298     while( p_buf != NULL )                                                  \
299     {                                                                       \
300         p_next = p_buf->p_next;                                             \
301         p_buffers->i_allocated -= p_buf->_private.i_size;                   \
302         free( p_buf );                                                      \
303         p_buf = p_next;                                                     \
304     }
305
306 #define BUFFERS_END_PACKETS_LOOP                                            \
307     while( p_packet != NULL )                                               \
308     {                                                                       \
309         p_next = p_packet->p_next;                                          \
310         free( p_packet );                                                   \
311         p_packet = p_next;                                                  \
312     }
313
314 #define BUFFERS_END_LOOP( FLAGS, NB_LIFO )                                  \
315     for( i = 0; i < NB_LIFO; i++ )                                          \
316     {                                                                       \
317         _data_packet_t * p_next;                                            \
318         _data_packet_t * p_buf = p_buffers->data[i].p_stack;                \
319         BUFFERS_END_BUFFERS_LOOP;                                           \
320     }                                                                       \
321
322 #define BUFFERS_END_LOOP_SHARED( FLAGS, NB_LIFO )                           \
323     {                                                                       \
324         /* Free data packets */                                             \
325         _data_packet_t * p_next;                                            \
326         _data_packet_t * p_packet = p_buffers->data.p_stack;                \
327         BUFFERS_END_PACKETS_LOOP;                                           \
328     }                                                                       \
329                                                                             \
330     for( i = 0; i < NB_LIFO; i++ )                                          \
331     {                                                                       \
332         _data_buffer_t * p_next;                                            \
333         _data_buffer_t * p_buf = p_buffers->buffers[i].p_stack;             \
334         BUFFERS_END_BUFFERS_LOOP;                                           \
335     }                                                                       \
336
337 #define BUFFERS_END( FLAGS, NB_LIFO, STAT_LOOP, LOOP )                      \
338 static void input_BuffersEnd( void * _p_buffers )                           \
339 {                                                                           \
340     _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers;          \
341                                                                             \
342     if( _p_buffers != NULL )                                                \
343     {                                                                       \
344         int i;                                                              \
345                                                                             \
346         if( p_main->b_stats )                                               \
347         {                                                                   \
348             int i;                                                          \
349             intf_StatMsg( "input buffers stats: pes: %d packets",           \
350                           p_buffers->pes.i_depth );                         \
351             STAT_LOOP( FLAGS, NB_LIFO );                                    \
352         }                                                                   \
353                                                                             \
354         {                                                                   \
355             /* Free PES */                                                  \
356             pes_packet_t * p_next, * p_packet = p_buffers->pes.p_stack;     \
357             BUFFERS_END_PACKETS_LOOP;                                       \
358         }                                                                   \
359                                                                             \
360         LOOP( FLAGS, NB_LIFO );                                             \
361                                                                             \
362         if( p_buffers->i_allocated )                                        \
363         {                                                                   \
364             intf_ErrMsg( "input buffers error: %d bytes have not been"      \
365                          " freed, expect memory leak",                      \
366                          p_buffers->i_allocated );                          \
367         }                                                                   \
368                                                                             \
369         vlc_mutex_destroy( &p_buffers->lock );                              \
370         free( _p_buffers );                                                 \
371     }                                                                       \
372 }
373
374 #define DECLARE_BUFFERS_END( FLAGS, NB_LIFO )                               \
375     BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT, BUFFERS_END_LOOP );
376
377 #define DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO )                        \
378     BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT_SHARED,                   \
379                  BUFFERS_END_LOOP_SHARED );
380
381 /*****************************************************************************
382  * input_NewPacket: return a pointer to a data packet of the appropriate size
383  *****************************************************************************/
384 #define BUFFERS_NEWPACKET_EXTRA_DECLARATION( FLAGS, NB_LIFO )               \
385     _data_packet_t **    pp_data = &p_buf;
386
387 #define BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED( FLAGS, NB_LIFO )        \
388     _data_packet_t *     p_data;                                            \
389     _data_packet_t **    pp_data = &p_data;
390
391 #define BUFFERS_NEWPACKET_EXTRA( FLAGS, NB_LIFO )
392
393 #define BUFFERS_NEWPACKET_EXTRA_SHARED( FLAGS, NB_LIFO )                    \
394     /* Find a data packet */                                                \
395     if( p_buffers->data.p_stack != NULL )                                   \
396     {                                                                       \
397         p_data = p_buffers->data.p_stack;                                   \
398         p_buffers->data.p_stack = p_data->p_next;                           \
399         p_buffers->data.i_depth--;                                          \
400     }                                                                       \
401     else                                                                    \
402     {                                                                       \
403         p_data = malloc( sizeof( _data_packet_t ) );                        \
404         if( p_data == NULL )                                                \
405         {                                                                   \
406             intf_ErrMsg( "Out of memory" );                                 \
407             vlc_mutex_unlock( &p_buffers->lock );                           \
408             return( NULL );                                                 \
409         }                                                                   \
410     }                                                                       \
411                                                                             \
412     if( i_size == 0 )                                                       \
413     {                                                                       \
414         /* Warning : in that case, the data packet is left partly           \
415          * uninitialized ; theorically only input_ShareBuffer may call      \
416          * this. */                                                         \
417         p_data->p_next = NULL;                                              \
418         p_data->b_discard_payload = 0;                                      \
419         return( (data_packet_t *)p_data );                                  \
420     }
421
422 #define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO, TYPE )                       \
423     (*pp_data)->p_demux_start = (byte_t *)*pp_data + sizeof( TYPE );
424
425 #define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO, TYPE )                \
426     (*pp_data)->_private.p_buffer = p_buf;                                  \
427     (*pp_data)->p_demux_start = (byte_t *)(*pp_data)->_private.p_buffer     \
428                                   + sizeof( TYPE );                         \
429     /* Initialize refcount */                                               \
430     p_buf->i_refcount = 1;
431
432 #define BUFFERS_NEWPACKET( FLAGS, NB_LIFO, TYPE, NAME, EXTRA_DECLARATION,   \
433                            EXTRA, END )                                     \
434 /* This one doesn't take p_buffers->lock. */                                \
435 static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers,      \
436                                                     size_t i_size )         \
437 {                                                                           \
438     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
439     int                 i_select;                                           \
440     TYPE *              p_buf;                                              \
441     EXTRA_DECLARATION( FLAGS, NB_LIFO );                                    \
442                                                                             \
443     /* Safety check */                                                      \
444     if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION )                     \
445     {                                                                       \
446         intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)",                   \
447                      p_buffers->i_allocated );                              \
448         return NULL;                                                        \
449     }                                                                       \
450                                                                             \
451     EXTRA( FLAGS, NB_LIFO );                                                \
452                                                                             \
453     for( i_select = 0; i_select < NB_LIFO - 1; i_select++ )                 \
454     {                                                                       \
455         if( i_size <= (2 * p_buffers->NAME[i_select].i_average_size         \
456                   + p_buffers->NAME[i_select + 1].i_average_size) / 3 )     \
457         {                                                                   \
458             break;                                                          \
459         }                                                                   \
460     }                                                                       \
461                                                                             \
462     if( p_buffers->NAME[i_select].p_stack != NULL )                         \
463     {                                                                       \
464         /* Take the packet from the cache */                                \
465         p_buf = p_buffers->NAME[i_select].p_stack;                          \
466         p_buffers->NAME[i_select].p_stack = p_buf->p_next;                  \
467         p_buffers->NAME[i_select].i_depth--;                                \
468                                                                             \
469         /* Reallocate the packet if it is too small or too large */         \
470         if( !(FLAGS & BUFFERS_UNIQUE_SIZE) &&                               \
471             (p_buf->_private.i_size < i_size                                \
472               || p_buf->_private.i_size > 3 * i_size) )                     \
473         {                                                                   \
474             p_buffers->i_allocated -= p_buf->_private.i_size;               \
475             p_buf = realloc( p_buf, sizeof( TYPE ) + i_size );              \
476             if( p_buf == NULL )                                             \
477             {                                                               \
478                 intf_ErrMsg( "Out of memory" );                             \
479                 return NULL;                                                \
480             }                                                               \
481             p_buf->_private.i_size = i_size;                                \
482             p_buffers->i_allocated += i_size;                               \
483         }                                                                   \
484     }                                                                       \
485     else                                                                    \
486     {                                                                       \
487         /* Allocate a new packet */                                         \
488         p_buf = malloc( sizeof( TYPE ) + i_size );                          \
489         if( p_buf == NULL )                                                 \
490         {                                                                   \
491             intf_ErrMsg( "Out of memory" );                                 \
492             return NULL;                                                    \
493         }                                                                   \
494         p_buf->_private.i_size = i_size;                                    \
495         p_buffers->i_allocated += i_size;                                   \
496     }                                                                       \
497                                                                             \
498     /* Initialize data */                                                   \
499     END( FLAGS, NB_LIFO, TYPE );                                            \
500     (*pp_data)->p_next = NULL;                                              \
501     (*pp_data)->b_discard_payload = 0;                                      \
502     (*pp_data)->p_payload_start = (*pp_data)->p_demux_start;                \
503     (*pp_data)->p_payload_end = (*pp_data)->p_payload_start + i_size;       \
504                                                                             \
505     return( (data_packet_t *)*pp_data );                                    \
506 }                                                                           \
507                                                                             \
508 static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size )  \
509 {                                                                           \
510     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
511     data_packet_t *     p_data;                                             \
512                                                                             \
513     /* Safety check */                                                      \
514     if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && i_size > INPUT_MAX_PACKET_SIZE )  \
515     {                                                                       \
516         intf_ErrMsg( "Packet too big (%d)", i_size );                       \
517         return NULL;                                                        \
518     }                                                                       \
519                                                                             \
520     vlc_mutex_lock( &p_buffers->lock );                                     \
521     p_data = _input_NewPacket( _p_buffers, i_size );                        \
522     vlc_mutex_unlock( &p_buffers->lock );                                   \
523     return( p_data );                                                       \
524 }
525
526 #define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO )                         \
527     BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_packet_t, data,                \
528             BUFFERS_NEWPACKET_EXTRA_DECLARATION, BUFFERS_NEWPACKET_EXTRA,   \
529             BUFFERS_NEWPACKET_END )
530
531 #define DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO )                  \
532     BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_buffer_t, buffers,             \
533             BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED,                     \
534             BUFFERS_NEWPACKET_EXTRA_SHARED, BUFFERS_NEWPACKET_END_SHARED )
535
536 /*****************************************************************************
537  * input_DeletePacket: put a packet back into the cache
538  *****************************************************************************/
539 #define BUFFERS_DELETEPACKET_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE )       \
540     _data_packet_t * p_buf = p_data;
541
542 #define BUFFERS_DELETEPACKET_EXTRA_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE )\
543     _data_buffer_t * p_buf = (_data_buffer_t *)p_data->_private.p_buffer;   \
544                                                                             \
545     /* Get rid of the data packet */                                        \
546     if( p_buffers->data.i_depth < DATA_CACHE_SIZE )                         \
547     {                                                                       \
548         /* Cache not full : store the packet in it */                       \
549         p_data->p_next = p_buffers->data.p_stack;                           \
550         p_buffers->data.p_stack = p_data;                                   \
551         p_buffers->data.i_depth++;                                          \
552     }                                                                       \
553     else                                                                    \
554     {                                                                       \
555         free( p_data );                                                     \
556     }                                                                       \
557                                                                             \
558     /* Decrement refcount */                                                \
559     p_buf->i_refcount--;                                                    \
560     if( p_buf->i_refcount > 0 )                                             \
561     {                                                                       \
562         return;                                                             \
563     }
564
565 #define BUFFERS_DELETEPACKETSTACK_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE )  \
566     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
567     _data_packet_t *    p_first = (_data_packet_t *)_p_first;               \
568     _data_packet_t **   pp_last = (_data_packet_t **)_pp_last;              \
569                                                                             \
570     /* Small hopeless optimization */                                       \
571     if( (FLAGS & BUFFERS_UNIQUE_SIZE)                                       \
572            && p_buffers->data[0].i_depth < DATA_CACHE_SIZE )                \
573     {                                                                       \
574         p_buffers->data[0].i_depth += i_nb;                                 \
575         *pp_last = p_buffers->data[0].p_stack;                              \
576         p_buffers->data[0].p_stack = p_first;                               \
577     }                                                                       \
578     else /* No semicolon after this or you will die */ 
579
580 #define BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED( FLAGS, NB_LIFO,             \
581                                                 DATA_CACHE_SIZE )
582
583 #define BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, TYPE,        \
584                               NAME, EXTRA, EXTRA_STACK )                    \
585 /* This one doesn't take p_buffers->lock. */                                \
586 static __inline__ void _input_DeletePacket( void * _p_buffers,              \
587                                             data_packet_t * _p_data )       \
588 {                                                                           \
589     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
590     _data_packet_t *    p_data = (_data_packet_t *)_p_data;                 \
591     int                 i_select;                                           \
592                                                                             \
593     while( p_data != NULL )                                                 \
594     {                                                                       \
595         _data_packet_t * p_next = p_data->p_next;                           \
596                                                                             \
597         EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE );                           \
598                                                                             \
599         for( i_select = 0; i_select < NB_LIFO - 1; i_select++ )             \
600         {                                                                   \
601             if( p_buf->_private.i_size <=                                   \
602                    (2 * p_buffers->NAME[i_select].i_average_size            \
603                       + p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
604             {                                                               \
605                 break;                                                      \
606             }                                                               \
607         }                                                                   \
608                                                                             \
609         if( p_buffers->NAME[i_select].i_depth < DATA_CACHE_SIZE )           \
610         {                                                                   \
611             /* Cache not full : store the packet in it */                   \
612             p_buf->p_next = p_buffers->NAME[i_select].p_stack;              \
613             p_buffers->NAME[i_select].p_stack = p_buf;                      \
614             p_buffers->NAME[i_select].i_depth++;                            \
615                                                                             \
616             if( !(FLAGS & BUFFERS_UNIQUE_SIZE) )                            \
617             {                                                               \
618                 /* Update Bresenham mean (very approximative) */            \
619                 p_buffers->NAME[i_select].i_average_size =                  \
620                     ( p_buf->_private.i_size                                \
621                        + p_buffers->NAME[i_select].i_average_size           \
622                        * (INPUT_BRESENHAM_NB - 1) )                         \
623                      / INPUT_BRESENHAM_NB;                                  \
624             }                                                               \
625         }                                                                   \
626         else                                                                \
627         {                                                                   \
628             p_buffers->i_allocated -= p_buf->_private.i_size;               \
629             free( p_buf );                                                  \
630         }                                                                   \
631                                                                             \
632         p_data = p_next;                                                    \
633     }                                                                       \
634 }                                                                           \
635                                                                             \
636 static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
637 {                                                                           \
638     _input_buffers_t *   p_buffers = (_input_buffers_t *)_p_buffers;        \
639                                                                             \
640     vlc_mutex_lock( &p_buffers->lock );                                     \
641     _input_DeletePacket( _p_buffers, p_data );                              \
642     vlc_mutex_unlock( &p_buffers->lock );                                   \
643 }                                                                           \
644                                                                             \
645 /* Delete a chained list of i_nb data packets. -- needed by DeletePES */    \
646 static __inline__ void _input_DeletePacketStack( void * _p_buffers,         \
647                                       data_packet_t * _p_first,             \
648                                       data_packet_t ** _pp_last,            \
649                                       unsigned int i_nb )                   \
650 {                                                                           \
651     /* Do not add code before, EXTRA_STACK makes its own declarations. */   \
652     EXTRA_STACK( FLAGS, NB_LIFO, DATA_CACHE_SIZE )                          \
653     /* No semicolon - PLEASE */                                             \
654     {                                                                       \
655         _input_DeletePacket( _p_buffers, _p_first );                        \
656     }                                                                       \
657 }
658
659 #define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE )     \
660     BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_packet_t,  \
661                           data, BUFFERS_DELETEPACKET_EXTRA,                 \
662                           BUFFERS_DELETEPACKETSTACK_EXTRA )
663
664 #define DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO,                \
665                                              DATA_CACHE_SIZE )              \
666     BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_buffer_t,  \
667                           buffers, BUFFERS_DELETEPACKET_EXTRA_SHARED,       \
668                           BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED )
669
670 /*****************************************************************************
671  * input_DeletePacketStack: optimize deleting of a stack of packets when
672  * knowing much information
673  *****************************************************************************/
674 /* AFAIK, this isn't used by anyone - it is here for completion.
675  * _input_DeletePacketStack is declared in DeletePacket because it is needed
676  * by DeletePES. */
677 #define DECLARE_BUFFERS_DELETEPACKETSTACK( FLAGS, NB_LIFO )                 \
678 static void input_DeletePacketStack( void * _p_buffers,                     \
679                                      data_packet_t * p_first,               \
680                                      data_packet_t ** pp_last,              \
681                                      unsigned int i_nb )                    \
682 {                                                                           \
683     _input_buffers_t *   p_buffers = (_input_buffers_t *)_p_buffers;        \
684                                                                             \
685     vlc_mutex_lock( &p_buffers->lock );                                     \
686     _input_DeletePacketStack( _p_buffers, p_first, pp_last, i_nb );         \
687     vlc_mutex_unlock( &p_buffers->lock );                                   \
688 }
689
690 /*****************************************************************************
691  * input_NewPES: return a pointer to a new PES packet
692  *****************************************************************************/
693 #define DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO )                            \
694 static pes_packet_t * input_NewPES( void * _p_buffers )                     \
695 {                                                                           \
696     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
697     pes_packet_t *      p_pes;                                              \
698                                                                             \
699     vlc_mutex_lock( &p_buffers->lock );                                     \
700                                                                             \
701     if( p_buffers->pes.p_stack != NULL )                                    \
702     {                                                                       \
703         p_pes = p_buffers->pes.p_stack;                                     \
704         p_buffers->pes.p_stack = p_pes->p_next;                             \
705         p_buffers->pes.i_depth--;                                           \
706     }                                                                       \
707     else                                                                    \
708     {                                                                       \
709         p_pes = malloc( sizeof( pes_packet_t ) );                           \
710         if( p_pes == NULL )                                                 \
711         {                                                                   \
712             intf_ErrMsg( "Out of memory" );                                 \
713             vlc_mutex_unlock( &p_buffers->lock );                           \
714             return( NULL );                                                 \
715         }                                                                   \
716     }                                                                       \
717                                                                             \
718     vlc_mutex_unlock( &p_buffers->lock );                                   \
719                                                                             \
720     /* Initialize data */                                                   \
721     p_pes->p_next = NULL;                                                   \
722     p_pes->b_data_alignment = p_pes->b_discontinuity =                      \
723         p_pes->i_pts = p_pes->i_dts = 0;                                    \
724     p_pes->i_pes_size = 0;                                                  \
725     p_pes->p_first = p_pes->p_last = NULL;                                  \
726     p_pes->i_nb_data = 0;                                                   \
727                                                                             \
728     return( p_pes );                                                        \
729 }
730
731 /*****************************************************************************
732  * input_DeletePES: put a pes and all data packets back into the cache
733  *****************************************************************************/
734 #define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE )         \
735 static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes )      \
736 {                                                                           \
737     _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers;          \
738                                                                             \
739     vlc_mutex_lock( &p_buffers->lock );                                     \
740                                                                             \
741     while( p_pes != NULL )                                                  \
742     {                                                                       \
743         pes_packet_t * p_next = p_pes->p_next;                              \
744                                                                             \
745         /* Delete all data packets */                                       \
746         if( p_pes->p_first != NULL )                                        \
747         {                                                                   \
748             _input_DeletePacketStack( _p_buffers, p_pes->p_first,           \
749                                       &p_pes->p_last->p_next,               \
750                                       p_pes->i_nb_data );                   \
751         }                                                                   \
752                                                                             \
753         if( p_buffers->pes.i_depth < PES_CACHE_SIZE )                       \
754         {                                                                   \
755             /* Cache not full : store the packet in it */                   \
756             p_pes->p_next = p_buffers->pes.p_stack;                         \
757             p_buffers->pes.p_stack = p_pes;                                 \
758             p_buffers->pes.i_depth++;                                       \
759         }                                                                   \
760         else                                                                \
761         {                                                                   \
762             free( p_pes );                                                  \
763         }                                                                   \
764                                                                             \
765         p_pes = p_next;                                                     \
766     }                                                                       \
767                                                                             \
768     vlc_mutex_unlock( &p_buffers->lock );                                   \
769 }
770
771 /*****************************************************************************
772  * input_BuffersToIO: return an IO vector (only with BUFFERS_UNIQUE_SIZE)
773  *****************************************************************************/
774 #define DECLARE_BUFFERS_TOIO( FLAGS, BUFFER_SIZE )                          \
775 static data_packet_t * input_BuffersToIO( void * _p_buffers,                \
776                                           struct iovec * p_iovec, int i_nb )\
777 {                                                                           \
778     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
779     data_packet_t *     p_data = NULL;                                      \
780     int                 i;                                                  \
781                                                                             \
782     vlc_mutex_lock( &p_buffers->lock );                                     \
783                                                                             \
784     for( i = i_nb - 1; i >= 0; i-- )                                        \
785     {                                                                       \
786         data_packet_t * p_next = _input_NewPacket( _p_buffers,              \
787                                           BUFFER_SIZE /* UNIQUE_SIZE */ );  \
788         if( p_next == NULL )                                                \
789         {                                                                   \
790             _input_DeletePacket( _p_buffers, p_data );                      \
791             return( NULL );                                                 \
792         }                                                                   \
793                                                                             \
794         p_iovec[i].iov_base = p_next->p_demux_start;                        \
795         p_iovec[i].iov_len = BUFFER_SIZE;                                   \
796         p_next->p_next = p_data;                                            \
797         p_data = p_next;                                                    \
798     }                                                                       \
799                                                                             \
800     vlc_mutex_unlock( &p_buffers->lock );                                   \
801                                                                             \
802     return( p_data );                                                       \
803 }
804
805 /*****************************************************************************
806  * input_ShareBuffer: return a new data_packet to the same buffer
807  *****************************************************************************/
808 #define DECLARE_BUFFERS_SHAREBUFFER( FLAGS )                                \
809 static data_packet_t * input_ShareBuffer( void * _p_buffers,                \
810                                           data_packet_t * _p_shared_data )  \
811 {                                                                           \
812     _input_buffers_t *  p_buffers = (_input_buffers_t *)_p_buffers;         \
813     _data_packet_t *    p_shared_data = (_data_packet_t *)_p_shared_data;   \
814     _data_packet_t *    p_data;                                             \
815     _data_buffer_t *    p_buf = p_shared_data->_private.p_buffer;           \
816                                                                             \
817     vlc_mutex_lock( &p_buffers->lock );                                     \
818                                                                             \
819     /* Get new data_packet_t, without a buffer through a special backdoor   \
820      * in _input_NewPacket. */                                              \
821     p_data = (_data_packet_t *)_input_NewPacket( _p_buffers, 0 );           \
822                                                                             \
823     /* Finish initialization of p_data */                                   \
824     p_data->_private.p_buffer = p_shared_data->_private.p_buffer;           \
825     p_data->p_demux_start = p_data->p_payload_start                         \
826              = (byte_t *)p_shared_data->_private.p_buffer                   \
827                  + sizeof( _data_buffer_t );                                \
828     p_data->p_payload_end = p_data->p_demux_start + p_buf->_private.i_size; \
829                                                                             \
830     /* Update refcount */                                                   \
831     p_buf->i_refcount++;                                                    \
832                                                                             \
833     vlc_mutex_unlock( &p_buffers->lock );                                   \
834                                                                             \
835     return( (data_packet_t *)p_data );                                      \
836 }
837
838
839 /*
840  * Optional MPEG demultiplexing
841  */
842
843 /*****************************************************************************
844  * Constants
845  *****************************************************************************/
846 #define TS_PACKET_SIZE      188                       /* Size of a TS packet */
847 #define PSI_SECTION_SIZE    4096            /* Maximum size of a PSI section */
848
849 #define PAT_UNINITIALIZED    (1 << 6)
850 #define PMT_UNINITIALIZED    (1 << 6)
851
852 #define PSI_IS_PAT          0x00
853 #define PSI_IS_PMT          0x01
854 #define UNKNOWN_PSI         0xff
855
856 /*****************************************************************************
857  * psi_section_t
858  *****************************************************************************
859  * Describes a PSI section. Beware, it doesn't contain pointers to the TS
860  * packets that contain it as for a PES, but the data themselves
861  *****************************************************************************/
862 typedef struct psi_section_s
863 {
864     byte_t                  buffer[PSI_SECTION_SIZE];
865
866     u8                      i_section_number;
867     u8                      i_last_section_number;
868     u8                      i_version_number;
869     u16                     i_section_length;
870     u16                     i_read_in_section;
871     
872     /* the PSI is complete */
873     boolean_t               b_is_complete;
874     
875     /* packet missed up ? */
876     boolean_t               b_trash;
877
878     /*about sections  */ 
879     boolean_t               b_section_complete;
880
881     /* where are we currently ? */
882     byte_t                * p_current;
883
884 } psi_section_t;
885
886 /*****************************************************************************
887  * es_ts_data_t: extension of es_descriptor_t
888  *****************************************************************************/
889 typedef struct es_ts_data_s
890 {
891     boolean_t               b_psi;   /* Does the stream have to be handled by
892                                       *                    the PSI decoder ? */
893
894     int                     i_psi_type;  /* There are different types of PSI */
895     
896     psi_section_t *         p_psi_section;                    /* PSI packets */
897
898     /* Markers */
899     int                     i_continuity_counter;
900 } es_ts_data_t;
901
902 /*****************************************************************************
903  * pgrm_ts_data_t: extension of pgrm_descriptor_t
904  *****************************************************************************/
905 typedef struct pgrm_ts_data_s
906 {
907     u16                     i_pcr_pid;             /* PCR ES, for TS streams */
908     int                     i_pmt_version;
909 } pgrm_ts_data_t;
910
911 /*****************************************************************************
912  * stream_ts_data_t: extension of stream_descriptor_t
913  *****************************************************************************/
914 typedef struct stream_ts_data_s
915 {
916     int i_pat_version;          /* Current version of the PAT */
917 } stream_ts_data_t;
918
919 /*****************************************************************************
920  * stream_ps_data_t: extension of stream_descriptor_t
921  *****************************************************************************/
922 typedef struct stream_ps_data_s
923 {
924     boolean_t               b_has_PSM;                 /* very rare, in fact */
925
926     u8                      i_PSM_version;
927 } stream_ps_data_t;
928
929 /* PSM version is 5 bits, so -1 is not a valid value */
930 #define EMPTY_PSM_VERSION   -1
931
932
933 /*****************************************************************************
934  * Prototypes
935  *****************************************************************************/
936 #ifndef PLUGIN
937 void input_ParsePES  ( struct input_thread_s *, struct es_descriptor_s * );
938 void input_GatherPES ( struct input_thread_s *, struct data_packet_s *,
939                        struct es_descriptor_s *, boolean_t, boolean_t );
940 es_descriptor_t * input_ParsePS( struct input_thread_s *,
941                                  struct data_packet_s * );
942 void input_DemuxPS   ( struct input_thread_s *, struct data_packet_s * );
943 void input_DemuxTS   ( struct input_thread_s *, struct data_packet_s * );
944 void input_DemuxPSI  ( struct input_thread_s *, struct data_packet_s *,
945                        struct es_descriptor_s *, boolean_t, boolean_t );
946 #else
947 #   define input_ParsePES p_symbols->input_ParsePES
948 #   define input_GatherPES p_symbols->input_GatherPES
949 #   define input_ParsePS p_symbols->input_ParsePS
950 #   define input_DemuxPS p_symbols->input_DemuxPS
951 #   define input_DemuxTS p_symbols->input_DemuxTS
952 #   define input_DemuxPSI p_symbols->input_DemuxPSI
953 #endif
954