⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * Initialize an input thread and run it. This thread will clean after itself, * you can forget about it. It can work either in blocking or non-blocking mode * * \param p_parent a vlc_object * \param p_item an input item * \param b_block should we block until read is finished ? * \return the input object id if non blocking, an error code else */int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,                   bool b_block ){    input_thread_t *p_input;    p_input = Create( p_parent, p_item, NULL, false, NULL );    if( !p_input )        return VLC_EGENERIC;    if( b_block )    {        RunAndDestroy( VLC_OBJECT(p_input) );        return VLC_SUCCESS;    }    else    {        if( vlc_thread_create( p_input, "input", RunAndDestroy,                               VLC_THREAD_PRIORITY_INPUT, true ) )        {            input_ChangeState( p_input, ERROR_S );            msg_Err( p_input, "cannot create input thread" );            vlc_object_release( p_input );            return VLC_EGENERIC;        }    }    return p_input->i_object_id;}/** * Initialize an input and initialize it to preparse the item * This function is blocking. It will only accept to parse files * * \param p_parent a vlc_object_t * \param p_item an input item * \return VLC_SUCCESS or an error */int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ){    input_thread_t *p_input;    /* Allocate descriptor */    p_input = Create( p_parent, p_item, NULL, true, NULL );    if( !p_input )        return VLC_EGENERIC;    if( !Init( p_input ) )        End( p_input );    vlc_object_detach( p_input );    vlc_object_release( p_input );    return VLC_SUCCESS;}/** * Request a running input thread to stop and die * * \param the input thread to stop */static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ){    vlc_list_t *p_list;    int i;    if( p_obj->i_object_type == VLC_OBJECT_VOUT ||        p_obj->i_object_type == VLC_OBJECT_AOUT ||        p_obj == VLC_OBJECT(p_input->p->p_sout) )        return;    vlc_object_kill( p_obj );    p_list = vlc_list_children( p_obj );    for( i = 0; i < p_list->i_count; i++ )        ObjectKillChildrens( p_input, p_list->p_values[i].p_object );    vlc_list_release( p_list );}void input_StopThread( input_thread_t *p_input ){    /* Set die for input and ALL of this childrens (even (grand-)grand-childrens)     * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to     * unlock the control loop */    ObjectKillChildrens( p_input, VLC_OBJECT(p_input) );    input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );}sout_instance_t * input_DetachSout( input_thread_t *p_input ){    sout_instance_t *p_sout = p_input->p->p_sout;    vlc_object_detach( p_sout );    p_input->p->p_sout = NULL;    return p_sout;}/***************************************************************************** * Run: main thread loop * This is the "normal" thread that spawns the input processing chain, * reads the stream, cleans up and waits *****************************************************************************/static void* Run( vlc_object_t *p_this ){    input_thread_t *p_input = (input_thread_t *)p_this;    /* Signal that the thread is launched */    vlc_thread_ready( p_input );    if( Init( p_input ) )    {        /* If we failed, wait before we are killed, and exit */        WaitDie( p_input );        /* Tell we're dead */        p_input->b_dead = true;        return NULL;    }    MainLoop( p_input );    if( !p_input->b_eof && !p_input->b_error && p_input->p->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->p_es_out ) )                break;            msg_Dbg( p_input, "waiting decoder fifos to empty" );            msleep( INPUT_IDLE_SLEEP );        }        /* We have finished */        input_ChangeState( p_input, END_S );    }    /* Wait until we are asked to die */    if( !p_input->b_die )    {        WaitDie( p_input );    }    /* Clean up */    End( p_input );    return NULL;}/***************************************************************************** * RunAndDestroy: 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 void* RunAndDestroy( vlc_object_t *p_this ){    input_thread_t *p_input = (input_thread_t *)p_this;    /* Signal that the thread is launched */    vlc_thread_ready( p_input );    if( Init( p_input ) )        goto exit;    MainLoop( p_input );    if( !p_input->b_eof && !p_input->b_error && p_input->p->input.b_eof )    {        /* We have finished demuxing data but not playing it */        while( !p_input->b_die )        {            if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )                break;            msg_Dbg( p_input, "waiting decoder fifos to empty" );            msleep( INPUT_IDLE_SLEEP );        }        /* We have finished */        input_ChangeState( p_input, END_S );    }    /* Clean up */    End( p_input );exit:    /* Release memory */    vlc_object_release( p_input );    return 0;}/***************************************************************************** * Main loop: Fill buffers from access, and demux *****************************************************************************/static void MainLoop( input_thread_t *p_input ){    int64_t i_start_mdate = mdate();    int64_t i_intf_update = 0;    int i_updates = 0;    /* Stop the timer */    stats_TimerStop( p_input, STATS_TIMER_INPUT_LAUNCHING );    while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )    {        bool b_force_update = false;        int i_ret;        int i_type;        vlc_value_t val;        /* Do the read */        if( p_input->i_state != PAUSE_S )        {            if( ( p_input->p->i_stop > 0 && p_input->i_time >= p_input->p->i_stop ) ||                ( p_input->p->i_run > 0 && i_start_mdate+p_input->p->i_run < mdate() ) )                i_ret = 0; /* EOF */            else                i_ret = p_input->p->input.p_demux->pf_demux(p_input->p->input.p_demux);            if( i_ret > 0 )            {                /* TODO */                if( p_input->p->input.b_title_demux &&                    p_input->p->input.p_demux->info.i_update )                {                    i_ret = UpdateFromDemux( p_input );                    b_force_update = true;                }                else if( !p_input->p->input.b_title_demux &&                          p_input->p->input.p_access &&                          p_input->p->input.p_access->info.i_update )                {                    i_ret = UpdateFromAccess( p_input );                    b_force_update = 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->p->input.b_eof = 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->p->input.i_title_start -                        p_input->p->input.i_title_offset;                    if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title )                        val.i_int = 0;                    input_ControlPush( p_input,                                       INPUT_CONTROL_SET_TITLE, &val );                    val.i_int = p_input->p->input.i_seekpoint_start -                        p_input->p->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->p->i_start > 0 )                    {                        val.i_time = p_input->p->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 );                    }                    /* */                    i_start_mdate = mdate();                }            }            else if( i_ret < 0 )            {                input_ChangeState( p_input, ERROR_S );            }            if( i_ret > 0 && p_input->p->i_slave > 0 )            {                SlaveDemux( p_input );            }        }        else        {            /* Small wait */            msleep( 10*1000 );        }        /* Handle control */        vlc_mutex_lock( &p_input->p->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 = true;        }        vlc_mutex_unlock( &p_input->p->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( !demux_Control( p_input->p->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( !demux_Control( p_input->p->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( !demux_Control( p_input->p->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 );                }            }            var_SetBool( p_input, "intf-change", true );            i_intf_update = mdate() + INT64_C(150000);        }        /* 150ms * 8 = ~ 1 second */        if( ++i_updates % 8 == 0 )        {            stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );            /* Are we the thread responsible for computing global stats ? */            if( libvlc_priv (p_input->p_libvlc)->p_stats_computer == p_input )            {                stats_ComputeGlobalStats( p_input->p_libvlc,                                          p_input->p_libvlc->p_stats );            }        }    }}static void InitStatistics( input_thread_t * p_input ){    if( p_input->b_preparsing ) return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -