vlc 调试记录
1)启动main函数,在vlc.c中
main函数中有一系列的初始化工作,主要工作是环境设置和消息通道等初始化
根据不同的操作系统得到或设置一系列的环境参数?
然后用liblvc_new初始化对libvlc的调用
仔细研究libvlc
libvlc_set_exit_handler (vlc, vlc_kill, &self);
libvlc_set_user_agent (vlc,"VLCmediaplayer","VLC/"PACKAGE_VERSION);
这两句暂时没弄懂什么意思
然后初始化playlist,初始化模块,初始化线程池,初始化界面
进入sigwait,等待消息参数
实际上,main里的过程相当于mfc的初始化界面和等待响应消息,只是vlc用自己的代码和数据结构写了一个mfc的框架和消息响应机制。由于不同的线程有不同的响应机制,先从access中的file.c入手,可以看看一个文件是怎么被打开的
界面应该是qt写的
2)access,文件读入过程分析
最顶层,libvlcapi libvlc_media_library_load (include/vlc/libvlc_media_library.h)传入参数 libvlc_media_library_t ,没有找到libvlc_media_library_t的定义
我日,在lib/media_library里找到了定义,难道是因为定义只会在头文件里去找?
是用正则表达式找到的
struct libvlc_media_library_t
{
libvlc_event_manager_t * p_event_manager;
libvlc_instance_t * p_libvlc_instance;
int i_refcount;
libvlc_media_list_t * p_mlist;
};
可以看出里面有一个media_list,一个libvlc实例
对libvlc_media_library_load() 的分析可以看出,传入参数media_library和psz_uri(应该是媒体文件的地址),如果media_list存在则释放,并用libvlc_instance重新创建一个,然后调用libvlc_media_list_add_file_content加入播放列表
PS。vlc对于媒体文件的操作都是以media_list来操作的
从该函数中调用的一个函数
libvlc_media_list_add_file_content( libvlc_media_list_t * p_mlist,
const char * psz_uri )
定位到其定义,可以看源代码
在这里,先用input_item_NewExt(),从传入的地址读取input_item_t
再用libvlc_media_new_from_input_item()从input_item转为libvlc_media,应该是libvlc其他函数可以调用的媒体格式
最后把转成libvlc_media的利用libvlc_media_list_add_media()添加到播放列表里去。
然后用input_Read读取这个media文件。
继续跟进input_Read()的源代码,可以看到VLC是如何调用module的。
传入时候的参数是这样
input_Read( p_mlist->p_libvlc_instance->p_libvlc_int, p_input_item );
本来定义是这样
int input_Read( vlc_object_t *p_parent, input_item_t *p_item )
说明文档如下
/**
* Initialize an input thread and run it until it stops by itself.
*
* \param p_parent a vlc_object
* \param p_item an input item
* \return an error code, VLC_SUCCESS on success
*/
看出input_read会独立开辟一个线程用来读取数据,传入参数是p_item
此函数会先用create创造一个线程,然后对线程进行初始化,如果初始化成功,这个线程被传入到线程池里一直执行,直到自己结束。
跟进初始化代码Init(p_input),p_input是input_thread_t,也就是处理输入的专用线程
Init里代码比较复杂,先跳过。
直接看InputSourceInit()里的代码,大概了解一下vlc是怎么调用模块的
用modules.c里有很多调用方法,比如直接按名字调用,按need_modules调用,按shortcut调用,按capbility调用,等等。。。
在inputsourceInit里,先把传入的地址(可能是本地也可能是网络uri)分离成各个部分可以用到的信息,比如access用的地址,文件头anchor用来判断需要用什么access module读入。
尝试在input_SplitMRL设置断点,传入本地播放文件,只有psz_access 和 psz_path,psz_dup 有值,可能demux和anchor是播放网络流媒体才会用到的。
在初始化界面,添加播放列表和播放的时候都会执行一次inputsource()函数,区别在前两次不检索播放文件,在播放本地文件的时候b_preaparse会变成flase,函数体中会先尝试access_demux来读入文件(本地测试时候没有成功过),然后再用access_NEW来找到需要的模块,返回access指针,在access_NEW()函数体中用module_need传入所需的capbility来查找模块。
p_access返回的指针被stream_AccessNew调用,目的是通过access读入视频流?根据名字分析貌似是这样。
浙公网安备 33010602011771号