access.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:17k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * access.c: Satellite card input
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2003 VideoLAN
  5.  *
  6.  * Authors: Johan Bilien <jobi@via.ecp.fr>
  7.  *          Christophe Massiot <massiot@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <vlc/vlc.h>
  29. #include <vlc/input.h>
  30. #include "../../demux/mpeg/system.h"
  31. #ifdef HAVE_UNISTD_H
  32. #   include <unistd.h>
  33. #endif
  34. #include <fcntl.h>
  35. #include <sys/types.h>
  36. #include <string.h>
  37. #include <errno.h>
  38. #ifdef STRNCASECMP_IN_STRINGS_H
  39. #   include <strings.h>
  40. #endif
  41. #include "dvb.h"
  42. /* These are for the Dreambox port. I have no idea whether they're correct
  43.  * for other DVB adapters. --Meuuh */
  44. #define SATELLITE_READ_ONCE (64 * 1024)
  45. #define DMX_BUFFER_SIZE (1024 * 1024)
  46. /*****************************************************************************
  47.  * Local prototypes
  48.  *****************************************************************************/
  49. static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
  50.                                      size_t i_len );
  51. static int     SatelliteSetArea    ( input_thread_t *, input_area_t * );
  52. static int     SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
  53. static void    SatelliteSeek       ( input_thread_t *, off_t );
  54. typedef struct demux_handle_t
  55. {
  56.     int i_pid;
  57.     int i_handle;
  58.     int i_type;
  59. } demux_handle_t;
  60. #define PAT_TYPE 1
  61. #define PMT_TYPE 2
  62. #define ES_TYPE 3
  63. #define MAX_DEMUX 8 
  64. typedef struct thread_sat_data_t
  65. {
  66.     int i_handle;
  67.     demux_handle_t p_demux_handles[MAX_DEMUX];
  68. } thread_sat_data_t;
  69. static void AllocateDemux( input_thread_t * p_input, int i_pid,
  70.                            int i_type )
  71. {
  72.     thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
  73.     int                 i_demux;
  74.     int                 i;
  75.     i_demux = config_GetInt( p_input, "dvb-dmx" );
  76.     /* Find first free slot */
  77.     for ( i = 0; i < MAX_DEMUX; i++ )
  78.     {
  79.         if ( !p_satellite->p_demux_handles[i].i_type )
  80.         {
  81.             if (ioctl_SetDMXFilter( i_demux, i_pid, &p_satellite->p_demux_handles[i].i_handle, 3) < 0)
  82.             {
  83.                 msg_Warn(p_input, "ioctl_SetDMXFilter failed (%d)", i_pid);
  84.                 break;
  85.             }
  86.             p_satellite->p_demux_handles[i].i_type = i_type;
  87.             p_satellite->p_demux_handles[i].i_pid = i_pid;
  88.             break;
  89.         }
  90.     }
  91. }
  92. static void CloseProgram( input_thread_t * p_input )
  93. {
  94.     thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
  95.     int i;
  96.     for ( i = 1; i < MAX_DEMUX; i++ )
  97.     {
  98.         if ( p_satellite->p_demux_handles[i].i_type )
  99.         {
  100.             ioctl_UnsetDMXFilter( p_satellite->p_demux_handles[i].i_handle );
  101.             p_satellite->p_demux_handles[i].i_type = 0;
  102.         }
  103.     }
  104. }
  105. /*****************************************************************************
  106.  * Open: open the dvr device
  107.  *****************************************************************************/
  108. int E_(Open) ( vlc_object_t *p_this )
  109. {
  110.     input_thread_t *    p_input = (input_thread_t *)p_this;
  111.     thread_sat_data_t * p_satellite;
  112.     char *              psz_parser;
  113.     char *              psz_next;
  114.     int                 i_freq = 0;
  115.     int                 i_srate = 0;
  116.     vlc_bool_t          b_pol = 0;
  117.     int                 i_fec = 0;
  118.     float               f_fec = 1./2;
  119.     vlc_bool_t          b_diseqc;
  120.     int                 i_lnb_lof1;
  121.     int                 i_lnb_lof2;
  122.     int                 i_lnb_slof;
  123.     int                 i_demux;
  124.     char                psz_dvr[255];
  125.     i_demux = config_GetInt( p_input, "dvb-dmx" );
  126.     snprintf(psz_dvr, sizeof(psz_dvr), DVR "%d", i_demux);
  127.     /* parse the options passed in command line : */
  128.     psz_parser = strdup( p_input->psz_name );
  129.     if( !psz_parser )
  130.     {
  131.         return( -1 );
  132.     }
  133.     p_input->pf_read = SatelliteRead;
  134.     p_input->pf_set_program = SatelliteSetProgram;
  135.     p_input->pf_set_area = SatelliteSetArea;
  136.     p_input->pf_seek = SatelliteSeek;
  137.     i_freq = (int)strtol( psz_parser, &psz_next, 10 );
  138.     if( *psz_next )
  139.     {
  140.         psz_parser = psz_next + 1;
  141.         b_pol = (vlc_bool_t)strtol( psz_parser, &psz_next, 10 );
  142.             if( *psz_next )
  143.             {
  144.                 psz_parser = psz_next + 1;
  145.                 i_fec = (int)strtol( psz_parser, &psz_next, 10 );
  146.                 if( *psz_next )
  147.                 {
  148.                     psz_parser = psz_next + 1;
  149.                     i_srate = (int)strtol( psz_parser, &psz_next, 10 );
  150.                 }
  151.             }
  152.     }
  153.     if( i_freq > (12999*1000) || i_freq < (10000*1000) )
  154.     {
  155.         msg_Warn( p_input, "invalid frequency, using default one" );
  156.         i_freq = config_GetInt( p_input, "frequency" );
  157.         if( i_freq && (i_freq > (12999*1000) || i_freq < (10000*1000)) )
  158.         {
  159.             msg_Err( p_input, "invalid default frequency" );
  160.             return -1;
  161.         }
  162.     }
  163.     if( i_freq && (i_srate > (30000*1000) || i_srate < (1000*1000)) )
  164.     {
  165.         msg_Warn( p_input, "invalid symbol rate, using default one" );
  166.         i_srate = config_GetInt( p_input, "symbol-rate" );
  167.         if( i_srate > (30000*1000) || i_srate < (1000*1000) )
  168.         {
  169.             msg_Err( p_input, "invalid default symbol rate" );
  170.             return -1;
  171.         }
  172.     }
  173.     if( i_freq && b_pol && b_pol != 1 )
  174.     {
  175.         msg_Warn( p_input, "invalid polarization, using default one" );
  176.         b_pol = config_GetInt( p_input, "polarization" );
  177.         if( b_pol && b_pol != 1 )
  178.         {
  179.             msg_Err( p_input, "invalid default polarization" );
  180.             return -1;
  181.         }
  182.     }
  183.     if( i_freq && (i_fec > 7 || i_fec < 1) )
  184.     {
  185.         msg_Warn( p_input, "invalid FEC, using default one" );
  186.         i_fec = config_GetInt( p_input, "fec" );
  187.         if( i_fec > 7 || i_fec < 1 )
  188.         {
  189.             msg_Err( p_input, "invalid default FEC" );
  190.             return -1;
  191.         }
  192.     }
  193.     if ( i_freq )
  194.     {
  195.         switch( i_fec )
  196.         {
  197.             case 1:
  198.                 f_fec = 1./2;
  199.                 break;
  200.             case 2:
  201.                 f_fec = 2./3;
  202.                 break;
  203.             case 3:
  204.                 f_fec = 3./4;
  205.                 break;
  206.             case 4:
  207.                 f_fec = 4./5;
  208.                 break;
  209.             case 5:
  210.                 f_fec = 5./6;
  211.                 break;
  212.             case 6:
  213.                 f_fec = 6./7;
  214.                 break;
  215.             case 7:
  216.                 f_fec = 7./8;
  217.                 break;
  218.             default:
  219.                 /* cannot happen */
  220.                 break;
  221.         }
  222.     }
  223.     /* Initialise structure */
  224.     p_satellite = malloc( sizeof( thread_sat_data_t ) );
  225.     if( p_satellite == NULL )
  226.     {
  227.         msg_Err( p_input, "out of memory" );
  228.         return -1;
  229.     }
  230.     memset( p_satellite, 0, sizeof( thread_sat_data_t ) );
  231.     p_input->p_access_data = (void *)p_satellite;
  232.     /* Open the DVR device */
  233.     msg_Dbg( p_input, "opening DVR device `%s'", psz_dvr );
  234.     if( (p_satellite->i_handle = open( psz_dvr,
  235.                                    /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
  236.     {
  237.         msg_Warn( p_input, "cannot open `%s' (%s)", psz_dvr, strerror(errno) );
  238.         free( p_satellite );
  239.         return -1;
  240.     }
  241.     /* FIXME : this is from the Dreambox port. I have no idea whether it
  242.      * hurts or helps other DVB interfaces, so I just leave it here.
  243.      * Feel free to remove it if it breaks. --Meuuh */
  244.     ioctl_SetBufferSize( p_satellite->i_handle, DMX_BUFFER_SIZE );
  245.     /* Get antenna configuration options */
  246.     b_diseqc = config_GetInt( p_input, "diseqc" );
  247.     i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
  248.     i_lnb_lof2 = config_GetInt( p_input, "lnb-lof2" );
  249.     i_lnb_slof = config_GetInt( p_input, "lnb-slof" );
  250.     /* Initialize the Satellite Card */
  251.     if ( i_freq )
  252.     {
  253.         int i_tuner = config_GetInt( p_input, "dvb-tuner" );
  254.         msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
  255.                           "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
  256.         if ( ioctl_SECControl( i_tuner, i_freq, b_pol, i_lnb_slof, b_diseqc ) < 0 )
  257.         {
  258.             msg_Err( p_input, "an error occurred when controling SEC" );
  259.             close( p_satellite->i_handle );
  260.             free( p_satellite );
  261.             return -1;
  262.         }
  263.         msg_Dbg( p_input, "initializing frontend device" );
  264.         switch (ioctl_SetQPSKFrontend ( i_tuner, i_freq, i_srate, f_fec,
  265.                     i_lnb_lof1, i_lnb_lof2, i_lnb_slof))
  266.         {
  267.             case -2:
  268.                 msg_Err( p_input, "frontend returned an unexpected event" );
  269.                 close( p_satellite->i_handle );
  270.                 free( p_satellite );
  271.                 return -1;
  272.                 break;
  273.             case -3:
  274.                 msg_Err( p_input, "frontend returned no event" );
  275.                 close( p_satellite->i_handle );
  276.                 free( p_satellite );
  277.                 return -1;
  278.                 break;
  279.             case -4:
  280.                 msg_Err( p_input, "frontend: timeout when polling for event" );
  281.                 close( p_satellite->i_handle );
  282.                 free( p_satellite );
  283.                 return -1;
  284.                 break;
  285.             case -5:
  286.                 msg_Err( p_input, "an error occured when polling frontend device" );
  287.                 close( p_satellite->i_handle );
  288.                 free( p_satellite );
  289.                 return -1;
  290.                 break;
  291.             case -1:
  292.                 msg_Err( p_input, "frontend returned a failure event" );
  293.                 close( p_satellite->i_handle );
  294.                 free( p_satellite );
  295.                 return -1;
  296.                 break;
  297.             default:
  298.                 break;
  299.         }
  300.     } /* i_freq */
  301.     msg_Dbg( p_input, "setting filter on PAT" );
  302.     AllocateDemux( p_input, 0, PAT_TYPE );
  303.     if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
  304.     {
  305.         msg_Err( p_input, "could not initialize stream structure" );
  306.         close( p_satellite->i_handle );
  307.         free( p_satellite );
  308.         return( -1 );
  309.     }
  310.     vlc_mutex_lock( &p_input->stream.stream_lock );
  311.     p_input->stream.b_pace_control = 1;
  312.     p_input->stream.b_seekable = 0;
  313.     p_input->stream.p_selected_area->i_tell = 0;
  314.     vlc_mutex_unlock( &p_input->stream.stream_lock );
  315.     p_input->i_mtu = SATELLITE_READ_ONCE;
  316.     p_input->stream.i_method = INPUT_METHOD_SATELLITE;
  317.     return 0;
  318. }
  319. /*****************************************************************************
  320.  * Close : Close the device
  321.  *****************************************************************************/
  322. void E_(Close) ( vlc_object_t *p_this )
  323. {
  324.     input_thread_t *    p_input = (input_thread_t *)p_this;
  325.     thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
  326.     msg_Dbg( p_input, "unsetting filters on all pids" );
  327.     CloseProgram( p_input );
  328.     close( p_satellite->p_demux_handles[0].i_handle );
  329.     close( p_satellite->i_handle );
  330. }
  331. /*****************************************************************************
  332.  * SatelliteRead: reads data from the satellite card
  333.  *****************************************************************************/
  334. static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
  335.                               size_t i_len )
  336. {
  337.     thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
  338.     ssize_t i_ret;
  339.     unsigned int i;
  340.     /* if not set, set filters to the PMTs */
  341.     /* This is kludgy and consumes way too much CPU power - the access
  342.      * module should have a callback from the demux when a new program
  343.      * is encountered. --Meuuh */
  344.     if ( !p_satellite->p_demux_handles[1].i_type )
  345.     {
  346.         int i_program = config_GetInt( p_input, "program" );
  347.         for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
  348.         {
  349.             /* Only set a filter on the selected program : some boards
  350.              * (read: Dreambox) only have 8 filters, so you don't want to
  351.              * spend them on unwanted PMTs. --Meuuh */
  352.             if ( (!i_program || p_input->stream.pp_programs[i]->i_number == i_program) )
  353.             {
  354.                 msg_Dbg( p_input, "setting filter on PMT pid %d",
  355.                          p_input->stream.pp_programs[i]->pp_es[0]->i_id );
  356.                 AllocateDemux( p_input, p_input->stream.pp_programs[i]->pp_es[0]->i_id, PMT_TYPE );
  357.             }
  358.         }
  359.     }
  360.     i_ret = read( p_satellite->i_handle, p_buffer, i_len );
  361.  
  362.     if( i_ret < 0 )
  363.     {
  364. #   ifdef HAVE_ERRNO_H
  365.         msg_Err( p_input, "read failed (%s)", strerror(errno) );
  366. #   else
  367.         msg_Err( p_input, "read failed" );
  368. #   endif
  369.     }
  370.  
  371.     return i_ret;
  372. }
  373. /*****************************************************************************
  374.  * SatelliteSetArea : Does nothing
  375.  *****************************************************************************/
  376. static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
  377. {
  378.     return -1;
  379. }
  380. /*****************************************************************************
  381.  * SatelliteSetProgram : Sets the card filters according to the
  382.  *                 selected program,
  383.  *                 and makes the appropriate changes to stream structure.
  384.  *****************************************************************************/
  385. int SatelliteSetProgram( input_thread_t    * p_input,
  386.                          pgrm_descriptor_t * p_new_prg )
  387. {
  388.     unsigned int i_es_index;
  389.     vlc_value_t val;
  390.     if ( p_input->stream.p_selected_program )
  391.     {
  392.         for ( i_es_index = 0 ; /* 0 should be the PMT */
  393.                 i_es_index < p_input->stream.p_selected_program->
  394.                     i_es_number ;
  395.                 i_es_index ++ )
  396.         {
  397. #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
  398.             if ( p_es->p_dec )
  399.             {
  400.                 input_UnselectES( p_input , p_es );
  401.             }
  402. #undef p_es
  403.         }
  404.     }
  405.     msg_Dbg( p_input, "unsetting filters on all pids" );
  406.     CloseProgram( p_input );
  407.     msg_Dbg( p_input, "setting filter on PMT pid %d",
  408.              p_new_prg->pp_es[0]->i_id );
  409.     AllocateDemux( p_input, p_new_prg->pp_es[0]->i_id, PMT_TYPE );
  410.     for ( i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
  411.     {
  412. #define p_es p_new_prg->pp_es[i_es_index]
  413.         switch( p_es->i_cat )
  414.         {
  415.             case VIDEO_ES:
  416.                 msg_Dbg(p_input, "setting filter on video ES 0x%x",
  417.                         p_es->i_id);
  418.                 /* Always set the filter. This may seem a little odd, but
  419.                  * it allows you to stream the video with demuxstream
  420.                  * without having a decoder or a stream output behind.
  421.                  * The result is you'll sometimes filter a PID which you
  422.                  * don't really want, but in the most common cases it
  423.                  * should be OK. --Meuuh */
  424.                 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
  425.                 input_SelectES( p_input , p_es );
  426.                 break;
  427.             case AUDIO_ES:
  428.                 msg_Dbg(p_input, "setting filter on audio ES 0x%x",
  429.                         p_es->i_id);
  430.                 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
  431.                 input_SelectES( p_input , p_es );
  432.                 break;
  433.             default:
  434.                 /* Do not select private streams. This is to avoid the
  435.                  * limit of 8 filters on the Dreambox and possibly on
  436.                  * other boards. We should probably change that to
  437.                  * have the DVB subtitles, but filtering all private
  438.                  * streams including DVB tables and padding seems
  439.                  * nonsense to me. --Meuuh */
  440. #if 0
  441.                 msg_Dbg(p_input, "setting filter on misc (0x%x) ES 0x%x",
  442.                         p_es->i_cat,
  443.                         p_es->i_id);
  444.                 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
  445.                 input_SelectES( p_input , p_es );
  446. #endif
  447.                 break;
  448. #undef p_es
  449.         }
  450.     }
  451.     p_input->stream.p_selected_program = p_new_prg;
  452.     /* Update the navigation variables without triggering a callback */
  453.     val.i_int = p_new_prg->i_number;
  454.     var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
  455.     return 0;
  456. }
  457. /*****************************************************************************
  458.  * SatelliteSeek: does nothing (not a seekable stream
  459.  *****************************************************************************/
  460. static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
  461. {
  462.     ;
  463. }