使用ffmpeg SDK的静态库进行链接到动态库时,会出现如下的报错:
/usr/bin/ld: /usr/local/lib/libavformat.a(allformats.o): relocation R_X86_64_32 against `ff_a64_muxer' can not be used when making a shared object; recompile with -fPIC /usr/local/lib/libavformat.a: error adding symbols: Bad value collect2: error: ld returned 1 exit status
这是因为,在将静态的ffmpeg SDK库链接到 .so 中时,需要对 libavcodec等使用 -fPIC重新编译;
这时,有两个解决办法:
方案A. 使用FFmpeg SDK的动态库, 在ffmpeg的configure 时设置如下:
--enable-shared --disable-static --enable-pic
ffmpeg SDK的动态库不会真正链接到目的.so中,需要单独安装;
方案B. 强行使用ffmpeg SDK的静态库,此时的configure 设置成如下:
--disable-shared --enable-static --enable-pic
是不起效果的;
需要关闭库的ASM配置(即不使用汇编优化),并在链接到目的.so时按特定顺序链接;
GCC 生成动态链接库
如果想创建一个动态链接库,可以使用 GCC 的-shared选项。输入文件可以是源文件、汇编文件或者目标文件。
另外还得结合-fPIC选项。-fPIC 选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code);
这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。
这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
例如,从源文件生成动态链接库:
$ gcc -fPIC -shared func.c -o libfunc.so
从目标文件生成动态链接库:
$ gcc -fPIC -c func.c -o func.o
$ gcc -shared func.o -o libfunc.so
-fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。
GCC 将动态链接库链接到可执行文件
如果希望将一个动态链接库链接到可执行文件,那么需要在命令行中列出动态链接库的名称,具体方式和普通的源文件、目标文件一样。
请看下面的例子:
$ gcc main.c libfunc.so -o app.out
将 main.c 和 libfunc.so 一起编译成 app.out,当 app.out 运行时,会动态地加载链接库 libfunc.so。
当然,必须要确保程序在运行时可以找到这个动态链接库。
你可以将链接库放到标准目录下,例如 /usr/lib,或者设置一个合适的环境变量,例如 LIBRARY_PATH。
不同系统,具有不同的加载链接库的方法
3.1. 修改x264的编译
$ cd x264-snapshot-20180117-2245-stable
$ ./configure --prefix=INSTALL_PATH --enable-static --disable-shared --enable-pic --disable-asm --disable-opencl
$ make && make install
3.2. 修改ffmpeg的configure配置项
./configure \
--prefix=INSTALL-PATH/install \
--enable-debug=3 --extra-cflags=-Wall --extra-cflags=-O3 --enable-pic \
--enable-gpl --enable-nonfree --enable-version3 \
--disable-asm \
--enable-postproc \
--disable-shared --enable-static \
--enable-pthreads --enable-runtime-cpudetect \
--extra-cflags='-IINSTALL-PATH/install/include -DREDIRECT_DEBUG_LOG' \
--extra-ldflags='-LINSTALL-PATH/install/lib -gl -lm -fPIC ' \
--enable-libx264 --enable-encoder=libx264 --disable-opencl \
--enable-libfdk_aac --enable-encoder=libfdk_aac --enable-decoder=libfdk_aac \
--enable-libopus --enable-encoder=libopus --enable-decoder=libopus \
--enable-muxer=adts \
--enable-avfilter --enable-filter=movie
3.3. 在.so中的makefile文件中的链接顺序:
LIB = -lrt -lz -lpthread -lm
$(FFMPEG_LIB_DIR)/libavutil.a $(FFMPEG_LIB_DIR)/libavformat.a
$(FFMPEG_LIB_DIR)/libavfilter.a $(FFMPEG_LIB_DIR)/libavdevice.a $(FFMPEG_LIB_DIR)/libpostproc.a
$(FFMPEG_LIB_DIR)/libswresample.a $(FFMPEG_LIB_DIR)/libswscale.a $(FFMPEG_LIB_DIR)/libopus.a
$(FFMPEG_LIB_DIR)/libavcodec.a $(FFMPEG_LIB_DIR)/libswresample.a $(FFMPEG_LIB_DIR)/libavutil.a
$(FFMPEG_LIB_DIR)/libx264.a $(FFMPEG_LIB_DIR)/libfdk-aac.a
$(FFMPEG_LIB_DIR)/libopus.a $(FFMPEG_LIB_DIR)/libavutil.a
-Wl,-Bdynamic -lssl -lcrypto -Wl,-Bdynamic -Wl,--as-needed
3.4. 注意
> 在关闭了x264的汇编后,可能会对H.264的编码带来10倍左右的性能差别;