📄 dvdnav.c
字号:
if( b_button_ok ) { int i; for( i = 0; i < 4; i++ ) { uint32_t i_yuv = p_sys->clut[(hl.palette>>(16+i*4))&0x0f]; uint8_t i_alpha = ( (hl.palette>>(i*4))&0x0f ) * 0xff / 0xf; p_sys->palette[i][0] = (i_yuv >> 16) & 0xff; p_sys->palette[i][1] = (i_yuv >> 0) & 0xff; p_sys->palette[i][2] = (i_yuv >> 8) & 0xff; p_sys->palette[i][3] = i_alpha; } vlc_mutex_lock( p_mutex ); val.i_int = hl.sx; var_Set( p_sys->p_input, "x-start", val ); val.i_int = hl.ex; var_Set( p_sys->p_input, "x-end", val ); val.i_int = hl.sy; var_Set( p_sys->p_input, "y-start", val ); val.i_int = hl.ey; var_Set( p_sys->p_input, "y-end", val ); val.p_address = (void *)p_sys->palette; var_Set( p_sys->p_input, "menu-palette", val ); val.b_bool = true; var_Set( p_sys->p_input, "highlight", val ); vlc_mutex_unlock( p_mutex ); msg_Dbg( p_demux, "buttonUpdate %d", i_button ); } else { msg_Dbg( p_demux, "buttonUpdate not done b=%d t=%d", i_button, i_title ); /* Show all */ vlc_mutex_lock( p_mutex ); val.b_bool = false; var_Set( p_sys->p_input, "highlight", val ); vlc_mutex_unlock( p_mutex ); } }}static void ESSubtitleUpdate( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; int i_spu = dvdnav_get_active_spu_stream( p_sys->dvdnav ); int32_t i_title, i_part; ButtonUpdate( p_demux, false ); dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part ); if( i_title > 0 ) return; if( i_spu >= 0 && i_spu <= 0x1f ) { ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)]; ESNew( p_demux, 0xbd20 + i_spu ); /* be sure to unselect it (reset) */ es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es, (bool)false ); /* now select it */ es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es ); } else { for( i_spu = 0; i_spu <= 0x1F; i_spu++ ) { ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)]; if( tk->b_seen ) { es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es, (bool)false ); } } }}/***************************************************************************** * DemuxBlock: demux a given block *****************************************************************************/static int DemuxBlock( demux_t *p_demux, const uint8_t *pkt, int i_pkt ){ demux_sys_t *p_sys = p_demux->p_sys; const 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 DVDNAV_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 ); } 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 ){ demux_sys_t *p_sys = p_demux->p_sys; ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)]; bool b_select = false; 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; } /* Add a new ES */ if( tk->fmt.i_cat == VIDEO_ES ) { switch( p_sys->i_aspect ) { case 1: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR; break; case 2: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 4 / 3; break; case 3: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 16 / 9; break; case 4: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 221 / 10; break; default: tk->fmt.video.i_aspect = 0; break; } b_select = true; } 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( i_audio >= 0 ) { int i_lang = dvdnav_audio_stream_to_lang( p_sys->dvdnav, i_audio ); if( i_lang != 0xffff ) { tk->fmt.psz_language = malloc( 3 ); tk->fmt.psz_language[0] = (i_lang >> 8)&0xff; tk->fmt.psz_language[1] = (i_lang )&0xff; tk->fmt.psz_language[2] = 0; } if( dvdnav_get_active_audio_stream( p_sys->dvdnav ) == i_audio ) { b_select = true; } } } else if( tk->fmt.i_cat == SPU_ES ) { int32_t i_title, i_part; int i_lang = dvdnav_spu_stream_to_lang( p_sys->dvdnav, i_id&0x1f ); if( i_lang != 0xffff ) { tk->fmt.psz_language = malloc( 3 ); tk->fmt.psz_language[0] = (i_lang >> 8)&0xff; tk->fmt.psz_language[1] = (i_lang )&0xff; tk->fmt.psz_language[2] = 0; } /* Palette */ tk->fmt.subs.spu.palette[0] = 0xBeef; memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut, 16 * sizeof( uint32_t ) ); /* We select only when we are not in the menu */ dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part ); if( i_title > 0 && dvdnav_get_active_spu_stream( p_sys->dvdnav ) == (i_id&0x1f) ) { b_select = true; } } tk->es = es_out_Add( p_demux->out, &tk->fmt ); if( b_select ) { es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es ); } tk->b_seen = true; if( tk->fmt.i_cat == VIDEO_ES ) ButtonUpdate( p_demux, false );}/***************************************************************************** * Event handler code *****************************************************************************/static int EventMouse( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static int EventKey ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static void* EventThread( vlc_object_t *p_this ){ event_thread_t *p_ev = (event_thread_t*)p_this; demux_sys_t *p_sys = p_ev->p_demux->p_sys; vlc_object_t *p_vout = NULL; vlc_mutex_init( &p_ev->lock ); p_ev->b_moved = false; p_ev->b_clicked = false; p_ev->i_key_action = 0; p_ev->b_still = false; /* catch all key event */ var_AddCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev ); /* main loop */ while( vlc_object_alive (p_ev) ) { bool b_activated = false; /* KEY part */ if( p_ev->i_key_action != 0 ) { pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav ); vlc_mutex_lock( &p_ev->lock ); switch( p_ev->i_key_action ) { case ACTIONID_NAV_LEFT: dvdnav_left_button_select( p_sys->dvdnav, pci ); break; case ACTIONID_NAV_RIGHT: dvdnav_right_button_select( p_sys->dvdnav, pci ); break; case ACTIONID_NAV_UP: dvdnav_upper_button_select( p_sys->dvdnav, pci ); break; case ACTIONID_NAV_DOWN: dvdnav_lower_button_select( p_sys->dvdnav, pci ); break; case ACTIONID_NAV_ACTIVATE: b_activated = true; ButtonUpdate( p_ev->p_demux, true ); dvdnav_button_activate( p_sys->dvdnav, pci ); break; default: break; } p_ev->i_key_action = 0; vlc_mutex_unlock( &p_ev->lock ); } /* VOUT part */ if( p_vout && ( p_ev->b_moved || p_ev->b_clicked ) ) { pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav ); vlc_value_t valx, valy; vlc_mutex_lock( &p_ev->lock ); var_Get( p_vout, "mouse-x", &valx ); var_Get( p_vout, "mouse-y", &valy ); if( p_ev->b_moved ) { dvdnav_mouse_select( p_sys->dvdnav, pci, valx.i_int, valy.i_int ); } if( p_ev->b_clicked ) { b_activated = true; ButtonUpdate( p_ev->p_demux, true ); dvdnav_mouse_activate( p_sys->dvdnav, pci, valx.i_int, valy.i_int ); } p_ev->b_moved = false; p_ev->b_clicked = false; vlc_mutex_unlock( &p_ev->lock ); } if( p_vout && !vlc_object_alive (p_vout) ) { var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev ); var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev ); vlc_object_release( p_vout ); p_vout = NULL; } if( p_vout == NULL ) { p_vout = vlc_object_find( p_sys->p_input, VLC_OBJECT_VOUT, FIND_CHILD ); if( p_vout) { var_AddCallback( p_vout, "mouse-moved", EventMouse, p_ev ); var_AddCallback( p_vout, "mouse-clicked", EventMouse, p_ev ); } } /* Still part */ vlc_mutex_lock( &p_ev->lock ); if( p_ev->b_still ) { if( /* b_activated || // This breaks menus */ ( p_ev->i_still_end > 0 && p_ev->i_still_end < mdate() )) { p_ev->b_still = false; dvdnav_still_skip( p_sys->dvdnav ); } } vlc_mutex_unlock( &p_ev->lock ); /* Wait a bit */ msleep( 10000 ); } /* Release callback */ if( p_vout ) { var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev ); var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev ); vlc_object_release( p_vout ); } var_DelCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev ); vlc_mutex_destroy( &p_ev->lock ); return NULL;}static int EventMouse( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ (void)p_this; (void)oldval; (void)newval; (void)p_data; event_thread_t *p_ev = p_data; vlc_mutex_lock( &p_ev->lock ); if( psz_var[6] == 'c' ) p_ev->b_clicked = true; else if( psz_var[6] == 'm' ) p_ev->b_moved = true; vlc_mutex_unlock( &p_ev->lock ); return VLC_SUCCESS;}static int EventKey( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ (void)p_this; (void)psz_var; (void)oldval; event_thread_t *p_ev = p_data; vlc_mutex_lock( &p_ev->lock ); p_ev->i_key_action = newval.i_int; vlc_mutex_unlock( &p_ev->lock ); return VLC_SUCCESS;}/***************************************************************************** * ProbeDVD: very weak probing that avoids going too often into a dvdnav_open() *****************************************************************************/static int ProbeDVD( demux_t *p_demux, char *psz_name ){ (void)p_demux;#ifdef HAVE_SYS_STAT_H struct stat stat_info; uint8_t pi_anchor[2]; uint16_t i_tag_id = 0; int i_fd, i_ret; if( !*psz_name ) { /* Triggers libdvdcss autodetection */ return VLC_SUCCESS; } if( utf8_stat( psz_name, &stat_info ) || !S_ISREG( stat_info.st_mode ) ) { /* Let dvdnav_open() do the probing */ return VLC_SUCCESS; } if( (i_fd = open( psz_name, O_RDONLY )) == -1 ) { /* Let dvdnav_open() do the probing */ return VLC_SUCCESS; } /* Try to find the anchor (2 bytes at LBA 256) */ i_ret = VLC_SUCCESS; if( lseek( i_fd, 256 * DVD_VIDEO_LB_LEN, SEEK_SET ) == -1 ) { i_ret = VLC_EGENERIC; } if( read( i_fd, pi_anchor, 2 ) == 2 ) { i_tag_id = GetWLE(pi_anchor); if( i_tag_id != 2 ) i_ret = VLC_EGENERIC; /* Not an anchor */ } else { i_ret = VLC_EGENERIC; } close( i_fd ); return i_ret;#else return VLC_SUCCESS;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -