📄 dvdnav.c
字号:
{ msg_Warn( p_demux, "cannot set title/chapter" ); return VLC_EGENERIC; } p_demux->info.i_update |= 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( p_demux->info.i_title == 0 ) { int i_ret; /* Special case */ switch( i ) { case 0: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Escape ); break; case 1: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root ); break; case 2: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title ); break; case 3: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Part ); break; case 4: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Subpicture ); break; case 5: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Audio ); break; case 6: i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Angle ); break; default: return VLC_EGENERIC; } if( i_ret != DVDNAV_STATUS_OK ) return VLC_EGENERIC; } else if( dvdnav_part_play( p_sys->dvdnav, p_demux->info.i_title, i + 1 ) != DVDNAV_STATUS_OK ) { 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, "dvdnav-caching" ) *1000; return VLC_SUCCESS; case DEMUX_GET_META: { const char *title_name = NULL; dvdnav_get_title_string(p_sys->dvdnav, &title_name); if( (NULL != title_name) && ('\0' != title_name[0]) ) { vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* ); vlc_meta_Set( p_meta, vlc_meta_Title, title_name ); return VLC_SUCCESS; } return VLC_EGENERIC; } /* TODO implement others */ default: return VLC_EGENERIC; }}static int ControlInternal( demux_t *p_demux, int i_query, ... ){ va_list args; int i_result; va_start( args, i_query ); i_result = Control( p_demux, i_query, args ); va_end( args ); return i_result;}/***************************************************************************** * Demux: *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; uint8_t buffer[DVD_VIDEO_LB_LEN]; uint8_t *packet = buffer; int i_event; int i_len;#if DVD_READ_CACHE if( dvdnav_get_next_cache_block( p_sys->dvdnav, &packet, &i_event, &i_len ) == DVDNAV_STATUS_ERR )#else if( dvdnav_get_next_block( p_sys->dvdnav, packet, &i_event, &i_len ) == DVDNAV_STATUS_ERR )#endif { msg_Warn( p_demux, "cannot get next block (%s)", dvdnav_err_to_string( p_sys->dvdnav ) ); if( p_demux->info.i_title == 0 ) { msg_Dbg( p_demux, "jumping to first title" ); return ControlInternal( p_demux, DEMUX_SET_TITLE, 1 ) == VLC_SUCCESS ? 1 : -1; } return -1; } switch( i_event ) { case DVDNAV_BLOCK_OK: /* mpeg block */ DemuxBlock( p_demux, packet, i_len ); break; case DVDNAV_NOP: /* Nothing */ msg_Dbg( p_demux, "DVDNAV_NOP" ); break; case DVDNAV_STILL_FRAME: { /* We send a dummy mpeg2 end of sequence to force still frame display */ static const uint8_t buffer[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB7, }; DemuxBlock( p_demux, buffer, sizeof(buffer) ); /* */ dvdnav_still_event_t *event = (dvdnav_still_event_t*)packet; vlc_mutex_lock( &p_sys->p_ev->lock ); if( !p_sys->p_ev->b_still ) { msg_Dbg( p_demux, "DVDNAV_STILL_FRAME" ); msg_Dbg( p_demux, " - length=0x%x", event->length ); p_sys->p_ev->b_still = true; if( event->length == 0xff ) { p_sys->p_ev->i_still_end = 0; } else { p_sys->p_ev->i_still_end = (int64_t)event->length * 1000000 + mdate() + p_sys->p_input->i_pts_delay; } } vlc_mutex_unlock( &p_sys->p_ev->lock ); msleep( 40000 ); break; } case DVDNAV_SPU_CLUT_CHANGE: { int i; msg_Dbg( p_demux, "DVDNAV_SPU_CLUT_CHANGE" ); /* Update color lookup table (16 *uint32_t in packet) */ memcpy( p_sys->clut, packet, 16 * sizeof( uint32_t ) ); /* HACK to get the SPU tracks registered in the right order */ for( i = 0; i < 0x1f; i++ ) { if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff ) ESNew( p_demux, 0xbd20 + i ); } /* END HACK */ break; } case DVDNAV_SPU_STREAM_CHANGE: { dvdnav_spu_stream_change_event_t *event = (dvdnav_spu_stream_change_event_t*)packet; int i; msg_Dbg( p_demux, "DVDNAV_SPU_STREAM_CHANGE" ); msg_Dbg( p_demux, " - physical_wide=%d", event->physical_wide ); msg_Dbg( p_demux, " - physical_letterbox=%d", event->physical_letterbox); msg_Dbg( p_demux, " - physical_pan_scan=%d", event->physical_pan_scan ); ESSubtitleUpdate( p_demux ); p_sys->b_spu_change = true; /* HACK to get the SPU tracks registered in the right order */ for( i = 0; i < 0x1f; i++ ) { if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff ) ESNew( p_demux, 0xbd20 + i ); } /* END HACK */ break; } case DVDNAV_AUDIO_STREAM_CHANGE: { dvdnav_audio_stream_change_event_t *event = (dvdnav_audio_stream_change_event_t*)packet; msg_Dbg( p_demux, "DVDNAV_AUDIO_STREAM_CHANGE" ); msg_Dbg( p_demux, " - physical=%d", event->physical ); /* TODO */ break; } case DVDNAV_VTS_CHANGE: { int32_t i_title = 0; int32_t i_part = 0; int i; dvdnav_vts_change_event_t *event = (dvdnav_vts_change_event_t*)packet; msg_Dbg( p_demux, "DVDNAV_VTS_CHANGE" ); msg_Dbg( p_demux, " - vtsN=%d", event->new_vtsN ); msg_Dbg( p_demux, " - domain=%d", event->new_domain ); /* dvdnav_get_video_aspect / dvdnav_get_video_scale_permission */ /* TODO check if we always have VTS and CELL */ p_sys->i_aspect = dvdnav_get_video_aspect( p_sys->dvdnav ); /* reset PCR */ 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 = false; } if( dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part ) == DVDNAV_STATUS_OK ) { if( i_title >= 0 && i_title < p_sys->i_title && p_demux->info.i_title != i_title ) { p_demux->info.i_update |= INPUT_UPDATE_TITLE; p_demux->info.i_title = i_title; } } break; } case DVDNAV_CELL_CHANGE: { int32_t i_title = 0; int32_t i_part = 0; dvdnav_cell_change_event_t *event = (dvdnav_cell_change_event_t*)packet; msg_Dbg( p_demux, "DVDNAV_CELL_CHANGE" ); msg_Dbg( p_demux, " - cellN=%d", event->cellN ); msg_Dbg( p_demux, " - pgN=%d", event->pgN ); msg_Dbg( p_demux, " - cell_length=%"PRId64, event->cell_length ); msg_Dbg( p_demux, " - pg_length=%"PRId64, event->pg_length ); msg_Dbg( p_demux, " - pgc_length=%"PRId64, event->pgc_length ); msg_Dbg( p_demux, " - cell_start=%"PRId64, event->cell_start ); msg_Dbg( p_demux, " - pg_start=%"PRId64, event->pg_start ); /* Store the lenght in time of the current PGC */ p_sys->i_pgc_length = event->pgc_length / 90 * 1000; /* FIXME is it correct or there is better way to know chapter change */ if( dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part ) == DVDNAV_STATUS_OK ) { if( i_title >= 0 && i_title < p_sys->i_title && i_part >= 1 && i_part <= p_sys->title[i_title]->i_seekpoint && p_demux->info.i_seekpoint != i_part - 1 ) { p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT; p_demux->info.i_seekpoint = i_part - 1; } } break; } case DVDNAV_NAV_PACKET: {#ifdef DVDNAV_DEBUG msg_Dbg( p_demux, "DVDNAV_NAV_PACKET" );#endif /* A lot of thing to do here : * - handle packet * - fetch pts (for time display) * - ... */ DemuxBlock( p_demux, packet, i_len ); if( p_sys->b_spu_change ) { ButtonUpdate( p_demux, false ); p_sys->b_spu_change = false; } break; } case DVDNAV_STOP: /* EOF */ msg_Dbg( p_demux, "DVDNAV_STOP" );#if DVD_READ_CACHE dvdnav_free_cache_block( p_sys->dvdnav, packet );#endif return 0; case DVDNAV_HIGHLIGHT: { dvdnav_highlight_event_t *event = (dvdnav_highlight_event_t*)packet; msg_Dbg( p_demux, "DVDNAV_HIGHLIGHT" ); msg_Dbg( p_demux, " - display=%d", event->display ); msg_Dbg( p_demux, " - buttonN=%d", event->buttonN ); ButtonUpdate( p_demux, false ); break; } case DVDNAV_HOP_CHANNEL: msg_Dbg( p_demux, "DVDNAV_HOP_CHANNEL" ); /* We should try to flush all our internal buffer */ break; case DVDNAV_WAIT: msg_Dbg( p_demux, "DVDNAV_WAIT" ); /* reset PCR */ es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); dvdnav_wait_skip( p_sys->dvdnav ); break; default: msg_Warn( p_demux, "Unknown event (0x%x)", i_event ); break; }#if DVD_READ_CACHE dvdnav_free_cache_block( p_sys->dvdnav, packet );#endif return 1;}/* Get a 2 char code * FIXME: partiallyy duplicated from src/input/es_out.c */static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var ){ const iso639_lang_t *pl; char *psz_lang; char *p; psz_lang = var_CreateGetString( p_demux, psz_var ); if( !psz_lang ) return strdup(LANGUAGE_DEFAULT); /* XXX: we will use only the first value * (and ignore other ones in case of a list) */ if( ( p = strchr( psz_lang, ',' ) ) ) *p = '\0'; for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ ) { if( *psz_lang == '\0' ) continue; if( !strcasecmp( pl->psz_eng_name, psz_lang ) || !strcasecmp( pl->psz_native_name, psz_lang ) || !strcasecmp( pl->psz_iso639_1, psz_lang ) || !strcasecmp( pl->psz_iso639_2T, psz_lang ) || !strcasecmp( pl->psz_iso639_2B, psz_lang ) ) break; } free( psz_lang ); if( pl->psz_iso639_1 != NULL ) return strdup( pl->psz_iso639_1 ); return strdup(LANGUAGE_DEFAULT);}static void DemuxTitles( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; input_title_t *t; seekpoint_t *s; int32_t i_titles; int i; /* Menu */ t = vlc_input_title_New(); t->b_menu = true; t->psz_name = strdup( "DVD Menu" ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Resume" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Root" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Title" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Chapter" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Subtitle" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Audio" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); s = vlc_seekpoint_New(); s->psz_name = strdup( "Angle" ); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); TAB_APPEND( p_sys->i_title, p_sys->title, t ); /* Find out number of titles/chapters */ dvdnav_get_number_of_titles( p_sys->dvdnav, &i_titles ); for( i = 1; i <= i_titles; i++ ) { int32_t i_chapters = 0; int j; dvdnav_get_number_of_parts( p_sys->dvdnav, i, &i_chapters ); t = vlc_input_title_New(); for( j = 0; j < __MAX( i_chapters, 1 ); j++ ) { s = vlc_seekpoint_New(); TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); } TAB_APPEND( p_sys->i_title, p_sys->title, t ); }}/***************************************************************************** * Update functions: *****************************************************************************/static void ButtonUpdate( demux_t *p_demux, bool b_mode ){ demux_sys_t *p_sys = p_demux->p_sys; vlc_value_t val; int32_t i_title, i_part; dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part ); if( var_Get( p_sys->p_input, "highlight-mutex", &val ) == VLC_SUCCESS ) { vlc_mutex_t *p_mutex = val.p_address; dvdnav_highlight_area_t hl; int32_t i_button; bool b_button_ok; if( dvdnav_get_current_highlight( p_sys->dvdnav, &i_button ) != DVDNAV_STATUS_OK ) { msg_Err( p_demux, "dvdnav_get_current_highlight failed" ); return; } b_button_ok = false; if( i_button > 0 && i_title == 0 ) { pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav ); b_button_ok = dvdnav_get_highlight_area( pci, i_button, b_mode, &hl ) == DVDNAV_STATUS_OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -