📄 access.c
字号:
vts.title_inf.p_title_start[i_vts_title-1].i_title_id; msg_Dbg( p_input, "title %d vts_title %d pgc %d", p_dvd->i_title, i_vts_title, p_dvd->i_title_id ); /* title set offset XXX: convert to block values */ p_dvd->i_vts_start = vts.i_pos + vts.manager_inf.i_title_vob_start_sector; /* last cell */ p_dvd->i_prg_cell = -1 + vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb; p_dvd->i_map_cell = 0; p_dvd->i_map_cell = CellPrg2Map( p_dvd ); i_last = CellLastSector( p_dvd ); /* first cell */ p_dvd->i_prg_cell = 0; p_dvd->i_map_cell = 0; p_dvd->i_angle_cell = 0; p_dvd->i_map_cell = CellPrg2Map ( p_dvd ); p_dvd->i_vts_lb = CellFirstSector( p_dvd ); p_dvd->i_last_lb = CellLastSector ( p_dvd ); /* Force libdvdcss to check its title key. * It is only useful for title cracking method. Methods using the * decrypted disc key are fast enough to check the key at each seek */ i_first = dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_vts_start + p_dvd->i_vts_lb, DVDCSS_SEEK_KEY ); if( i_first < 0 ) { msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) ); return -1; } /* Area definition */ p_input->stream.p_selected_area->i_start = LB2OFF( i_first ); p_input->stream.p_selected_area->i_size = LB2OFF( i_last + 1 - p_dvd->i_vts_lb ); /* Destroy obsolete ES by reinitializing programs */ DVDFlushStream( p_input ); /* Angle management: angles are handled through programs */ p_dvd->i_angle_nb = DVDReadAngle( p_input ); if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb ) { p_dvd->i_angle = 1; } DVDSetProgram( p_input, p_input->stream.pp_programs[p_dvd->i_angle-1] ); msg_Dbg( p_input, "title first %i, last %i, size %i", i_first, i_last, i_last + 1 - p_dvd->i_vts_lb ); IfoPrintTitle( p_dvd ); /* No PSM to read in DVD mode, we already have all information */ p_input->stream.p_selected_program->b_is_ok = 1; /* Find all ES in title with ifo data */ DVDReadVideo( p_input ); DVDReadAudio( p_input ); DVDReadSPU ( p_input ); if( p_input->p_demux ) { DVDLaunchDecoders( p_input ); } /* Update the navigation variables without triggering a callback */ val.i_int = p_area->i_id; var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL ); var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL ); for( i = 1; i <= p_area->i_part_nb; i++ ) { val.i_int = i; var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, &val, NULL ); } } /* i_title >= 0 */ else { p_area = p_input->stream.p_selected_area; } /* Chapter selection */ p_dvd->i_chapter = DVDSetChapter( p_dvd, p_area->i_part ); p_input->stream.p_selected_area->i_tell = DVDTell; /* warn interface that something has changed */ p_input->stream.b_seekable = 1; p_input->stream.b_changed = 1; /* Update the navigation variables without triggering a callback */ val.i_int = p_area->i_part; var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL ); return 0;}#undef vts#undef vmg#define title \ p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title/***************************************************************************** * DVDRead: reads data packets. ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of * bytes. *****************************************************************************/static ssize_t DVDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_count ){ thread_dvd_data_t * p_dvd; int i_read; int i_blocks; int i_block_once = 0; p_dvd = (thread_dvd_data_t *)(p_input->p_access_data); i_read = 0; i_blocks = OFF2LB(i_count); while( i_blocks ) { i_block_once = LbMaxOnce( p_dvd ); if( i_block_once > i_blocks ) { i_block_once = i_blocks; } else if( i_block_once <= 0 ) { /* EOT */ break; } if( i_block_once != dvdcss_read( p_dvd->dvdhandle, p_buffer, i_block_once, DVDCSS_READ_DECRYPT ) ) { return -1; } i_blocks -= i_block_once; i_read += i_block_once; p_buffer += LB2OFF( i_block_once ); /* Update global position */ p_dvd->i_vts_lb += i_block_once; } vlc_mutex_lock( &p_input->stream.stream_lock ); if( p_dvd->b_new_chapter ) { p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_dvd->b_new_chapter = 0; } if( ( p_input->stream.p_selected_area->i_tell + LB2OFF( i_read ) >= p_input->stream.p_selected_area->i_size ) || ( i_block_once <= 0 ) ) { if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb ) { /* EOF */ vlc_mutex_unlock( &p_input->stream.stream_lock ); return 0; } /* EOT */ msg_Dbg( p_input, "new title" ); p_dvd->i_title++; DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] ); } vlc_mutex_unlock( &p_input->stream.stream_lock ); return LB2OFF( i_read );}/***************************************************************************** * DVDSeek : Goes to a given position on the stream. ***************************************************************************** * This one is used by the input and translate chronological position from * input to logical position on the device. * The lock should be taken before calling this function. *****************************************************************************/static void DVDSeek( input_thread_t * p_input, off_t i_off ){ thread_dvd_data_t * p_dvd; p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data); vlc_mutex_lock( &p_input->stream.stream_lock ); p_dvd->i_vts_lb = OFF2LB(i_off + p_input->stream.p_selected_area->i_start) - p_dvd->i_vts_start; vlc_mutex_unlock( &p_input->stream.stream_lock ); p_dvd->i_prg_cell = Lb2CellPrg( p_dvd ); p_dvd->i_map_cell = Lb2CellMap( p_dvd ); if( CellIsInterleaved( p_dvd ) ) { /* if we're inside a multi-angle zone, we have to choose i_sector * in the current angle ; we can't do it all the time since cells * can be very wide out of such zones */ p_dvd->i_vts_lb = CellFirstSector( p_dvd ); } p_dvd->i_last_lb = CellLastSector( p_dvd ); p_dvd->i_chapter = CellPrg2Chapter( p_dvd ); if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_vts_start + p_dvd->i_vts_lb, DVDCSS_SEEK_MPEG ) < 0 ) { msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) ); p_input->b_error = 1; return; } vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_input->stream.p_selected_area->i_tell = DVDTell; vlc_mutex_unlock( &p_input->stream.stream_lock ); msg_Dbg( p_input, "program cell: %d cell: %d chapter: %d tell "I64Fd, p_dvd->i_prg_cell, p_dvd->i_map_cell, p_dvd->i_chapter, DVDTell ); return;}/***************************************************************************** * DVDParse: parse command line *****************************************************************************/static char * DVDParse( input_thread_t * p_input ){ thread_dvd_data_t * p_dvd; struct stat stat_info; char * psz_parser; char * psz_device; char * psz_raw; char * psz_next; vlc_bool_t b_options = 0; int i_title = 1; int i_chapter = 1; int i_angle = 1; int i; p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);#ifdef WIN32 /* On Win32 we want the DVD access plugin to be explicitly requested, * we end up with lots of problems otherwise */ if( !p_input->psz_access || !*p_input->psz_access ) return NULL;#endif psz_parser = psz_device = strdup( p_input->psz_name ); if( !psz_parser ) { return NULL; } /* Parse input string : * [device][@rawdevice][@[title][,[chapter][,angle]]] */ while( *psz_parser && *psz_parser != '@' ) { psz_parser++; } if( *psz_parser == '@' ) { /* Maybe found raw device or option list */ *psz_parser = '\0'; psz_raw = ++psz_parser; } else { psz_raw = ""; } if( *psz_parser && !strtol( psz_parser, NULL, 10 ) ) { /* what we've found is either a raw device or a partial option * list e.g. @,29 or both a device and a list ; search end of string */ while( *psz_parser && *psz_parser != '@' ) { psz_parser++; } if( *psz_parser == '@' ) { /* found end of raw device, and beginning of options */ *psz_parser = '\0'; ++psz_parser; b_options = 1; } else { psz_parser = psz_raw + 1; for( i=0 ; i<3 ; i++ ) { if( !*psz_parser ) { /* we have only a raw device */ break; } if( strtol( psz_parser, NULL, 10 ) ) { /* we have only a partial list of options, no device */ psz_parser = psz_raw; psz_raw = ""; b_options = 1; break; } psz_parser++; } } } else { /* found beginning of options ; no raw device specified */ psz_raw = ""; b_options = 1; } if( b_options ) { /* Found options */ i_title = (int)strtol( psz_parser, &psz_next, 10 ); if( *psz_next ) { psz_parser = psz_next + 1; i_chapter = (int)strtol( psz_parser, &psz_next, 10 ); if( *psz_next ) { i_angle = (int)strtol( psz_next + 1, NULL, 10 ); } } p_dvd->i_title = i_title ? i_title : 1; p_dvd->i_chapter = i_chapter ? i_chapter : 1; p_dvd->i_angle = i_angle ? i_angle : 1; } if( *psz_raw ) { if( *psz_raw ) { /* check the raw device */ if( stat( psz_raw, &stat_info ) == -1 ) { msg_Warn( p_input, "cannot stat() raw device `%s' (%s)", psz_raw, strerror(errno)); /* put back '@' */ *(psz_raw - 1) = '@'; psz_raw = ""; } else { char * psz_env;#ifndef WIN32 if( !S_ISCHR(stat_info.st_mode) ) { msg_Warn( p_input, "raw device %s is" " not a valid char device", psz_raw ); /* put back '@' */ *(psz_raw - 1) = '@'; psz_raw = ""; } else#endif { psz_env = malloc( strlen("DVDCSS_RAW_DEVICE=") + strlen( psz_raw ) + 1 ); sprintf( psz_env, "DVDCSS_RAW_DEVICE=%s", psz_raw ); putenv( psz_env ); } } } else { psz_raw = ""; } } if( !*psz_device ) { free( psz_device ); if( !p_input->psz_access ) { /* no device and no access specified: we probably don't want DVD */ return NULL; } psz_device = config_GetPsz( p_input, "dvd" ); }#ifndef WIN32 /* check block device */ if( stat( psz_device, &stat_info ) == -1 ) { msg_Warn( p_input, "cannot stat() device `%s' (%s)", psz_device, strerror(errno)); free( psz_device ); return NULL; } if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) ) { msg_Warn( p_input, "dvd module discarded (not a valid block device)" ); free( psz_device ); return NULL; }#endif msg_Dbg( p_input, "dvd=%s raw=%s title=%d chapter=%d angle=%d", psz_device, psz_raw, p_dvd->i_title, p_dvd->i_chapter, p_dvd->i_angle ); return psz_device;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -