VLC播放主要流程

前言

VLC 播放流程大概是先加载解封装器,然后通过es_out控制所有的stream。然后会加载decoder。最终通过resource文件的方法交给输出 模块。下面简要介绍。

正文

播放器主要分为三层。主要通过两个接口实现了功能隔离。分别是es_out.c和decoder.c的实现了:

//控制解封装后的的数据,通过send增加数据
static const struct es_out_callbacks es_out_cbs =
{
    .add = EsOutAdd,
    .send = EsOutSend,
    .del = EsOutDel,
    .control = EsOutControl,
    .destroy = EsOutDelete,
    .priv_control = EsOutPrivControl,
};

//解封装后的数据传给输出
static const struct decoder_owner_callbacks dec_video_cbs =
{
    .video = {
        .get_device = ModuleThread_GetDecoderDevice,
        .format_update = ModuleThread_UpdateVideoFormat,
        .buffer_new = ModuleThread_NewVideoBuffer,
        .queue = ModuleThread_QueueVideo,
        .queue_cc = ModuleThread_QueueCc,
        .get_display_date = ModuleThread_GetDisplayDate,
        .get_display_rate = ModuleThread_GetDisplayRate,
    },
    .get_attachments = InputThread_GetInputAttachments,
};
static const struct decoder_owner_callbacks dec_audio_cbs =
{
    .audio = {
        .format_update = ModuleThread_UpdateAudioFormat,
        .queue = ModuleThread_QueueAudio,
    },
    .get_attachments = InputThread_GetInputAttachments,
};

解封装部分主要通过Run方法开启的线程实现多线程的解封装。

int input_Start( input_thread_t *p_input )
{
    void *(*func)(void *) = Run;
    /* Create thread and wait for its readiness. */
    priv->is_running = !vlc_clone( &priv->thread, func, priv );
}

static void *Run( void *data )
{

    if( !Init( p_input ) )
    {
        MainLoop( p_input, true ); /* FIXME it can be wrong (like with VLM) */

        End( p_input );
    }
}

这是核心问题,主要是初始化,加载读取存储截至的资源(比如网络资源,硬盘等)加载stream filter(比如缓存控制等),最后加载解封装器。然后通过MainLoop,的MainLoopDemux的demux_Demux。本质上就是调用demux模块的demux_pf的。
拿到的结果交给第二部分。EsOutSend。最终交给decoder。然后返回给dec.c中。
第三部分则通过ModuleThread_QueueAudio。拿到解码后的数据,然后调用audiofilter,处理声音,最终交给aout 的play函数,最终初始化audiotrack,播放数据。

你可能感兴趣的:(音视频,android)