Author:baohonglai
Email:baohonglai@gmail.com
版权所有。转载本BLOG内任何文章,请以超链接形式注明出处。
VLC流程的分析
模块的加载
模块的加载分为两部分:模块的初始化,模块的加载。
模块的初始化
- libvlc_new 函数初始化
- libvlc_InternalInit函数调用module_InitBank ()初始化一个成员为module_t的结构体链表。
- libvlc_InternalInit 调用module_LoadPlugins会加载进现有的modules。
- module_LoadPlugins 调用module_InitStaticModules函数从vlc_static_modules数组中开始加载,vlc_static_modules保存的是每个modules的入口的函数指针。
- vlc_static_modules的取得,不同的平台取得的方法不同,以IOS为例,通过aggregateStaticPlugin.sh脚本遍历modules目录下的静态库,生成一个函数指针列表,如vlc-plugins.h中的int vlc_entry__http (int ()(void , void , int, …), void ); 然后该脚本还会根据这个列表生成vlc_static_modules数组,里面的成员都是这种函数指针的声明符,如下,这只是代码片段
const void * vlc_static_modules [] = {
vlc_entry__http,
vlc_entry__httplive,
NULL
}; - 有了例如vlc_entry__http 这样的声明符,如何与每个module模块对应起来呢?首先,像vlc_entry__http这样的只是声明符,并没有实际的地址,所以,需要对应的模块定义一个与该名字相同的函数名,这样就能调用了。在例如http.c文件中都有一个vlc_module_begin ()宏,该宏的具体定义在vlc_plugin.h中,它的定义了每个模块对应一个入口函数。
- module_InitStaticModules函数会遍历vlc_static_modules数组,调用每个模块的入口函数,加载每个模块的相关信息。值得注意的信息有,会加载模块的描述信息,简称,以及注册回调函数(open,close)。
模块的调用
模块的调用,只有在需要的时候才调用,不需要以后就可以移除掉了。下面我们以http模块的调用为例,介绍它的流程。
1. 视频首次播放时调用libvlc_media_player_play(),然后调用Input_create()以及input_start()。
2. 在input_start()里会调用vlc_clone()创建一个子线程来管理播放器的流程控制,子线程的入口是run()函数,run()会调用init()进行初始化,init()会调用InputSourceInit()函数。
3. 在InputSourceInit函数中,首先调用input_SplitMRL()函数解析出视频URL的获取方法如file,或者http,域名,文件路径等。然后调用access_New(),初始化一个access的对象进入到获取视频的阶段。
4. 在access_New()中,会调用module_need()函数开始加载模块,参数会传入http字符串代表模块的名字。
5. 调用vlc_module_load(obj, cap, name, strict, generic_start, obj),在这里多传入了一个generic_start函数指针,在vlc_module_load函数中通过模块名字的简称进行匹配,查找加载什么模块,查找的方法,就是遍历链表。查找到以后就调用module_load (obj, cand, probe, args)这里的probe就是前面的generic参数,在该函数中会调用probe也就是前面的generic将模块的m->pf_activate激活,而每个模块的m->pf_activate就是每个模块的注册时(vlc_module_set (VLC_MODULE_CB_OPEN, activate)都是注册的open函数指针,就这样,就加载进了http模块。
视频的播放流程
视频的播放