📄 vcd.c
字号:
for ( i_index = 0 ; i_index < i_blocks ; i_index++ ) { if ( ioctl_ReadSectors( VLC_OBJECT(p_input), p_vcd->vcddev, p_vcd->i_sector, p_buffer + i_index * VCD_DATA_SIZE, 1, VCD_TYPE ) < 0 ) { msg_Err( p_input, "could not read sector %d", p_vcd->i_sector ); return -1; } p_vcd->i_sector ++; if ( p_vcd->i_sector == p_vcd->p_sectors[p_vcd->i_track + 1] ) { input_area_t *p_area; if ( p_vcd->i_track >= p_vcd->i_nb_tracks - 1 ) return 0; /* EOF */ vlc_mutex_lock( &p_input->stream.stream_lock ); p_area = p_input->stream.pp_areas[ p_input->stream.p_selected_area->i_id + 1 ]; msg_Dbg( p_input, "new title" ); p_area->i_part = 1; VCDSetArea( p_input, p_area ); vlc_mutex_unlock( &p_input->stream.stream_lock ); } /* Update chapter */ else if( p_vcd->b_valid_ep && /* FIXME kludge so that read does not update chapter * when a manual chapter change was requested and not * yet accomplished */ !p_input->stream.p_new_area ) { int i_entry; vlc_mutex_lock( &p_input->stream.stream_lock ); i_entry = p_input->stream.p_selected_area->i_plugin_data /* 1st entry point of the track (area)*/ + p_input->stream.p_selected_area->i_part - 1; if( i_entry + 1 < p_vcd->i_entries_nb && p_vcd->i_sector >= p_vcd->p_entries[i_entry + 1] ) { vlc_value_t val; msg_Dbg( p_input, "new chapter" ); p_input->stream.p_selected_area->i_part ++; /* Update the navigation variables without triggering * a callback */ val.i_int = p_input->stream.p_selected_area->i_part; var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL ); } vlc_mutex_unlock( &p_input->stream.stream_lock ); } i_read += VCD_DATA_SIZE; } if ( i_len % VCD_DATA_SIZE ) /* this should not happen */ { if ( ioctl_ReadSectors( VLC_OBJECT(p_input), p_vcd->vcddev, p_vcd->i_sector, p_last_sector, 1, VCD_TYPE ) < 0 ) { msg_Err( p_input, "could not read sector %d", p_vcd->i_sector ); return -1; } p_input->p_vlc->pf_memcpy( p_buffer + i_blocks * VCD_DATA_SIZE, p_last_sector, i_len % VCD_DATA_SIZE ); i_read += i_len % VCD_DATA_SIZE; } return i_read;}/***************************************************************************** * VCDSetProgram: Does nothing since a VCD is mono_program *****************************************************************************/static int VCDSetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_program){ return 0;}/***************************************************************************** * VCDSetArea: initialize input data for title x, chapter y. * It should be called for each user navigation request. ****************************************************************************/static int VCDSetArea( input_thread_t * p_input, input_area_t * p_area ){ thread_vcd_data_t * p_vcd; vlc_value_t val; p_vcd = (thread_vcd_data_t*)p_input->p_access_data; /* we can't use the interface slider until initilization is complete */ p_input->stream.b_seekable = 0; if( p_area != p_input->stream.p_selected_area ) { unsigned int i; /* Reset the Chapter position of the current title */ p_input->stream.p_selected_area->i_part = 1; p_input->stream.p_selected_area->i_tell = 0; /* Change the default area */ p_input->stream.p_selected_area = p_area; /* Change the current track */ /* The first track is not a valid one */ p_vcd->i_track = p_area->i_id; p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track]; /* 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 ); } } if( p_vcd->b_valid_ep ) { int i_entry = p_area->i_plugin_data /* 1st entry point of the track (area)*/ + p_area->i_part - 1; p_vcd->i_sector = p_vcd->p_entries[i_entry]; } else p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track]; p_input->stream.p_selected_area->i_tell = (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE - p_input->stream.p_selected_area->i_start; /* 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;}/**************************************************************************** * VCDSeek ****************************************************************************/static void VCDSeek( input_thread_t * p_input, off_t i_off ){ thread_vcd_data_t * p_vcd; unsigned int i_index; p_vcd = (thread_vcd_data_t *) p_input->p_access_data; p_vcd->i_sector = p_vcd->p_sectors[p_vcd->i_track] + i_off / (off_t)VCD_DATA_SIZE; vlc_mutex_lock( &p_input->stream.stream_lock );#define p_area p_input->stream.p_selected_area /* Find chapter */ if( p_vcd->b_valid_ep ) { for( i_index = 2 ; i_index <= p_area->i_part_nb; i_index ++ ) { if( p_vcd->i_sector < p_vcd->p_entries[p_area->i_plugin_data + i_index - 1] ) { vlc_value_t val; p_area->i_part = i_index - 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 ); break; } } }#undef p_area p_input->stream.p_selected_area->i_tell = (off_t)p_vcd->i_sector * (off_t)VCD_DATA_SIZE - p_input->stream.p_selected_area->i_start; vlc_mutex_unlock( &p_input->stream.stream_lock );}/***************************************************************************** * VCDEntryPoints: Reads the information about the entry points on the disc. *****************************************************************************/static int VCDEntryPoints( input_thread_t * p_input ){ thread_vcd_data_t * p_vcd; byte_t * p_sector; entries_sect_t entries; uint16_t i_nb; int i, i_entry_index = 0; int i_previous_track = -1; p_vcd = (thread_vcd_data_t *) p_input->p_access_data; p_sector = malloc( VCD_DATA_SIZE * sizeof( byte_t ) ); if( p_sector == NULL ) { msg_Err( p_input, "not enough memory for entry points treatment" ); return -1; } if( ioctl_ReadSectors( VLC_OBJECT(p_input), p_vcd->vcddev, VCD_ENTRIES_SECTOR, p_sector, 1, VCD_TYPE ) < 0 ) { msg_Err( p_input, "could not read entry points sector" ); free( p_sector ); return( -1 ); } memcpy( &entries, p_sector, CD_SECTOR_SIZE ); free( p_sector ); if( (i_nb = U16_AT( &entries.i_entries_nb )) > 500 ) { msg_Err( p_input, "invalid entry points number" ); return( -1 ); } p_vcd->p_entries = malloc( sizeof( int ) * i_nb ); if( p_vcd->p_entries == NULL ) { msg_Err( p_input, "not enough memory for entry points treatment" ); return -1; } if( strncmp( entries.psz_id, "ENTRYVCD", sizeof( entries.psz_id ) ) && strncmp( entries.psz_id, "ENTRYSVD", sizeof( entries.psz_id ) )) { msg_Err( p_input, "unrecognized entry points format" ); free( p_vcd->p_entries ); return -1; } p_vcd->i_entries_nb = 0;#define i_track BCD_TO_BIN(entries.entry[i].i_track) /* Reset the i_part_nb for each track */ for( i = 0 ; i < i_nb ; i++ ) { if( i_track <= p_input->stream.i_area_nb ) { p_input->stream.pp_areas[i_track-1]->i_part_nb = 0; } } for( i = 0 ; i < i_nb ; i++ ) { if( i_track <= p_input->stream.i_area_nb ) { p_vcd->p_entries[i_entry_index] = (MSF_TO_LBA2( BCD_TO_BIN( entries.entry[i].msf.minute ), BCD_TO_BIN( entries.entry[i].msf.second ), BCD_TO_BIN( entries.entry[i].msf.frame ) )); p_input->stream.pp_areas[i_track-1]->i_part_nb ++; /* if this entry belongs to a new track */ if( i_track != i_previous_track ) { /* i_plugin_data is used to store the first entry of the area*/ p_input->stream.pp_areas[i_track-1]->i_plugin_data = i_entry_index; i_previous_track = i_track; } msg_Dbg( p_input, "entry point %i begins at LBA: %i", i_entry_index, p_vcd->p_entries[i_entry_index] ); i_entry_index ++; p_vcd->i_entries_nb ++; } else msg_Warn( p_input, "wrong track number found in entry points" ); }#undef i_track return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -