Commit 8b8bfe34 authored by Christophe Massiot's avatar Christophe Massiot

* modules/access/satellite: Big rework of the old satellite module.

  - ability to select between different tuners if the board has several
    tuners
  - abitility to select between different demux if the board has several
    demuxes
  - if frequency isn't specified, do not try to tune the tuner and
    assume some other software already did it
  - set a bigger buffer size to avoid packet losses
  - do not filter too many PIDs since some board only have 8 filters
  - kludged so that the module works perfectly well with the demuxstream
    demuxer
  - use DMX_PES_OTHER all the time because some boards do not have a
    decoder chip (this may be a problem for you)

This changeset is part of the Dreambox port of VLC.
parent 4343919e
/***************************************************************************** /*****************************************************************************
* access.c: Satellite card input * access.c: Satellite card input
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2002 VideoLAN * Copyright (C) 1998-2003 VideoLAN
* *
* Authors: Johan Bilien <jobi@via.ecp.fr> * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -47,7 +48,8 @@ ...@@ -47,7 +48,8 @@
#include "dvb.h" #include "dvb.h"
#define SATELLITE_READ_ONCE 3 #define SATELLITE_READ_ONCE 80
#define DMX_BUFFER_SIZE (1024 * 1024)
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -77,6 +79,10 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -77,6 +79,10 @@ int E_(Open) ( vlc_object_t *p_this )
int i_lnb_lof1; int i_lnb_lof1;
int i_lnb_lof2; int i_lnb_lof2;
int i_lnb_slof; 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 : */ /* parse the options passed in command line : */
...@@ -115,14 +121,14 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -115,14 +121,14 @@ int E_(Open) ( vlc_object_t *p_this )
{ {
msg_Warn( p_input, "invalid frequency, using default one" ); msg_Warn( p_input, "invalid frequency, using default one" );
i_freq = config_GetInt( p_input, "frequency" ); 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" ); msg_Err( p_input, "invalid default frequency" );
return -1; 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" ); msg_Warn( p_input, "invalid symbol rate, using default one" );
i_srate = config_GetInt( p_input, "symbol-rate" ); i_srate = config_GetInt( p_input, "symbol-rate" );
...@@ -133,7 +139,7 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -133,7 +139,7 @@ int E_(Open) ( vlc_object_t *p_this )
} }
} }
if( b_pol && b_pol != 1 ) if( i_freq && b_pol && b_pol != 1 )
{ {
msg_Warn( p_input, "invalid polarization, using default one" ); msg_Warn( p_input, "invalid polarization, using default one" );
b_pol = config_GetInt( p_input, "polarization" ); b_pol = config_GetInt( p_input, "polarization" );
...@@ -144,7 +150,7 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -144,7 +150,7 @@ int E_(Open) ( vlc_object_t *p_this )
} }
} }
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" ); msg_Warn( p_input, "invalid FEC, using default one" );
i_fec = config_GetInt( p_input, "fec" ); i_fec = config_GetInt( p_input, "fec" );
...@@ -155,32 +161,35 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -155,32 +161,35 @@ int E_(Open) ( vlc_object_t *p_this )
} }
} }
switch( i_fec ) if ( i_freq )
{ {
case 1: switch( i_fec )
f_fec = 1./2; {
break; case 1:
case 2: f_fec = 1./2;
f_fec = 2./3; break;
break; case 2:
case 3: f_fec = 2./3;
f_fec = 3./4; break;
break; case 3:
case 4: f_fec = 3./4;
f_fec = 4./5; break;
break; case 4:
case 5: f_fec = 4./5;
f_fec = 5./6; break;
break; case 5:
case 6: f_fec = 5./6;
f_fec = 6./7; break;
break; case 6:
case 7: f_fec = 6./7;
f_fec = 7./8; break;
break; case 7:
default: f_fec = 7./8;
/* cannot happen */ break;
break; default:
/* cannot happen */
break;
}
} }
...@@ -196,16 +205,21 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -196,16 +205,21 @@ int E_(Open) ( vlc_object_t *p_this )
p_input->p_access_data = (void *)p_satellite; p_input->p_access_data = (void *)p_satellite;
/* Open the DVR device */ /* 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) ) /*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 ); free( p_satellite );
return -1; 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 */ /* Get antenna configuration options */
b_diseqc = config_GetInt( p_input, "diseqc" ); b_diseqc = config_GetInt( p_input, "diseqc" );
i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" ); i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
...@@ -214,58 +228,63 @@ int E_(Open) ( vlc_object_t *p_this ) ...@@ -214,58 +228,63 @@ int E_(Open) ( vlc_object_t *p_this )
/* Initialize the Satellite Card */ /* Initialize the Satellite Card */
msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, " if ( i_freq )
"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 )
{ {
msg_Err( p_input, "an error occured when controling SEC" ); int i_tuner = config_GetInt( p_input, "dvb-tuner" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
}
msg_Dbg( p_input, "initializing frontend device" ); msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
switch (ioctl_SetQPSKFrontend ( i_freq, i_srate, f_fec, "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
i_lnb_lof1, i_lnb_lof2, i_lnb_slof))
{ if ( ioctl_SECControl( i_tuner, i_freq, b_pol, i_lnb_slof, b_diseqc ) < 0 )
case -2: {
msg_Err( p_input, "frontend returned an unexpected event" ); msg_Err( p_input, "an error occured when controling SEC" );
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 ); close( p_satellite->i_handle );
free( p_satellite ); free( p_satellite );
return -1; 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" ); 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" ); msg_Err( p_input, "an error occured when setting filter on PAT" );
close( p_satellite->i_handle ); close( p_satellite->i_handle );
...@@ -332,19 +351,30 @@ static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer, ...@@ -332,19 +351,30 @@ static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
{ {
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data; input_socket_t * p_access_data = (input_socket_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;
/* if not set, set filters to the PMTs */ /* 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++ ) 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 ); 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, &p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
3 ); 3 ) < 0)
{
msg_Err(p_input, "ioctl_SetDMXFilter failed");
}
} }
} }
...@@ -380,6 +410,7 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -380,6 +410,7 @@ 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 )
{ {
...@@ -402,7 +433,7 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -402,7 +433,7 @@ int SatelliteSetProgram( input_thread_t * p_input,
} }
} }
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 )
...@@ -410,22 +441,57 @@ int SatelliteSetProgram( input_thread_t * p_input, ...@@ -410,22 +441,57 @@ int SatelliteSetProgram( input_thread_t * p_input,
case MPEG1_VIDEO_ES: case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES: case MPEG2_VIDEO_ES:
case MPEG2_MOTO_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; break;
case MPEG1_AUDIO_ES: case MPEG1_AUDIO_ES:
case MPEG2_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 ); input_SelectES( p_input , p_es );
} }
break; break;
default: default:
ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3); /* Do not select private streams. This is to avoid the
input_SelectES( p_input , p_es ); * 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; break;
#undef p_es #undef p_es
} }
......
...@@ -50,13 +50,16 @@ ...@@ -50,13 +50,16 @@
*****************************************************************************/ *****************************************************************************/
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 secCommand scmd;
struct secCmdSequence scmds; struct secCmdSequence scmds;
int sec; 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; return -1;
} }
...@@ -100,15 +103,18 @@ static int check_qpsk( int ); ...@@ -100,15 +103,18 @@ static int check_qpsk( int );
* ioctl_SetQPSKFrontend : controls the FE device * 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) int lnb_lof1, int lnb_lof2, int lnb_slof)
{ {
FrontendParameters fep; FrontendParameters fep;
int front; int front;
int rc; int rc;
char psz_fe[255];
snprintf(psz_fe, sizeof(psz_fe), FRONTEND "%d", fe_nb);
/* Open the frontend device */ /* Open the frontend device */
if((front = open(FRONTEND,O_RDWR)) < 0) if((front = open(psz_fe, O_RDWR)) < 0)
{ {
return -1; return -1;
} }
...@@ -187,12 +193,15 @@ static int check_qpsk(int front) ...@@ -187,12 +193,15 @@ static int check_qpsk(int front)
* ioctl_SetDMXAudioFilter : controls the demux to add a filter * 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; struct dmxPesFilterParams s_filter_params;
char psz_dmx[255];
snprintf(psz_dmx, sizeof(psz_dmx), DMX "%d", dmx_nb);
/* We first open the device */ /* 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; return -1;
} }
...@@ -203,6 +212,12 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type ) ...@@ -203,6 +212,12 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
s_filter_params.output = DMX_OUT_TS_TAP; s_filter_params.output = DMX_OUT_TS_TAP;
switch ( i_type ) 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: case 1:
s_filter_params.pesType = DMX_PES_VIDEO; s_filter_params.pesType = DMX_PES_VIDEO;
break; break;
...@@ -210,6 +225,8 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type ) ...@@ -210,6 +225,8 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
s_filter_params.pesType = DMX_PES_AUDIO; s_filter_params.pesType = DMX_PES_AUDIO;
break; break;
case 3: case 3:
#endif
default:
s_filter_params.pesType = DMX_PES_OTHER; s_filter_params.pesType = DMX_PES_OTHER;
break; break;
} }
...@@ -233,3 +250,12 @@ int ioctl_UnsetDMXFilter(int demux) ...@@ -233,3 +250,12 @@ int ioctl_UnsetDMXFilter(int demux)
close(demux); close(demux);
return 0; return 0;
} }
/*****************************************************************************
* ioctl_SetBufferSize :
*****************************************************************************/
int ioctl_SetBufferSize(int handle, size_t size)
{
return ioctl(handle, DMX_SET_BUFFER_SIZE, size);
}
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
/***************************************************************************** /*****************************************************************************
* Prototypes * Prototypes
*****************************************************************************/ *****************************************************************************/
int ioctl_SECControl( int , int , int , int ); int ioctl_SECControl( int, int , int , int , int );
int ioctl_SetQPSKFrontend ( int , int , int , int , int , int ); int ioctl_SetQPSKFrontend ( int, int , int , int , int , int , int );
int ioctl_SetDMXFilter( int , int *, int ); int ioctl_SetDMXFilter( int, int , int *, int );
int ioctl_UnsetDMXFilter( int ); int ioctl_UnsetDMXFilter( int );
int ioctl_SetBufferSize( int, size_t );
...@@ -38,6 +38,12 @@ void E_(Close) ( vlc_object_t * ); ...@@ -38,6 +38,12 @@ void E_(Close) ( vlc_object_t * );
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
#define DEMUX_TEXT N_("Demux number")
#define DEMUX_LONGTEXT ""
#define TUNER_TEXT N_("Tuner number")
#define TUNER_LONGTEXT ""
#define FREQ_TEXT N_("Satellite default transponder frequency (KHz)") #define FREQ_TEXT N_("Satellite default transponder frequency (KHz)")
#define FREQ_LONGTEXT "" #define FREQ_LONGTEXT ""
...@@ -64,7 +70,11 @@ void E_(Close) ( vlc_object_t * ); ...@@ -64,7 +70,11 @@ void E_(Close) ( vlc_object_t * );
vlc_module_begin(); vlc_module_begin();
add_category_hint( N_("Input"), NULL, VLC_FALSE ); add_category_hint( N_("Input"), NULL, VLC_FALSE );
add_integer( "frequency", 11954000, NULL, FREQ_TEXT, FREQ_LONGTEXT, add_integer( "dvb-dmx", 0, NULL, DEMUX_TEXT, DEMUX_LONGTEXT,
VLC_FALSE );
add_integer( "dvb-tuner", 0, NULL, TUNER_TEXT, TUNER_LONGTEXT,
VLC_FALSE );
add_integer( "frequency", 0, NULL, FREQ_TEXT, FREQ_LONGTEXT,
VLC_FALSE ); VLC_FALSE );
add_integer( "polarization", 0, NULL, POL_TEXT, POL_LONGTEXT, add_integer( "polarization", 0, NULL, POL_TEXT, POL_LONGTEXT,
VLC_FALSE ); VLC_FALSE );
......
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