Commit 605a3534 authored by Christophe Massiot's avatar Christophe Massiot

Next Generation Buffer Manager for DVD and VCD plug-ins.

parent ba2dbc41
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders * input_ext-dec.h: structures exported to the VideoLAN decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-dec.h,v 1.44 2001/12/12 13:48:09 massiot Exp $ * $Id: input_ext-dec.h,v 1.45 2001/12/19 10:00:00 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr> * Michel Kaempf <maxx@via.ecp.fr>
...@@ -44,16 +44,17 @@ typedef struct data_packet_s ...@@ -44,16 +44,17 @@ typedef struct data_packet_s
{ {
/* Nothing before this line, the code relies on that */ /* Nothing before this line, the code relies on that */
byte_t * p_buffer; /* raw data packet */ byte_t * p_buffer; /* raw data packet */
byte_t * p_buffer_end;
long l_size; /* buffer size */
/* Decoders information */ /* Decoders information */
byte_t * p_demux_start; /* start of the PS or TS packet */
byte_t * p_payload_start; byte_t * p_payload_start;
/* start of the PES payload in this packet */ /* start of the PES payload in this packet */
byte_t * p_payload_end; /* guess ? :-) */ byte_t * p_payload_end; /* guess ? :-) */
boolean_t b_discard_payload; /* is the packet messed up ? */ boolean_t b_discard_payload; /* is the packet messed up ? */
int * pi_refcount; int * pi_refcount;
unsigned int i_size; /* buffer size */
long l_size; /* buffer size */
/* Used to chain the TS packets that carry data for a same PES or PSI */ /* Used to chain the TS packets that carry data for a same PES or PSI */
struct data_packet_s * p_next; struct data_packet_s * p_next;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* but exported to plug-ins * but exported to plug-ins
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: input_ext-plugins.h,v 1.10 2001/12/12 13:48:09 massiot Exp $ * $Id: input_ext-plugins.h,v 1.11 2001/12/19 10:00:00 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -107,7 +107,7 @@ static __inline__ void input_NullPacket( input_thread_t * p_input, ...@@ -107,7 +107,7 @@ static __inline__ void input_NullPacket( input_thread_t * p_input,
return; return;
} }
memset( p_pad_data->p_buffer, 0, PADDING_PACKET_SIZE ); memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
p_pad_data->b_discard_payload = 1; p_pad_data->b_discard_payload = 1;
p_pes = p_es->p_pes; p_pes = p_es->p_pes;
...@@ -244,23 +244,23 @@ typedef struct input_buffers_s \ ...@@ -244,23 +244,23 @@ typedef struct input_buffers_s \
} input_buffers_t; } input_buffers_t;
#define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \ #define DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ) \
typedef struct data_buffer_s \
{ \
int i_refcount; \
int i_size; \
struct data_buffers_s * p_next; \
byte_t payload_start; \
} data_buffer_t; \
\
typedef struct input_buffers_s \ typedef struct input_buffers_s \
{ \ { \
vlc_mutex_t lock; \ vlc_mutex_t lock; \
PACKETS_LIFO( pes_packet_t, pes ) \ PACKETS_LIFO( pes_packet_t, pes ) \
PACKETS_LIFO( data_packet_t, data ) \ PACKETS_LIFO( data_packet_t, data ) \
BUFFERS_LIFO( data_buffers_t, buffers[NB_LIFO] ) \ BUFFERS_LIFO( data_buffer_t, buffers[NB_LIFO] ) \
size_t i_allocated; \ size_t i_allocated; \
} input_buffers_t; } input_buffers_t;
typedef struct data_buffer_s
{
int i_refcount;
unsigned int i_size;
struct data_buffer_s * p_next;
byte_t payload_start;
} data_buffer_t;
/***************************************************************************** /*****************************************************************************
* input_BuffersInit: initialize the cache structures, return a pointer to it * input_BuffersInit: initialize the cache structures, return a pointer to it
...@@ -284,14 +284,80 @@ static void * input_BuffersInit( void ) \ ...@@ -284,14 +284,80 @@ static void * input_BuffersInit( void ) \
/***************************************************************************** /*****************************************************************************
* input_BuffersEnd: free all cached structures * input_BuffersEnd: free all cached structures
*****************************************************************************/ *****************************************************************************/
#define DECLARE_BUFFERS_END( FLAGS, NB_LIFO ) \ #define BUFFERS_END_STAT_BUFFERS_LOOP( STRUCT ) \
for( i = 0; i < NB_LIFO; i++ ) \
{ \
if( FLAGS & BUFFERS_UNIQUE_SIZE ) \
{ \
intf_StatMsg( \
"input buffers stats: " #STRUCT "[%d]: %d packets", \
i, p_buffers->STRUCT[i].i_depth ); \
} \
else \
{ \
intf_StatMsg( \
"input buffers stats: " #STRUCT "[%d]: %d bytes, %d packets", \
i, p_buffers->STRUCT[i].i_average_size, \
p_buffers->STRUCT[i].i_depth ); \
} \
}
#define BUFFERS_END_STAT( FLAGS, NB_LIFO ) \
BUFFERS_END_STAT_BUFFERS_LOOP( data );
#define BUFFERS_END_STAT_SHARED( FLAGS, NB_LIFO ) \
intf_StatMsg( "input buffers stats: data: %d packets", \
p_buffers->data.i_depth ); \
BUFFERS_END_STAT_BUFFERS_LOOP( buffers );
#define BUFFERS_END_BUFFERS_LOOP \
while( p_buf != NULL ) \
{ \
p_next = p_buf->p_next; \
p_buffers->i_allocated -= p_buf->i_size; \
free( p_buf ); \
p_buf = p_next; \
}
#define BUFFERS_END_PACKETS_LOOP \
while( p_packet != NULL ) \
{ \
p_next = p_packet->p_next; \
free( p_packet ); \
p_packet = 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; \
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; \
BUFFERS_END_PACKETS_LOOP; \
} \
\
for( i = 0; i < NB_LIFO; i++ ) \
{ \
data_buffer_t * p_next; \
data_buffer_t * p_buf = p_buffers->buffers[i].p_stack; \
BUFFERS_END_BUFFERS_LOOP; \
} \
#define BUFFERS_END( FLAGS, NB_LIFO, STAT_LOOP, LOOP ) \
static void input_BuffersEnd( void * _p_buffers ) \ 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 ) \ if( _p_buffers != NULL ) \
{ \ { \
pes_packet_t * p_pes = p_buffers->pes.p_stack; \
int i; \ int i; \
\ \
if( p_main->b_stats ) \ if( p_main->b_stats ) \
...@@ -299,37 +365,16 @@ static void input_BuffersEnd( void * _p_buffers ) \ ...@@ -299,37 +365,16 @@ static void input_BuffersEnd( void * _p_buffers ) \
int i; \ int i; \
intf_StatMsg( "input buffers stats: pes: %d packets", \ intf_StatMsg( "input buffers stats: pes: %d packets", \
p_buffers->pes.i_depth ); \ p_buffers->pes.i_depth ); \
for( i = 0; i < NB_LIFO; i++ ) \ STAT_LOOP( FLAGS, NB_LIFO ); \
{ \
intf_StatMsg( \
"input buffers stats: data[%d]: %d bytes, %d packets", \
i, p_buffers->data[i].i_average_size, \
p_buffers->data[i].i_depth ); \
} \
} \ } \
\ \
/* Free PES */ \
while( p_pes != NULL ) \
{ \ { \
pes_packet_t * p_next = p_pes->p_next; \ /* Free PES */ \
free( p_pes ); \ pes_packet_t * p_next, * p_packet = p_buffers->pes.p_stack; \
p_pes = p_next; \ BUFFERS_END_PACKETS_LOOP; \
} \ } \
\ \
for( i = 0; i < NB_LIFO; i++ ) \ LOOP( FLAGS, NB_LIFO ); \
{ \
data_packet_t * p_data = p_buffers->data[i].p_stack; \
\
/* Free data packets */ \
while( p_data != NULL ) \
{ \
data_packet_t * p_next = p_data->p_next; \
p_buffers->i_allocated -= p_data->p_buffer_end \
- p_data->p_buffer; \
free( p_data ); \
p_data = p_next; \
} \
} \
\ \
if( p_buffers->i_allocated ) \ if( p_buffers->i_allocated ) \
{ \ { \
...@@ -343,83 +388,135 @@ static void input_BuffersEnd( void * _p_buffers ) \ ...@@ -343,83 +388,135 @@ static void input_BuffersEnd( void * _p_buffers ) \
} \ } \
} }
#define DECLARE_BUFFERS_END( FLAGS, NB_LIFO ) \
BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT, BUFFERS_END_LOOP );
#define DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO ) \
BUFFERS_END( FLAGS, NB_LIFO, BUFFERS_END_STAT_SHARED, \
BUFFERS_END_LOOP_SHARED );
/***************************************************************************** /*****************************************************************************
* input_NewPacket: return a pointer to a data packet of the appropriate size * input_NewPacket: return a pointer to a data packet of the appropriate size
*****************************************************************************/ *****************************************************************************/
#define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \ #define BUFFERS_NEWPACKET_EXTRA_DECLARATION( FLAGS, NB_LIFO ) \
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;
#define BUFFERS_NEWPACKET_EXTRA( FLAGS, NB_LIFO )
#define BUFFERS_NEWPACKET_EXTRA_SHARED( FLAGS, NB_LIFO ) \
/* Find a data packet */ \
if( p_buffers->data.p_stack != NULL ) \
{ \
p_data = p_buffers->data.p_stack; \
p_buffers->data.p_stack = p_data->p_next; \
p_buffers->data.i_depth--; \
} \
else \
{ \
p_data = malloc( sizeof( data_packet_t ) ); \
if( p_data == NULL ) \
{ \
intf_ErrMsg( "Out of memory" ); \
vlc_mutex_unlock( &p_buffers->lock ); \
return( NULL ); \
} \
} \
\
if( i_size == 0 ) \
{ \
/* Warning : in that case, the data packet is left partly \
* uninitialized ; theorically only input_ShareBuffer may call \
* this. */ \
p_data->p_next = NULL; \
p_data->b_discard_payload = 0; \
return p_data; \
}
#define BUFFERS_NEWPACKET_END( FLAGS, NB_LIFO )
#define BUFFERS_NEWPACKET_END_SHARED( FLAGS, NB_LIFO ) \
/* Initialize refcount */ \
p_buf->i_refcount = 1;
#define BUFFERS_NEWPACKET( FLAGS, NB_LIFO, TYPE, NAME, EXTRA_DECLARATION, \
EXTRA, END ) \
static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers, \ static __inline__ data_packet_t * _input_NewPacket( void * _p_buffers, \
size_t i_size ) \ 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; \ int i_select; \
data_packet_t * p_data; \ TYPE * p_buf; \
EXTRA_DECLARATION( FLAGS, NB_LIFO ); \
\ \
/* Safety check */ \ /* Safety check */ \
if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION ) \ if( p_buffers->i_allocated > INPUT_MAX_ALLOCATION ) \
{ \ { \
vlc_mutex_unlock( &p_buffers->lock ); \
intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)", \ intf_ErrMsg( "INPUT_MAX_ALLOCATION reached (%d)", \
p_buffers->i_allocated ); \ p_buffers->i_allocated ); \
return NULL; \ return NULL; \
} \ } \
\ \
EXTRA( FLAGS, NB_LIFO ); \
\
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \ for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
{ \ { \
if( i_size <= (2 * p_buffers->data[i_select].i_average_size \ if( i_size <= (2 * p_buffers->NAME[i_select].i_average_size \
+ p_buffers->data[i_select + 1].i_average_size) / 3 ) \ + p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
{ \ { \
break; \ break; \
} \ } \
} \ } \
\ \
if( p_buffers->data[i_select].p_stack != NULL ) \ if( p_buffers->NAME[i_select].p_stack != NULL ) \
{ \ { \
/* Take the packet from the cache */ \ /* Take the packet from the cache */ \
p_data = p_buffers->data[i_select].p_stack; \ p_buf = p_buffers->NAME[i_select].p_stack; \
p_buffers->data[i_select].p_stack = p_data->p_next; \ p_buffers->NAME[i_select].p_stack = p_buf->p_next; \
p_buffers->data[i_select].i_depth--; \ p_buffers->NAME[i_select].i_depth--; \
\ \
/* Reallocate the packet if it is too small or too large */ \ /* Reallocate the packet if it is too small or too large */ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && \ if( !(FLAGS & BUFFERS_UNIQUE_SIZE) && \
(p_data->p_buffer_end - p_data->p_buffer < i_size || \ (p_buf->i_size < i_size || p_buf->i_size > 3 * i_size) ) \
p_data->p_buffer_end - p_data->p_buffer > 3 * i_size) ) \
{ \ { \
p_buffers->i_allocated -= p_data->p_buffer_end \ p_buffers->i_allocated -= p_buf->i_size; \
- p_data->p_buffer; \ p_buf = realloc( p_buf, sizeof( TYPE ) + i_size ); \
p_data = realloc( p_data, sizeof( data_packet_t ) + i_size ); \ if( p_buf == NULL ) \
if( p_data == NULL ) \
{ \ { \
vlc_mutex_unlock( &p_buffers->lock ); \
intf_ErrMsg( "Out of memory" ); \ intf_ErrMsg( "Out of memory" ); \
return NULL; \ return NULL; \
} \ } \
p_data->p_buffer = (byte_t *)p_data + sizeof( data_packet_t ); \ p_buf->i_size = i_size; \
p_data->p_buffer_end = p_data->p_buffer + i_size; \
p_buffers->i_allocated += i_size; \ p_buffers->i_allocated += i_size; \
} \ } \
} \ } \
else \ else \
{ \ { \
/* Allocate a new packet */ \ /* Allocate a new packet */ \
p_data = malloc( sizeof( data_packet_t ) + i_size ); \ p_buf = malloc( sizeof( TYPE ) + i_size ); \
if( p_data == NULL ) \ if( p_buf == NULL ) \
{ \ { \
vlc_mutex_unlock( &p_buffers->lock ); \
intf_ErrMsg( "Out of memory" ); \ intf_ErrMsg( "Out of memory" ); \
return NULL; \ return NULL; \
} \ } \
p_data->p_buffer = (byte_t *)p_data + sizeof( data_packet_t ); \ p_buf->i_size = i_size; \
p_data->p_buffer_end = p_data->p_buffer + i_size; \
p_buffers->i_allocated += i_size; \ p_buffers->i_allocated += i_size; \
} \ } \
\ \
/* Initialize data */ \ /* Initialize data */ \
p_data->p_next = NULL; \ (*pp_data)->p_next = NULL; \
p_data->b_discard_payload = 0; \ (*pp_data)->b_discard_payload = 0; \
p_data->p_payload_start = p_data->p_buffer; \ (*pp_data)->p_buffer = (byte_t *)p_buf; \
p_data->p_payload_end = p_data->p_buffer + i_size; \ (*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; \
\ \
return( p_data ); \ END( FLAGS, NB_LIFO ); \
\
return( *pp_data ); \
} \ } \
\ \
static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
...@@ -440,46 +537,84 @@ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \ ...@@ -440,46 +537,84 @@ static data_packet_t * input_NewPacket( void * _p_buffers, size_t i_size ) \
return( p_data ); \ return( p_data ); \
} }
#define DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ) \
BUFFERS_NEWPACKET( FLAGS, NB_LIFO, data_packet_t, data, \
BUFFERS_NEWPACKET_EXTRA_DECLARATION, BUFFERS_NEWPACKET_EXTRA, \
BUFFERS_NEWPACKET_END )
#define DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO ) \
BUFFERS_NEWPACKET( FLAGS, NB_LIFO, data_buffer_t, buffers, \
BUFFERS_NEWPACKET_EXTRA_DECLARATION_SHARED, \
BUFFERS_NEWPACKET_EXTRA_SHARED, BUFFERS_NEWPACKET_END_SHARED )
/***************************************************************************** /*****************************************************************************
* input_DeletePacket: put a packet back into the cache * input_DeletePacket: put a packet back into the cache
*****************************************************************************/ *****************************************************************************/
#define DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \ #define BUFFERS_DELETEPACKET_EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ) \
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; \
\
/* Get rid of the data packet */ \
if( p_buffers->data.i_depth < DATA_CACHE_SIZE ) \
{ \
/* Cache not full : store the packet in it */ \
p_data->p_next = p_buffers->data.p_stack; \
p_buffers->data.p_stack = p_data; \
p_buffers->data.i_depth++; \
} \
else \
{ \
free( p_data ); \
} \
\
/* Decrement refcount */ \
p_buf->i_refcount--; \
if( p_buf->i_refcount > 0 ) \
{ \
return; \
}
#define BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, DATA_CACHE_SIZE, TYPE, \
NAME, EXTRA ) \
static __inline__ void _input_DeletePacket( void * _p_buffers, \ 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; \
int i_select, i_size; \ int i_select; \
\
EXTRA( FLAGS, NB_LIFO, DATA_CACHE_SIZE ); \
\ \
i_size = p_data->p_buffer_end - p_data->p_buffer; \
for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \ for( i_select = 0; i_select < NB_LIFO - 1; i_select++ ) \
{ \ { \
if( i_size <= (2 * p_buffers->data[i_select].i_average_size \ if( p_buf->i_size <= (2 * p_buffers->NAME[i_select].i_average_size \
+ p_buffers->data[i_select + 1].i_average_size) / 3 ) \ + p_buffers->NAME[i_select + 1].i_average_size) / 3 ) \
{ \ { \
break; \ break; \
} \ } \
} \ } \
\ \
if( p_buffers->data[i_select].i_depth < DATA_CACHE_SIZE ) \ if( p_buffers->NAME[i_select].i_depth < DATA_CACHE_SIZE ) \
{ \ { \
/* Cache not full : store the packet in it */ \ /* Cache not full : store the packet in it */ \
p_data->p_next = p_buffers->data[i_select].p_stack; \ p_buf->p_next = p_buffers->NAME[i_select].p_stack; \
p_buffers->data[i_select].p_stack = p_data; \ p_buffers->NAME[i_select].p_stack = p_buf; \
p_buffers->data[i_select].i_depth++; \ p_buffers->NAME[i_select].i_depth++; \
\ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) ) \ if( !(FLAGS & BUFFERS_UNIQUE_SIZE) ) \
{ \ { \
/* Update Bresenham mean (very approximative) */ \ /* Update Bresenham mean (very approximative) */ \
p_buffers->data[i_select].i_average_size = ( i_size \ p_buffers->NAME[i_select].i_average_size = ( p_buf->i_size \
+ p_buffers->data[i_select].i_average_size \ + p_buffers->NAME[i_select].i_average_size \
* (INPUT_BRESENHAM_NB - 1) ) \ * (INPUT_BRESENHAM_NB - 1) ) \
/ INPUT_BRESENHAM_NB; \ / INPUT_BRESENHAM_NB; \
} \ } \
} \ } \
else \ else \
{ \ { \
p_buffers->i_allocated -= p_data->p_buffer_end - p_data->p_buffer; \ p_buffers->i_allocated -= p_buf->i_size; \
free( p_data ); \ free( p_buf ); \
} \ } \
} \ } \
\ \
...@@ -492,6 +627,15 @@ static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \ ...@@ -492,6 +627,15 @@ static void input_DeletePacket( void * _p_buffers, data_packet_t * p_data ) \
vlc_mutex_unlock( &p_buffers->lock ); \ vlc_mutex_unlock( &p_buffers->lock ); \
} }
#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 )
#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 )
/***************************************************************************** /*****************************************************************************
* input_NewPES: return a pointer to a new PES packet * input_NewPES: return a pointer to a new PES packet
*****************************************************************************/ *****************************************************************************/
...@@ -536,18 +680,13 @@ static pes_packet_t * input_NewPES( void * _p_buffers ) \ ...@@ -536,18 +680,13 @@ static pes_packet_t * input_NewPES( void * _p_buffers ) \
/***************************************************************************** /*****************************************************************************
* input_DeletePES: put a pes and all data packets back into the cache * input_DeletePES: put a pes and all data packets back into the cache
*****************************************************************************/ *****************************************************************************/
#define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, DATA_CACHE_SIZE, \ #define DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, PES_CACHE_SIZE ) \
PES_CACHE_SIZE ) \
static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \ 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 ); \ vlc_mutex_lock( &p_buffers->lock ); \
\ \
if( !(FLAGS & BUFFERS_UNIQUE_SIZE) \
|| p_buffers->data[0].i_depth > DATA_CACHE_SIZE ) \
/* This is a little inaccurate but who cares if we have too many \
* packets in the cache ? */ \
{ \ { \
data_packet_t * p_data = p_pes->p_first; \ data_packet_t * p_data = p_pes->p_first; \
while( p_data != NULL ) \ while( p_data != NULL ) \
...@@ -556,13 +695,6 @@ static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \ ...@@ -556,13 +695,6 @@ static void input_DeletePES( void * _p_buffers, pes_packet_t * p_pes ) \
_input_DeletePacket( _p_buffers, p_data ); \ _input_DeletePacket( _p_buffers, p_data ); \
p_data = p_next; \ p_data = p_next; \
} \ } \
} \
else \
{ \
/* NB_LIFO == 1 and we can keep all data packets */ \
p_pes->p_last->p_next = p_buffers->data[0].p_stack; \
p_buffers->data[0].p_stack = p_pes->p_first; \
p_buffers->data[0].i_depth += p_pes->i_nb_data; \
} \ } \
\ \
if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \ if( p_buffers->pes.i_depth < PES_CACHE_SIZE ) \
...@@ -608,13 +740,43 @@ static data_packet_t * input_BuffersToIO( void * _p_buffers, \ ...@@ -608,13 +740,43 @@ static data_packet_t * input_BuffersToIO( void * _p_buffers, \
return( NULL ); \ return( NULL ); \
} \ } \
\ \
p_iovec[i].iov_base = p_next->p_payload_start; \ p_iovec[i].iov_base = p_next->p_demux_start; \
p_iovec[i].iov_len = BUFFER_SIZE; \ p_iovec[i].iov_len = BUFFER_SIZE; \
p_next->p_next = p_data; \ p_next->p_next = p_data; \
p_data = p_next; \ p_data = p_next; \
} \ } \
\ \
vlc_mutex_unlock( &p_buffers->lock ); \ vlc_mutex_unlock( &p_buffers->lock ); \
\
return( p_data ); \
}
/*****************************************************************************
* input_ShareBuffer: return a new data_packet to the same buffer
*****************************************************************************/
#define DECLARE_BUFFERS_SHAREBUFFER( FLAGS ) \
static data_packet_t * input_ShareBuffer( void * _p_buffers, \
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; \
\
vlc_mutex_lock( &p_buffers->lock ); \
\
/* Get new data_packet_t */ \
p_data = _input_NewPacket( _p_buffers, 0 ); \
\
/* Finish initialization of p_data */ \
p_data->p_buffer = p_shared_data->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; \
\
/* Update refcount */ \
p_buf->i_refcount++; \
\
vlc_mutex_unlock( &p_buffers->lock ); \
\ \
return( p_data ); \ return( p_data ); \
} }
......
...@@ -4,13 +4,12 @@ ...@@ -4,13 +4,12 @@
* This plugins should handle all the known specificities of the DVD format, * This plugins should handle all the known specificities of the DVD format,
* especially the 2048 bytes logical block size. * especially the 2048 bytes logical block size.
* It depends on: * It depends on:
* -input_netlist used to read packets
* -libdvdcss for access and unscrambling * -libdvdcss for access and unscrambling
* -dvd_ifo for ifo parsing and analyse * -dvd_ifo for ifo parsing and analyse
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.106 2001/12/10 04:53:10 sam Exp $ * $Id: input_dvd.c,v 1.107 2001/12/19 10:00:00 massiot Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -95,9 +94,6 @@ ...@@ -95,9 +94,6 @@
#define DVD_BLOCK_READ_ONCE 64 #define DVD_BLOCK_READ_ONCE 64
#define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE) #define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE)
/* Size of netlist */
#define DVD_NETLIST_SIZE 256
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -119,6 +115,21 @@ static int DVDFindCell( thread_dvd_data_t * ); ...@@ -119,6 +115,21 @@ static int DVDFindCell( thread_dvd_data_t * );
static int DVDFindSector( thread_dvd_data_t * ); static int DVDFindSector( thread_dvd_data_t * );
static int DVDChapterSelect( thread_dvd_data_t *, int ); static int DVDChapterSelect( thread_dvd_data_t *, int );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, DVD_LB_SIZE );
DECLARE_BUFFERS_SHAREBUFFER( FLAGS );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much. * we don't pollute the namespace too much.
...@@ -136,10 +147,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -136,10 +147,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_area = DVDSetArea; input.pf_set_area = DVDSetArea;
input.pf_set_program = DVDSetProgram; input.pf_set_program = DVDSetProgram;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DVDRewind; input.pf_rewind = DVDRewind;
input.pf_seek = DVDSeek; input.pf_seek = DVDSeek;
#undef input #undef input
...@@ -194,7 +205,12 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -194,7 +205,12 @@ static void DVDInit( input_thread_t * p_input )
} }
p_input->p_plugin_data = (void *)p_dvd; p_input->p_plugin_data = (void *)p_dvd;
p_input->p_method_data = NULL;
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
p_input->b_error = 1;
return;
}
p_dvd->dvdhandle = (dvdcss_handle) p_input->p_handle; p_dvd->dvdhandle = (dvdcss_handle) p_input->p_handle;
...@@ -211,11 +227,6 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -211,11 +227,6 @@ static void DVDInit( input_thread_t * p_input )
/* this value mustn't be modifed */ /* this value mustn't be modifed */
p_input->i_read_once = DVD_DATA_READ_ONCE; p_input->i_read_once = DVD_DATA_READ_ONCE;
/* Reading structures initialisation */
input_NetlistInit( p_input, DVD_NETLIST_SIZE, 2 * DVD_NETLIST_SIZE,
DVD_NETLIST_SIZE, DVD_LB_SIZE, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo allocation & initialisation */ /* Ifo allocation & initialisation */
if( IfoCreate( p_dvd ) < 0 ) if( IfoCreate( p_dvd ) < 0 )
{ {
...@@ -385,7 +396,7 @@ static void DVDEnd( input_thread_t * p_input ) ...@@ -385,7 +396,7 @@ static void DVDEnd( input_thread_t * p_input )
free( p_dvd ); free( p_dvd );
input_NetlistEnd( p_input ); input_BuffersEnd( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
...@@ -829,9 +840,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -829,9 +840,7 @@ static int DVDRead( input_thread_t * p_input,
data_packet_t ** pp_packets ) data_packet_t ** pp_packets )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
netlist_t * p_netlist; struct iovec p_vec[DVD_DATA_READ_ONCE];
struct iovec * p_vec;
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
u8 * pi_cur; u8 * pi_cur;
int i_block_once; int i_block_once;
int i_packet_size; int i_packet_size;
...@@ -843,9 +852,9 @@ static int DVDRead( input_thread_t * p_input, ...@@ -843,9 +852,9 @@ static int DVDRead( input_thread_t * p_input,
boolean_t b_eof; boolean_t b_eof;
boolean_t b_eot; boolean_t b_eot;
boolean_t b_eoc; boolean_t b_eoc;
data_packet_t * p_data;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (netlist_t *)p_input->p_method_data;
b_eoc = 0; b_eoc = 0;
i_sector = p_dvd->i_title_start + p_dvd->i_sector; i_sector = p_dvd->i_title_start + p_dvd->i_sector;
...@@ -909,23 +918,20 @@ static int DVDRead( input_thread_t * p_input, ...@@ -909,23 +918,20 @@ static int DVDRead( input_thread_t * p_input,
/* /*
intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter ); intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
*/ */
p_netlist->i_read_once = i_block_once;
/* Get an iovec pointer */ /* Get iovecs */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) p_data = input_BuffersToIO( p_input->p_method_data, p_vec,
DVD_DATA_READ_ONCE );
if ( p_data == NULL )
{ {
intf_ErrMsg( "dvd error: can't get iovec" ); return( -1 );
return -1;
} }
/* Reads from DVD */ /* Reads from DVD */
i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec, i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec,
i_block_once, DVDCSS_READ_DECRYPT ); i_block_once, DVDCSS_READ_DECRYPT );
/* Update netlist indexes: we don't do it in DVDGetiovec since we
* need know the real number of blocks read */
input_NetlistMviovec( p_netlist, i_read_blocks, pp_data );
/* Update global position */ /* Update global position */
p_dvd->i_sector += i_read_blocks; p_dvd->i_sector += i_read_blocks;
...@@ -934,9 +940,10 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o ...@@ -934,9 +940,10 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o
/* Read headers to compute payload length */ /* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ ) for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ )
{ {
data_packet_t * p_current = p_data;
i_pos = 0; i_pos = 0;
while( i_pos < p_netlist->i_buffer_size ) while( i_pos < DVD_LB_SIZE )
{ {
pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos;
...@@ -945,21 +952,26 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o ...@@ -945,21 +952,26 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o
{ {
/* That's the case for all packets, except pack header. */ /* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 ); i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = input_NetlistNewPtr( p_netlist );
(*pp_data[i_iovec]->pi_refcount)++;
pp_packets[i_packet]->pi_refcount =
pp_data[i_iovec]->pi_refcount;
pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
} }
else else
{ {
/* MPEG-2 Pack header. */ /* MPEG-2 Pack header. */
i_packet_size = 8; i_packet_size = 8;
pp_packets[i_packet] = pp_data[i_iovec]; }
if( i_pos != 0 )
{
pp_packets[i_packet] = input_ShareBuffer(
p_input->p_method_data, p_current );
}
else
{
pp_packets[i_packet] = p_data;
p_data = p_data->p_next;
} }
pp_packets[i_packet]->p_payload_start = pp_packets[i_packet]->p_payload_start =
pp_packets[i_packet]->p_buffer + i_pos; pp_packets[i_packet]->p_demux_start =
pp_packets[i_packet]->p_demux_start + i_pos;
pp_packets[i_packet]->p_payload_end = pp_packets[i_packet]->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6; pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
...@@ -971,6 +983,13 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o ...@@ -971,6 +983,13 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o
pp_packets[i_packet] = NULL; pp_packets[i_packet] = NULL;
while( p_data != NULL )
{
data_packet_t * p_next = p_data->p_next;
p_input->pf_delete_packet( p_input->p_method_data, p_data );
p_data = p_next;
}
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell = p_input->stream.p_selected_area->i_tell =
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* It depends on: libdvdread for ifo files and block reading. * It depends on: libdvdread for ifo files and block reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: input_dvdread.c,v 1.3 2001/12/07 18:33:07 sam Exp $ * $Id: input_dvdread.c,v 1.4 2001/12/19 10:00:00 massiot Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -87,9 +87,6 @@ ...@@ -87,9 +87,6 @@
#define DVD_BLOCK_READ_ONCE 64 #define DVD_BLOCK_READ_ONCE 64
#define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE) #define DVD_DATA_READ_ONCE (4 * DVD_BLOCK_READ_ONCE)
/* Size of netlist */
#define DVD_NETLIST_SIZE 512
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -108,6 +105,21 @@ static int DvdReadRewind ( struct input_thread_s * ); ...@@ -108,6 +105,21 @@ static int DvdReadRewind ( struct input_thread_s * );
static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data ); static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data );
static void DvdReadFindCell ( thread_dvd_data_t * p_dvd ); static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_UNIQUE_SIZE
#define NB_LIFO 1
DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, DVD_LB_SIZE );
DECLARE_BUFFERS_SHAREBUFFER( FLAGS );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much. * we don't pollute the namespace too much.
...@@ -124,10 +136,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -124,10 +136,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_read = DvdReadRead; input.pf_read = DvdReadRead;
input.pf_set_area = DvdReadSetArea; input.pf_set_area = DvdReadSetArea;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = input_NetlistNewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = input_NetlistNewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = input_NetlistDeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = input_NetlistDeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = DvdReadRewind; input.pf_rewind = DvdReadRewind;
input.pf_seek = DvdReadSeek; input.pf_seek = DvdReadSeek;
#undef input #undef input
...@@ -188,7 +200,12 @@ static void DvdReadInit( input_thread_t * p_input ) ...@@ -188,7 +200,12 @@ static void DvdReadInit( input_thread_t * p_input )
p_dvd->p_vts_file = NULL; p_dvd->p_vts_file = NULL;
p_input->p_plugin_data = (void *)p_dvd; p_input->p_plugin_data = (void *)p_dvd;
p_input->p_method_data = NULL;
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
p_input->b_error = 1;
return;
}
/* We read DVD_BLOCK_READ_ONCE in each loop, so the input will receive /* We read DVD_BLOCK_READ_ONCE in each loop, so the input will receive
* DVD_DATA_READ_ONCE at most */ * DVD_DATA_READ_ONCE at most */
...@@ -196,11 +213,6 @@ static void DvdReadInit( input_thread_t * p_input ) ...@@ -196,11 +213,6 @@ static void DvdReadInit( input_thread_t * p_input )
/* this value mustn't be modifed */ /* this value mustn't be modifed */
p_input->i_read_once = DVD_DATA_READ_ONCE; p_input->i_read_once = DVD_DATA_READ_ONCE;
/* Reading structures initialisation */
input_NetlistInit( p_input, DVD_NETLIST_SIZE, 2 * DVD_NETLIST_SIZE,
DVD_NETLIST_SIZE, DVD_VIDEO_LB_LEN, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvdread info: netlist initialized" );
/* Ifo allocation & initialisation */ /* Ifo allocation & initialisation */
if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) ) if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
{ {
...@@ -349,9 +361,7 @@ static void DvdReadEnd( input_thread_t * p_input ) ...@@ -349,9 +361,7 @@ static void DvdReadEnd( input_thread_t * p_input )
ifoClose( p_dvd->p_vts_file ); ifoClose( p_dvd->p_vts_file );
ifoClose( p_dvd->p_vmg_file ); ifoClose( p_dvd->p_vmg_file );
/* Close netlist */ input_BuffersEnd( p_input->p_method_data );
input_NetlistEnd( p_input );
p_input->p_method_data = NULL;
} }
#define p_pgc p_dvd->p_cur_pgc #define p_pgc p_dvd->p_cur_pgc
...@@ -775,10 +785,8 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -775,10 +785,8 @@ static int DvdReadRead( input_thread_t * p_input,
data_packet_t ** pp_packets ) data_packet_t ** pp_packets )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
netlist_t * p_netlist;
u8 p_data[DVD_VIDEO_LB_LEN]; u8 p_data[DVD_VIDEO_LB_LEN];
struct iovec * p_vec; struct iovec p_vec[DVD_DATA_READ_ONCE];
struct data_packet_s * pp_data[DVD_DATA_READ_ONCE];
u8 * pi_cur; u8 * pi_cur;
int i_blocks; int i_blocks;
int i_read; int i_read;
...@@ -786,9 +794,9 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -786,9 +794,9 @@ static int DvdReadRead( input_thread_t * p_input,
int i_packet_size; int i_packet_size;
int i_packet; int i_packet;
int i_pos; int i_pos;
data_packet_t * p_data;
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (netlist_t *)p_input->p_method_data;
/* /*
* Playback by cell in this pgc, starting at the cell for our chapter. * Playback by cell in this pgc, starting at the cell for our chapter.
...@@ -838,13 +846,14 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -838,13 +846,14 @@ static int DvdReadRead( input_thread_t * p_input,
i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE
? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len; ? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len;
p_dvd->i_pack_len -= i_blocks; p_dvd->i_pack_len -= i_blocks;
p_netlist->i_read_once = i_blocks;
/* Get an iovec pointer */ /* Get iovecs */
if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) p_data = input_BuffersToIO( p_input->p_method_data, p_vec,
DVD_DATA_READ_ONCE );
if ( p_data == NULL )
{ {
intf_ErrMsg( "dvdread error: can't get iovec" ); return( -1 );
return -1;
} }
/* Reads from DVD */ /* Reads from DVD */
...@@ -861,18 +870,15 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -861,18 +870,15 @@ static int DvdReadRead( input_thread_t * p_input,
/* /*
intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block ); intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );
*/ */
/* Update netlist indexes: we don't do it in DVDGetiovec since we
* need know the real number of blocks read */
input_NetlistMviovec( p_netlist, i_read, pp_data );
i_packet = 0; i_packet = 0;
/* Read headers to compute payload length */ /* Read headers to compute payload length */
for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ ) for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ )
{ {
data_packet_t * p_current = p_data;
i_pos = 0; i_pos = 0;
while( i_pos < p_netlist->i_buffer_size ) while( i_pos < DVD_LB_SIZE )
{ {
pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos;
...@@ -881,22 +887,27 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -881,22 +887,27 @@ static int DvdReadRead( input_thread_t * p_input,
{ {
/* That's the case for all packets, except pack header. */ /* That's the case for all packets, except pack header. */
i_packet_size = U16_AT( pi_cur + 4 ); i_packet_size = U16_AT( pi_cur + 4 );
pp_packets[i_packet] = input_NetlistNewPtr( p_netlist );
(*pp_data[i_iovec]->pi_refcount)++;
pp_packets[i_packet]->pi_refcount =
pp_data[i_iovec]->pi_refcount;
pp_packets[i_packet]->p_buffer = pp_data[i_iovec]->p_buffer;
} }
else else
{ {
/* MPEG-2 Pack header. */ /* MPEG-2 Pack header. */
i_packet_size = 8; i_packet_size = 8;
pp_packets[i_packet] = pp_data[i_iovec]; }
if( i_pos != 0 )
{
pp_packets[i_packet] = input_ShareBuffer(
p_input->p_method_data, p_current );
}
else
{
pp_packets[i_packet] = p_data;
p_data = p_data->p_next;
} }
pp_packets[i_packet]->p_payload_start = pp_packets[i_packet]->p_payload_start =
pp_packets[i_packet]->p_buffer + i_pos; pp_packets[i_packet]->p_demux_start =
pp_packets[i_packet]->p_demux_start + i_pos;
pp_packets[i_packet]->p_payload_end = pp_packets[i_packet]->p_payload_end =
pp_packets[i_packet]->p_payload_start + i_packet_size + 6; pp_packets[i_packet]->p_payload_start + i_packet_size + 6;
...@@ -911,6 +922,13 @@ static int DvdReadRead( input_thread_t * p_input, ...@@ -911,6 +922,13 @@ static int DvdReadRead( input_thread_t * p_input,
pp_packets[i_packet] = NULL; pp_packets[i_packet] = NULL;
while( p_data != NULL )
{
data_packet_t * p_next = p_data->p_next;
p_input->pf_delete_packet( p_input->p_method_data, p_data );
p_data = p_next;
}
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.p_selected_area->i_tell = p_input->stream.p_selected_area->i_tell =
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_es.c: Elementary Stream demux and packet management * input_es.c: Elementary Stream demux and packet management
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: input_es.c,v 1.5 2001/12/13 17:58:16 jobi Exp $ * $Id: input_es.c,v 1.6 2001/12/19 10:00:00 massiot Exp $
* *
* Author: Christophe Massiot <massiot@via.ecp.fr> * Author: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -99,7 +99,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO ); ...@@ -99,7 +99,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 ); DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150, 150 ); DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, ES_PACKET_SIZE ); DECLARE_BUFFERS_TOIO( FLAGS, ES_PACKET_SIZE );
/***************************************************************************** /*****************************************************************************
...@@ -204,7 +204,7 @@ static int ESRead( input_thread_t * p_input, ...@@ -204,7 +204,7 @@ static int ESRead( input_thread_t * p_input,
if ( p_data == NULL ) if ( p_data == NULL )
{ {
return( -1 ); /* empty netlist */ return( -1 );
} }
memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) ); memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) );
...@@ -216,7 +216,7 @@ static int ESRead( input_thread_t * p_input, ...@@ -216,7 +216,7 @@ static int ESRead( input_thread_t * p_input,
return( -1 ); return( -1 );
} }
for( i_loop=0; i_loop * ES_PACKET_SIZE < i_read; i_loop++ ) for( i_loop = 0; i_loop * ES_PACKET_SIZE < i_read; i_loop++ )
{ {
pp_packets[i_loop] = p_data; pp_packets[i_loop] = p_data;
p_data = p_data->p_next; p_data = p_data->p_next;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ps.c: PS demux and packet management * input_ps.c: PS demux and packet management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_ps.c,v 1.5 2001/12/19 03:50:22 sam Exp $ * $Id: input_ps.c,v 1.6 2001/12/19 10:00:00 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr> * Cyril Deguet <asmax@via.ecp.fr>
...@@ -103,7 +103,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO ); ...@@ -103,7 +103,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 ); DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150, 150 ); DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
/***************************************************************************** /*****************************************************************************
...@@ -482,11 +482,11 @@ static int PSRead( input_thread_t * p_input, ...@@ -482,11 +482,11 @@ static int PSRead( input_thread_t * p_input,
if( U32_AT(p_header) != 0x1B9 ) if( U32_AT(p_header) != 0x1B9 )
{ {
/* Copy the header we already read. */ /* Copy the header we already read. */
memcpy( p_data->p_buffer, p_header, 6 ); memcpy( p_data->p_demux_start, p_header, 6 );
/* Read the remaining of the packet. */ /* Read the remaining of the packet. */
if( i_packet_size && (i_error = if( i_packet_size && (i_error =
SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) ) SafeRead( p_input, p_data->p_demux_start + 6, i_packet_size )) )
{ {
return( i_error ); return( i_error );
} }
...@@ -494,12 +494,12 @@ static int PSRead( input_thread_t * p_input, ...@@ -494,12 +494,12 @@ static int PSRead( input_thread_t * p_input,
/* In MPEG-2 pack headers we still have to read stuffing bytes. */ /* In MPEG-2 pack headers we still have to read stuffing bytes. */
if( U32_AT(p_header) == 0x1BA ) if( U32_AT(p_header) == 0x1BA )
{ {
if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 ) if( i_packet_size == 8 && (p_data->p_demux_start[13] & 0x7) != 0 )
{ {
/* MPEG-2 stuffing bytes */ /* MPEG-2 stuffing bytes */
byte_t p_garbage[8]; byte_t p_garbage[8];
if( (i_error = SafeRead( p_input, p_garbage, if( (i_error = SafeRead( p_input, p_garbage,
p_data->p_buffer[13] & 0x7)) ) p_data->p_demux_start[13] & 0x7)) )
{ {
return( i_error ); return( i_error );
} }
...@@ -509,7 +509,7 @@ static int PSRead( input_thread_t * p_input, ...@@ -509,7 +509,7 @@ static int PSRead( input_thread_t * p_input,
else else
{ {
/* Copy the small header. */ /* Copy the small header. */
memcpy( p_data->p_buffer, p_header, 4 ); memcpy( p_data->p_demux_start, p_header, 4 );
} }
/* Give the packet to the other input stages. */ /* Give the packet to the other input stages. */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ts.c: TS demux and netlist management * input_ts.c: TS demux and netlist management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_ts.c,v 1.4 2001/12/12 17:41:15 massiot Exp $ * $Id: input_ts.c,v 1.5 2001/12/19 10:00:00 massiot Exp $
* *
* Authors: Henri Fallon <henri@videolan.org> * Authors: Henri Fallon <henri@videolan.org>
* *
...@@ -102,7 +102,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO ); ...@@ -102,7 +102,7 @@ DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 1000 ); DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 1000 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ); DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000, 150 ); DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_TOIO( FLAGS, TS_PACKET_SIZE ); DECLARE_BUFFERS_TOIO( FLAGS, TS_PACKET_SIZE );
/***************************************************************************** /*****************************************************************************
...@@ -326,10 +326,10 @@ static int TSRead( input_thread_t * p_input, ...@@ -326,10 +326,10 @@ static int TSRead( input_thread_t * p_input,
p_data = p_data->p_next; p_data = p_data->p_next;
pp_packets[i_loop]->p_next = NULL; pp_packets[i_loop]->p_next = NULL;
if( pp_packets[i_loop]->p_buffer[0] != 0x47 ) if( pp_packets[i_loop]->p_demux_start[0] != 0x47 )
intf_ErrMsg( "input error: bad TS packet (starts with " intf_ErrMsg( "input error: bad TS packet (starts with "
"0x%.2x, should be 0x47)", "0x%.2x, should be 0x47)",
pp_packets[i_loop]->p_buffer[0] ); pp_packets[i_loop]->p_demux_start[0] );
} }
for( ; i_loop < INPUT_READ_ONCE ; i_loop++ ) for( ; i_loop < INPUT_READ_ONCE ; i_loop++ )
{ {
......
...@@ -95,11 +95,19 @@ static void VCDClose ( struct input_thread_s *); ...@@ -95,11 +95,19 @@ static void VCDClose ( struct input_thread_s *);
static void VCDEnd ( struct input_thread_s *); static void VCDEnd ( struct input_thread_s *);
static void VCDSeek ( struct input_thread_s *, off_t ); static void VCDSeek ( struct input_thread_s *, off_t );
static int VCDRewind ( struct input_thread_s * ); static int VCDRewind ( struct input_thread_s * );
static struct data_packet_s * NewPacket( void *, size_t );
static pes_packet_t * NewPES ( void * );
static void DeletePacket ( void *, data_packet_t * );
static void DeletePES ( void *, pes_packet_t *);
/*****************************************************************************
* Declare a buffer manager
*****************************************************************************/
#define FLAGS BUFFERS_NOFLAGS
#define NB_LIFO 2
DECLARE_BUFFERS_EMBEDDED( FLAGS, NB_LIFO );
DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO );
DECLARE_BUFFERS_END( FLAGS, NB_LIFO );
DECLARE_BUFFERS_NEWPACKET( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPACKET( FLAGS, NB_LIFO, 150 );
DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO );
DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 150 );
/***************************************************************************** /*****************************************************************************
...@@ -119,10 +127,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) ...@@ -119,10 +127,10 @@ void _M( input_getfunctions )( function_list_t * p_function_list )
input.pf_set_area = VCDSetArea; input.pf_set_area = VCDSetArea;
input.pf_set_program = VCDSetProgram; input.pf_set_program = VCDSetProgram;
input.pf_demux = input_DemuxPS; input.pf_demux = input_DemuxPS;
input.pf_new_packet = NewPacket; input.pf_new_packet = input_NewPacket;
input.pf_new_pes = NewPES; input.pf_new_pes = input_NewPES;
input.pf_delete_packet = DeletePacket; input.pf_delete_packet = input_DeletePacket;
input.pf_delete_pes = DeletePES; input.pf_delete_pes = input_DeletePES;
input.pf_rewind = VCDRewind; input.pf_rewind = VCDRewind;
input.pf_seek = VCDSeek; input.pf_seek = VCDSeek;
#undef input #undef input
...@@ -227,10 +235,13 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -227,10 +235,13 @@ static void VCDInit( input_thread_t * p_input )
return; return;
} }
p_input->p_plugin_data = (void *)p_vcd; p_input->p_plugin_data = (void *)p_vcd;
p_input->p_method_data = NULL;
if( (p_input->p_method_data = input_BuffersInit()) == NULL )
{
p_input->b_error = 1;
return;
}
p_vcd->vcdhandle = p_input->i_handle; p_vcd->vcdhandle = p_input->i_handle;
p_vcd->b_end_of_track = 0; p_vcd->b_end_of_track = 0;
...@@ -243,63 +254,6 @@ static void VCDInit( input_thread_t * p_input ) ...@@ -243,63 +254,6 @@ static void VCDInit( input_thread_t * p_input )
p_input->i_read_once = VCD_DATA_ONCE; p_input->i_read_once = VCD_DATA_ONCE;
p_packet_cache = malloc( sizeof(packet_cache_t) );
if ( p_packet_cache == NULL )
{
intf_ErrMsg( "vcd error: out of memory" );
p_input->b_error = 1;
return;
}
p_input->p_method_data = (void *)p_packet_cache;
/* Initialize packet cache mutex */
vlc_mutex_init( &p_packet_cache->lock );
/* allocates the data cache */
p_packet_cache->data.p_stack = malloc( DATA_CACHE_SIZE *
sizeof(data_packet_t*) );
if ( p_packet_cache->data.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->data.l_index = 0;
/* allocates the PES cache */
p_packet_cache->pes.p_stack = malloc( PES_CACHE_SIZE *
sizeof(pes_packet_t*) );
if ( p_packet_cache->pes.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->pes.l_index = 0;
/* allocates the small buffer cache */
p_packet_cache->smallbuffer.p_stack = malloc( SMALL_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->smallbuffer.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->smallbuffer.l_index = 0;
/* allocates the large buffer cache */
p_packet_cache->largebuffer.p_stack = malloc( LARGE_CACHE_SIZE *
sizeof(packet_buffer_t) );
if ( p_packet_cache->largebuffer.p_stack == NULL )
{
intf_ErrMsg( "Out of memory" );
p_input->b_error = 1;
return;
}
p_packet_cache->largebuffer.l_index = 0;
/* Set stream and area data */ /* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
...@@ -405,6 +359,7 @@ static void VCDEnd( input_thread_t * p_input ) ...@@ -405,6 +359,7 @@ static void VCDEnd( input_thread_t * p_input )
free( p_vcd ); free( p_vcd );
input_BuffersEnd( p_input->p_method_data );
} }
/***************************************************************************** /*****************************************************************************
...@@ -584,7 +539,8 @@ static int VCDRead( input_thread_t * p_input, ...@@ -584,7 +539,8 @@ static int VCDRead( input_thread_t * p_input,
/* Fetch a packet of the appropriate size. */ /* Fetch a packet of the appropriate size. */
p_data = NewPacket( p_input->p_method_data, i_packet_size + 6 ); p_data = p_input->pf_new_packet( p_input->p_method_data,
i_packet_size + 6 );
if( p_data == NULL ) if( p_data == NULL )
{ {
...@@ -594,7 +550,7 @@ static int VCDRead( input_thread_t * p_input, ...@@ -594,7 +550,7 @@ static int VCDRead( input_thread_t * p_input,
if( U32_AT(p_buffer) != 0x1B9 ) if( U32_AT(p_buffer) != 0x1B9 )
{ {
p_main->fast_memcpy( p_data->p_buffer, p_buffer + i_index, p_main->fast_memcpy( p_data->p_demux_start, p_buffer + i_index,
6 + i_packet_size ); 6 + i_packet_size );
i_index += ( 6 + i_packet_size ); i_index += ( 6 + i_packet_size );
...@@ -602,7 +558,7 @@ static int VCDRead( input_thread_t * p_input, ...@@ -602,7 +558,7 @@ static int VCDRead( input_thread_t * p_input,
else else
{ {
/* Copy the small header. */ /* Copy the small header. */
memcpy( p_data->p_buffer, p_buffer + i_index, 4 ); memcpy( p_data->p_demux_start, p_buffer + i_index, 4 );
i_index += 4; i_index += 4;
} }
...@@ -684,359 +640,3 @@ static void VCDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -684,359 +640,3 @@ static void VCDSeek( input_thread_t * p_input, off_t i_off )
return ; return ;
} }
/*
* Packet management utilities
*/
/*****************************************************************************
* NewPacket: allocates a data packet
*****************************************************************************/
static struct data_packet_s * NewPacket( void * p_packet_cache,
size_t l_size )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
long l_index;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "PPacket cache not initialized" );
return NULL;
}
#endif
/* Safety check */
if( l_size > INPUT_MAX_PACKET_SIZE )
{
intf_ErrMsg( "Packet too big (%d)", l_size );
return NULL;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is empty */
if( p_cache->data.l_index == 0 )
{
/* Allocates a new packet */
p_data = malloc( sizeof(data_packet_t) );
if( p_data == NULL )
{
intf_ErrMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
if( (p_data = p_cache->data.p_stack[ -- p_cache->data.l_index ])
== NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
if( l_size < MAX_SMALL_SIZE )
{
/* Small buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->smallbuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if( p_data->p_buffer == NULL )
{
intf_DbgMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->smallbuffer.l_index;
if( (p_data->p_buffer = p_cache->smallbuffer.p_stack[l_index].p_data)
== NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->smallbuffer.p_stack[l_index].l_size < l_size ||
p_cache->smallbuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->smallbuffer.p_stack[l_index].l_size;
}
}
}
else
{
/* Large buffer */
/* Checks whether the buffer cache is empty */
if( p_cache->largebuffer.l_index == 0 )
{
/* Allocates a new packet */
p_data->p_buffer = malloc( l_size );
if ( p_data->p_buffer == NULL )
{
intf_ErrMsg( "Out of memory" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer allocated" );
#endif
p_data->l_size = l_size;
}
else
{
/* Takes the packet out from the cache */
l_index = -- p_cache->largebuffer.l_index;
p_data->p_buffer = p_cache->largebuffer.p_stack[l_index].p_data;
if( p_data->p_buffer == NULL )
{
intf_ErrMsg( "NULL packet in the small buffer cache" );
free( p_data );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
/* Reallocates the packet if it is too small or too large */
if( p_cache->largebuffer.p_stack[l_index].l_size < l_size ||
p_cache->largebuffer.p_stack[l_index].l_size > 2*l_size )
{
p_data->p_buffer = realloc( p_data->p_buffer, l_size );
p_data->l_size = l_size;
}
else
{
p_data->l_size = p_cache->largebuffer.p_stack[l_index].l_size;
}
}
}
vlc_mutex_unlock( &p_cache->lock );
/* Initialize data */
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
p_data->p_payload_start = p_data->p_buffer;
p_data->p_payload_end = p_data->p_buffer + l_size;
return( p_data );
}
/*****************************************************************************
* NewPES: allocates a pes packet
*****************************************************************************/
static pes_packet_t * NewPES( void * p_packet_cache )
{
packet_cache_t * p_cache;
pes_packet_t * p_pes;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return NULL;
}
#endif
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is empty */
if( p_cache->pes.l_index == 0 )
{
/* Allocates a new packet */
p_pes = malloc( sizeof(pes_packet_t) );
if( p_pes == NULL )
{
intf_DbgMsg( "Out of memory" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet allocated" );
#endif
}
else
{
/* Takes the packet out from the cache */
p_pes = p_cache->pes.p_stack[ -- p_cache->pes.l_index ];
if( p_pes == NULL )
{
intf_ErrMsg( "NULL packet in the data cache" );
vlc_mutex_unlock( &p_cache->lock );
return NULL;
}
}
vlc_mutex_unlock( &p_cache->lock );
p_pes->b_data_alignment = p_pes->b_discontinuity =
p_pes->i_pts = p_pes->i_dts = 0;
p_pes->i_pes_size = 0;
p_pes->p_first = NULL;
return( p_pes );
}
/*****************************************************************************
* DeletePacket: deletes a data packet
*****************************************************************************/
static void DeletePacket( void * p_packet_cache,
data_packet_t * p_data )
{
packet_cache_t * p_cache;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_data );
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the data cache is full */
if ( p_cache->data.l_index < DATA_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->data.p_stack[ p_cache->data.l_index ++ ] = p_data;
/* Small buffer or large buffer? */
if ( p_data->l_size < MAX_SMALL_SIZE )
{
/* Checks whether the small buffer cache is full */
if ( p_cache->smallbuffer.l_index < SMALL_CACHE_SIZE )
{
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index ].l_size = p_data->l_size;
p_cache->smallbuffer.p_stack[
p_cache->smallbuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: small buffer freed" );
#endif
}
}
else
{
/* Checks whether the large buffer cache is full */
if ( p_cache->largebuffer.l_index < LARGE_CACHE_SIZE )
{
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index ].l_size = p_data->l_size;
p_cache->largebuffer.p_stack[
p_cache->largebuffer.l_index++ ].p_data = p_data->p_buffer;
}
else
{
ASSERT( p_data->p_buffer );
free( p_data->p_buffer );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: large buffer freed" );
#endif
}
}
}
else
{
/* Cache full: the packet must be freed */
free( p_data->p_buffer );
free( p_data );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: data packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
/*****************************************************************************
* DeletePES: deletes a PES packet and associated data packets
*****************************************************************************/
static void DeletePES( void * p_packet_cache, pes_packet_t * p_pes )
{
packet_cache_t * p_cache;
data_packet_t * p_data;
data_packet_t * p_next;
p_cache = (packet_cache_t *)p_packet_cache;
#ifdef DEBUG
if ( p_cache == NULL )
{
intf_ErrMsg( "Packet cache not initialized" );
return;
}
#endif
ASSERT( p_pes);
p_data = p_pes->p_first;
while( p_data != NULL )
{
p_next = p_data->p_next;
DeletePacket( p_cache, p_data );
p_data = p_next;
}
vlc_mutex_lock( &p_cache->lock );
/* Checks whether the PES cache is full */
if ( p_cache->pes.l_index < PES_CACHE_SIZE )
{
/* Cache not full: store the packet in it */
p_cache->pes.p_stack[ p_cache->pes.l_index ++ ] = p_pes;
}
else
{
/* Cache full: the packet must be freed */
free( p_pes );
#ifdef TRACE_INPUT
intf_DbgMsg( "PS input: PES packet freed" );
#endif
}
vlc_mutex_unlock( &p_cache->lock );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg_system.c: TS, PS and PES management * mpeg_system.c: TS, PS and PES management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: mpeg_system.c,v 1.75 2001/12/17 16:42:27 sam Exp $ * $Id: mpeg_system.c,v 1.76 2001/12/19 10:00:00 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr> * Michel Lespinasse <walken@via.ecp.fr>
...@@ -508,13 +508,13 @@ static u16 GetID( data_packet_t * p_data ) ...@@ -508,13 +508,13 @@ static u16 GetID( data_packet_t * p_data )
{ {
u16 i_id; u16 i_id;
i_id = p_data->p_payload_start[3]; /* stream_id */ i_id = p_data->p_demux_start[3]; /* stream_id */
if( i_id == 0xBD ) if( i_id == 0xBD )
{ {
/* FIXME : this is not valid if the header is split in multiple /* FIXME : this is not valid if the header is split in multiple
* packets */ * packets */
/* stream_private_id */ /* stream_private_id */
i_id |= p_data->p_payload_start[ 9 + p_data->p_payload_start[8] ] << 8; i_id |= p_data->p_demux_start[ 9 + p_data->p_demux_start[8] ] << 8;
} }
return( i_id ); return( i_id );
} }
...@@ -533,14 +533,14 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -533,14 +533,14 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
int i; int i;
int i_new_es_number = 0; int i_new_es_number = 0;
if( p_data->p_payload_start + 10 > p_data->p_payload_end ) if( p_data->p_demux_start + 10 > p_data->p_payload_end )
{ {
intf_ErrMsg( "input error: PSM too short : packet corrupt" ); intf_ErrMsg( "input error: PSM too short : packet corrupt" );
return; return;
} }
if( p_demux->b_has_PSM if( p_demux->b_has_PSM
&& p_demux->i_PSM_version == (p_data->p_payload_start[6] & 0x1F) ) && p_demux->i_PSM_version == (p_data->p_demux_start[6] & 0x1F) )
{ {
/* Already got that one. */ /* Already got that one. */
return; return;
...@@ -548,12 +548,12 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -548,12 +548,12 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
intf_DbgMsg( "input: building PSM" ); intf_DbgMsg( "input: building PSM" );
p_demux->b_has_PSM = 1; p_demux->b_has_PSM = 1;
p_demux->i_PSM_version = p_data->p_payload_start[6] & 0x1F; p_demux->i_PSM_version = p_data->p_demux_start[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over /* Go to elementary_stream_map_length, jumping over
* program_stream_info. */ * program_stream_info. */
p_byte = p_data->p_payload_start + 10 p_byte = p_data->p_demux_start + 10
+ U16_AT(&p_data->p_payload_start[8]); + U16_AT(&p_data->p_demux_start[8]);
if( p_byte > p_data->p_payload_end ) if( p_byte > p_data->p_payload_end )
{ {
intf_ErrMsg( "input error: PSM too short, packet corrupt" ); intf_ErrMsg( "input error: PSM too short, packet corrupt" );
...@@ -658,7 +658,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -658,7 +658,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
u32 i_code; u32 i_code;
es_descriptor_t * p_es = NULL; es_descriptor_t * p_es = NULL;
i_code = p_data->p_payload_start[3]; i_code = p_data->p_demux_start[3];
if( i_code > 0xBC ) /* ES start code */ if( i_code > 0xBC ) /* ES start code */
{ {
...@@ -697,7 +697,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -697,7 +697,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
i_id, 0 ); i_id, 0 );
if( p_es != NULL ) if( p_es != NULL )
{ {
p_es->i_stream_id = p_data->p_payload_start[3]; p_es->i_stream_id = p_data->p_demux_start[3];
/* Set stream type and auto-spawn. */ /* Set stream type and auto-spawn. */
if( (i_id & 0xF0) == 0xE0 ) if( (i_id & 0xF0) == 0xE0 )
...@@ -797,10 +797,10 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -797,10 +797,10 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
boolean_t b_trash = 0; boolean_t b_trash = 0;
es_descriptor_t * p_es = NULL; es_descriptor_t * p_es = NULL;
i_code = ((u32)p_data->p_payload_start[0] << 24) i_code = ((u32)p_data->p_demux_start[0] << 24)
| ((u32)p_data->p_payload_start[1] << 16) | ((u32)p_data->p_demux_start[1] << 16)
| ((u32)p_data->p_payload_start[2] << 8) | ((u32)p_data->p_demux_start[2] << 8)
| p_data->p_payload_start[3]; | p_data->p_demux_start[3];
if( i_code <= 0x1BC ) if( i_code <= 0x1BC )
{ {
switch( i_code ) switch( i_code )
...@@ -811,12 +811,12 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -811,12 +811,12 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
mtime_t scr_time; mtime_t scr_time;
u32 i_mux_rate; u32 i_mux_rate;
if( (p_data->p_payload_start[4] & 0xC0) == 0x40 ) if( (p_data->p_demux_start[4] & 0xC0) == 0x40 )
{ {
/* MPEG-2 */ /* MPEG-2 */
byte_t p_header[14]; byte_t p_header[14];
byte_t * p_byte; byte_t * p_byte;
p_byte = p_data->p_payload_start; p_byte = p_data->p_demux_start;
if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 ) if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 )
{ {
...@@ -848,7 +848,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -848,7 +848,7 @@ void input_DemuxPS( input_thread_t * p_input, data_packet_t * p_data )
/* MPEG-1 SCR is like PTS. */ /* MPEG-1 SCR is like PTS. */
byte_t p_header[12]; byte_t p_header[12];
byte_t * p_byte; byte_t * p_byte;
p_byte = p_data->p_payload_start; p_byte = p_data->p_demux_start;
if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 ) if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 )
{ {
...@@ -951,7 +951,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -951,7 +951,7 @@ void input_DemuxTS( input_thread_t * p_input, data_packet_t * p_data )
es_ts_data_t * p_es_demux = NULL; es_ts_data_t * p_es_demux = NULL;
pgrm_ts_data_t * p_pgrm_demux = NULL; pgrm_ts_data_t * p_pgrm_demux = NULL;
#define p (p_data->p_buffer) #define p (p_data->p_demux_start)
/* Extract flags values from TS common header. */ /* Extract flags values from TS common header. */
i_pid = ((p[1] & 0x1F) << 8) | p[2]; i_pid = ((p[1] & 0x1F) << 8) | p[2];
b_unit_start = (p[1] & 0x40); b_unit_start = (p[1] & 0x40);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment