zoukankan      html  css  js  c++  java
  • VLC-Android和VLC几个关键宏定义的分析

    在用SourceInsight分析VLC-Android源码过程中,有几个宏定义在源代码中一直没有找到出处,比如 HAVE_DYNAMIC_PLUGINS和__PLUGIN__,以及MODULE_NAME和MODULE_STRING,在网上找了VLC源码的分 析资料都是老版本的,老版本中MODULE_NAME在每一个MODULES模块下面都有定义,MODULE_STRING也有如下宏定义:

     

    [cpp] view plaincopy
     
    1. #define STRINGIFY(z)   UGLY_KLUDGE(z)  
    2. #define UGLY_KLUDGE(z)  #z  
    3. #define MODULE_STRING  STRINGIFY(MODULE_NAME)  
    但是在新版本的VLC源码中,MODULE_NAME除了在vlc/src/libvlc-modules.c文件中有#define MODULE_NAME main 的定义外,其他再无出处,MODULE_STRING更是没有找到任何定义,后来发现实际上GCC在编译时可以向源文件中传递宏定义,形式如gcc -Dmacro 或者 gcc -Dmacro=defn,于是去看查看makefile文件,果然在modules/common.am文件中有如下发现

     

     

    [cpp] view plaincopy
     
    1. # Module name from object or executable file name.  
    2. MODULE_NAME = $$(p="$@"; p="$${p##*/}"; p="$${p#lib}"; echo "$${p%_plugin*}")  
    3.   
    4. AM_CPPFLAGS =   
    5.     -DMODULE_NAME=$(MODULE_NAME)   
    6.     -DMODULE_NAME_IS_$(MODULE_NAME)   
    7.     -DMODULE_STRING="$(MODULE_NAME)"  
    8. if HAVE_DYNAMIC_PLUGINS  
    9. AM_CPPFLAGS += -D__PLUGIN__  
    10. endif  
    实际上问题已经逐渐明朗,就是在编译过程中gcc向源文件传递了宏定义,为了查看编译选项,分别对VLC-Android和VLC的vlc/modules/demux/live555.cpp的的编译选项进行了输出,这里做的办法是对vlc/modules/demux/makefile.in文件进行了修改,找到编译目标

     

     

    [cpp] view plaincopy
     
    1. liblive555_plugin_la-live555.lo: live555.cpp  

    在其下面添加如下代码

     

     

    [cpp] view plaincopy
     
    1. @am__fastdepCXX_TRUE@   echo $(AM_V_CXX) $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblive555_plugin_la_CPPFLAGS) $(CPPFLAGS)   
    2. $(liblive555_plugin_la_CXXFLAGS) $(CXXFLAGS)  -E -o testlive555.txt live555.cpp  
    并在编译前用script -a test.txt命令进行终端输出记录,得到如下结果

     

    VLC-Android输出如下:

     

    [cpp] view plaincopy
     
    1. echo @echo "  CXX   " liblive555_plugin_la-live555.lo;  
    2.  /androidApp/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin//arm-linux-androideabi-g++   
    3. --sysroot=/androidApp/android-ndk-r8b/platforms/android-9/arch-arm -DHAVE_CONFIG_H -I. -I../../../modules/demux -I../..    
    4. -DMODULE_NAME=$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")   
    5. -DMODULE_NAME_IS_$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")   
    6. -DMODULE_STRING="$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")"    
    7. -I../../../include -I../../include -I/androidApp/android-ndk-r8b/sources/cxx-stl/gnu-libstdc++/4.6/include   
    8. -I/androidApp/android-ndk-r8b/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include   
    9. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include    
    10. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include/liveMedia   
    11. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include/groupsock   
    12. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include/BasicUsageEnvironment   
    13. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include/UsageEnvironment -g -O2   
    14. -fstrict-aliasing -funsafe-math-optimizations -mlong-calls   
    15. -I/vlc-android/android/vlc/contrib/arm-linux-androideabi/include -Wall -Wextra -Wsign-compare   
    16. -Wundef -Wpointer-arith -Wvolatile-register-var -fvisibility=hidden -ffast-math -funroll-loops  
    17. @echo   CXX    liblive555_plugin_la-live555.lo  

    VLC输出如下:

     

     

    [cpp] view plaincopy
     
    1. echo @echo "  CXX   " liblive555_plugin_la-live555.lo;   
    2. g++ -DHAVE_CONFIG_H -I. -I../..    
    3. -DMODULE_NAME=$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")   
    4. -DMODULE_NAME_IS_$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")   
    5. -DMODULE_STRING="$(p="liblive555_plugin_la-live555.lo"; p="${p##*/}"; p="${p#lib}"; echo "${p%_plugin*}")"   
    6. -D__PLUGIN__    
    7. -I../../include -I../../include    
    8. -I/home/vlc/contrib/i486-linux-gnu/include    
    9. -I/home/vlc/contrib/i486-linux-gnu/include/liveMedia   
    10. -I/home/vlc/contrib/i486-linux-gnu/include/groupsock   
    11. -I/home/vlc/contrib/i486-linux-gnu/include/BasicUsageEnvironment   
    12. -I/home/vlc/contrib/i486-linux-gnu/include/UsageEnvironment -g -O2   
    13. -I/home/vlc/contrib/i486-linux-gnu/include -Wall -Wextra -Wsign-compare -Wundef -Wpointer-arith   
    14. -Wvolatile-register-var -fvisibility=hidden -ffast-math -funroll-loops -fomit-frame-pointer  
    15. @echo   CXX    liblive555_plugin_la-live555.lo  

    从上面的输出可以看出,gcc的确添加了MODULE_NAME,MODULE_NAME_IS_,MODULE_STRING的宏定义,但是两个还略有 不同,即VLC还添加了__PLUGIN__的宏定义,而VLC-Android没有,这就是VLC-Android和VLC的根本的不同,VLC- Android的各个模块实际上是静态加载的,而VLC的各个模块默认是动态加载的,对于动态加载如网上的很多资料所说,除了main模块调用的实际函数 为导出函数vlc_entry_main,其他模块导出的均为vlc_entry__2_1_0a(本文VLC版本为2.0.4)。而对于静态加载,每一 个模块都有它自己的导出函数,为了验证,同样对live555.cpp文件进行预编译处理,即gcc -E,如上面代码在makefile.in中的配置,注意去掉echo。我们查看两个工程的输出文档testlive555.txt,可以发现如下:

     

    VLC-Android中的该文件内容为:

     

    [cpp] view plaincopy
     
    1. extern "C" int vlc_entry__live555 (vlc_set_cb, void *);   
    2. extern "C" int vlc_entry__live555 (vlc_set_cb vlc_set, void *opaque)  
    3. {   
    4.     module_t *module;   
    5.     module_config_t *config = __null;   
    6.     if (vlc_set (opaque, __null, VLC_MODULE_CREATE, &module)) goto error;   
    7.     if (vlc_set (opaque, module, VLC_MODULE_NAME, ("live555"))) goto error;  
    8. ...   
    而VLC中的该文件内容为:

     

     

    [cpp] view plaincopy
     
    1. extern "C" __attribute__((visibility("default"))) int vlc_entry__2_1_0a (vlc_set_cb, void *);   
    2. extern "C" __attribute__((visibility("default"))) int vlc_entry__2_1_0a (vlc_set_cb vlc_set, void *opaque)   
    3. {   
    4.     module_t *module;   
    5.     module_config_t *config = __null;   
    6.     if (vlc_set (opaque, __null, VLC_MODULE_CREATE, &module)) goto error;   
    7.     if (vlc_set (opaque, module, VLC_MODULE_NAME, ("live555"))) goto error;  
    8. ...  

    说明分析结果为真,实际上代码中也已经有了说明,我们查看vlc/include/vlc_plugin.h中有如下定义

     

    [cpp] view plaincopy
     
    1. # define MODULE_SYMBOL 2_1_0a  
    2. # define MODULE_SUFFIX "__2_1_0a"  
    3.   
    4. #define CONCATENATE( y, z ) CRUDE_HACK( y, z )  
    5. #define CRUDE_HACK( y, z )  y##__##z  
    6.   
    7. #ifdef __PLUGIN__  
    8. #   define __VLC_SYMBOL( symbol  ) CONCATENATE( symbol, MODULE_SYMBOL )  
    9. #else  
    10. #   define __VLC_SYMBOL( symbol )  CONCATENATE( symbol, MODULE_NAME )  
    11. #endif  

    即定义了__PLUGIN__,那么就用MODULE_SYMBOL,否则就用MODULE_NAME,那么__PLUGIN__又在哪里定义了呢?为什么VLC-Android和VLC又不同呢,我们回到上面的源头,发现

     

    [cpp] view plaincopy
     
    1. if HAVE_DYNAMIC_PLUGINS  
    2. AM_CPPFLAGS += -D__PLUGIN__  
    3. endif  

    那么这个HAVE_DYNAMIC_PLUGINS又从哪里来呢?这实际上就是VLC-Android和VLC两者的不同,一个有宏定义__PLUGIN__,一个没有宏定义__PLUGIN__。

     

    而实际上HAVE_DYNAMIC_PLUGINS是在运行configure过程中对其进行配置的。

    我们在vlc/configure.ac中发现有如下代码:

     

    [cpp] view plaincopy
     
    1. dnl Check for dynamic plugins  
    2. LIBDL=""  
    3. have_dynamic_objects="no"  
    4. VLC_SAVE_FLAGS  
    5. AC_SEARCH_LIBS(dlopen, [dl svld], [  
    6.   AS_IF([test "$ac_cv_search_dlopen" != "none required"], [  
    7.     LIBDL="$ac_cv_search_dlopen"  
    8.   ])  
    9.   have_dynamic_objects="yes"  
    10. ])  
    11. VLC_RESTORE_FLAGS  
    12.   
    13. # Windows  
    14. AS_IF([test "${SYS}" = "mingw32"], [  
    15.   LIBDL=""  
    16.   have_dynamic_objects="yes" #assume we can use shared objects  
    17. ])  
    18.   
    19. AS_IF([test "${enable_shared}" = "no"], [  
    20.   have_dynamic_objects=no  
    21. ])  
    22. AM_CONDITIONAL(HAVE_DYNAMIC_PLUGINS, [test "${have_dynamic_objects}" != "no"])  

    这就是问题的源头所在了,即在运行configure时是否配置了--enable-shared来决定HAVE_DYNAMIC_PLUGINS为 true还是false,因此我们再去查看运行configure时的配置,在VLC-Android的android目录下的configure.sh 文件中,我们发现了如下代码:

     

     

    [cpp] view plaincopy
     
    1. sh $VLC_SOURCEDIR/configure --host=$TARGET_TUPLE --build=x86_64-unknown-linux $EXTRA_PARAMS   
    2.                 --enable-live555 --enable-realrtsp   
    3.                 --enable-avformat   
    4.                 --enable-swscale   
    5.                 --enable-avcodec   
    6.                 --enable-opus   
    7.                 --enable-opensles   
    8.                 --enable-android-surface   
    9.                 --enable-mkv   
    10.                 --enable-taglib   
    11.                 --enable-dvbpsi   
    12.                 --disable-vlc --disable-shared   

    问题实际上已经浮出水面,这里配置了--disable-shared,而在VLC中我们一般保持默认配置,为此我们再运行vlc目录下的configure --help来查看默认配置选项,在输出的文档中我们发现了如下描诉:

     

     

    [cpp] view plaincopy
     
    1. --enable-shared[=PKGS]  build shared libraries [default=yes]  
    2.  --enable-static[=PKGS]  build static libraries [default=no]  
    3.  --with-pic              try to use only PIC/non-PIC objects [default=use  
    4.                          both]  
    5.  --enable-fast-install[=PKGS]  
    6.                          optimize for fast installation [default=yes]  

    即默认配置为--enable-shared,再结合前面的代码,就可以知道VLC-Android中的HAVE_DYNAMIC_PLUGINS值为 FALSE,而VLC中的HAVE_DYNAMIC_PLUGINS值为TRUE,从而添加了__PLUGIN__的宏定义。以此为源头从而影响了 VLC-Android和VLC后面的一系列不同的代码。
  • 相关阅读:
    Notepadd ++ PluginManager安装
    Srping cloud Ribbon 自定义负载均衡
    Spring cloud Eureka 和 Zookeeper 比较
    Spring cloud info信息显示
    kafka 在Windows端安装 找不到或无法加载主类 的解决方案
    Linux kafka 单机安装
    mina
    @bzoj
    @51nod
    @topcoder
  • 原文地址:https://www.cnblogs.com/shakin/p/4123496.html
Copyright © 2011-2022 走看看