📄 input.c
字号:
val.i_int = p_area->i_part; var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL ); return VLC_SUCCESS;}/***************************************************************************** * DvdReadRead: reads data packets. ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of * bytes. *****************************************************************************/static ssize_t DvdReadRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_count ){ thread_dvd_data_t * p_dvd; byte_t * p_buf; unsigned int i_blocks_once; unsigned int i_blocks; int i_read; int i_read_total; vlc_bool_t b_eot = VLC_FALSE; p_dvd = (thread_dvd_data_t *)p_input->p_access_data; p_buf = p_buffer; /* * Playback by cell in this pgc, starting at the cell for our chapter. */ i_blocks = OFF2LB( i_count ); i_read_total = 0; i_read = 0; while( i_blocks ) { /* * End of pack, we select the following one */ if( ! p_dvd->i_pack_len ) { /* * Read NAV packet. */ if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu, 1, p_buf ) ) != 1 ) { msg_Err( p_input, "read failed for block %d", p_dvd->i_next_vobu ); return -1; } /* basic check to be sure we don't have a empty title * go to next title if so */ //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf ); /* * Parse the contained dsi packet. */ DvdReadHandleDSI( p_dvd, p_buf ); /* End of title */ if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 ) { b_eot = 1; break; } assert( p_dvd->i_pack_len < 1024 ); /* FIXME: Ugly kludge: we send the pack block to the input for it * sometimes has a zero scr and restart the sync */ p_dvd->i_cur_block ++; //p_dvd->i_pack_len++; i_read_total++; p_buf += DVD_VIDEO_LB_LEN; i_blocks--; } /* * Compute the number of blocks to read */ i_blocks_once = __MIN( p_dvd->i_pack_len, i_blocks ); p_dvd->i_pack_len -= i_blocks_once; /* Reads from DVD */ i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block, i_blocks_once, p_buf ); if( (unsigned int)i_read != i_blocks_once ) { msg_Err( p_input, "read failed for %d/%d blocks at 0x%02x", i_read, i_blocks_once, p_dvd->i_cur_block ); return -1; } i_blocks -= i_read; i_read_total += i_read; p_dvd->i_cur_block += i_read; p_buf += LB2OFF( i_read ); }/* msg_Dbg( p_input, "i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );*/ vlc_mutex_lock( &p_input->stream.stream_lock ); if( p_dvd->b_eoc ) { /* We modify i_part only at end of chapter not to erase * some modification from the interface */ p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; p_dvd->b_eoc = VLC_FALSE; } if( ( LB2OFF( p_dvd->i_cur_block ) - p_input->stream.p_selected_area->i_start ) >= p_input->stream.p_selected_area->i_size || b_eot ) { if( ( p_input->stream.p_selected_area->i_id + 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" ); DvdReadSetArea( p_input, p_input->stream.pp_areas[ p_input->stream.p_selected_area->i_id+1] ); } vlc_mutex_unlock( &p_input->stream.stream_lock ); return LB2OFF( i_read_total );}#undef p_pgc/***************************************************************************** * DvdReadSeek : 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 DvdReadSeek( input_thread_t * p_input, off_t i_off ){ thread_dvd_data_t * p_dvd; unsigned int i_lb; unsigned int i_tmp; unsigned int i_chapter = 0; unsigned int i_cell = 0; unsigned int i_vobu = 0; unsigned int i_sub_cell = 0; vlc_mutex_lock( &p_input->stream.stream_lock ); i_off += p_input->stream.p_selected_area->i_start; vlc_mutex_unlock( &p_input->stream.stream_lock ); i_lb = OFF2LB( i_off ); p_dvd = ( thread_dvd_data_t * )p_input->p_access_data; /* find cell */ while( p_dvd->p_cur_pgc->cell_playback[i_cell].last_sector < i_lb ) { i_cell++; } /* find chapter */ do { pgc_t * p_pgc; int pgc_id, pgn; i_chapter++; pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[ p_dvd->i_ttn-1].ptt[i_chapter-1].pgcn; pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[ p_dvd->i_ttn-1].ptt[i_chapter-1].pgn; p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc; i_tmp = p_pgc->program_map[pgn-1]; } while( i_tmp <= i_cell ); /* find vobu */ while( p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu] <= i_lb ) { i_vobu++; } /* find sub_cell */ while( p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell].start_sector < p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu-1] ) { i_sub_cell++; }/* msg_Dbg( p_input, "cell %d i_sub_cell %d chapter %d vobu %d cell_sector %d vobu_sector %d sub_cell_sector %d", i_cell, i_sub_cell,i_chapter, i_vobu, p_dvd->p_cur_pgc->cell_playback[i_cell].first_sector, p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu], p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell-1].start_sector);*/ p_dvd->i_cur_block = i_lb; p_dvd->i_next_vobu = p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu]; p_dvd->i_pack_len = p_dvd->i_next_vobu - i_lb; p_dvd->i_cur_cell = i_cell; p_dvd->i_chapter = i_chapter; DvdReadFindCell( p_dvd ); vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.p_selected_area->i_tell = LB2OFF ( p_dvd->i_cur_block ) - p_input->stream.p_selected_area->i_start; p_input->stream.p_selected_area->i_part = p_dvd->i_chapter; vlc_mutex_unlock( &p_input->stream.stream_lock ); return;}/***************************************************************************** * DvdReadHandleDSI *****************************************************************************/static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data ){ navRead_DSI( &(p_dvd->dsi_pack), &(p_data[ DSI_START_BYTE ]) ); /* * Determine where we go next. These values are the ones we mostly * care about. */ p_dvd->i_cur_block = p_dvd->dsi_pack.dsi_gi.nv_pck_lbn; /* * If we're not at the end of this cell, we can determine the next * VOBU to display using the VOBU_SRI information section of the * DSI. Using this value correctly follows the current angle, * avoiding the doubled scenes in The Matrix, and makes our life * really happy. */ if( p_dvd->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) {#if 1 switch( ( p_dvd->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 ) { case 0x4: /* interleaved unit with no angle */ if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != 0 ) { p_dvd->i_next_vobu = p_dvd->i_cur_block + p_dvd->dsi_pack.sml_pbi.ilvu_sa; p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea; } else { p_dvd->i_next_vobu = p_dvd->i_cur_block + p_dvd->dsi_pack.dsi_gi.vobu_ea + 1; p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea; } break; case 0x5: /* vobu is end of ilvu */ if( p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address ) { p_dvd->i_next_vobu = p_dvd->i_cur_block + p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address; p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea; break; } case 0x6: /* vobu is beginning of ilvu */ case 0x9: /* next scr is 0 */ case 0xa: /* entering interleaved section */ case 0x8: /* non interleaved cells in interleaved section */ default: p_dvd->i_next_vobu = p_dvd->i_cur_block + ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff ); p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea; break; }#else p_dvd->i_next_vobu = p_dvd->i_cur_block + ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff ); p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;#endif } else { p_dvd->i_cur_cell = p_dvd->i_next_cell; DvdReadFindCell( p_dvd ); p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea; p_dvd->i_next_vobu = p_dvd->p_cur_pgc->cell_playback[p_dvd->i_cur_cell].first_sector; }#if 0 msg_Dbg( p_input, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d", p_dvd->dsi_pack.dsi_gi.nv_pck_scr, p_dvd->dsi_pack.dsi_gi.nv_pck_lbn, p_dvd->dsi_pack.dsi_gi.vobu_ea, p_dvd->dsi_pack.dsi_gi.vobu_vob_idn, p_dvd->dsi_pack.dsi_gi.vobu_c_idn ); msg_Dbg( p_input, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d", p_dvd->dsi_pack.sml_pbi.category, p_dvd->dsi_pack.sml_pbi.ilvu_ea, p_dvd->dsi_pack.sml_pbi.ilvu_sa, p_dvd->dsi_pack.sml_pbi.size ); msg_Dbg( p_input, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d", p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff, p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle - 1 ].address, p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle ].address);#endif}/***************************************************************************** * DvdReadFindCell *****************************************************************************/static void DvdReadFindCell( thread_dvd_data_t * p_dvd ){ int pgc_id, pgn; int i = 0; pgc_t * p_pgc;#define cell p_dvd->p_cur_pgc->cell_playback if( cell[p_dvd->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ) {#if 0 p_dvd->i_next_cell = p_dvd->i_cur_cell + p_dvd->i_angle_nb; p_dvd->i_cur_cell += p_dvd->i_angle - 1;#else p_dvd->i_cur_cell += p_dvd->i_angle - 1; while( cell[p_dvd->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL ) { i++; } p_dvd->i_next_cell = p_dvd->i_cur_cell + i + 1;#endif } else { p_dvd->i_next_cell = p_dvd->i_cur_cell + 1; }#undef cell pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[ p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgcn; pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[ p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgn; p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc; if( p_pgc->program_map[pgn-1] <= p_dvd->i_cur_cell ) { p_dvd->i_chapter++; p_dvd->b_eoc = VLC_TRUE; }}/***************************************************************************** * DvdReadLaunchDecoders *****************************************************************************/static void DvdReadLauchDecoders( input_thread_t * p_input ){ thread_dvd_data_t * p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); int i_audio, i_spu; input_SelectES( p_input, p_input->stream.pp_es[0] ); /* For audio: first one if none or a not existing one specified */ i_audio = config_GetInt( p_input, "audio-channel" ); if( i_audio < 0 /*|| i_audio > i_audio_nb*/ ) { config_PutInt( p_input, "audio-channel", 1 ); i_audio = 1; } if( i_audio > 0/* && i_audio_nb > 0*/ ) { if( config_GetInt( p_input, "audio-type" ) == REQUESTED_A52 ) { int i_a52 = i_audio; while( ( p_input->stream.pp_es[i_a52]->i_fourcc != VLC_FOURCC('a','5','2','b') ) && ( i_a52 <= p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams ) ) { i_a52++; } if( p_input->stream.pp_es[i_a52]->i_fourcc == VLC_FOURCC('a','5','2','b') ) { input_SelectES( p_input, p_input->stream.pp_es[i_a52] ); } } else { input_SelectES( p_input, p_input->stream.pp_es[i_audio] ); } } /* for spu, default is none */ i_spu = config_GetInt( p_input, "spu-channel" ); if( i_spu < 0 /*|| i_spu > i_spu_nb*/ ) { config_PutInt( p_input, "spu-channel", 0 ); i_spu = 0; } if( i_spu > 0 /*&& i_spu_nb > 0*/ ) { i_spu += p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams; input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -