X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fdvdread.c;h=dd5d7edf56a7a68013afce37fed2a6c65f7df964;hb=76ed22f1237d5d8eade31749c6f27aa8ed4312c4;hp=dee89348449799e7d4cf40976cbee58a2558f442;hpb=a90a19a6b0468ea9fedadc27cfc1118d70295263;p=vlc diff --git a/modules/access/dvdread.c b/modules/access/dvdread.c index dee8934844..dd5d7edf56 100644 --- a/modules/access/dvdread.c +++ b/modules/access/dvdread.c @@ -87,7 +87,7 @@ static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); vlc_module_begin(); - set_name( _("DVD without menus") ); + set_shortname( _("DVD without menus") ); set_description( _("DVDRead Input (DVD without menu support)") ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_ACCESS ); @@ -139,11 +139,14 @@ struct demux_sys_t int i_title_end_block; int i_title_blocks; int i_title_offset; + mtime_t i_title_cur_time; int i_title_start_cell; int i_title_end_cell; int i_cur_cell; int i_next_cell; + mtime_t i_cell_cur_time; + mtime_t i_cell_duration; /* Track */ ps_track_t tk[PS_TK_COUNT]; @@ -250,6 +253,9 @@ static int Open( vlc_object_t *p_this ) ps_track_init( p_sys->tk ); p_sys->i_aspect = -1; p_sys->i_mux_rate = 0; + p_sys->i_title_cur_time = (mtime_t) 0; + p_sys->i_cell_cur_time = (mtime_t) 0; + p_sys->i_cell_duration = (mtime_t) 0; p_sys->p_dvdread = p_dvdread; p_sys->p_vmg_file = p_vmg_file; @@ -263,7 +269,13 @@ static int Open( vlc_object_t *p_this ) p_sys->i_angle = val.i_int > 0 ? val.i_int : 1; DemuxTitles( p_demux, &p_sys->i_angle ); - DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ); + if( DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ) != VLC_SUCCESS ) + { + Close( p_this ); + msg_Err( p_demux, "DvdReadSetArea(0,0,%i) failed (can't decrypt DVD?)", + p_sys->i_angle ); + return VLC_EGENERIC; + } /* Update default_pts to a suitable value for dvdread access */ var_Create( p_demux, "dvdread-caching", @@ -300,6 +312,44 @@ static void Close( vlc_object_t *p_this ) free( p_sys ); } +static int64_t dvdtime_to_time( dvd_time_t *dtime, uint8_t still_time ) +{ +/* Macro to convert Binary Coded Decimal to Decimal */ +#define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f)) + + double f_fps, f_ms; + int64_t i_micro_second = 0; + + if (still_time == 0 || still_time == 0xFF) + { + i_micro_second += (int64_t)(BCD2D(dtime->hour)) * 60 * 60 * 1000000; + i_micro_second += (int64_t)(BCD2D(dtime->minute)) * 60 * 1000000; + i_micro_second += (int64_t)(BCD2D(dtime->second)) * 1000000; + + switch((dtime->frame_u & 0xc0) >> 6) + { + case 1: + f_fps = 25.0; + break; + case 3: + f_fps = 29.97; + break; + default: + f_fps = 2500.0; + break; + } + f_ms = BCD2D(dtime->frame_u&0x3f) * 1000.0 / f_fps; + i_micro_second += (int64_t)(f_ms * 1000.0); + } + else + { + i_micro_second = still_time; + i_micro_second = (int64_t)((double)i_micro_second * 1000000.0); + } + + return i_micro_second; +} + /***************************************************************************** * Control: *****************************************************************************/ @@ -336,10 +386,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); - if( p_sys->i_mux_rate > 0 ) + if( p_sys->i_title_cur_time > 0 ) { - *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN * - p_sys->i_title_offset / 50 / p_sys->i_mux_rate; + *pi64 = (int64_t)p_sys->i_title_cur_time; return VLC_SUCCESS; } *pi64 = 0; @@ -347,10 +396,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); - if( p_sys->i_mux_rate > 0 ) + if (p_demux->info.i_title >= 0 && p_demux->info.i_title < p_sys->i_titles) { - *pi64 = (int64_t)1000000 * DVD_VIDEO_LB_LEN * - p_sys->i_title_blocks / 50 / p_sys->i_mux_rate; + *pi64 = dvdtime_to_time( &p_sys->p_cur_pgc->playback_time, 0 ); return VLC_SUCCESS; } *pi64 = 0; @@ -453,7 +501,7 @@ static int Demux( demux_t *p_demux ) DvdReadHandleDSI( p_demux, p_buffer ); /* End of title */ - if( p_sys->i_next_vobu > p_sys->i_title_end_block ) + if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) { if( p_sys->i_title + 1 >= p_sys->i_titles ) { @@ -478,7 +526,7 @@ static int Demux( demux_t *p_demux ) DemuxBlock( p_demux, p_buffer, DVD_VIDEO_LB_LEN ); } - if( p_sys->i_cur_block > p_sys->i_title_end_block ) + if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) { if( p_sys->i_title + 1 >= p_sys->i_titles ) { @@ -571,7 +619,7 @@ static int DemuxBlock( demux_t *p_demux, uint8_t *pkt, int i_pkt ) 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; +/* if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;*/ } block_Release( p_pkt ); break; @@ -1083,6 +1131,12 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data ) p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn; p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea; + /* + * Store the timecodes so we can get the current time + */ + p_sys->i_title_cur_time = (mtime_t) p_sys->dsi_pack.dsi_gi.nv_pck_scr / 90 * 1000; + p_sys->i_cell_cur_time = (mtime_t) dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 ); + /* * 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 @@ -1140,27 +1194,38 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data ) else if( p_sys->dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL ) { p_sys->i_cur_cell = p_sys->i_next_cell; + + /* End of title */ + if( p_sys->i_cur_cell >= p_sys->p_cur_pgc->nr_of_cells ) return; + DvdReadFindCell( p_demux ); p_sys->i_next_vobu = p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector; + + p_sys->i_cell_duration = (mtime_t)dvdtime_to_time( &p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].playback_time, 0 ); } + #if 0 - msg_Dbg( p_demux, 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d", + msg_Dbg( p_demux, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d c_time %lld", p_sys->dsi_pack.dsi_gi.nv_pck_scr, p_sys->dsi_pack.dsi_gi.nv_pck_lbn, p_sys->dsi_pack.dsi_gi.vobu_ea, p_sys->dsi_pack.dsi_gi.vobu_vob_idn, - p_sys->dsi_pack.dsi_gi.vobu_c_idn ); + p_sys->dsi_pack.dsi_gi.vobu_c_idn, + dvdtime_to_time( &p_sys->dsi_pack.dsi_gi.c_eltm, 0 ) ); + + msg_Dbg( p_demux, "cell duration: %lld", + (mtime_t)dvdtime_to_time( &p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].playback_time, 0 ) ); - msg_Dbg( p_demux, 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d", + msg_Dbg( p_demux, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d", p_sys->dsi_pack.sml_pbi.category, p_sys->dsi_pack.sml_pbi.ilvu_ea, p_sys->dsi_pack.sml_pbi.ilvu_sa, p_sys->dsi_pack.sml_pbi.size ); - msg_Dbg( p_demux, 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d", + msg_Dbg( p_demux, "next_vobu %d next_ilvu1 %d next_ilvu2 %d", p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff, p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle - 1 ].address, p_sys->dsi_pack.sml_agli.data[ p_sys->i_angle ].address);