X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fsatellite%2Faccess.c;h=23819a02e78f6b11a259bccf103c31fb8ab8b821;hb=f0251c53bd46a47a96563aece4054399c450f7ba;hp=fc32d9399b80a6b7e48d23b0cdaa998093fb4bff;hpb=66c62b438630d3836cfe5c15226ae0a9db89a342;p=vlc diff --git a/modules/access/satellite/access.c b/modules/access/satellite/access.c index fc32d9399b..23819a02e7 100644 --- a/modules/access/satellite/access.c +++ b/modules/access/satellite/access.c @@ -1,9 +1,10 @@ /***************************************************************************** * access.c: Satellite card input ***************************************************************************** - * Copyright (C) 1998-2002 VideoLAN + * Copyright (C) 1998-2003 VideoLAN * * Authors: Johan Bilien + * Christophe Massiot * * 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 @@ -47,7 +48,10 @@ #include "dvb.h" -#define SATELLITE_READ_ONCE 3 +/* These are for the Dreambox port. I have no idea whether they're correct + * for other DVB adapters. --Meuuh */ +#define SATELLITE_READ_ONCE (64 * 1024) +#define DMX_BUFFER_SIZE (1024 * 1024) /***************************************************************************** * Local prototypes @@ -58,16 +62,74 @@ static int SatelliteSetArea ( input_thread_t *, input_area_t * ); static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_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 *****************************************************************************/ int E_(Open) ( vlc_object_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_next; - int i_fd = 0; int i_freq = 0; int i_srate = 0; vlc_bool_t b_pol = 0; @@ -77,6 +139,10 @@ int E_(Open) ( vlc_object_t *p_this ) 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 : */ @@ -111,29 +177,29 @@ int E_(Open) ( vlc_object_t *p_this ) } - if( i_freq > 12999 || i_freq < 10000 ) + if( i_freq > (12999*1000) || i_freq < (10000*1000) ) { msg_Warn( p_input, "invalid frequency, using default one" ); i_freq = config_GetInt( p_input, "frequency" ); - if( i_freq > 12999 || i_freq < 10000 ) + if( i_freq && (i_freq > (12999*1000) || i_freq < (10000*1000)) ) { msg_Err( p_input, "invalid default frequency" ); return -1; } } - if( i_srate > 30000 || i_srate < 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( i_srate > 30000 || i_srate < 1000 ) + if( i_srate > (30000*1000) || i_srate < (1000*1000) ) { msg_Err( p_input, "invalid default symbol rate" ); return -1; } } - 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" ); @@ -144,7 +210,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" ); i_fec = config_GetInt( p_input, "fec" ); @@ -155,57 +221,65 @@ int E_(Open) ( vlc_object_t *p_this ) } } - 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; + } } /* Initialise structure */ - p_satellite = malloc( sizeof( input_socket_t ) ); + p_satellite = malloc( sizeof( thread_sat_data_t ) ); if( p_satellite == NULL ) { msg_Err( p_input, "out of memory" ); return -1; } + memset( p_satellite, 0, sizeof( thread_sat_data_t ) ); 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" ); @@ -215,65 +289,62 @@ int E_(Open) ( vlc_object_t *p_this ) /* 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 * 1000, b_pol, i_lnb_slof * 1000, - 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 * 1000, i_srate* 1000, f_fec, - i_lnb_lof1 * 1000, i_lnb_lof2 * 1000, i_lnb_slof * 1000)) - { - 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 occurred when controling SEC" ); close( p_satellite->i_handle ); free( p_satellite ); return -1; - break; - default: - break; - } + } - msg_Dbg( p_input, "setting filter on PAT" ); + 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 */ - if ( ioctl_SetDMXFilter( 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; - } + msg_Dbg( p_input, "setting filter on PAT" ); + AllocateDemux( p_input, 0, PAT_TYPE ); if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 ) { @@ -291,7 +362,7 @@ int E_(Open) ( vlc_object_t *p_this ) vlc_mutex_unlock( &p_input->stream.stream_lock ); - p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE; + p_input->i_mtu = SATELLITE_READ_ONCE; p_input->stream.i_method = INPUT_METHOD_SATELLITE; return 0; @@ -303,57 +374,62 @@ int E_(Open) ( vlc_object_t *p_this ) void E_(Close) ( vlc_object_t *p_this ) { input_thread_t * p_input = (input_thread_t *)p_this; - input_socket_t * p_satellite; - int i_es_index; + thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data; - if ( p_input->stream.p_selected_program ) - { - for ( i_es_index = 1 ; - 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_decoder_fifo ) - { - ioctl_UnsetDMXFilter( p_es->i_demux_fd ); - } -#undef p_es - } - } + msg_Dbg( p_input, "unsetting filters on all pids" ); + CloseProgram( p_input ); + close( p_satellite->p_demux_handles[0].i_handle ); - p_satellite = (input_socket_t *)p_input; close( p_satellite->i_handle ); } - /***************************************************************************** * SatelliteRead: reads data from the satellite card *****************************************************************************/ static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer, - size_t i_len ) + size_t i_len ) { - int i; + thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data; + ssize_t i_ret; + + unsigned int i; /* if not set, set filters to the PMTs */ - for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) + /* 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 */ + if ( !p_satellite->p_demux_handles[1].i_type ) { - if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 ) + int i_program = config_GetInt( p_input, "program" ); + + for( i = 0; i < p_input->stream.i_pgrm_number; i++ ) { - 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, - &p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd, - 3 ); + /* 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) ) + { + 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 ); + } } } - return input_FDRead( p_input, p_buffer, i_len ); + i_ret = read( p_satellite->i_handle, p_buffer, i_len ); + + if( i_ret < 0 ) + { +# ifdef HAVE_ERRNO_H + msg_Err( p_input, "read failed (%s)", strerror(errno) ); +# else + msg_Err( p_input, "read failed" ); +# endif + } + + return i_ret; } - - - /***************************************************************************** * SatelliteSetArea : Does nothing *****************************************************************************/ @@ -370,53 +446,70 @@ static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area ) int SatelliteSetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg ) { - int i_es_index; + unsigned int i_es_index; + vlc_value_t val; 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_number ; i_es_index ++ ) { #define p_es p_input->stream.p_selected_program->pp_es[i_es_index] - if ( p_es->p_decoder_fifo ) + if ( p_es->p_dec ) { 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 } } - for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ ) + 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 ++ ) { #define p_es p_new_prg->pp_es[i_es_index] switch( p_es->i_cat ) { - case MPEG1_VIDEO_ES: - case MPEG2_VIDEO_ES: - if ( config_GetInt( p_input, "video" ) ) - { - ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1); - input_SelectES( p_input , p_es ); - } + case VIDEO_ES: + msg_Dbg(p_input, "setting filter on video ES 0x%x", + p_es->i_id); + /* Always 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 */ + AllocateDemux( p_input, p_es->i_id, ES_TYPE ); + input_SelectES( p_input , p_es ); break; - case MPEG1_AUDIO_ES: - case MPEG2_AUDIO_ES: - if ( config_GetInt( p_input, "audio" ) ) - { - ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2); - input_SelectES( p_input , p_es ); - } + + case AUDIO_ES: + msg_Dbg(p_input, "setting filter on audio ES 0x%x", + p_es->i_id); + AllocateDemux( p_input, p_es->i_id, ES_TYPE ); + input_SelectES( p_input , p_es ); break; + default: - ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3); + /* 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); + AllocateDemux( p_input, p_es->i_id, ES_TYPE ); input_SelectES( p_input , p_es ); +#endif break; #undef p_es } @@ -424,7 +517,11 @@ int SatelliteSetProgram( input_thread_t * p_input, p_input->stream.p_selected_program = p_new_prg; - return( 0 ); + /* Update the navigation variables without triggering a callback */ + val.i_int = p_new_prg->i_number; + var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL ); + + return 0; } /***************************************************************************** @@ -432,5 +529,6 @@ int SatelliteSetProgram( input_thread_t * p_input, *****************************************************************************/ static void SatelliteSeek( input_thread_t * p_input, off_t i_off ) { - return; + ; } +