📄 pvr.c
字号:
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; } } 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 ); } else { char *psz_parser_init; psz_parser_init = psz_parser; while ( (*psz_parser != ':') && (*psz_parser != ',') && (*psz_parser != '\0') ) { psz_parser++; } psz_device = calloc( psz_parser - psz_parser_init + 1, 1 ); if( !psz_device ) return VLC_ENOMEM; strncpy( psz_device, psz_parser_init, psz_parser - psz_parser_init ); } if( *psz_parser ) psz_parser++; else break; } } free( psz_tofree ); if( psz_device ) { free( p_sys->psz_videodev ); p_sys->psz_videodev = psz_device; } /* open the device */ p_sys->i_fd = open( p_sys->psz_videodev, O_RDWR ); if( p_sys->i_fd < 0 ) { msg_Err( p_access, "Cannot open device (%m)." ); Close( VLC_OBJECT(p_access) ); return VLC_EGENERIC; } msg_Dbg( p_access, "Using video device: %s.", p_sys->psz_videodev); /* See what version of ivtvdriver is running */ result = ioctl( p_sys->i_fd, VIDIOC_QUERYCAP, &device_capability ); if( result < 0 ) { msg_Err( p_access, "unknown ivtv/pvr driver version in use" ); Close( VLC_OBJECT(p_access) ); return VLC_EGENERIC; } msg_Dbg( p_access, "%s driver (%s on %s) version %02x.%02x.%02x", device_capability.driver, device_capability.card, device_capability.bus_info, ( device_capability.version >> 16 ) & 0xff, ( device_capability.version >> 8 ) & 0xff, ( device_capability.version ) & 0xff); if ( strncmp( (char *) device_capability.driver, "ivtv", 4 ) || device_capability.version >= 0x000800 ) { /* Drivers > 0.8.0 use v4l2 API instead of IVTV ioctls */ msg_Dbg( p_access, "this driver uses the v4l2 API" ); p_sys->b_v4l2_api = true; } else { p_sys->b_v4l2_api = false; } /* set the input */ if ( p_sys->i_input != -1 ) { result = ioctl( p_sys->i_fd, VIDIOC_S_INPUT, &p_sys->i_input ); if ( result < 0 ) msg_Warn( p_access, "Failed to select the requested input pin." ); else msg_Dbg( p_access, "input set to: %d", p_sys->i_input ); } /* set the video standard */ if ( p_sys->i_standard != V4L2_STD_UNKNOWN ) { result = ioctl( p_sys->i_fd, VIDIOC_S_STD, &p_sys->i_standard ); if ( result < 0 ) msg_Warn( p_access, "Failed to set the requested video standard." ); else msg_Dbg( p_access, "video standard set to: %x", p_sys->i_standard); } /* set the picture size */ if ( (p_sys->i_width != -1) || (p_sys->i_height != -1) ) { struct v4l2_format vfmt; memset( &vfmt, 0, sizeof(struct v4l2_format) ); vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; result = ioctl( p_sys->i_fd, VIDIOC_G_FMT, &vfmt ); if ( result < 0 ) { msg_Warn( p_access, "Failed to read current picture size." ); } 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; } result = ioctl( p_sys->i_fd, VIDIOC_S_FMT, &vfmt ); if ( result < 0 ) { msg_Warn( p_access, "Failed to set requested picture size." ); } else { msg_Dbg( p_access, "picture size set to: %dx%d", vfmt.fmt.pix.width, vfmt.fmt.pix.height ); } } } /* set the frequency */ if ( p_sys->i_frequency != -1 ) { int i_fd; struct v4l2_tuner vt; /* TODO: let the user choose the tuner */ memset( &vt, 0, sizeof(struct v4l2_tuner) ); if ( (p_sys->i_frequency >= pi_radio_range[0]) && (p_sys->i_frequency <= pi_radio_range[1]) ) { p_sys->i_radio_fd = open( p_sys->psz_radiodev, O_RDWR ); if( p_sys->i_radio_fd < 0 ) { msg_Err( p_access, "Cannot open radio device (%m)." ); Close( VLC_OBJECT(p_access) ); return VLC_EGENERIC; } msg_Dbg( p_access, "using radio device: %s", p_sys->psz_radiodev ); i_fd = p_sys->i_radio_fd; } else { i_fd = p_sys->i_fd; p_sys->i_radio_fd = -1; } result = ioctl( i_fd, VIDIOC_G_TUNER, &vt ); if ( result < 0 ) { msg_Warn( p_access, "Failed to read tuner information (%m)." ); } else { struct v4l2_frequency vf; memset( &vf, 0, sizeof(struct v4l2_frequency) ); vf.tuner = vt.index; result = ioctl( i_fd, VIDIOC_G_FREQUENCY, &vf ); if ( result < 0 ) { msg_Warn( p_access, "Failed to read tuner frequency (%m)." ); } else { if( vt.capability & V4L2_TUNER_CAP_LOW ) vf.frequency = p_sys->i_frequency * 16; else vf.frequency = (p_sys->i_frequency * 16 + 500) / 1000; result = ioctl( i_fd, VIDIOC_S_FREQUENCY, &vf ); if( result < 0 ) { msg_Warn( p_access, "Failed to set tuner frequency (%m)." ); } else { msg_Dbg( p_access, "tuner frequency set to: %d", p_sys->i_frequency ); } } } } /* control parameters */ if ( p_sys->i_volume != -1 ) { struct v4l2_control ctrl; memset( &ctrl, 0, sizeof(struct v4l2_control) ); ctrl.id = V4L2_CID_AUDIO_VOLUME; ctrl.value = p_sys->i_volume; result = ioctl( p_sys->i_fd, VIDIOC_S_CTRL, &ctrl ); if ( result < 0 ) { msg_Warn( p_access, "Failed to set the volume." ); } } /* codec parameters */ if ( (p_sys->i_framerate != -1) || (p_sys->i_bitrate_mode != -1) || (p_sys->i_bitrate_peak != -1) || (p_sys->i_keyint != -1) || (p_sys->i_bframes != -1) || (p_sys->i_bitrate != -1) || (p_sys->i_audio_bitmask != -1) ) { if( p_sys->b_v4l2_api ) {#ifdef HAVE_NEW_LINUX_VIDEODEV2_H result = ConfigureV4L2( p_access ); if( result != VLC_SUCCESS ) { Close( VLC_OBJECT(p_access) ); return result; }#else msg_Warn( p_access, "You have new ivtvdrivers, " "but this vlc was built against an old v4l2 version." );#endif } else { result = ConfigureIVTV( p_access ); if( result != VLC_SUCCESS ) { Close( VLC_OBJECT(p_access) ); return result; } } } return VLC_SUCCESS;}/***************************************************************************** * Close: close the device *****************************************************************************/static void Close( vlc_object_t * p_this ){ access_t *p_access = (access_t*) p_this; access_sys_t *p_sys = (access_sys_t *) p_access->p_sys; if ( p_sys->i_fd != -1 ) close( p_sys->i_fd ); if ( p_sys->i_radio_fd != -1 ) close( p_sys->i_radio_fd ); free( p_sys->psz_videodev ); free( p_sys->psz_radiodev ); free( p_sys );}/***************************************************************************** * Read *****************************************************************************/static ssize_t Read( access_t * p_access, uint8_t * p_buffer, size_t i_len ){ access_sys_t *p_sys = (access_sys_t *) p_access->p_sys; struct pollfd ufd; int i_ret; ufd.fd = p_sys->i_fd; ufd.events = POLLIN; if( p_access->info.b_eof ) return 0; do { if( !vlc_object_alive (p_access) ) return 0; ufd.revents = 0; } while( ( i_ret = poll( &ufd, 1, 500 ) ) == 0 ); if( i_ret < 0 ) { msg_Err( p_access, "Polling error (%m)." ); return -1; } i_ret = read( p_sys->i_fd, p_buffer, i_len ); if( i_ret == 0 ) { p_access->info.b_eof = true; } else if( i_ret > 0 ) { p_access->info.i_pos += i_ret; } return i_ret;}/***************************************************************************** * Control *****************************************************************************/static int Control( access_t *p_access, int i_query, va_list args ){ bool *pb_bool; int *pi_int; int64_t *pi_64; switch( i_query ) { /* */ case ACCESS_CAN_SEEK: case ACCESS_CAN_FASTSEEK: pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = false; break; case ACCESS_CAN_PAUSE: pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = false; break; case ACCESS_CAN_CONTROL_PACE: pb_bool = (bool*)va_arg( args, bool* ); *pb_bool = false; break; /* */ case ACCESS_GET_MTU: pi_int = (int*)va_arg( args, int * ); *pi_int = 0; break; case ACCESS_GET_PTS_DELAY: pi_64 = (int64_t*)va_arg( args, int64_t * ); *pi_64 = (int64_t)var_GetInteger( p_access, "pvr-caching" ) * 1000; break; /* */ case ACCESS_SET_PAUSE_STATE: /* Nothing to do */ break; case ACCESS_GET_TITLE_INFO: case ACCESS_SET_TITLE: case ACCESS_SET_SEEKPOINT: case ACCESS_SET_PRIVATE_ID_STATE: case ACCESS_GET_CONTENT_TYPE: return VLC_EGENERIC; default: msg_Warn( p_access, "Unimplemented query in control." ); return VLC_EGENERIC; } return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -