input_satellite.c 14.4 KB
Newer Older
Johan Bilien's avatar
 
Johan Bilien committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*****************************************************************************
 * input_satellite.c: Satellite card input
 *****************************************************************************
 * Copyright (C) 1998-2002 VideoLAN
 *
 * Authors: Johan Bilien <jobi@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
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#include <videolan/vlc.h>

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif

#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>

#ifdef STRNCASECMP_IN_STRINGS_H
#   include <strings.h>
#endif

#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
#include "input_ext-plugins.h"

#include "satellite_tools.h"

#define SATELLITE_READ_ONCE 3

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
57
58
59
60
61
62
63
static int     SatelliteOpen       ( input_thread_t * );
static void    SatelliteClose      ( input_thread_t * );
static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
                                     size_t i_len );
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 );
Johan Bilien's avatar
 
Johan Bilien committed
64
65
66
67
68
69
70
71
72
73

/*****************************************************************************
 * Functions exported as capabilities. They are declared as static so that
 * we don't pollute the namespace too much.
 *****************************************************************************/
void _M( access_getfunctions )( function_list_t * p_function_list )
{
#define access p_function_list->functions.access
    access.pf_open             = SatelliteOpen;
    access.pf_close            = SatelliteClose;
74
    access.pf_read             = SatelliteRead;
Johan Bilien's avatar
 
Johan Bilien committed
75
76
77
78
79
80
81
82
83
84
85
    access.pf_set_area         = SatelliteSetArea;
    access.pf_set_program      = SatelliteSetProgram;
    access.pf_seek             = SatelliteSeek;
#undef access
}

/*****************************************************************************
 * SatelliteOpen : open the dvr device
 *****************************************************************************/
static int SatelliteOpen( input_thread_t * p_input )
{
86
87
88
89
90
91
92
    input_socket_t *    p_satellite;
    char *              psz_parser;
    char *              psz_next;
    int                 i_fd = 0;
    int                 i_freq = 0;
    int                 i_srate = 0;
    boolean_t           b_pol = 0;
93
    int                 i_fec = 0;
94
95
96
97
98
    float               f_fec = 1./2;
    boolean_t           b_diseqc;
    int                 i_lnb_lof1;
    int                 i_lnb_lof2;
    int                 i_lnb_slof;
Johan Bilien's avatar
 
Johan Bilien committed
99
100

    /* parse the options passed in command line : */
Johan Bilien's avatar
   
Johan Bilien committed
101

Johan Bilien's avatar
 
Johan Bilien committed
102
    psz_parser = strdup( p_input->psz_name );
Johan Bilien's avatar
   
Johan Bilien committed
103

Johan Bilien's avatar
 
Johan Bilien committed
104
105
106
107
    if( !psz_parser )
    {
        return( -1 );
    }
Johan Bilien's avatar
   
Johan Bilien committed
108

Johan Bilien's avatar
 
Johan Bilien committed
109
    i_freq = (int)strtol( psz_parser, &psz_next, 10 );
Johan Bilien's avatar
   
Johan Bilien committed
110

111
    if( *psz_next )
Johan Bilien's avatar
 
Johan Bilien committed
112
113
114
    {
        psz_parser = psz_next + 1;
        b_pol = (boolean_t)strtol( psz_parser, &psz_next, 10 );
115
            if( *psz_next )
Johan Bilien's avatar
 
Johan Bilien committed
116
117
            {
                psz_parser = psz_next + 1;
118
119
120
121
122
123
                i_fec = (int)strtol( psz_parser, &psz_next, 10 );
                if( *psz_next )
                {
                    psz_parser = psz_next + 1;
                    i_srate = (int)strtol( psz_parser, &psz_next, 10 );
                }
Johan Bilien's avatar
 
Johan Bilien committed
124
125
126
127
            }

    }

128
129
    if( i_freq > 12999 || i_freq < 10000 )
    {
130
        intf_WarnMsg( 1, "input: satellite: invalid frequency, using "\
131
                "default one" );
132
133
134
135
136
137
        i_freq = config_GetIntVariable( "frequency" );
        if( i_freq > 12999 || i_freq < 10000 )
        {
            intf_ErrMsg( "input: satellite: invalid default frequency" );
            return -1;
        }
138
139
140
141
    }

    if( i_srate > 30000 || i_srate < 1000 )
    {
142
        intf_WarnMsg( 1, "input: satellite: invalid symbol rate, using "\
143
                "default one" );
144
        i_srate = config_GetIntVariable( "symbol-rate" );
145
146
147
148
149
        if( i_srate > 30000 || i_srate < 1000 )
        {
            intf_ErrMsg( "input: satellite: invalid default symbol rate" );
            return -1;
        }
150
151
    }

152
    if( b_pol && b_pol != 1 )
153
    {
154
        intf_WarnMsg( 1, "input: satellite: invalid polarization, using "\
155
                "default one" );
156
        b_pol = config_GetIntVariable( "polarization" );
157
158
159
160
161
162
        fprintf(stderr, "%d\n", b_pol);
        if( b_pol && b_pol != 1 )
        {
            intf_ErrMsg( "input: satellite: invalid default polarization" );
            return -1;
        }
163
164
165
166
    }

    if( i_fec > 7 || i_fec < 1 )
    {
167
        intf_WarnMsg( 1, "input: satellite: invalid FEC, using default one " );
168
        i_fec = config_GetIntVariable( "fec" );
169
170
171
172
173
        if( i_fec > 7 || i_fec < 1 )
        {
            intf_ErrMsg( "input: satellite: invalid default FEC" );
            return -1;
        }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    }

    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 */
201
            break;
202
    }
Johan Bilien's avatar
   
Johan Bilien committed
203
204


Johan Bilien's avatar
 
Johan Bilien committed
205
206
    /* Initialise structure */
    p_satellite = malloc( sizeof( input_socket_t ) );
Johan Bilien's avatar
   
Johan Bilien committed
207

Johan Bilien's avatar
 
Johan Bilien committed
208
209
210
211
212
213
214
    if( p_satellite == NULL )
    {
        intf_ErrMsg( "input: satellite: Out of memory" );
        return -1;
    }

    p_input->p_access_data = (void *)p_satellite;
Johan Bilien's avatar
   
Johan Bilien committed
215

Johan Bilien's avatar
 
Johan Bilien committed
216
    /* Open the DVR device */
Johan Bilien's avatar
   
Johan Bilien committed
217

Johan Bilien's avatar
 
Johan Bilien committed
218
    intf_WarnMsg( 2, "input: opening file `%s'", DVR);
Johan Bilien's avatar
   
Johan Bilien committed
219

Johan Bilien's avatar
 
Johan Bilien committed
220
221
222
223
    if( (p_satellite->i_handle = open( DVR,
                                   /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
    {
        intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
224
        free( p_satellite );
Johan Bilien's avatar
 
Johan Bilien committed
225
226
227
        return -1;
    }

Johan Bilien's avatar
   
Johan Bilien committed
228

229
    /* Get antenna configuration options */
230
231
232
233
    b_diseqc = config_GetIntVariable( "diseqc" );
    i_lnb_lof1 = config_GetIntVariable( "lnb-lof1" );
    i_lnb_lof2 = config_GetIntVariable( "lnb-lof2" );
    i_lnb_slof = config_GetIntVariable( "lnb-slof" );
234

Johan Bilien's avatar
 
Johan Bilien committed
235
236
    /* Initialize the Satellite Card */

237
238
239
    intf_WarnMsg( 2, "Initializing Sat Card with Freq: %d, Pol: %d, "\
                        "FEC: %03f, Srate: %d",
                        i_freq, b_pol, f_fec, i_srate );
Johan Bilien's avatar
   
Johan Bilien committed
240

241
    if ( ioctl_SECControl( i_freq * 1000, b_pol, i_lnb_slof * 1000,
242
                b_diseqc ) < 0 )
Johan Bilien's avatar
 
Johan Bilien committed
243
244
    {
        intf_ErrMsg("input: satellite: An error occured when controling SEC");
245
246
        close( p_satellite->i_handle );
        free( p_satellite );
Johan Bilien's avatar
 
Johan Bilien committed
247
248
        return -1;
    }
Johan Bilien's avatar
   
Johan Bilien committed
249

Johan Bilien's avatar
 
Johan Bilien committed
250
    intf_WarnMsg( 3, "Initializing Frontend device" );
251
    switch (ioctl_SetQPSKFrontend ( i_freq * 1000, i_srate* 1000, f_fec,
252
                i_lnb_lof1 * 1000, i_lnb_lof2 * 1000, i_lnb_slof * 1000))
Johan Bilien's avatar
 
Johan Bilien committed
253
254
    {
        case -2:
255
256
            intf_ErrMsg( "input: satellite: Frontend returned"\
                    "an unexpected event" );
Johan Bilien's avatar
 
Johan Bilien committed
257
258
259
260
261
            close( p_satellite->i_handle );
            free( p_satellite );
            return -1;
            break;
        case -3:
Johan Bilien's avatar
   
Johan Bilien committed
262
            intf_ErrMsg( "input: satellite: Frontend returned\
Johan Bilien's avatar
 
Johan Bilien committed
263
264
265
266
267
268
                    no event" );
            close( p_satellite->i_handle );
            free( p_satellite );
            return -1;
            break;
        case -4:
Johan Bilien's avatar
   
Johan Bilien committed
269
            intf_ErrMsg( "input: satellite: Frontend: time out\
Johan Bilien's avatar
 
Johan Bilien committed
270
271
272
273
274
275
                    when polling for event" );
            close( p_satellite->i_handle );
            free( p_satellite );
            return -1;
            break;
        case -5:
Johan Bilien's avatar
   
Johan Bilien committed
276
             intf_ErrMsg( "input: satellite: An error occured when polling\
Johan Bilien's avatar
 
Johan Bilien committed
277
278
279
280
281
282
                    Frontend device" );
            close( p_satellite->i_handle );
            free( p_satellite );
            return -1;
            break;
        case -1:
Johan Bilien's avatar
   
Johan Bilien committed
283
             intf_ErrMsg( "input: satellite: Frontend returned\
Johan Bilien's avatar
 
Johan Bilien committed
284
285
286
287
288
289
290
291
292
293
                    an failure event" );
            close( p_satellite->i_handle );
            free( p_satellite );
            return -1;
            break;
        default:
            break;
    }

    intf_WarnMsg( 3, " Setting filter on PAT " );
Johan Bilien's avatar
   
Johan Bilien committed
294

Johan Bilien's avatar
 
Johan Bilien committed
295
296
    if ( ioctl_SetDMXFilter( 0, &i_fd, 3 ) < 0 )
    {
Johan Bilien's avatar
   
Johan Bilien committed
297
        intf_ErrMsg( "input: satellite: An error occured when setting\
Johan Bilien's avatar
 
Johan Bilien committed
298
                filter on PAT" );
299
300
        close( p_satellite->i_handle );
        free( p_satellite );
Johan Bilien's avatar
 
Johan Bilien committed
301
302
303
304
305
        return -1;
    }

    if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
    {
Johan Bilien's avatar
   
Johan Bilien committed
306
        intf_ErrMsg( "input: satellite: Not enough memory to allow stream\
Johan Bilien's avatar
 
Johan Bilien committed
307
                        structure" );
308
        close( p_satellite->i_handle );
309
        free( p_satellite );
Johan Bilien's avatar
 
Johan Bilien committed
310
311
        return( -1 );
    }
Johan Bilien's avatar
   
Johan Bilien committed
312

Johan Bilien's avatar
 
Johan Bilien committed
313
314
315
316
317
    vlc_mutex_lock( &p_input->stream.stream_lock );

    p_input->stream.b_pace_control = 1;
    p_input->stream.b_seekable = 0;
    p_input->stream.p_selected_area->i_tell = 0;
Johan Bilien's avatar
   
Johan Bilien committed
318

Johan Bilien's avatar
 
Johan Bilien committed
319
320
321
322
    vlc_mutex_unlock( &p_input->stream.stream_lock );

    p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
    p_input->stream.i_method = INPUT_METHOD_SATELLITE;
Johan Bilien's avatar
   
Johan Bilien committed
323

Johan Bilien's avatar
 
Johan Bilien committed
324
    return 0;
325
}
Johan Bilien's avatar
 
Johan Bilien committed
326
327
328
329
330
331
332
333
334
335
336
337
338

/*****************************************************************************
 * SatelliteClose : Closes the device
 *****************************************************************************/
static void SatelliteClose( input_thread_t * p_input )
{
    input_socket_t *    p_satellite;
    int                 i_es_index;

    if ( p_input->stream.p_selected_program )
    {
        for ( i_es_index = 1 ;
                i_es_index < p_input->stream.p_selected_program->
Johan Bilien's avatar
   
Johan Bilien committed
339
                    i_es_number ;
Johan Bilien's avatar
 
Johan Bilien committed
340
341
342
343
344
                i_es_index ++ )
        {
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
            if ( p_es->p_decoder_fifo )
            {
345
                ioctl_UnsetDMXFilter( p_es->i_demux_fd );
Johan Bilien's avatar
 
Johan Bilien committed
346
347
348
349
            }
#undef p_es
        }
    }
Johan Bilien's avatar
   
Johan Bilien committed
350

Johan Bilien's avatar
 
Johan Bilien committed
351
352
353
    p_satellite = (input_socket_t *)p_input;
    close( p_satellite->i_handle );
}
Johan Bilien's avatar
   
Johan Bilien committed
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

/*****************************************************************************
 * SatelliteRead: reads data from the satellite card
 *****************************************************************************/
static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
                size_t i_len )
{
    int i;

    /* if not set, set filters to the PMTs */
    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 )
        {
            intf_WarnMsg( 2, "input: satellite: 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 );
        }
    }

    return input_FDRead( p_input, p_buffer, i_len );
}




Johan Bilien's avatar
 
Johan Bilien committed
383
384
385
386
387
388
389
390
391
/*****************************************************************************
 * SatelliteSetArea : Does nothing
 *****************************************************************************/
static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
{
    return -1;
}

/*****************************************************************************
Johan Bilien's avatar
   
Johan Bilien committed
392
 * SatelliteSetProgram : Sets the card filters according to the
Johan Bilien's avatar
 
Johan Bilien committed
393
394
395
 *                 selected program,
 *                 and makes the appropriate changes to stream structure.
 *****************************************************************************/
Johan Bilien's avatar
   
Johan Bilien committed
396
int SatelliteSetProgram( input_thread_t    * p_input,
Johan Bilien's avatar
 
Johan Bilien committed
397
398
399
400
401
402
                         pgrm_descriptor_t * p_new_prg )
{
    int                 i_es_index;

    if ( p_input->stream.p_selected_program )
    {
Johan Bilien's avatar
   
Johan Bilien committed
403
        for ( i_es_index = 1 ; /* 0 should be the PMT */
Johan Bilien's avatar
 
Johan Bilien committed
404
                i_es_index < p_input->stream.p_selected_program->
Johan Bilien's avatar
   
Johan Bilien committed
405
                    i_es_number ;
Johan Bilien's avatar
 
Johan Bilien committed
406
407
408
409
410
411
                i_es_index ++ )
        {
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
            if ( p_es->p_decoder_fifo )
            {
                input_UnselectES( p_input , p_es );
Johan Bilien's avatar
   
Johan Bilien committed
412
            }
413
            if ( p_es->i_demux_fd )
Johan Bilien's avatar
   
Johan Bilien committed
414
            {
415
416
                ioctl_UnsetDMXFilter( p_es->i_demux_fd );
                p_es->i_demux_fd = 0;
Johan Bilien's avatar
 
Johan Bilien committed
417
418
419
420
            }
#undef p_es
        }
    }
Johan Bilien's avatar
   
Johan Bilien committed
421

Johan Bilien's avatar
 
Johan Bilien committed
422
423
424
425
426
427
428
429
430
    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 ( p_main->b_video )
                {
431
                    ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1);
Johan Bilien's avatar
 
Johan Bilien committed
432
433
434
435
436
437
438
                    input_SelectES( p_input , p_es );
                }
                break;
            case MPEG1_AUDIO_ES:
            case MPEG2_AUDIO_ES:
                if ( p_main->b_audio )
                {
439
                    ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2);
Johan Bilien's avatar
 
Johan Bilien committed
440
441
442
443
                    input_SelectES( p_input , p_es );
                }
                break;
            default:
444
                ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3);
Johan Bilien's avatar
 
Johan Bilien committed
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
                input_SelectES( p_input , p_es );
                break;
#undef p_es
        }
    }

    p_input->stream.p_selected_program = p_new_prg;

    return( 0 );
}

/*****************************************************************************
 * SatelliteSeek: does nothing (not a seekable stream
 *****************************************************************************/
static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
{
    return;
}