📄 input.c
字号:
***************************************************************************** * This function should not return until the thread is effectively cancelled. *****************************************************************************/void input_DestroyThread( input_thread_t *p_input ){ /* Join the thread */ vlc_thread_join( p_input ); /* Delete input lock (only after thread joined) */ vlc_mutex_destroy( &p_input->lock_control ); /* TODO: maybe input_DestroyThread should also delete p_input instead * of the playlist but I'm not sure if it's possible */}/***************************************************************************** * Run: main thread loop ***************************************************************************** * Thread in charge of processing the network packets and demultiplexing. * * TODO: * read subtitle support (XXX take care of spu-delay in the right way). * multi-input support (XXX may be done with subs) *****************************************************************************/static int Run( input_thread_t *p_input ){ int64_t i_intf_update = 0; /* Signal that the thread is launched */ vlc_thread_ready( p_input ); if( Init( p_input, VLC_FALSE ) ) { /* If we failed, wait before we are killed, and exit */ p_input->b_error = VLC_TRUE; Error( p_input ); /* Tell we're dead */ p_input->b_dead = VLC_TRUE; return 0; } /* Main loop */ while( !p_input->b_die && !p_input->b_error && !p_input->input.b_eof ) { vlc_bool_t b_force_update = VLC_FALSE; int i_ret; int i_type; vlc_value_t val; /* Do the read */ if( p_input->i_state != PAUSE_S ) { if( p_input->i_stop <= 0 || p_input->i_time < p_input->i_stop ) i_ret=p_input->input.p_demux->pf_demux(p_input->input.p_demux); else i_ret = 0; /* EOF */ if( i_ret > 0 ) { /* TODO */ if( p_input->input.b_title_demux && p_input->input.p_demux->info.i_update ) { i_ret = UpdateFromDemux( p_input ); b_force_update = VLC_TRUE; } else if( !p_input->input.b_title_demux && p_input->input.p_access && p_input->input.p_access->info.i_update ) { i_ret = UpdateFromAccess( p_input ); b_force_update = VLC_TRUE; } } if( i_ret == 0 ) /* EOF */ { vlc_value_t repeat; var_Get( p_input, "input-repeat", &repeat ); if( repeat.i_int == 0 ) { /* End of file - we do not set b_die because only the * playlist is allowed to do so. */ msg_Dbg( p_input, "EOF reached" ); p_input->input.b_eof = VLC_TRUE; } else { msg_Dbg( p_input, "repeating the same input (%d)", repeat.i_int ); if( repeat.i_int > 0 ) { repeat.i_int--; var_Set( p_input, "input-repeat", repeat ); } /* Seek to start title/seekpoint */ val.i_int = p_input->input.i_title_start - p_input->input.i_title_offset; if( val.i_int < 0 || val.i_int >= p_input->input.i_title ) val.i_int = 0; input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val ); val.i_int = p_input->input.i_seekpoint_start - p_input->input.i_seekpoint_offset; if( val.i_int > 0 /* TODO: check upper boundary */ ) input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val ); /* Seek to start position */ if( p_input->i_start > 0 ) { val.i_time = p_input->i_start; input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &val ); } else { val.f_float = 0.0; input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, &val ); } } } else if( i_ret < 0 ) { p_input->b_error = VLC_TRUE; } if( i_ret > 0 && p_input->i_slave > 0 ) { SlaveDemux( p_input ); } } else { /* Small wait */ msleep( 10*1000 ); } /* Handle control */ vlc_mutex_lock( &p_input->lock_control ); ControlReduce( p_input ); while( !ControlPopNoLock( p_input, &i_type, &val ) ) { msg_Dbg( p_input, "control type=%d", i_type ); if( Control( p_input, i_type, val ) ) b_force_update = VLC_TRUE; } vlc_mutex_unlock( &p_input->lock_control ); if( b_force_update || i_intf_update < mdate() ) { vlc_value_t val; double f_pos; int64_t i_time, i_length; /* update input status variables */ if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_POSITION, &f_pos ) ) { val.f_float = (float)f_pos; var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL ); } if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) ) { p_input->i_time = i_time; val.i_time = i_time; var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL ); } if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_LENGTH, &i_length ) ) { vlc_value_t old_val; var_Get( p_input, "length", &old_val ); val.i_time = i_length; var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL ); if( old_val.i_time != val.i_time ) { UpdateItemLength( p_input, i_length, VLC_TRUE ); } } var_SetBool( p_input, "intf-change", VLC_TRUE ); i_intf_update = mdate() + I64C(150000); } } if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof ) { /* We have finish to demux data but not to play them */ while( !p_input->b_die ) { if( input_EsOutDecodersEmpty( p_input->p_es_out ) ) break; msg_Dbg( p_input, "waiting decoder fifos to empty" ); msleep( INPUT_IDLE_SLEEP ); } /* We have finished */ p_input->b_eof = VLC_TRUE; } /* Wait we are asked to die */ if( !p_input->b_die ) { Error( p_input ); } /* Clean up */ End( p_input ); return 0;}static int Init( input_thread_t * p_input, vlc_bool_t b_quick ){ char *psz; char *psz_subtitle; vlc_value_t val; double f_fps; vlc_meta_t *p_meta, *p_meta_tmp; int i_es_out_mode; int i, i_delay; /* Initialize optional stream output. (before access/demuxer) * XXX: we add a special case if the uri starts by vlc. * else 'vlc in.file --sout "" vlc:quit' cannot work (the output will * be destroyed in case of a file). * (this will break playing of file starting by 'vlc:' but I don't * want to add more logic, just force file by file:// or code it ;) */ if( !b_quick ) { psz = var_GetString( p_input, "sout" ); if( *psz && strncasecmp( p_input->input.p_item->psz_uri, "vlc:", 4 ) ) { p_input->p_sout = sout_NewInstance( p_input, psz ); if( p_input->p_sout == NULL ) { msg_Err( p_input, "cannot start stream output instance, " \ "aborting" ); free( psz ); return VLC_EGENERIC; } } free( psz ); } /* Create es out */ p_input->p_es_out = input_EsOutNew( p_input ); es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE ); es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE ); if( InputSourceInit( p_input, &p_input->input, p_input->input.p_item->psz_uri, NULL, b_quick ) ) { goto error; } /* Create global title (from master) */ if( !b_quick ) { p_input->i_title = p_input->input.i_title; p_input->title = p_input->input.title; p_input->i_title_offset = p_input->input.i_title_offset; p_input->i_seekpoint_offset = p_input->input.i_seekpoint_offset; if( p_input->i_title > 0 ) { /* Setup variables */ input_ControlVarNavigation( p_input ); input_ControlVarTitle( p_input, 0 ); } /* Global flag */ p_input->b_can_pace_control = p_input->input.b_can_pace_control; p_input->b_can_pause = p_input->input.b_can_pause; /* Fix pts delay */ if( p_input->i_pts_delay <= 0 ) p_input->i_pts_delay = DEFAULT_PTS_DELAY; /* If the desynchronisation requested by the user is < 0, we need to * cache more data. */ var_Get( p_input, "audio-desync", &val ); if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000); /* Update cr_average depending on the caching */ p_input->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000); p_input->input.i_cr_average /= 10; if( p_input->input.i_cr_average <= 0 ) p_input->input.i_cr_average = 1; } /* Load master infos */ /* Init length */ if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_LENGTH, &val.i_time ) && val.i_time > 0 ) { var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL ); UpdateItemLength( p_input, val.i_time, b_quick ); p_input->input.p_item->i_duration = val.i_time; } /* Start title/chapter */ if( !b_quick ) { val.i_int = p_input->input.i_title_start - p_input->input.i_title_offset; if( val.i_int > 0 && val.i_int < p_input->input.i_title ) input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val ); val.i_int = p_input->input.i_seekpoint_start - p_input->input.i_seekpoint_offset; if( val.i_int > 0 /* TODO: check upper boundary */ ) input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val ); /* Start time*/ /* Set start time */ p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) * I64C(1000000); p_input->i_stop = (int64_t)var_GetInteger( p_input, "stop-time" ) * I64C(1000000); if( p_input->i_start > 0 ) { if( p_input->i_start >= val.i_time ) { msg_Warn( p_input, "invalid start-time ignored" ); } else { vlc_value_t s; msg_Dbg( p_input, "starting at time: %ds", (int)( p_input->i_start / I64C(1000000) ) ); s.i_time = p_input->i_start; input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s ); } } if( p_input->i_stop > 0 && p_input->i_stop <= p_input->i_start ) { msg_Warn( p_input, "invalid stop-time ignored" ); p_input->i_stop = 0; } /* Load subtitles */ /* Get fps and set it if not already set */ if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) && f_fps > 1.0 ) { float f_requested_fps; var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT ); var_SetFloat( p_input, "sub-original-fps", f_fps ); f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" ); if( f_requested_fps != f_fps ) { var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| VLC_VAR_DOINHERIT ); var_SetFloat( p_input, "sub-fps", f_requested_fps ); } } i_delay = var_CreateGetInteger( p_input, "sub-delay" ); if( i_delay != 0 ) { var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -