/*****************************************************************************
* access.c: Satellite card input
*****************************************************************************
- * Copyright (C) 1998-2002 VideoLAN
+ * Copyright (C) 1998-2003 VideoLAN
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
+ * Christophe Massiot <massiot@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "dvb.h"
-#define SATELLITE_READ_ONCE 3
+#define SATELLITE_READ_ONCE 80
+#define DMX_BUFFER_SIZE (1024 * 1024)
/*****************************************************************************
* Local prototypes
int i_lnb_lof1;
int i_lnb_lof2;
int i_lnb_slof;
+ int i_demux;
+ char psz_dvr[255];
+ i_demux = config_GetInt( p_input, "dvb-dmx" );
+ snprintf(psz_dvr, sizeof(psz_dvr), DVR "%d", i_demux);
/* parse the options passed in command line : */
{
msg_Warn( p_input, "invalid frequency, using default one" );
i_freq = config_GetInt( p_input, "frequency" );
- if( i_freq > (12999*1000) || i_freq < (10000*1000) )
+ if( i_freq && (i_freq > (12999*1000) || i_freq < (10000*1000)) )
{
msg_Err( p_input, "invalid default frequency" );
return -1;
}
}
- if( i_srate > (30000*1000) || i_srate < (1000*1000) )
+ if( i_freq && (i_srate > (30000*1000) || i_srate < (1000*1000)) )
{
msg_Warn( p_input, "invalid symbol rate, using default one" );
i_srate = config_GetInt( p_input, "symbol-rate" );
}
}
- if( b_pol && b_pol != 1 )
+ if( i_freq && b_pol && b_pol != 1 )
{
msg_Warn( p_input, "invalid polarization, using default one" );
b_pol = config_GetInt( p_input, "polarization" );
}
}
- if( i_fec > 7 || i_fec < 1 )
+ if( i_freq && (i_fec > 7 || i_fec < 1) )
{
msg_Warn( p_input, "invalid FEC, using default one" );
i_fec = config_GetInt( p_input, "fec" );
}
}
- switch( i_fec )
+ if ( i_freq )
{
- case 1:
- f_fec = 1./2;
- break;
- case 2:
- f_fec = 2./3;
- break;
- case 3:
- f_fec = 3./4;
- break;
- case 4:
- f_fec = 4./5;
- break;
- case 5:
- f_fec = 5./6;
- break;
- case 6:
- f_fec = 6./7;
- break;
- case 7:
- f_fec = 7./8;
- break;
- default:
- /* cannot happen */
- break;
+ switch( i_fec )
+ {
+ case 1:
+ f_fec = 1./2;
+ break;
+ case 2:
+ f_fec = 2./3;
+ break;
+ case 3:
+ f_fec = 3./4;
+ break;
+ case 4:
+ f_fec = 4./5;
+ break;
+ case 5:
+ f_fec = 5./6;
+ break;
+ case 6:
+ f_fec = 6./7;
+ break;
+ case 7:
+ f_fec = 7./8;
+ break;
+ default:
+ /* cannot happen */
+ break;
+ }
}
p_input->p_access_data = (void *)p_satellite;
/* Open the DVR device */
- msg_Dbg( p_input, "opening DVR device `%s'", DVR );
+ msg_Dbg( p_input, "opening DVR device `%s'", psz_dvr );
- if( (p_satellite->i_handle = open( DVR,
+ if( (p_satellite->i_handle = open( psz_dvr,
/*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
{
- msg_Warn( p_input, "cannot open `%s' (%s)", DVR, strerror(errno) );
+ msg_Warn( p_input, "cannot open `%s' (%s)", psz_dvr, strerror(errno) );
free( p_satellite );
return -1;
}
+ /* FIXME : this is from the Dreambox port. I have no idea whether it
+ * hurts or helps other DVB interfaces, so I just leave it here.
+ * Feel free to remove it if it breaks. --Meuuh */
+ ioctl_SetBufferSize( p_satellite->i_handle, DMX_BUFFER_SIZE );
+
/* Get antenna configuration options */
b_diseqc = config_GetInt( p_input, "diseqc" );
i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
/* Initialize the Satellite Card */
- msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
- "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
-
- if ( ioctl_SECControl( i_freq, b_pol, i_lnb_slof, b_diseqc ) < 0 )
+ if ( i_freq )
{
- msg_Err( p_input, "an error occured when controling SEC" );
- close( p_satellite->i_handle );
- free( p_satellite );
- return -1;
- }
+ int i_tuner = config_GetInt( p_input, "dvb-tuner" );
- msg_Dbg( p_input, "initializing frontend device" );
- switch (ioctl_SetQPSKFrontend ( i_freq, i_srate, f_fec,
- i_lnb_lof1, i_lnb_lof2, i_lnb_slof))
- {
- case -2:
- msg_Err( p_input, "frontend returned an unexpected event" );
- close( p_satellite->i_handle );
- free( p_satellite );
- return -1;
- break;
- case -3:
- msg_Err( p_input, "frontend returned no event" );
- close( p_satellite->i_handle );
- free( p_satellite );
- return -1;
- break;
- case -4:
- msg_Err( p_input, "frontend: timeout when polling for event" );
- close( p_satellite->i_handle );
- free( p_satellite );
- return -1;
- break;
- case -5:
- msg_Err( p_input, "an error occured when polling frontend device" );
- close( p_satellite->i_handle );
- free( p_satellite );
- return -1;
- break;
- case -1:
- msg_Err( p_input, "frontend returned a failure event" );
+ msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
+ "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
+
+ if ( ioctl_SECControl( i_tuner, i_freq, b_pol, i_lnb_slof, b_diseqc ) < 0 )
+ {
+ msg_Err( p_input, "an error occured when controling SEC" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
- break;
- default:
- break;
- }
+ }
+
+ msg_Dbg( p_input, "initializing frontend device" );
+ switch (ioctl_SetQPSKFrontend ( i_tuner, i_freq, i_srate, f_fec,
+ i_lnb_lof1, i_lnb_lof2, i_lnb_slof))
+ {
+ case -2:
+ msg_Err( p_input, "frontend returned an unexpected event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -3:
+ msg_Err( p_input, "frontend returned no event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -4:
+ msg_Err( p_input, "frontend: timeout when polling for event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -5:
+ msg_Err( p_input, "an error occured when polling frontend device" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ case -1:
+ msg_Err( p_input, "frontend returned a failure event" );
+ close( p_satellite->i_handle );
+ free( p_satellite );
+ return -1;
+ break;
+ default:
+ break;
+ }
+ } /* i_freq */
msg_Dbg( p_input, "setting filter on PAT" );
- if ( ioctl_SetDMXFilter( 0, &i_fd, 3 ) < 0 )
+ 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 );
{
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
ssize_t i_ret;
-
+ int i_program = config_GetInt( p_input, "program" );
+ int i_demux = config_GetInt( p_input, "dvb-dmx" );
+
unsigned int i;
/* if not set, set filters to the PMTs */
+ /* This is kludgy and consumes way too much CPU power - the access
+ * module should have a callback from the demux when a new program
+ * is encountered. --Meuuh */
for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
{
- if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
+ /* Only set a filter on the selected program : some boards
+ * (read: Dreambox) only have 8 filters, so you don't want to
+ * spend them on unwanted PMTs. --Meuuh */
+ 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",
+ msg_Dbg( p_input, "setting filter on PMT pid %d",
p_input->stream.pp_programs[i]->pp_es[0]->i_id );
- ioctl_SetDMXFilter( p_input->stream.pp_programs[i]->pp_es[0]->i_id,
+ if (ioctl_SetDMXFilter( i_demux, p_input->stream.pp_programs[i]->pp_es[0]->i_id,
&p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
- 3 );
+ 3 ) < 0)
+ {
+ msg_Err(p_input, "ioctl_SetDMXFilter failed");
+ }
}
}
{
unsigned int i_es_index;
vlc_value_t val;
+ int i_demux = config_GetInt( p_input, "dvb-dmx" );
if ( p_input->stream.p_selected_program )
{
}
}
- 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]
switch( p_es->i_cat )
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
case MPEG2_MOTO_VIDEO_ES:
- if ( input_SelectES( p_input , p_es ) == 0 )
+ msg_Dbg(p_input, "setting filter on video ES 0x%x",
+ p_es->i_id);
+ /* First set the filter. This may seem a little odd, but
+ * it allows you to stream the video with demuxstream
+ * without having a decoder or a stream output behind.
+ * The result is you'll sometimes filter a PID which you
+ * don't really want, but in the most common cases it
+ * should be OK. --Meuuh */
+ if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 1) < 0)
+ {
+ msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
+ }
+ else
{
- ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1);
+ input_SelectES( p_input , p_es );
}
break;
+
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
- if ( input_SelectES( p_input , p_es ) == 0 )
+ msg_Dbg(p_input, "setting filter on audio ES 0x%x",
+ p_es->i_id);
+ if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 3) < 0)
+ {
+ msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
+ }
+ else
{
- ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2);
input_SelectES( p_input , p_es );
}
break;
default:
- ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3);
- input_SelectES( p_input , p_es );
+ /* Do not select private streams. This is to avoid the
+ * limit of 8 filters on the Dreambox and possibly on
+ * other boards. We should probably change that to
+ * have the DVB subtitles, but filtering all private
+ * streams including DVB tables and padding seems
+ * nonsense to me. --Meuuh */
+#if 0
+ msg_Dbg(p_input, "setting filter on misc (0x%x) ES 0x%x",
+ p_es->i_cat,
+ p_es->i_id);
+ if (ioctl_SetDMXFilter( i_demux, p_es->i_id, &p_es->i_demux_fd, 3) < 0)
+ {
+ msg_Dbg(p_input, "ioctl_SetDMXFilter failed");
+ }
+ else
+ {
+ input_SelectES( p_input , p_es );
+ }
+#endif
break;
#undef p_es
}
*****************************************************************************/
-int ioctl_SECControl( int freq, int pol, int lnb_slof, int diseqc)
+int ioctl_SECControl( int sec_nb, int freq, int pol, int lnb_slof, int diseqc )
{
struct secCommand scmd;
struct secCmdSequence scmds;
int sec;
+ char psz_sec[255];
- if((sec = open(SEC,O_RDWR)) < 0)
+ snprintf(psz_sec, sizeof(psz_sec), SEC "%d", sec_nb);
+
+ if((sec = open(psz_sec, O_RDWR)) < 0)
{
return -1;
}
* ioctl_SetQPSKFrontend : controls the FE device
*****************************************************************************/
-int ioctl_SetQPSKFrontend (int freq, int srate, int fec,\
+int ioctl_SetQPSKFrontend (int fe_nb, int freq, int srate, int fec,\
int lnb_lof1, int lnb_lof2, int lnb_slof)
{
FrontendParameters fep;
int front;
int rc;
+ char psz_fe[255];
+
+ snprintf(psz_fe, sizeof(psz_fe), FRONTEND "%d", fe_nb);
/* Open the frontend device */
- if((front = open(FRONTEND,O_RDWR)) < 0)
+ if((front = open(psz_fe, O_RDWR)) < 0)
{
return -1;
}
* ioctl_SetDMXAudioFilter : controls the demux to add a filter
*****************************************************************************/
-int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
+int ioctl_SetDMXFilter( int dmx_nb, int i_pid, int * pi_fd , int i_type )
{
struct dmxPesFilterParams s_filter_params;
-
+ char psz_dmx[255];
+
+ snprintf(psz_dmx, sizeof(psz_dmx), DMX "%d", dmx_nb);
+
/* We first open the device */
- if ((*pi_fd = open(DMX, O_RDWR|O_NONBLOCK)) < 0)
+ if ((*pi_fd = open(psz_dmx, O_RDWR|O_NONBLOCK)) < 0)
{
return -1;
}
s_filter_params.output = DMX_OUT_TS_TAP;
switch ( i_type )
{
+ /* AFAIK you shouldn't use DMX_PES_VIDEO and DMX_PES_AUDIO
+ * unless you want to use a hardware decoder. In all cases
+ * I know DMX_PES_OTHER is quite enough for what we want to
+ * do. In case you have problems, you can still try to
+ * reenable them here : --Meuuh */
+#if 0
case 1:
s_filter_params.pesType = DMX_PES_VIDEO;
break;
s_filter_params.pesType = DMX_PES_AUDIO;
break;
case 3:
+#endif
+ default:
s_filter_params.pesType = DMX_PES_OTHER;
break;
}
close(demux);
return 0;
}
+
+
+/*****************************************************************************
+ * ioctl_SetBufferSize :
+ *****************************************************************************/
+int ioctl_SetBufferSize(int handle, size_t size)
+{
+ return ioctl(handle, DMX_SET_BUFFER_SIZE, size);
+}