]> git.sesse.net Git - vlc/commitdiff
* modules/access/satellite: Big rework of the old satellite module.
authorChristophe Massiot <massiot@videolan.org>
Fri, 7 Nov 2003 13:28:23 +0000 (13:28 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 7 Nov 2003 13:28:23 +0000 (13:28 +0000)
  - 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.

modules/access/satellite/access.c
modules/access/satellite/dvb.c
modules/access/satellite/dvb.h
modules/access/satellite/satellite.c

index 44e4b0461c2a28d84dad60b318db68af158ed412..55200f669c5d09b5371c7fe94f2374c1adc4c3b4 100644 (file)
@@ -1,9 +1,10 @@
 /*****************************************************************************
  * 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
@@ -47,7 +48,8 @@
 
 #include "dvb.h"
 
-#define SATELLITE_READ_ONCE 3
+#define SATELLITE_READ_ONCE 80
+#define DMX_BUFFER_SIZE (1024 * 1024)
 
 /*****************************************************************************
  * Local prototypes
@@ -77,6 +79,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 : */
 
@@ -115,14 +121,14 @@ int E_(Open) ( vlc_object_t *p_this )
     {
         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" );
@@ -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" );
         b_pol = config_GetInt( p_input, "polarization" );
@@ -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" );
         i_fec = config_GetInt( p_input, "fec" );
@@ -155,32 +161,35 @@ 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;
+        }
     }
 
 
@@ -196,16 +205,21 @@ int E_(Open) ( vlc_object_t *p_this )
     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" );
@@ -214,58 +228,63 @@ 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, 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 );
@@ -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;
     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");
+            }
         }
     }
 
@@ -380,6 +410,7 @@ int SatelliteSetProgram( input_thread_t    * p_input,
 {
     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 )
     {
@@ -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]
         switch( p_es->i_cat )
@@ -410,22 +441,57 @@ int SatelliteSetProgram( input_thread_t    * p_input,
             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
         }
index 563b63032b118e92206be075f9e43d31fd921ecc..2e5809b080e10122cf11d8d1aef6bfa886527f0a 100644 (file)
  *****************************************************************************/
 
 
-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;
     }
@@ -100,15 +103,18 @@ static int check_qpsk( int );
  * 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;
     }
@@ -187,12 +193,15 @@ static int check_qpsk(int front)
  * 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;
     }
@@ -203,6 +212,12 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
     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;
@@ -210,6 +225,8 @@ int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type )
             s_filter_params.pesType =   DMX_PES_AUDIO;
             break;
         case 3:
+#endif
+        default:
             s_filter_params.pesType =   DMX_PES_OTHER;
             break;
     }
@@ -233,3 +250,12 @@ int ioctl_UnsetDMXFilter(int demux)
     close(demux);
     return 0;
 }
+
+
+/*****************************************************************************
+ * ioctl_SetBufferSize :
+ *****************************************************************************/
+int ioctl_SetBufferSize(int handle, size_t size)
+{
+    return ioctl(handle, DMX_SET_BUFFER_SIZE, size);
+}
index ada004897c8cd34b6b71304a32010f65732c5344..178f551896e955ac9cb184f093b3052c97dee2c2 100644 (file)
@@ -33,7 +33,8 @@
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
-int ioctl_SECControl( int , int , int , int );
-int ioctl_SetQPSKFrontend ( int , int , int , int , int , int );
-int ioctl_SetDMXFilter( int , int *, int );
+int ioctl_SECControl( int, int , int , int , int );
+int ioctl_SetQPSKFrontend ( int, int , int , int , int , int , int );
+int ioctl_SetDMXFilter( int, int , int *, int );
 int ioctl_UnsetDMXFilter( int );
+int ioctl_SetBufferSize( int, size_t );
index 2740d002223ecf1e41f3418aeee2b6825064d750..bc1034fdeab7ea26ab608d22be32f037c35b870a 100644 (file)
@@ -38,6 +38,12 @@ void E_(Close)   ( vlc_object_t * );
  * 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_LONGTEXT ""
 
@@ -64,7 +70,11 @@ void E_(Close)   ( vlc_object_t * );
 
 vlc_module_begin();
     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 );
         add_integer( "polarization", 0, NULL, POL_TEXT, POL_LONGTEXT,
                      VLC_FALSE );