* but exported to plug-ins
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: input_ext-plugins.h,v 1.13 2001/12/27 03:47:08 massiot Exp $
+ * $Id: input_ext-plugins.h,v 1.14 2001/12/29 03:07:51 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
#define BUFFERS_UNIQUE_SIZE 1 /* Only with NB_LIFO == 1 */
/*****************************************************************************
- * input_buffers_t: defines a LIFO per data type to keep
+ * _input_buffers_t: defines a LIFO per data type to keep
*****************************************************************************/
-#define PACKETS_LIFO( TYPE, NAME ) \
+#define PACKETS_LIFO( TYPE, NAME ) \
struct \
{ \
TYPE * p_stack; \
} NAME;
#define DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO ) \
-typedef struct input_buffers_s \
+typedef struct _input_buffers_s \
{ \
vlc_mutex_t lock; \
PACKETS_LIFO( pes_packet_t, pes ) \
- BUFFERS_LIFO( data_packet_t, data[NB_LIFO] ) \
+ BUFFERS_LIFO( _data_packet_t, data[NB_LIFO] ) \
size_t i_allocated; \
-} input_buffers_t;
+} _input_buffers_t;
#define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \
-typedef struct input_buffers_s \
+typedef struct _input_buffers_s \
{ \
vlc_mutex_t lock; \
PACKETS_LIFO( pes_packet_t, pes ) \
- PACKETS_LIFO( data_packet_t, data ) \
+ PACKETS_LIFO( _data_packet_t, data ) \
BUFFERS_LIFO( _data_buffer_t, buffers[NB_LIFO] ) \
size_t i_allocated; \
-} input_buffers_t;
+} _input_buffers_t;
+/* Data buffer, used in case the buffer can be shared between several data
+ * packets */
typedef struct _data_buffer_s
{
- int i_refcount;
- unsigned int i_size;
struct _data_buffer_s * p_next;
+
+ /* number of data packets this buffer is referenced from - when it falls
+ * down to 0, the buffer is freed */
+ int i_refcount;
+
+ struct /* for compatibility with _data_packet_t */
+ {
+ /* size of the current buffer (starting right thereafter) */
+ unsigned int i_size;
+ } _private;
} _data_buffer_t;
+/* We overload the data_packet_t type to add private members */
+typedef struct _data_packet_s
+{
+ struct _data_packet_s * p_next;
+
+ DATA_PACKET
+
+ union
+ {
+ struct _data_buffer_s * p_buffer; /* in case of shared buffers */
+ /* size of the embedded buffer (starting right thereafter) */
+ unsigned int i_size;
+ } _private;
+} _data_packet_t;
+
/*****************************************************************************
* input_BuffersInit: initialize the cache structures, return a pointer to it
#define DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ) \
static void * input_BuffersInit( void ) \
{ \
- input_buffers_t * p_buffers = malloc( sizeof( input_buffers_t ) ); \
+ _input_buffers_t * p_buffers = malloc( sizeof( _input_buffers_t ) ); \
\
if( p_buffers == NULL ) \
{ \
return( NULL ); \
} \
\
- memset( p_buffers, 0, sizeof( input_buffers_t ) ); \
+ memset( p_buffers, 0, sizeof( _input_buffers_t ) ); \
vlc_mutex_init( &p_buffers->lock ); \
\
return (void *)p_buffers; \
while( p_buf != NULL ) \
{ \
p_next = p_buf->p_next; \
- p_buffers->i_allocated -= p_buf->i_size; \
+ p_buffers->i_allocated -= p_buf->_private.i_size; \
free( p_buf ); \
p_buf = p_next; \
}
#define BUFFERS_END_LOOP( FLAGS, NB_LIFO ) \
for( i = 0; i < NB_LIFO; i++ ) \
{ \
- data_packet_t * p_next; \
- data_packet_t * p_buf = p_buffers->data[i].p_stack; \
+ _data_packet_t * p_next; \
+ _data_packet_t * p_buf = p_buffers->data[i].p_stack; \
BUFFERS_END_BUFFERS_LOOP; \
} \
#define BUFFERS_END_LOOP_SHARED( FLAGS, NB_LIFO ) \
{ \
/* Free data packets */ \
- data_packet_t * p_next; \
- data_packet_t * p_packet = p_buffers->data.p_stack; \
+ _data_packet_t * p_next; \
+ _data_packet_t * p_packet = p_buffers->data.p_stack; \
BUFFERS_END_PACKETS_LOOP; \
} \
\
#define BUFFERS_END( FLAGS, NB_LIFO, STAT_LOOP, LOOP ) \
static void input_BuffersEnd( void * _p_buffers ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
if( _p_buffers != NULL ) \
{ \
* input_NewPacket: return a pointer to a data packet of the appropriate size
*****************************************************************************/
#define BUFFERS_NEWPACKET_EXTRA_DECLARATION( FLAGS, NB_LIFO ) \
- data_packet_t ** pp_data = &p_buf;
+ _data_packet_t ** pp_data = &p_buf;
#define BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED( FLAGS, NB_LIFO ) \
- data_packet_t * p_data; \
- data_packet_t ** pp_data = &p_data;
+ _data_packet_t * p_data; \
+ _data_packet_t ** pp_data = &p_data;
#define BUFFERS_NEWPACKET_EXTRA( FLAGS, NB_LIFO )
} \
else \
{ \
- p_data = malloc( sizeof( data_packet_t ) ); \
+ p_data = malloc( sizeof( _data_packet_t ) ); \
if( p_data == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
* this. */ \
p_data->p_next = NULL; \
p_data->b_discard_payload = 0; \
- return p_data; \
+ return( (data_packet_t *)p_data ); \
}
-#define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO )
+#define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO, TYPE ) \
+ (*pp_data)->p_demux_start = (byte_t *)*pp_data + sizeof( TYPE );
-#define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO ) \
+#define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO, TYPE ) \
+ (*pp_data)->_private.p_buffer = p_buf; \
+ (*pp_data)->p_demux_start = (byte_t *)(*pp_data)->_private.p_buffer \
+ + sizeof( TYPE ); \
/* Initialize refcount */ \
p_buf->i_refcount = 1;
#define BUFFERS_NEWPACKET( FLAGS, NB_LIFO, TYPE, NAME, EXTRA_DECLARATION, \
EXTRA, END ) \
+/* This one doesn't take p_buffers->lock. */ \
static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers, \
size_t i_size ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
int i_select; \
TYPE * p_buf; \
EXTRA_DECLARATION( FLAGS, NB_LIFO ); \
\
/* Reallocate the packet if it is too small or too large */ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && \
- (p_buf->i_size < i_size || p_buf->i_size > 3 * i_size) ) \
+ (p_buf->_private.i_size < i_size \
+ || p_buf->_private.i_size > 3 * i_size) ) \
{ \
- p_buffers->i_allocated -= p_buf->i_size; \
+ p_buffers->i_allocated -= p_buf->_private.i_size; \
p_buf = realloc( p_buf, sizeof( TYPE ) + i_size ); \
if( p_buf == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
return NULL; \
} \
- p_buf->i_size = i_size; \
+ p_buf->_private.i_size = i_size; \
p_buffers->i_allocated += i_size; \
} \
} \
intf_ErrMsg( "Out of memory" ); \
return NULL; \
} \
- p_buf->i_size = i_size; \
+ p_buf->_private.i_size = i_size; \
p_buffers->i_allocated += i_size; \
} \
\
/* Initialize data */ \
+ END( FLAGS, NB_LIFO, TYPE ); \
(*pp_data)->p_next = NULL; \
(*pp_data)->b_discard_payload = 0; \
- (*pp_data)->p_buffer = (byte_t *)p_buf; \
- (*pp_data)->p_demux_start = (*pp_data)->p_buffer + sizeof( TYPE ); \
(*pp_data)->p_payload_start = (*pp_data)->p_demux_start; \
(*pp_data)->p_payload_end = (*pp_data)->p_payload_start + i_size; \
\
- END( FLAGS, NB_LIFO ); \
- \
- return( *pp_data ); \
+ return( (data_packet_t *)*pp_data ); \
} \
\
static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
data_packet_t * p_data; \
\
/* Safety check */ \
}
#define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \
- BUFFERS_NEWPACKET( FLAGS, NB_LIFO, data_packet_t, data, \
+ BUFFERS_NEWPACKET( FLAGS, NB_LIFO, _data_packet_t, data, \
BUFFERS_NEWPACKET_EXTRA_DECLARATION, BUFFERS_NEWPACKET_EXTRA, \
BUFFERS_NEWPACKET_END )
* input_DeletePacket: put a packet back into the cache
*****************************************************************************/
#define BUFFERS_DELETEPACKET_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
- data_packet_t * p_buf = p_data;
+ _data_packet_t * p_buf = p_data;
#define BUFFERS_DELETEPACKET_EXTRA_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE )\
- _data_buffer_t * p_buf = (_data_buffer_t *)p_data->p_buffer; \
+ _data_buffer_t * p_buf = (_data_buffer_t *)p_data->_private.p_buffer; \
\
/* Get rid of the data packet */ \
if( p_buffers->data.i_depth < DATA_CACHE_SIZE ) \
return; \
}
+#define BUFFERS_DELETEPACKETSTACK_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
+ _data_packet_t * p_first = (_data_packet_t *)_p_first; \
+ _data_packet_t ** pp_last = (_data_packet_t **)_pp_last; \
+ \
+ /* Small hopeless optimization */ \
+ if( (FLAGS & BUFFERS_UNIQUE_SIZE) \
+ && p_buffers->data[0].i_depth < DATA_CACHE_SIZE ) \
+ { \
+ p_buffers->data[0].i_depth += i_nb; \
+ *pp_last = p_buffers->data[0].p_stack; \
+ p_buffers->data[0].p_stack = p_first; \
+ } \
+ else /* No semicolon after this or you will die */
+
+#define BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED( FLAGS, NB_LIFO, \
+ DATA_CACHE_SIZE )
+
#define BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, TYPE, \
- NAME, EXTRA ) \
+ NAME, EXTRA, EXTRA_STACK ) \
+/* This one doesn't take p_buffers->lock. */ \
static __inline__ void _input_DeletePacket( void * _p_buffers, \
- data_packet_t * p_data ) \
+ data_packet_t * _p_data ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
+ _data_packet_t * p_data = (_data_packet_t *)_p_data; \
int i_select; \
\
while( p_data != NULL ) \
{ \
- data_packet_t * p_next = p_data->p_next; \
+ _data_packet_t * p_next = p_data->p_next; \
\
EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ); \
\
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
{ \
- if( p_buf->i_size <= \
+ if( p_buf->_private.i_size <= \
(2 * p_buffers->NAME[i_select].i_average_size \
+ p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
{ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) ) \
{ \
/* Update Bresenham mean (very approximative) */ \
- p_buffers->NAME[i_select].i_average_size = ( p_buf->i_size \
- + p_buffers->NAME[i_select].i_average_size \
+ p_buffers->NAME[i_select].i_average_size = \
+ ( p_buf->_private.i_size \
+ + p_buffers->NAME[i_select].i_average_size \
* (INPUT_BRESENHAM_NB - 1) ) \
/ INPUT_BRESENHAM_NB; \
} \
} \
else \
{ \
- p_buffers->i_allocated -= p_buf->i_size; \
+ p_buffers->i_allocated -= p_buf->_private.i_size; \
free( p_buf ); \
} \
\
\
static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
vlc_mutex_lock( &p_buffers->lock ); \
_input_DeletePacket( _p_buffers, p_data ); \
vlc_mutex_unlock( &p_buffers->lock ); \
+} \
+ \
+/* Delete a chained list of i_nb data packets. -- needed by DeletePES */ \
+static __inline__ void _input_DeletePacketStack( void * _p_buffers, \
+ data_packet_t * _p_first, \
+ data_packet_t ** _pp_last, \
+ unsigned int i_nb ) \
+{ \
+ /* Do not add code before, EXTRA_STACK makes its own declarations. */ \
+ EXTRA_STACK( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
+ /* No semicolon - PLEASE */ \
+ { \
+ _input_DeletePacket( _p_buffers, _p_first ); \
+ } \
}
#define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
- BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, data_packet_t, \
- data, BUFFERS_DELETEPACKET_EXTRA )
+ BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_packet_t, \
+ data, BUFFERS_DELETEPACKET_EXTRA, \
+ BUFFERS_DELETEPACKETSTACK_EXTRA )
#define DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, \
DATA_CACHE_SIZE ) \
BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, _data_buffer_t, \
- buffers, BUFFERS_DELETEPACKET_EXTRA_SHARED )
+ buffers, BUFFERS_DELETEPACKET_EXTRA_SHARED, \
+ BUFFERS_DELETEPACKETSTACK_EXTRA_SHARED )
+
+/*****************************************************************************
+ * input_DeletePacketStack: optimize deleting of a stack of packets when
+ * knowing much information
+ *****************************************************************************/
+/* AFAIK, this isn't used by anyone - it is here for completion.
+ * _input_DeletePacketStack is declared in DeletePacket because it is needed
+ * by DeletePES. */
+#define DECLARE_BUFFERS_DELETEPACKETSTACK( FLAGS, NB_LIFO ) \
+static void input_DeletePacketStack( void * _p_buffers, \
+ data_packet_t * p_first, \
+ data_packet_t ** pp_last, \
+ unsigned int i_nb ) \
+{ \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
+ \
+ vlc_mutex_lock( &p_buffers->lock ); \
+ _input_DeletePacketStack( _p_buffers, p_first, pp_last, i_nb ); \
+ vlc_mutex_unlock( &p_buffers->lock ); \
+}
/*****************************************************************************
* input_NewPES: return a pointer to a new PES packet
#define DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ) \
static pes_packet_t * input_NewPES( void * _p_buffers ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
pes_packet_t * p_pes; \
\
vlc_mutex_lock( &p_buffers->lock ); \
/*****************************************************************************
* input_DeletePES: put a pes and all data packets back into the cache
*****************************************************************************/
-#define BUFFERS_DELETEPES_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
- /* Small hopeless optimization */ \
- if( (FLAGS & BUFFERS_UNIQUE_SIZE) \
- && p_buffers->data[0].i_depth < DATA_CACHE_SIZE ) \
- { \
- p_buffers->data[0].i_depth += p_pes->i_nb_data; \
- p_pes->p_last->p_next = p_buffers->data[0].p_stack; \
- p_buffers->data[0].p_stack = p_pes->p_first; \
- } \
- else /* No semicolon after this or you will die */
-
-#define BUFFERS_DELETEPES_EXTRA_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE )
-
-#define BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE, PES_CACHE_SIZE, \
- EXTRA ) \
+#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE ) \
static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
{ \
pes_packet_t * p_next = p_pes->p_next; \
\
- /* Delete all data packets - no semicolon, PLEASE */ \
- EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
+ /* Delete all data packets */ \
+ if( p_pes->p_first != NULL ) \
{ \
- _input_DeletePacket( _p_buffers, p_pes->p_first ); \
+ _input_DeletePacketStack( _p_buffers, p_pes->p_first, \
+ &p_pes->p_last->p_next, \
+ p_pes->i_nb_data ); \
} \
\
if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \
vlc_mutex_unlock( &p_buffers->lock ); \
}
-#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE, \
- PES_CACHE_SIZE ) \
- BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE, PES_CACHE_SIZE, \
- BUFFERS_DELETEPES_EXTRA )
-
-#define DECLARE_BUFFERS_DELETEPES_SHARED( FLAGS, NB_LIFO, DATA_CACHE_SIZE, \
- PES_CACHE_SIZE ) \
- BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE, PES_CACHE_SIZE, \
- BUFFERS_DELETEPES_EXTRA_SHARED )
-
/*****************************************************************************
- * input_BuffersToIO: return an io vector (only with BUFFERS_UNIQUE_SIZE)
+ * input_BuffersToIO: return an IO vector (only with BUFFERS_UNIQUE_SIZE)
*****************************************************************************/
#define DECLARE_BUFFERS_TOIO( FLAGS, BUFFER_SIZE ) \
static data_packet_t * input_BuffersToIO( void * _p_buffers, \
- struct iovec * p_iovec, int i_nb ) \
+ struct iovec * p_iovec, int i_nb )\
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
data_packet_t * p_data = NULL; \
int i; \
\
BUFFER_SIZE /* UNIQUE_SIZE */ ); \
if( p_next == NULL ) \
{ \
- while( p_data != NULL ) \
- { \
- p_next = p_data->p_next; \
- _input_DeletePacket( _p_buffers, p_data ); \
- p_data = p_next; \
- } \
+ _input_DeletePacket( _p_buffers, p_data ); \
return( NULL ); \
} \
\
*****************************************************************************/
#define DECLARE_BUFFERS_SHAREBUFFER( FLAGS ) \
static data_packet_t * input_ShareBuffer( void * _p_buffers, \
- data_packet_t * p_shared_data ) \
+ data_packet_t * _p_shared_data ) \
{ \
- input_buffers_t * p_buffers = (input_buffers_t *)_p_buffers; \
- data_packet_t * p_data; \
- _data_buffer_t * p_buf = (_data_buffer_t *)p_shared_data->p_buffer; \
+ _input_buffers_t * p_buffers = (_input_buffers_t *)_p_buffers; \
+ _data_packet_t * p_shared_data = (_data_packet_t *)_p_shared_data; \
+ _data_packet_t * p_data; \
+ _data_buffer_t * p_buf = p_shared_data->_private.p_buffer; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
- /* Get new data_packet_t */ \
- p_data = _input_NewPacket( _p_buffers, 0 ); \
+ /* Get new data_packet_t, without a buffer through a special backdoor \
+ * in _input_NewPacket. */ \
+ p_data = (_data_packet_t *)_input_NewPacket( _p_buffers, 0 ); \
\
/* Finish initialization of p_data */ \
- p_data->p_buffer = p_shared_data->p_buffer; \
+ p_data->_private.p_buffer = p_shared_data->_private.p_buffer; \
p_data->p_demux_start = p_data->p_payload_start \
- = p_shared_data->p_buffer + sizeof( _data_buffer_t ); \
- p_data->p_payload_end = p_shared_data->p_buffer + p_buf->i_size; \
+ = (byte_t *)p_shared_data->_private.p_buffer \
+ + sizeof( _data_buffer_t ); \
+ p_data->p_payload_end = p_data->p_demux_start + p_buf->_private.i_size; \
\
/* Update refcount */ \
p_buf->i_refcount++; \
\
vlc_mutex_unlock( &p_buffers->lock ); \
\
- return( p_data ); \
+ return( (data_packet_t *)p_data ); \
}