📄 dvdread.c
字号:
INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; p_demux->info.i_title = i; p_demux->info.i_seekpoint = 0; return VLC_SUCCESS; case DEMUX_SET_SEEKPOINT: i = (int)va_arg( args, int ); if( DvdReadSetArea( p_demux, -1, i, -1 ) != VLC_SUCCESS ) { msg_Warn( p_demux, "cannot set title/chapter" ); return VLC_EGENERIC; } p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT; p_demux->info.i_seekpoint = i; return VLC_SUCCESS; case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = (int64_t)var_GetInteger( p_demux, "dvdread-caching" )*1000; return VLC_SUCCESS; /* TODO implement others */ default: return VLC_EGENERIC; }}/***************************************************************************** * Demux: *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; uint8_t p_buffer[DVD_VIDEO_LB_LEN * DVD_BLOCK_READ_ONCE]; int i_blocks_once, i_read; int i; /* * Playback by cell in this pgc, starting at the cell for our chapter. */ /* * Check end of pack, and select the following one */ if( !p_sys->i_pack_len ) { /* Read NAV packet */ if( DVDReadBlocks( p_sys->p_title, p_sys->i_next_vobu, 1, p_buffer ) != 1 ) { msg_Err( p_demux, "read failed for block %d", p_sys->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_demux, p_buffer ); /* End of title */ if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) { if( p_sys->i_title + 1 >= p_sys->i_titles ) { return 0; /* EOF */ } DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 ); } if( p_sys->i_pack_len >= 1024 ) { msg_Err( p_demux, "i_pack_len >= 1024 (%i). " "This shouldn't happen!", p_sys->i_pack_len ); return 0; /* EOF */ } /* FIXME: Ugly kludge: we send the pack block to the input for it * sometimes has a zero scr and restart the sync */ p_sys->i_cur_block++; p_sys->i_title_offset++; DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN ); } if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) { if( p_sys->i_title + 1 >= p_sys->i_titles ) { return 0; /* EOF */ } DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 ); } /* * Read actual data */ i_blocks_once = __MIN( p_sys->i_pack_len, DVD_BLOCK_READ_ONCE ); p_sys->i_pack_len -= i_blocks_once; /* Reads from DVD */ i_read = DVDReadBlocks( p_sys->p_title, p_sys->i_cur_block, i_blocks_once, p_buffer ); if( i_read != i_blocks_once ) { msg_Err( p_demux, "read failed for %d/%d blocks at 0x%02x", i_read, i_blocks_once, p_sys->i_cur_block ); return -1; } p_sys->i_cur_block += i_read; p_sys->i_title_offset += i_read;#if 0 msg_Dbg( p_demux, "i_blocks: %d len: %d current: 0x%02x", i_read, p_sys->i_pack_len, p_sys->i_cur_block );#endif for( i = 0; i < i_read; i++ ) { DemuxBlock( p_demux, p_buffer + i * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN ); }#undef p_pgc return 1;}/***************************************************************************** * DemuxBlock: demux a given block *****************************************************************************/static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt ){ demux_sys_t *p_sys = p_demux->p_sys; uint8_t *p = pkt; while( p < &pkt[i_pkt] ) { int i_size = ps_pkt_size( p, &pkt[i_pkt] - p ); block_t *p_pkt; if( i_size <= 0 ) { break; } /* Create a block */ p_pkt = block_New( p_demux, i_size ); memcpy( p_pkt->p_buffer, p, i_size); /* Parse it and send it */ switch( 0x100 | p[3] ) { case 0x1b9: case 0x1bb: case 0x1bc:#ifdef DVDREAD_DEBUG if( p[3] == 0xbc ) { msg_Warn( p_demux, "received a PSM packet" ); } else if( p[3] == 0xbb ) { msg_Warn( p_demux, "received a SYSTEM packet" ); }#endif block_Release( p_pkt ); break; case 0x1ba: { int64_t i_scr; int i_mux_rate; if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr ); if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate; } block_Release( p_pkt ); break; } default: { int i_id = ps_pkt_id( p_pkt ); if( i_id >= 0xc0 ) { ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)]; if( !tk->b_seen ) { ESNew( p_demux, i_id, 0 ); } if( tk->b_seen && tk->es && !ps_pkt_parse_pes( p_pkt, tk->i_skip ) ) { es_out_Send( p_demux->out, tk->es, p_pkt ); } else { block_Release( p_pkt ); } } else { block_Release( p_pkt ); } break; } } p += i_size; } return VLC_SUCCESS;}/***************************************************************************** * ESNew: register a new elementary stream *****************************************************************************/static void ESNew( demux_t *p_demux, int i_id, int i_lang ){ demux_sys_t *p_sys = p_demux->p_sys; ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)]; char psz_language[3]; if( tk->b_seen ) return; if( ps_track_fill( tk, 0, i_id ) ) { msg_Warn( p_demux, "unknown codec for id=0x%x", i_id ); return; } psz_language[0] = psz_language[1] = psz_language[2] = 0; if( i_lang && i_lang != 0xffff ) { psz_language[0] = (i_lang >> 8)&0xff; psz_language[1] = (i_lang )&0xff; } /* Add a new ES */ if( tk->fmt.i_cat == VIDEO_ES ) { if( p_sys->i_aspect >= 0 ) { tk->fmt.video.i_aspect = p_sys->i_aspect; } } else if( tk->fmt.i_cat == AUDIO_ES ) { int i_audio = -1; /* find the audio number PLEASE find another way */ if( (i_id&0xbdf8) == 0xbd88 ) /* dts */ { i_audio = i_id&0x07; } else if( (i_id&0xbdf0) == 0xbd80 ) /* a52 */ { i_audio = i_id&0xf; } else if( (i_id&0xbdf0) == 0xbda0 ) /* lpcm */ { i_audio = i_id&0x1f; } else if( ( i_id&0xe0 ) == 0xc0 ) /* mpga */ { i_audio = i_id&0x1f; } if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language ); } else if( tk->fmt.i_cat == SPU_ES ) { /* Palette */ tk->fmt.subs.spu.palette[0] = 0xBeef; memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut, 16 * sizeof( uint32_t ) ); if( psz_language[0] ) tk->fmt.psz_language = strdup( psz_language ); } tk->es = es_out_Add( p_demux->out, &tk->fmt ); tk->b_seen = VLC_TRUE;}/***************************************************************************** * DvdReadSetArea: initialize input data for title x, chapter y. * It should be called for each user navigation request. ***************************************************************************** * Take care that i_title and i_chapter start from 0. *****************************************************************************/static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter, int i_angle ){ demux_sys_t *p_sys = p_demux->p_sys; int pgc_id = 0, pgn = 0; int i;#define p_pgc p_sys->p_cur_pgc#define p_vmg p_sys->p_vmg_file#define p_vts p_sys->p_vts_file if( i_title >= 0 && i_title < p_sys->i_titles && i_title != p_sys->i_title ) { int i_start_cell, i_end_cell; if( p_sys->p_title != NULL ) DVDCloseFile( p_sys->p_title ); if( p_vts != NULL ) ifoClose( p_vts ); p_sys->i_title = i_title; /* * We have to load all title information */ msg_Dbg( p_demux, "open VTS %d, for title %d", p_vmg->tt_srpt->title[i_title].title_set_nr, i_title + 1 ); /* Ifo vts */ if( !( p_vts = ifoOpen( p_sys->p_dvdread, p_vmg->tt_srpt->title[i_title].title_set_nr ) ) ) { msg_Err( p_demux, "fatal error in vts ifo" ); return VLC_EGENERIC; } /* Title position inside the selected vts */ p_sys->i_ttn = p_vmg->tt_srpt->title[i_title].vts_ttn; /* Find title start/end */ pgc_id = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgcn; pgn = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].ptt[0].pgn; p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc; p_sys->i_title_start_cell = i_start_cell = p_pgc->program_map[pgn - 1] - 1; p_sys->i_title_start_block = p_pgc->cell_playback[i_start_cell].first_sector; p_sys->i_title_end_cell = i_end_cell = p_pgc->nr_of_cells - 1; p_sys->i_title_end_block = p_pgc->cell_playback[i_end_cell].last_sector; p_sys->i_title_offset = 0; p_sys->i_title_blocks = 0; for( i = i_start_cell; i <= i_end_cell; i++ ) { p_sys->i_title_blocks += p_pgc->cell_playback[i].last_sector - p_pgc->cell_playback[i].first_sector + 1; } msg_Dbg( p_demux, "title %d vts_title %d pgc %d pgn %d " "start %d end %d blocks: %d", i_title + 1, p_sys->i_ttn, pgc_id, pgn, p_sys->i_title_start_block, p_sys->i_title_end_block, p_sys->i_title_blocks ); /* * Set properties for current chapter */ p_sys->i_chapter = 0; p_sys->i_chapters = p_vts->vts_ptt_srpt->title[p_sys->i_ttn - 1].nr_of_ptts; pgc_id = p_vts->vts_ptt_srpt->title[ p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgcn; pgn = p_vts->vts_ptt_srpt->title[ p_sys->i_ttn - 1].ptt[p_sys->i_chapter].pgn; p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id - 1].pgc; p_sys->i_pack_len = 0; p_sys->i_next_cell = p_sys->i_cur_cell = p_pgc->program_map[pgn - 1] - 1; DvdReadFindCell( p_demux ); p_sys->i_next_vobu = p_sys->i_cur_block = p_pgc->cell_playback[p_sys->i_cur_cell].first_sector; /* * Angle management */ p_sys->i_angles = p_vmg->tt_srpt->title[i_title].nr_of_angles; if( p_sys->i_angle > p_sys->i_angles ) p_sys->i_angle = 1; /* * We've got enough info, time to open the title set data. */ if( !( p_sys->p_title = DVDOpenFile( p_sys->p_dvdread, p_vmg->tt_srpt->title[i_title].title_set_nr, DVD_READ_TITLE_VOBS ) ) ) { msg_Err( p_demux, "cannot open title (VTS_%02d_1.VOB)", p_vmg->tt_srpt->title[i_title].title_set_nr ); return VLC_EGENERIC; } //IfoPrintTitle( p_demux ); /* * Destroy obsolete ES by reinitializing program 0 * and find all ES in title with ifo data */ es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); for( i = 0; i < PS_TK_COUNT; i++ ) { ps_track_t *tk = &p_sys->tk[i]; if( tk->b_seen ) { es_format_Clean( &tk->fmt ); if( tk->es ) es_out_Del( p_demux->out, tk->es ); } tk->b_seen = VLC_FALSE; } if( p_demux->info.i_title != i_title ) { p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; p_demux->info.i_title = i_title; p_demux->info.i_seekpoint = 0; } /* TODO: re-add angles */ ESNew( p_demux, 0xe0, 0 ); /* Video, FIXME ? */ p_sys->i_aspect = p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio;#define audio_control \ p_sys->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1] /* Audio ES, in the order they appear in the .ifo */ for( i = 1; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams; i++ ) { int i_position = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -