📄 input.c
字号:
/* Set die for all stream */ p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD ); for( i = 0; i < p_list->i_count; i++ ) { p_list->p_values[i].p_object->b_die = VLC_TRUE; } vlc_list_release( p_list ); /* Set die for all demux */ p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD ); for( i = 0; i < p_list->i_count; i++ ) { p_list->p_values[i].p_object->b_die = VLC_TRUE; } vlc_list_release( p_list ); input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );}/** * Clean up a dead input thread * This function does not return until the thread is effectively cancelled. * * \param the input thread to kill */void input_DestroyThread( input_thread_t *p_input ){ if( 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 * This is the "normal" thread that spawns the input processing chain, * reads the stream, cleans up and waits *****************************************************************************/static int Run( input_thread_t *p_input ){ 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; } MainLoop( p_input ); 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 until we are asked to die */ if( !p_input->b_die ) { Error( p_input ); } /* Clean up */ End( p_input ); return 0;}/***************************************************************************** * RunAndClean: main thread loop * This is the "just forget me" thread that spawns the input processing chain, * reads the stream, cleans up and releases memory *****************************************************************************/static int RunAndClean( input_thread_t *p_input ){ /* Signal that the thread is launched */ vlc_thread_ready( p_input ); if( Init( p_input, VLC_FALSE ) ) { /* If we failed, just exit */ return 0; } MainLoop( p_input ); if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof ) { /* We have finished demuxing data but not playing it */ 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; } /* Clean up */ End( p_input ); /* Release memory */ vlc_object_detach( p_input ); vlc_object_destroy( p_input ); return 0;}/***************************************************************************** * Main loop: Fill buffers from access, and demux *****************************************************************************/static void MainLoop( input_thread_t *p_input ){ int64_t i_intf_update = 0; 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. */ input_ChangeState( p_input, END_S ); 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); } }}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 ) { /* Prepare statistics */ counter_t *p_counter; stats_Create( p_input, "read_bytes", STATS_READ_BYTES, VLC_VAR_INTEGER, STATS_COUNTER ); stats_Create( p_input, "read_packets", STATS_READ_PACKETS, VLC_VAR_INTEGER, STATS_COUNTER ); stats_Create( p_input, "demux_read", STATS_DEMUX_READ, VLC_VAR_INTEGER, STATS_COUNTER ); stats_Create( p_input, "input_bitrate", STATS_INPUT_BITRATE, VLC_VAR_FLOAT, STATS_DERIVATIVE ); stats_Create( p_input, "demux_bitrate", STATS_DEMUX_BITRATE, VLC_VAR_FLOAT, STATS_DERIVATIVE ); p_counter = stats_CounterGet( p_input, p_input->i_object_id, STATS_INPUT_BITRATE ); if( p_counter ) p_counter->update_interval = 1000000; p_counter = stats_CounterGet( p_input, p_input->i_object_id, STATS_DEMUX_BITRATE ); if( p_counter ) p_counter->update_interval = 1000000; stats_Create( p_input, "played_abuffers", STATS_PLAYED_ABUFFERS, VLC_VAR_INTEGER, STATS_COUNTER ); stats_Create( p_input, "lost_abuffers", STATS_LOST_ABUFFERS, VLC_VAR_INTEGER, STATS_COUNTER ); /* handle sout */ 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 ) { input_ChangeState( p_input, ERROR_S ); 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 ); var_Create( p_input, "bit-rate", VLC_VAR_INTEGER ); var_Create( p_input, "sample-rate", VLC_VAR_INTEGER ); 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -