ffmpeg 纯静态编译,以及添加自定义库流程摘要

简介: 需求:    1. 纯静态编译ffmpeg ,即ldd ./ffmpeg 的结果是:not a dynamic executable    2.  修改ffmpeg 项目,添加自定义功能库    3. 自定义库由c++实现,要求能被纯c的ffmpeg项目调用    4. 自定义库必须使用g++ 的一些高级特性编译,要求g++支持c++11    5. 自定义库使用了pthread库 和openmp 库    6. 自定义库使用了opencv 3.0.0库,    7. 禁用所有的图形显示库x11,xcb,声音设备avdevice等等,静态链接这些库,会很痛苦。

需求:

   1. 纯静态编译ffmpeg ,即ldd ./ffmpeg 的结果是:not a dynamic executable
   2.  修改ffmpeg 项目,添加自定义功能库
   3. 自定义库由c++实现,要求能被纯c的ffmpeg项目调用
   4. 自定义库必须使用g++ 的一些高级特性编译,要求g++支持c++11
   5. 自定义库使用了pthread库 和openmp 库
   6. 自定义库使用了opencv 3.0.0库,
   7. 禁用所有的图形显示库x11,xcb,声音设备avdevice等等,静态链接这些库,会很痛苦。
 
动手之前需要注意:
A. ffmpeg.org ( CentOS或  Ubuntu)的方法是不能达到需求1的,因为它大量使用包管理软件(yum 或apt-get)安装一些ffmpeg的依赖库,而这些依赖库大多是动态版本(.so.*) 。这就使得编译ffmpeg时,无法静态链接这些依赖库。因而,非开发工具(如gcc g++ pkg-config aotoconf etc )的依赖库(如ass,freetype,sdl theora, jpeg png,etc),需要手动下载它们的源码(以及这些依赖库的依赖库),然后编译得到静态库(.a)。一般来说,这些依赖库多数是configure 配置,然后make,make install。
./configure ***  --enable-shared=no --enable-static=yes --with-***=/dir
 
B.自定义功能库也类似于上述方法写好myfunc.cpp,然后g++编译,ar打包成.a。但是由于我们写好的cpp要求c++11特性,而CentOS6.5上的gcc/g++版本为4.4.7不支持c++11。因而,需要安装gcc4.8以上版本。从repo里面无法安装较新的gcc的话,只能自行下载gcc源码,自行编译了。然而发现了一个第三方的编译好的工具链 devtool3,它提供了gcc 4.9.2 以及配套的binutils工具。然而,不要急,先不要安装它,看完本注意事项。
 
C.要求c++打包的库能够被ffmpeg的项目链接,要求libstdc++.a (-lstdc++);能够使用openmp,要求libgomp.a ( -fopenmp); libstdc++.a可以通过yum install libstdc++-static得到,但是libgomp.a则没有对应的方法。
 
综合B和C的注意事项,我们应该自行编译gcc,而不是使用系统自带的gcc或者yum apt-get下载安装的,因为自行编译gcc能够直接得到libstdc++.a和libgomp.a这些静态库。我选用的版本是gcc4.8.4,同样地配置它编译出静态库。配套的Binutils也需要重新编译。
 
D. glibc是GNU的标准C库实现,如果要静态链接glibc这些底层的库_——libc.a,libm.a,librt.a,libdl.a,libpthread.a ,需要安装glibc的静态版本
#yum install glibc-static, 
#whereis libc.a(找到路径)
#cp 路径/libc.a ~mydir/(其它4个库类似,重新拷贝到一个新的位置,以防链接时优先选择动态链接,当然把这个路径放在LDFLAGS最前面)
 
E.opencv 和ffmpeg在配置阶段(分别使用cmake和configure),务必关闭所有的与图形IO相关的依赖,因为图形库的静态版本,太难找了,依赖关系特别冗长繁杂。
 
F. 最终链接ffmpeg时候,由于ffmpeg依赖了一些库如x264,x265,freetype等,它们各自依赖了glibc的一些库如librt,libm,libc,libdl。因而原始命令(#make -n|grep ffmpeg_g)中glibc的一些库(libm,libc,librt,libdl,libpthread)被反复调用,分布于多个地方,如下:
 gcc  -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -L/home/ffmpeg/ffmpeg_sjtu/lib  -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample   -o ffmpeg_g cmdutils.o ffmpeg_opt.o ffmpeg_filter.o ffmpeg.o   -lavdevice -lavfilter -lavformat -lavcodec -lpostproc -lswresample -lswscale -lavutil  -L/home/ffmpeg/ffmpeg_build/lib -lx265 -lstdc++ -lm -lrt -ldl -L/home/ffmpeg/ffmpeg_build/lib -lx264  -lpthread -lm -ldl -L/home/ffmpeg/ffmpeg_build/lib -lvpx -lm -lpthread -L/home/ffmpeg/ffmpeg_build/lib -lvpx -lm -lpthread -L/home/ffmpeg/ffmpeg_build/lib -lvpx  -lm -lpthread -L/home/ffmpeg/ffmpeg_build/lib -lvpx -lm -lpthread -ltheoraenc -ltheoradec -logg -L/home/ffmpeg/ffmpeg_build/lib -lopus -lm -lmp3lame -L/home/ffmpeg/ffmpeg_build/lib -lfribidi -L/home/ffmpeg/ffmpeg_build/lib -lfreetype -lz -L/home/ffmpeg/ffmpeg_build/lib -lfontconfig -lxml2 -llzma -lm -lfreetype -lz -L/home/ffmpeg/ffmpeg_build/lib -lfdk-aac -lm -L/home/ffmpeg/ffmpeg_build/lib -lass -lharfbuzz -lfontconfig -lenca -lfribidi -lxml2 -llzma -lm -lfreetype -lz -lm -llzma -lbz2 -lz  -pthread -lrt -lstdc++      -L/home/ffmpeg/sjtu_fruc/lib -lsjtu_fruc  - fopenmp   -L/usr/local/lib -L/usr/local/share/OpenCV/3rdparty/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core -lopencv_hal -lzlib -llibjpeg -llibwebp -llibpng -llibtiff -llibjasper -ltbb -lippicv  -lstdc++  -ldl -lm -lpthread -lrt   
 
因此,为了能够静态链接glibc的几个库,需要手动修改这条最终的链接命令:把所有glibc的库放到最后,以如下方式:
 -lm -lrt -ldl  -lm -lpthread -lrt    -static -lc
 
注意,-static -lc (libc.a)必须放到最后(pthread之后),因为pthread和c库有函数重定义的冲突。
 
这条语句最终为:
printf "LD\t%s\n" ffmpeg_g; gcc  -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -L/home/ffmpeg/ffmpeg_sjtu/lib  -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample   -o ffmpeg_g cmdutils.o ffmpeg_opt.o ffmpeg_filter.o ffmpeg.o   -lavdevice -lavfilter -lavformat -lavcodec -lpostproc -lswresample -lswscale -lavutil  -L/home/ffmpeg/ffmpeg_build/lib -lx265 -L/home/ffmpeg/ffmpeg_build/lib -lx264 -L/home/ffmpeg/ffmpeg_build/lib -lvpx  -L/home/ffmpeg/ffmpeg_build/lib -lvpx  -L/home/ffmpeg/ffmpeg_build/lib -lvpx  -L/home/ffmpeg/ffmpeg_build/lib -lvpx -ltheoraenc -ltheoradec -logg -L/home/ffmpeg/ffmpeg_build/lib -lopus -lmp3lame -L/home/ffmpeg/ffmpeg_build/lib -lfribidi -L/home/ffmpeg/ffmpeg_build/lib -lfreetype -lz -L/home/ffmpeg/ffmpeg_build/lib -lfontconfig -lxml2 -llzma -lfreetype -lz -L/home/ffmpeg/ffmpeg_build/lib -lfdk-aac -L/home/ffmpeg/ffmpeg_build/lib -lass -lharfbuzz -lfontconfig -lenca -lfribidi -lxml2 -llzma -lfreetype -lz  -llzma -lbz2 -lz   -L/home/ffmpeg/sjtu_fruc/lib -lsjtu_fruc  -fopenmp   -L/usr/local/lib -L/usr/local/share/OpenCV/3rdparty/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core -lopencv_hal -lzlib -llibjpeg -llibwebp -llibpng -llibtiff -llibjasper -ltbb -lippicv -lstdc++  -lm -lrt -ldl  -lm -lpthread -lrt   -static -lc
 
尽管它执行会报出一些warnning,但是,不影响生成ffmpeg_g可执行文件。
然后执行,
#cp ffmpeg_g ffmpeg
#strip ffmpeg
即可
 
测试ffmpeg
目录
相关文章
|
1月前
|
缓存 并行计算 Ubuntu
Jetson 学习笔记(十一):jetson agx xavier 源码编译ffmpeg(3.4.1)和opencv(3.4.0)
本文是关于在Jetson AGX Xavier上编译FFmpeg(3.4.1)和OpenCV(3.4.0)的详细教程,包括编译需求、步骤、测试和可能遇到的问题及其解决方案。还提供了Jetson AGX Xavier编译CUDA版本的OpenCV 4.5.0的相关信息。
59 4
Jetson 学习笔记(十一):jetson agx xavier 源码编译ffmpeg(3.4.1)和opencv(3.4.0)
|
1月前
|
Ubuntu 应用服务中间件 nginx
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
本文是关于Ubuntu系统中使用ffmpeg 3.2.16源码编译OpenCV 3.4.0的安装笔记,包括安装ffmpeg、编译OpenCV、卸载OpenCV以及常见报错处理。
140 2
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
|
5月前
|
存储
FFmpeg的流程
FFmpeg的流程
|
29天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
81 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
6月前
|
Linux
Linux编译FFmpeg
Linux编译FFmpeg
144 0
|
4月前
|
存储 编解码 容器
FFmpeg avformat_open_input() 函数返回错误protocol not found解决方法(实测有效!附简单FFMPEG的编解码流程)
我个人出现这个错误的时候是在打开文件时报的错误,开始以为我需要加上资源文件,那样QT确实能检测到文件的存在,但是在Debug中他是检测不到这个文件的。
436 1
|
6月前
|
算法 Linux Windows
FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
在Windows环境下为FFmpeg集成字幕渲染库libass涉及多个步骤,包括安装freetype、libxml2、gperf、fontconfig、fribidi、harfbuzz和libass。每个库的安装都需要下载源码、配置、编译和安装,并更新PKG_CONFIG_PATH环境变量。最后,重新配置并编译FFmpeg以启用libass及相关依赖。完成上述步骤后,通过`ffmpeg -version`确认libass已成功集成。
141 1
FFmpeg开发笔记(十七)Windows环境给FFmpeg集成字幕库libass
|
5月前
FFMpeg解复用流程
FFMpeg解复用流程
|
5月前
|
Ubuntu
蓝易云 - Ubuntu18.04安装编译ffmpeg库
现在,你应该已经在你的Ubuntu 18.04系统上成功安装和编译了FFmpeg库。你可以通过运行 `ffmpeg -version`来验证安装是否成功。
67 0
|
6月前
|
Ubuntu Linux Shell
Android-NDK-clang 编译 FFmpeg
Android-NDK-clang 编译 FFmpeg
191 0