pvr.c 25.1 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * pvr.c
 *****************************************************************************
 * Copyright (C) 2001, 2002 VideoLAN
5
 * $Id$
6 7 8 9 10 11 12
 *
 * Authors: Eric Petit <titer@videolan.org>
 *
 * 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.
13
 *
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 * 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 <vlc/vlc.h>
#include <vlc/input.h>

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
35
#include <errno.h>
36 37 38 39 40 41 42
#include <linux/types.h>
#include <sys/ioctl.h>
#include "videodev2.h"

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
43 44
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
45 46 47 48 49 50

#define DEVICE_TEXT N_( "Device" )
#define DEVICE_LONGTEXT N_( "PVR video device" )

#define NORM_TEXT N_( "Norm" )
#define NORM_LONGTEXT N_( "Defines the norm of the stream (Automatic, SECAM, PAL, or NTSC)" )
51
static int i_norm_list[] = { V4L2_STD_UNKNOWN, V4L2_STD_SECAM, V4L2_STD_PAL,
52 53
                             V4L2_STD_NTSC };
static char *psz_norm_list_text[] = { N_("Automatic"), N_("SECAM"),
Felix Paul Kühne's avatar
Felix Paul Kühne committed
54
                                      N_("PAL"),  N_("NTSC") };
55 56 57 58 59 60 61 62 63

#define WIDTH_TEXT N_( "Width" )
#define WIDTH_LONGTEXT N_( "Width of the stream to capture (-1 for " \
                           "autodetect)" )
#define HEIGHT_TEXT N_( "Height" )
#define HEIGHT_LONGTEXT N_( "Height of the stream to capture (-1 for " \
                           "autodetect)" )
#define FREQUENCY_TEXT N_( "Frequency" )
#define FREQUENCY_LONGTEXT N_( "Frequency to capture (in kHz), if applicable" )
64
#define FRAMERATE_TEXT N_( "Framerate" )
65
#define FRAMERATE_LONGTEXT N_( "Framerate to capture, if applicable (-1 for " \
zorglub's avatar
zorglub committed
66
                               "auto)" )
67
#define KEYINT_TEXT N_( "Key interval" )
zorglub's avatar
zorglub committed
68 69
#define KEYINT_LONGTEXT N_( "Interval between keyframes (-1 for " \
                                " auto)" )
70
#define BFRAMES_TEXT N_( "B Frames" )
Felix Paul Kühne's avatar
Felix Paul Kühne committed
71
#define BFRAMES_LONGTEXT N_("If this option is set, B-Frames will be used. " \
zorglub's avatar
zorglub committed
72
                            "Use this option to set the number of B-Frames.")
73
#define BITRATE_TEXT N_( "Bitrate" )
74
#define BITRATE_LONGTEXT N_( "Bitrate to use (-1 for default)" )
75 76 77 78 79
#define BITRATE_PEAK_TEXT N_( "Bitrate peak" )
#define BITRATE_PEAK_LONGTEXT N_( "Peak bitrate in VBR mode" )
#define BITRATE_MODE_TEXT N_( "Bitrate mode (vbr or cbr)" )
#define BITRATE_MODE_LONGTEXT N_( "Bitrate mode to use" )
#define BITMASK_TEXT N_( "Audio bitmask" )
zorglub's avatar
zorglub committed
80
#define BITMASK_LONGTEXT N_("This option allows setting of bitmask that will get used by the audio part of the card." )
81 82
#define CHAN_TEXT N_( "Channel" )
#define CHAN_LONGTEXT N_( "Channel of the card to use (Usually, 0 = tuner, " \
Felix Paul Kühne's avatar
Felix Paul Kühne committed
83
                          "1 = composite, 2 = svideo)" )
84 85 86 87

static int i_bitrates[] = { 0, 1 };
static char *psz_bitrates_list_text[] = { N_("vbr"), N_("cbr") };

88
vlc_module_begin();
89
    set_shortname( _("PVR") );
gbazin's avatar
 
gbazin committed
90
    set_description( _("MPEG Encoding cards input (with ivtv drivers)") );
zorglub's avatar
zorglub committed
91 92
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACCESS );
93
    set_capability( "access2", 0 );
94
    add_shortcut( "pvr" );
95 96 97 98 99 100 101 102

    add_string( "pvr-device", "/dev/video0", NULL, DEVICE_TEXT,
                            DEVICE_LONGTEXT, VLC_FALSE );

    add_integer( "pvr-norm", V4L2_STD_UNKNOWN , NULL, NORM_TEXT,
                             NORM_LONGTEXT, VLC_FALSE );
       change_integer_list( i_norm_list, psz_norm_list_text, 0 );

103
    add_integer( "pvr-width", -1, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, VLC_TRUE );
104
    add_integer( "pvr-height", -1, NULL, WIDTH_TEXT, WIDTH_LONGTEXT,
105
                                         VLC_TRUE );
106
    add_integer( "pvr-frequency", -1, NULL, FREQUENCY_TEXT, FREQUENCY_LONGTEXT,
107
                                         VLC_FALSE );
108
    add_integer( "pvr-framerate", -1, NULL, FRAMERATE_TEXT, FRAMERATE_LONGTEXT,
109
                                         VLC_TRUE );
110
    add_integer( "pvr-keyint", -1, NULL, KEYINT_TEXT, KEYINT_LONGTEXT,
111
                                         VLC_TRUE );
112
    add_integer( "pvr-bframes", -1, NULL, FRAMERATE_TEXT, FRAMERATE_LONGTEXT,
113
                                         VLC_TRUE );
114
    add_integer( "pvr-bitrate", -1, NULL, BITRATE_TEXT, BITRATE_LONGTEXT,
115 116 117 118 119
                                         VLC_FALSE );
    add_integer( "pvr-bitrate-peak", -1, NULL, BITRATE_PEAK_TEXT,
                                         BITRATE_PEAK_LONGTEXT, VLC_TRUE );
    add_integer( "pvr-bitrate-mode", -1, NULL, BITRATE_MODE_TEXT,
                                         BITRATE_MODE_LONGTEXT, VLC_TRUE );
120 121 122 123 124 125
        change_integer_list( i_bitrates, psz_bitrates_list_text, 0 );
    add_integer( "pvr-audio-bitmask", -1, NULL, BITMASK_TEXT,
                                         BITMASK_LONGTEXT, VLC_TRUE );
    add_integer( "pvr-channel", -1, NULL, CHAN_TEXT,
                                          CHAN_LONGTEXT, VLC_TRUE );

126 127
    set_callbacks( Open, Close );
vlc_module_end();
128

129
/*****************************************************************************
130
 * Prototypes
131
 *****************************************************************************/
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
static int Read   ( access_t *, uint8_t *, int );
static int Control( access_t *, int, va_list );

/* ivtv specific ioctls */
#define IVTV_IOC_G_CODEC    0xFFEE7703
#define IVTV_IOC_S_CODEC    0xFFEE7704

/* for use with IVTV_IOC_G_CODEC and IVTV_IOC_S_CODEC */

struct ivtv_ioctl_codec {
        uint32_t aspect;
        uint32_t audio_bitmask;
        uint32_t bframes;
        uint32_t bitrate_mode;
        uint32_t bitrate;
        uint32_t bitrate_peak;
        uint32_t dnr_mode;
        uint32_t dnr_spatial;
        uint32_t dnr_temporal;
        uint32_t dnr_type;
        uint32_t framerate;
        uint32_t framespergop;
        uint32_t gop_closure;
        uint32_t pulldown;
        uint32_t stream_type;
};

159 160 161 162
struct access_sys_t
{
    /* file descriptor */
    int i_fd;
163

164 165 166 167 168 169
    /* options */
    int i_standard;
    int i_width;
    int i_height;
    int i_frequency;
    int i_framerate;
170
    int i_keyint;
171
    int i_bframes;
172 173
    int i_bitrate;
    int i_bitrate_peak;
bigben's avatar
-pvr.c  
bigben committed
174
    int i_bitrate_mode;
175
    int i_audio_bitmask;
176
    int i_input;
177 178 179 180 181 182 183
};

/*****************************************************************************
 * Open: open the device
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
184
    access_t *p_access = (access_t*) p_this;
185 186
    access_sys_t * p_sys;
    char * psz_tofree, * psz_parser, * psz_device;
187
    vlc_value_t val;
188 189 190 191

    struct v4l2_format vfmt;
    struct v4l2_frequency vf;
    struct ivtv_ioctl_codec codec;
192 193 194

    //psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );

195 196 197 198
    p_access->pf_read = Read;
    p_access->pf_block = NULL;
    p_access->pf_seek = NULL;
    p_access->pf_control = Control;
199 200 201 202 203 204
    p_access->info.i_update = 0;
    p_access->info.i_size = 0;
    p_access->info.i_pos = 0;
    p_access->info.b_eof = VLC_FALSE;
    p_access->info.i_title = 0;
    p_access->info.i_seekpoint = 0;
205 206 207

    /* create private access data */
    p_sys = calloc( sizeof( access_sys_t ), 1 );
208
    p_access->p_sys = p_sys;
209 210

    /* defaults values */
211 212
    var_Create( p_access, "pvr-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    var_Create( p_access, "pvr-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-device" , &val);
    psz_device = val.psz_string;

    var_Create( p_access, "pvr-norm", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-norm" , &val);
    p_sys->i_standard = val.i_int;

    var_Create( p_access, "pvr-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-width" , &val);
    p_sys->i_width = val.i_int;

    var_Create( p_access, "pvr-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-height" , &val);
    p_sys->i_height = val.i_int;

    var_Create( p_access, "pvr-frequency", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-frequency" , &val);
    p_sys->i_frequency = val.i_int;

    var_Create( p_access, "pvr-framerate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-framerate" , &val);
    p_sys->i_framerate = val.i_int;

    var_Create( p_access, "pvr-keyint", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-keyint" , &val);
    p_sys->i_keyint = val.i_int;
240

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    var_Create( p_access, "pvr-bframes", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-bframes" , &val);
    p_sys->i_bframes = val.b_bool;

    var_Create( p_access, "pvr-bitrate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-bitrate" , &val);
    p_sys->i_bitrate = val.i_int;

    var_Create( p_access, "pvr-bitrate-peak", VLC_VAR_INTEGER |
                                              VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-bitrate-peak" , &val);
    p_sys->i_bitrate_peak = val.i_int;

    var_Create( p_access, "pvr-bitrate-mode", VLC_VAR_INTEGER |
                                              VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-bitrate-mode" , &val);
    p_sys->i_bitrate_mode = val.i_int;

    var_Create( p_access, "pvr-audio-bitmask", VLC_VAR_INTEGER |
                                              VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-audio-bitmask" , &val);
    p_sys->i_audio_bitmask = val.i_int;
    var_Create( p_access, "pvr-channel", VLC_VAR_INTEGER |
                                              VLC_VAR_DOINHERIT );
    var_Get( p_access, "pvr-channel" , &val);
    p_sys->i_input = val.i_int;

268
    /* parse command line options */
269
    psz_tofree = strdup( p_access->psz_path );
270 271 272 273 274 275
    psz_parser = psz_tofree;

    if( *psz_parser )
    {
        for( ;; )
        {
276 277 278 279 280
            if ( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
            {
                char *psz_parser_init;
                psz_parser += strlen( "norm=" );
                psz_parser_init = psz_parser;
281
                while ( *psz_parser != ':' && *psz_parser != ','
282
                                                    && *psz_parser != '\0' )
283 284 285
                {
                    psz_parser++;
                }
286 287 288 289

                if ( !strncmp( psz_parser_init, "secam" ,
                               psz_parser - psz_parser_init ) )
                {
290
                    p_sys->i_standard = V4L2_STD_SECAM;
291 292 293 294
                }
                else if ( !strncmp( psz_parser_init, "pal" ,
                                    psz_parser - psz_parser_init ) )
                {
295
                    p_sys->i_standard = V4L2_STD_PAL;
296 297 298 299
                }
                else if ( !strncmp( psz_parser_init, "ntsc" ,
                                    psz_parser - psz_parser_init ) )
                {
300
                    p_sys->i_standard = V4L2_STD_NTSC;
301 302 303 304 305 306
                }
                else
                {
                    p_sys->i_standard = strtol( psz_parser_init ,
                                                &psz_parser, 0 );
                }
307
            }
308 309
            else if( !strncmp( psz_parser, "channel=",
                               strlen( "channel=" ) ) )
310 311
            {
                p_sys->i_input =
312
                  strtol( psz_parser + strlen( "channel=" ),
313 314
                            &psz_parser, 0 );
            }
315
            else if( !strncmp( psz_parser, "device=", strlen( "device=" ) ) )
316
            {
317
                psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );
318 319
                sprintf( psz_device, "/dev/video%ld",
                            strtol( psz_parser + strlen( "device=" ),
320
                            &psz_parser, 0 ) );
321 322 323 324 325
            }
            else if( !strncmp( psz_parser, "frequency=",
                               strlen( "frequency=" ) ) )
            {
                p_sys->i_frequency =
326 327
                  strtol( psz_parser + strlen( "frequency=" ),
                            &psz_parser, 0 );
328
            }
329 330 331 332 333 334 335
            else if( !strncmp( psz_parser, "framerate=",
                               strlen( "framerate=" ) ) )
            {
                p_sys->i_framerate =
                    strtol( psz_parser + strlen( "framerate=" ),
                            &psz_parser, 0 );
            }
336 337 338 339 340 341 342 343 344 345 346 347 348 349
            else if( !strncmp( psz_parser, "keyint=",
                               strlen( "keyint=" ) ) )
            {
                p_sys->i_keyint =
                    strtol( psz_parser + strlen( "keyint=" ),
                            &psz_parser, 0 );
            }
            else if( !strncmp( psz_parser, "bframes=",
                               strlen( "bframes=" ) ) )
            {
                p_sys->i_bframes =
                    strtol( psz_parser + strlen( "bframes=" ),
                            &psz_parser, 0 );
            }
350

351 352 353 354 355 356 357 358 359 360 361 362 363 364
            else if( !strncmp( psz_parser, "width=",
                               strlen( "width=" ) ) )
            {
                p_sys->i_width =
                    strtol( psz_parser + strlen( "width=" ),
                            &psz_parser, 0 );
            }
            else if( !strncmp( psz_parser, "height=",
                               strlen( "height=" ) ) )
            {
                p_sys->i_height =
                    strtol( psz_parser + strlen( "height=" ),
                            &psz_parser, 0 );
            }
365 366 367 368 369 370 371
            else if( !strncmp( psz_parser, "audio=",
                               strlen( "audio=" ) ) )
            {
                p_sys->i_audio_bitmask =
                    strtol( psz_parser + strlen( "audio=" ),
                            &psz_parser, 0 );
            }
372 373 374 375 376 377 378 379 380 381 382 383 384 385
            else if( !strncmp( psz_parser, "bitrate=",
                               strlen( "bitrate=" ) ) )
            {
                p_sys->i_bitrate =
                    strtol( psz_parser + strlen( "bitrate=" ),
                            &psz_parser, 0 );
            }
            else if( !strncmp( psz_parser, "maxbitrate=",
                               strlen( "maxbitrate=" ) ) )
            {
                p_sys->i_bitrate_peak =
                    strtol( psz_parser + strlen( "maxbitrate=" ),
                            &psz_parser, 0 );
            }
bigben's avatar
-pvr.c  
bigben committed
386 387 388 389 390 391 392
            else if( !strncmp( psz_parser, "bitratemode=",
                               strlen( "bitratemode=" ) ) )
            {
                char *psz_parser_init;
                psz_parser += strlen( "bitratemode=" );
                psz_parser_init = psz_parser;
                while ( *psz_parser != ':' && *psz_parser != ','
393
                         && *psz_parser != '\0' )
bigben's avatar
-pvr.c  
bigben committed
394 395 396 397
                {
                    psz_parser++;
                }

398 399 400 401 402 403 404 405 406 407
                if ( !strncmp( psz_parser_init, "vbr" ,
                               psz_parser - psz_parser_init ) )
                {
                     p_sys->i_bitrate_mode = 0;
                }
                else if ( !strncmp( psz_parser_init, "cbr" ,
                                    psz_parser - psz_parser_init ) )
                {
                    p_sys->i_bitrate_mode = 1;
                }
bigben's avatar
-pvr.c  
bigben committed
408
            }
409 410 411 412 413 414 415 416 417 418
            else if( !strncmp( psz_parser, "size=",
                               strlen( "size=" ) ) )
            {
                p_sys->i_width =
                    strtol( psz_parser + strlen( "size=" ),
                            &psz_parser, 0 );
                p_sys->i_height =
                    strtol( psz_parser + 1 ,
                            &psz_parser, 0 );
            }
419
            else
420 421 422
            {
                char *psz_parser_init;
                psz_parser_init = psz_parser;
423
                while ( *psz_parser != ':' && *psz_parser != ',' && *psz_parser != '\0' )
424 425 426 427
                {
                    psz_parser++;
                }
                psz_device = calloc( psz_parser - psz_parser_init + 1, 1 );
428 429
                strncpy( psz_device, psz_parser_init,
                         psz_parser - psz_parser_init );
430
            }
431 432 433 434 435 436 437
            if( *psz_parser )
                psz_parser++;
            else
                break;
        }
    }

438 439 440 441 442 443 444 445
    //give a default value to psz_device if none has bee specified

    if (!psz_device)
    {
        psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );
        strcpy( psz_device, "/dev/video0" );
    }

446 447 448 449 450
    free( psz_tofree );

    /* open the device */
    if( ( p_sys->i_fd = open( psz_device, O_RDWR ) ) < 0 )
    {
451
        msg_Err( p_access, "cannot open device (%s)", strerror( errno ) );
452 453 454
        return VLC_EGENERIC;
    }
    else
bigben's avatar
bigben committed
455
    {
456
        msg_Dbg( p_access, "using video device: %s",psz_device);
bigben's avatar
bigben committed
457
    }
458

459
    free( psz_device );
460

461
    /* set the input */
462 463 464 465
    if ( p_sys->i_input != -1 )
    {
        if ( ioctl( p_sys->i_fd, VIDIOC_S_INPUT, &p_sys->i_input ) < 0 )
        {
466
            msg_Warn( p_access, "VIDIOC_S_INPUT failed" );
467 468 469
        }
        else
        {
470
            msg_Dbg( p_access, "input set to:%d", p_sys->i_input);
471 472 473 474 475 476 477 478
        }
    }

    /* set the video standard */
    if ( p_sys->i_standard != V4L2_STD_UNKNOWN )
    {
        if ( ioctl( p_sys->i_fd, VIDIOC_S_STD, &p_sys->i_standard ) < 0 )
        {
479
            msg_Warn( p_access, "VIDIOC_S_STD failed" );
480 481 482
        }
        else
        {
483
            msg_Dbg( p_access, "video standard set to:%x", p_sys->i_standard);
484 485 486 487 488 489 490 491
        }
    }

    /* set the picture size */
    if ( p_sys->i_width != -1 || p_sys->i_height != -1 )
    {
        if ( ioctl( p_sys->i_fd, VIDIOC_G_FMT, &vfmt ) < 0 )
        {
492
            msg_Warn( p_access, "VIDIOC_G_FMT failed" );
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
        }
        else
        {
            if ( p_sys->i_width != -1 )
            {
                vfmt.fmt.pix.width = p_sys->i_width;
            }

            if ( p_sys->i_height != -1 )
            {
                vfmt.fmt.pix.height = p_sys->i_height;
            }

            if ( ioctl( p_sys->i_fd, VIDIOC_S_FMT, &vfmt ) < 0 )
            {
508
                msg_Warn( p_access, "VIDIOC_S_FMT failed" );
509 510 511
            }
            else
            {
512
                msg_Dbg( p_access, "picture size set to:%dx%d",
513 514 515 516 517 518 519
                         vfmt.fmt.pix.width, vfmt.fmt.pix.height );
            }
        }
    }

    /* set the frequency */
    if ( p_sys->i_frequency != -1 )
bigben's avatar
bigben committed
520
    {
521 522
        vf.tuner = 0; /* TODO: let the user choose the tuner */
        if ( ioctl( p_sys->i_fd, VIDIOC_G_FREQUENCY, &vf ) < 0 )
bigben's avatar
bigben committed
523
        {
524
            msg_Warn( p_access, "VIDIOC_G_FREQUENCY failed (%s)",
525 526 527 528 529 530 531
                      strerror( errno ) );
        }
        else
        {
            vf.frequency = p_sys->i_frequency * 16 / 1000;
            if( ioctl( p_sys->i_fd, VIDIOC_S_FREQUENCY, &vf ) < 0 )
            {
532
                msg_Warn( p_access, "VIDIOC_S_FREQUENCY failed (%s)",
533 534 535 536
                          strerror( errno ) );
            }
            else
            {
537
                msg_Dbg( p_access, "Tuner frequency set to:%d",
538 539
                         p_sys->i_frequency);
            }
bigben's avatar
bigben committed
540 541
        }
    }
542 543 544 545 546

    /* codec parameters */
    if ( p_sys->i_framerate != -1
            || p_sys->i_bitrate_mode != -1
            || p_sys->i_bitrate_peak != -1
547 548
            || p_sys->i_keyint != -1
            || p_sys->i_bframes != -1
549 550 551 552
            || p_sys->i_bitrate != -1
            || p_sys->i_audio_bitmask != -1 )
    {
        if ( ioctl( p_sys->i_fd, IVTV_IOC_G_CODEC, &codec ) < 0 )
bigben's avatar
bigben committed
553
        {
554
            msg_Warn( p_access, "IVTV_IOC_G_CODEC failed" );
bigben's avatar
bigben committed
555
        }
556 557 558
        else
        {
            if ( p_sys->i_framerate != -1 )
bigben's avatar
bigben committed
559
            {
560 561 562 563 564 565 566 567 568 569 570
                switch ( p_sys->i_framerate )
                {
                    case 30:
                        codec.framerate = 0;
                        break;

                    case 25:
                        codec.framerate = 1;
                        break;

                    default:
571
                        msg_Warn( p_access, "invalid framerate, reverting to 25" );
572 573 574
                        codec.framerate = 1;
                        break;
                }
bigben's avatar
bigben committed
575
            }
576 577

            if ( p_sys->i_bitrate != -1 )
bigben's avatar
bigben committed
578
            {
579 580 581 582 583 584 585 586 587
                codec.bitrate = p_sys->i_bitrate;
            }

            if ( p_sys->i_bitrate_peak != -1 )
            {
                codec.bitrate_peak = p_sys->i_bitrate_peak;
            }

            if ( p_sys->i_bitrate_mode != -1 )
bigben's avatar
bigben committed
588
            {
589
                codec.bitrate_mode = p_sys->i_bitrate_mode;
bigben's avatar
bigben committed
590
            }
591

592
            if ( p_sys->i_audio_bitmask != -1 )
bigben's avatar
bigben committed
593
            {
594
                codec.audio_bitmask = p_sys->i_audio_bitmask;
bigben's avatar
bigben committed
595
            }
596 597 598 599
            if ( p_sys->i_keyint != -1 )
            {
                codec.framespergop = p_sys->i_keyint;
            }
600

601 602 603 604
            if ( p_sys->i_bframes != -1 )
            {
                codec.bframes = p_sys->i_bframes;
            }
605 606
            if( ioctl( p_sys->i_fd, IVTV_IOC_S_CODEC, &codec ) < 0 )
            {
607
                msg_Warn( p_access, "IVTV_IOC_S_CODEC failed" );
608 609
            }
            else
bigben's avatar
bigben committed
610
            {
611
                msg_Dbg( p_access, "Setting codec parameters to:  framerate: %d, bitrate: %d/%d/%d",
612
               codec.framerate, codec.bitrate, codec.bitrate_peak, codec.bitrate_mode );
bigben's avatar
bigben committed
613
            }
614 615
        }
    }
616

617
    /* do a quick read */
618
#if 0
619 620 621 622 623
    if ( p_sys->i_fd )
    {
        if ( read( p_sys->i_fd, psz_tmp, 1 ) )
        {
            msg_Dbg(p_input, "Could read byte from device");
bigben's avatar
bigben committed
624
        }
625 626 627 628 629
        else
        {
            msg_Warn(p_input, "Could not read byte from device");
        }
    }
630
#endif
631

632
    return VLC_SUCCESS;
633 634 635 636 637 638 639
}

/*****************************************************************************
 * Close: close the device
 *****************************************************************************/
static void Close( vlc_object_t * p_this )
{
640 641
    access_t *p_access = (access_t*) p_this;
    access_sys_t * p_sys = p_access->p_sys;
642 643 644 645 646 647 648 649

    close( p_sys->i_fd );
    free( p_sys );
}

/*****************************************************************************
 * Read
 *****************************************************************************/
Laurent Aimar's avatar
Laurent Aimar committed
650
static int Read( access_t * p_access, uint8_t * p_buffer, int i_len )
651
{
652
    access_sys_t * p_sys = p_access->p_sys;
653 654

    int i_ret;
655

656 657 658 659 660 661 662 663
    struct timeval timeout;
    fd_set fds;

    FD_ZERO( &fds );
    FD_SET( p_sys->i_fd, &fds );
    timeout.tv_sec = 0;
    timeout.tv_usec = 500000;

664
    if( p_access->info.b_eof )
665 666
        return 0;

667
    while( !( i_ret = select( p_sys->i_fd + 1, &fds, NULL, NULL, &timeout) ) )
668 669 670 671 672 673
    {
        FD_ZERO( &fds );
        FD_SET( p_sys->i_fd, &fds );
        timeout.tv_sec = 0;
        timeout.tv_usec = 500000;

Laurent Aimar's avatar
Laurent Aimar committed
674
        if( p_access->b_die )
675 676 677 678 679
            return 0;
    }

    if( i_ret < 0 )
    {
680
        msg_Err( p_access, "select error (%s)", strerror( errno ) );
681 682 683 684
        return -1;
    }

    i_ret = read( p_sys->i_fd, p_buffer, i_len );
685 686
    if( i_ret == 0 )
    {
687
        p_access->info.b_eof = VLC_TRUE;
688
    }
689
    else if( i_ret > 0 )
690
    {
691
        p_access->info.i_pos += i_ret;
692 693
    }

694 695 696
    return i_ret;
}

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
/*****************************************************************************
 * Control
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    vlc_bool_t   *pb_bool;
    int          *pi_int;
    int64_t      *pi_64;

    switch( i_query )
    {
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = VLC_FALSE;
            break;
        case ACCESS_CAN_PAUSE:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = VLC_FALSE;
            break;
        case ACCESS_CAN_CONTROL_PACE:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = VLC_FALSE;
            break;

        /* */
        case ACCESS_GET_MTU:
            pi_int = (int*)va_arg( args, int * );
            *pi_int = 0;
            break;
729

730 731
        case ACCESS_GET_PTS_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
732
            *pi_64 = (int64_t)var_GetInteger( p_access, "pvr-caching" ) * I64C(1000);
733 734 735 736 737 738 739
            break;

        /* */
        case ACCESS_SET_PAUSE_STATE:
            /* Nothing to do */
            break;

740 741 742
        case ACCESS_GET_TITLE_INFO:
        case ACCESS_SET_TITLE:
        case ACCESS_SET_SEEKPOINT:
743
        case ACCESS_SET_PRIVATE_ID_STATE:
744 745
            return VLC_EGENERIC;

746
        default:
747
            msg_Warn( p_access, "unimplemented query in control" );
748 749 750 751 752 753
            return VLC_EGENERIC;

    }
    return VLC_SUCCESS;
}