接到的新任务: 音视频同步, 而公司的视频播放已经由一位牛人做好,我必须把音频播放及同步两个功能加入到播放器中,因此在后面的流程学习中,在记录完程序初始化流程完成后,就先记录VLC音频播放流程了。
不废话了,接前一章。
先找到加载libplugin.dll的地方:
->a. libvlc_new(vlc_argc, vlc_argv)
->b. libvlc_init_threads()
->c. libvlc_InteralCreate()
->d. libvlc_InternalInit()
->d.1 module_InitBank()
->d.2 module_LoadPlugins(p_libvlc )
->d.3 AllocatePluginFile("libplugin.dll"),在文件module.c中.
在软件使用中,可以将所有的插件都生成到统一个库中,比如libplugin.dll中,在程序中几经波折,总算是到了加载动态库的地方,那么我是反向回溯的方式,去学习组件的加载及调用过程的。我们进入到AllocatePluginFile这个接口中:
->s1: module_load(*libplugins.dll**): 加载动态库
->s2:sprintf(psz_name, "vlc_entry__%s", loopPszName[workFlag]); loopPszName是一个静态的变量
以其中的一个名称为例 loopPszName[74] = "aout_directx"
那么psz_name ="vlc_entry_aout_directx";
->s3: module_CallWithName(psz_name): 最终调用到
GetProcAddress( (HMODULE)handle, (char *)psz_function ). 这里就会产生一个问题,
这个psz_name = "vlc_entry_aout_directx"在动态库中是如何识别的?
->s4: 现在就到vlc的各个插件的定义的地方去了:
在下面的代码中 __VLC_SYMBOL(vlc_entry, symbol) 这个函数中调用:
vlc_module_set (p_module, VLC_MODULE_NAME, (const char *)(MODULE_STRING))
这个MODULE_STRING 从哪儿冒出来的呢?那么我们设置预编译:
MODULE_NAME=aout_directx
MODULE_NAME_IS_directx
MODULE_STRING=\"aout_directx\"
vlc_module_begin(vout_directx)
vlc_module_end()
#define vlc_module_begin( symbol )
EXTERN_SYMBOL DLL_SYMBOL \
int CDECL_SYMBOL __VLC_SYMBOL(vlc_entry, symbol) ( module_t *p_module ); \
\
EXTERN_SYMBOL DLL_SYMBOL \
int CDECL_SYMBOL __VLC_SYMBOL(vlc_entry, symbol) ( module_t *p_module ) \
{ \
module_config_t *p_config = NULL; \
if (vlc_module_set (p_module, VLC_MODULE_NAME, \
(const char *)(MODULE_STRING))) \
goto error; \
{ \
module_t *p_submodule = p_module;
#define vlc_module_end( ) \
} \
(void)p_config; \
return VLC_SUCCESS; \
\
error: \
return VLC_EGENERIC; \
}
看了以上的定义就是完整的实现了aout_directx的插件定义流程。那么在调用中是如何实现的呢?
--------------------------------------------------------------------------------------------------------
s1. 我们来看module.c中的module_need()接口:
-> struct module_t
{
…….
int ( * pf_activate ) ( vlc_object_t * );
void ( * pf_deactivate ) ( vlc_object_t * );
}
在上面的vlc_module_begin(aout_directx)中就能看到的
set_callbacks( OpenAudio, CloseAudio ).
在module_need()的调用中
ret = p_cand->pf_activate( p_this ); 就将执行OpenAudio()接口
---->那么现在的问题继续来了,在vlc的如此多的插件中,是如何识别哪个插件是自己需要调用的呢?
-----------------------------------------------------------------------------------------------------------
s1. 在audio_output/output.c中 aout_OutputNew() 中 /* Find the best output plug-in. */
p_aout->output.p_module = module_need( p_aout, "audio output", "$aout", false );
s2. 在module_need()接口中是如何找到最合适的plug-in的?
module_need(vlc_object_t *p_this,const char *psz_capability,const char *psz_name, bool b_stric)
参数中:psz_capability: 可以理解为该插件提供什么服务
s3. 首先获取到所有的插件
/* Sort the modules and test them */
size_t count;
module_t **p_all = (module_t **)module_list_get (&count);
p_list = (module_list_t *)malloc( count * sizeof( module_list_t ) );
s4. 然后在这些所有的插件中找根据插件提供的服务进行匹配,如果插件能力跟调用时匹配就将该插件的指针
(已经加载到内存中了的)放入的plist中).
/* Test that this module can do what we need */
if(!module_provides( p_module, psz_capability))
continue;
s5. 对pList进行排序: 执行qsort((), 然后执行找到第一个匹配的module 执行之
怎么才叫找到了第一个匹配的module呢? 那就是pf_activate() 返回VLC_SUCESS