如何将libavcodec也静态编译并可链接到.so中

1 问题与解决

使用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时按特定顺序链接;

 

2 方案A的原理

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 方案B

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倍左右的性能差别;

你可能感兴趣的:(流媒体:,FFmpeg专项)