Commit 407540bf authored by Christophe Massiot's avatar Christophe Massiot

* modules/access/satellite/access.c: do not use p_es->i_demux_fd ; fixed

  demux filters leak (particularly harmful on the Dreambox) ; correctly
  handle PAT and PMT changes.
parent e4345c82
...@@ -60,16 +60,74 @@ static int SatelliteSetArea ( input_thread_t *, input_area_t * ); ...@@ -60,16 +60,74 @@ static int SatelliteSetArea ( input_thread_t *, input_area_t * );
static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * ); static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
static void SatelliteSeek ( input_thread_t *, off_t ); static void SatelliteSeek ( input_thread_t *, off_t );
typedef struct demux_handle_t
{
int i_pid;
int i_handle;
int i_type;
} demux_handle_t;
#define PAT_TYPE 1
#define PMT_TYPE 2
#define ES_TYPE 3
#define MAX_DEMUX 8
typedef struct thread_sat_data_t
{
int i_handle;
demux_handle_t p_demux_handles[MAX_DEMUX];
} thread_sat_data_t;
static void AllocateDemux( input_thread_t * p_input, int i_pid,
int i_type )
{
thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
int i_demux;
int i;
i_demux = config_GetInt( p_input, "dvb-dmx" );
/* Find first free slot */
for ( i = 0; i < MAX_DEMUX; i++ )
{
if ( !p_satellite->p_demux_handles[i].i_type )
{
if (ioctl_SetDMXFilter( i_demux, i_pid, &p_satellite->p_demux_handles[i].i_handle, 3) < 0)
{
msg_Warn(p_input, "ioctl_SetDMXFilter failed (%d)", i_pid);
break;
}
p_satellite->p_demux_handles[i].i_type = i_type;
p_satellite->p_demux_handles[i].i_pid = i_pid;
break;
}
}
}
static void CloseProgram( input_thread_t * p_input )
{
thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
int i;
for ( i = 1; i < MAX_DEMUX; i++ )
{
if ( p_satellite->p_demux_handles[i].i_type )
{
ioctl_UnsetDMXFilter( p_satellite->p_demux_handles[i].i_handle );
p_satellite->p_demux_handles[i].i_type = 0;
}
}
}
/***************************************************************************** /*****************************************************************************
* Open: open the dvr device * Open: open the dvr device
*****************************************************************************/ *****************************************************************************/
int E_(Open) ( vlc_object_t *p_this ) int E_(Open) ( vlc_object_t *p_this )
{ {
input_thread_t * p_input = (input_thread_t *)p_this; input_thread_t * p_input = (input_thread_t *)p_this;
input_socket_t * p_satellite; thread_sat_data_t * p_satellite;
char * psz_parser; char * psz_parser;
char * psz_next; char * psz_next;
int i_fd = 0;
int i_freq = 0; int i_freq = 0;
int i_srate = 0; int i_srate = 0;
vlc_bool_t b_pol = 0; vlc_bool_t b_pol = 0;
...@@ -194,13 +252,14 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -194,13 +252,14 @@ int E_(Open) ( vlc_object_t *p_this )
/* Initialise structure */ /* Initialise structure */
p_satellite = malloc( sizeof( input_socket_t ) ); p_satellite = malloc( sizeof( thread_sat_data_t ) );
if( p_satellite == NULL ) if( p_satellite == NULL )
{ {
msg_Err( p_input, "out of memory" ); msg_Err( p_input, "out of memory" );
return -1; return -1;
} }
memset( p_satellite, 0, sizeof( thread_sat_data_t ) );
p_input->p_access_data = (void *)p_satellite; p_input->p_access_data = (void *)p_satellite;
...@@ -283,14 +342,7 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -283,14 +342,7 @@ int E_(Open) ( vlc_object_t *p_this )
} /* i_freq */ } /* i_freq */
msg_Dbg( p_input, "setting filter on PAT" ); msg_Dbg( p_input, "setting filter on PAT" );
AllocateDemux( p_input, 0, PAT_TYPE );
if ( ioctl_SetDMXFilter( i_demux, 0, &i_fd, 3 ) < 0 )
{
msg_Err( p_input, "an error occured when setting filter on PAT" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
}
if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 ) if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
{ {
...@@ -320,26 +372,12 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -320,26 +372,12 @@ int E_(Open) ( vlc_object_t *p_this )
void E_(Close) ( vlc_object_t *p_this ) void E_(Close) ( vlc_object_t *p_this )
{ {
input_thread_t * p_input = (input_thread_t *)p_this; input_thread_t * p_input = (input_thread_t *)p_this;
input_socket_t * p_satellite; thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
unsigned int i_es_index;
if ( p_input->stream.p_selected_program ) msg_Dbg( p_input, "unsetting filters on all pids" );
{ CloseProgram( p_input );
for ( i_es_index = 1 ; close( p_satellite->p_demux_handles[0].i_handle );
i_es_index < p_input->stream.p_selected_program->
i_es_number ;
i_es_index ++ )
{
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
if ( p_es->p_dec )
{
ioctl_UnsetDMXFilter( p_es->i_demux_fd );
}
#undef p_es
}
}
p_satellite = (input_socket_t *)p_input;
close( p_satellite->i_handle ); close( p_satellite->i_handle );
} }
...@@ -349,10 +387,8 @@ void E_(Close) ( vlc_object_t *p_this ) ...@@ -349,10 +387,8 @@ void E_(Close) ( vlc_object_t *p_this )
static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer, static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len ) size_t i_len )
{ {
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data; thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
ssize_t i_ret; ssize_t i_ret;
int i_program = config_GetInt( p_input, "program" );
int i_demux = config_GetInt( p_input, "dvb-dmx" );
unsigned int i; unsigned int i;
...@@ -360,25 +396,25 @@ static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer, ...@@ -360,25 +396,25 @@ static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
/* This is kludgy and consumes way too much CPU power - the access /* This is kludgy and consumes way too much CPU power - the access
* module should have a callback from the demux when a new program * module should have a callback from the demux when a new program
* is encountered. --Meuuh */ * is encountered. --Meuuh */
for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) if ( !p_satellite->p_demux_handles[1].i_type )
{ {
/* Only set a filter on the selected program : some boards int i_program = config_GetInt( p_input, "program" );
* (read: Dreambox) only have 8 filters, so you don't want to
* spend them on unwanted PMTs. --Meuuh */ for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
if ( (!i_program || p_input->stream.pp_programs[i]->i_number == i_program) && p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
{ {
msg_Dbg( p_input, "setting filter on PMT pid %d", /* Only set a filter on the selected program : some boards
p_input->stream.pp_programs[i]->pp_es[0]->i_id ); * (read: Dreambox) only have 8 filters, so you don't want to
if (ioctl_SetDMXFilter( i_demux, p_input->stream.pp_programs[i]->pp_es[0]->i_id, * spend them on unwanted PMTs. --Meuuh */
&p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd, if ( (!i_program || p_input->stream.pp_programs[i]->i_number == i_program) )
3 ) < 0)
{ {
msg_Err(p_input, "ioctl_SetDMXFilter failed"); msg_Dbg( p_input, "setting filter on PMT pid %d",
p_input->stream.pp_programs[i]->pp_es[0]->i_id );
AllocateDemux( p_input, p_input->stream.pp_programs[i]->pp_es[0]->i_id, PMT_TYPE );
} }
} }
} }
i_ret = read( p_access_data->i_handle, p_buffer, i_len ); i_ret = read( p_satellite->i_handle, p_buffer, i_len );
if( i_ret < 0 ) if( i_ret < 0 )
{ {
...@@ -410,11 +446,10 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -410,11 +446,10 @@ int SatelliteSetProgram( input_thread_t * p_input,
{ {
unsigned int i_es_index; unsigned int i_es_index;
vlc_value_t val; vlc_value_t val;
int i_demux = config_GetInt( p_input, "dvb-dmx" );
if ( p_input->stream.p_selected_program ) if ( p_input->stream.p_selected_program )
{ {
for ( i_es_index = 1 ; /* 0 should be the PMT */ for ( i_es_index = 0 ; /* 0 should be the PMT */
i_es_index < p_input->stream.p_selected_program-> i_es_index < p_input->stream.p_selected_program->
i_es_number ; i_es_number ;
i_es_index ++ ) i_es_index ++ )
...@@ -424,54 +459,41 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -424,54 +459,41 @@ int SatelliteSetProgram( input_thread_t * p_input,
{ {
input_UnselectES( p_input , p_es ); input_UnselectES( p_input , p_es );
} }
if ( p_es->i_demux_fd )
{
ioctl_UnsetDMXFilter( p_es->i_demux_fd );
p_es->i_demux_fd = 0;
}
#undef p_es #undef p_es
} }
} }
msg_Dbg( p_input, "unsetting filters on all pids" );
CloseProgram( p_input );
msg_Dbg( p_input, "setting filter on PMT pid %d",
p_new_prg->pp_es[0]->i_id );
AllocateDemux( p_input, p_new_prg->pp_es[0]->i_id, PMT_TYPE );
for ( i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ ) for ( i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
{ {
#define p_es p_new_prg->pp_es[i_es_index] #define p_es p_new_prg->pp_es[i_es_index]
switch( p_es->i_cat ) switch( p_es->i_cat )
{ {
case MPEG1_VIDEO_ES: case VIDEO_ES:
case MPEG2_VIDEO_ES:
case MPEG2_MOTO_VIDEO_ES:
msg_Dbg(p_input, "setting filter on video ES 0x%x", msg_Dbg(p_input, "setting filter on video ES 0x%x",
p_es->i_id); p_es->i_id);
/* First set the filter. This may seem a little odd, but /* Always set the filter. This may seem a little odd, but
* it allows you to stream the video with demuxstream * it allows you to stream the video with demuxstream
* without having a decoder or a stream output behind. * without having a decoder or a stream output behind.
* The result is you'll sometimes filter a PID which you * The result is you'll sometimes filter a PID which you
* don't really want, but in the most common cases it * don't really want, but in the most common cases it
* should be OK. --Meuuh */ * should be OK. --Meuuh */
if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 1) < 0) AllocateDemux( p_input, p_es->i_id, ES_TYPE );
{ input_SelectES( p_input , p_es );
msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
}
else
{
input_SelectES( p_input , p_es );
}
break; break;
case MPEG1_AUDIO_ES: case AUDIO_ES:
case MPEG2_AUDIO_ES:
msg_Dbg(p_input, "setting filter on audio ES 0x%x", msg_Dbg(p_input, "setting filter on audio ES 0x%x",
p_es->i_id); p_es->i_id);
if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 3) < 0) AllocateDemux( p_input, p_es->i_id, ES_TYPE );
{ input_SelectES( p_input , p_es );
msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
}
else
{
input_SelectES( p_input , p_es );
}
break; break;
default: default:
/* Do not select private streams. This is to avoid the /* Do not select private streams. This is to avoid the
* limit of 8 filters on the Dreambox and possibly on * limit of 8 filters on the Dreambox and possibly on
...@@ -483,14 +505,8 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -483,14 +505,8 @@ int SatelliteSetProgram( input_thread_t * p_input,
msg_Dbg(p_input, "setting filter on misc (0x%x) ES 0x%x", msg_Dbg(p_input, "setting filter on misc (0x%x) ES 0x%x",
p_es->i_cat, p_es->i_cat,
p_es->i_id); p_es->i_id);
if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 3) < 0) AllocateDemux( p_input, p_es->i_id, ES_TYPE );
{ input_SelectES( p_input , p_es );
msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
}
else
{
input_SelectES( p_input , p_es );
}
#endif #endif
break; break;
#undef p_es #undef p_es
......
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