折腾人的ffmpeg源码与ndk
作者:互联网
必要的条件,首先库和头文件是必须的,所有核心函数都在库里面,其次是,要实现类似命令行的操作,或者有一个输入文件路径的函数,几经查找,在雷霄骅大神的CSDN文章中找到了相关的答案。
https://blog.csdn.net/leixiaohua1020/article/details/39760711
不过虽然有大神的文章在手,这方面依旧是很棘手的,因为拷贝进来的文件都是ffmpeg的源代码,而非编译后被筛选出来和so库对应上的头文件,那就得具体问题具体分析,这些头文件对我有什么用。
根据网上查到的各种资料,需要从ffmpeg源码目录中提取的头文件和源文件有ffmpeg.h,ffmpeg.c,ffmpeg_filter.c,ffmpeg_opt.c,cmdutils.h,cmdutils.c,cmdutils_common_opts.h和comfig.h,但是我用的是4.3版本(之后由于自己误操作太多,下载了3.4-4.4的版本试了个遍,最后一次测试换成了4.2.2,不过错误依旧,但是4.3 应该也是OK的)的ffmpeg,没有cmdutils_common_opts.h。
经过实际测试,当把上述头文件和源文件导入项目进行编译会提示缺少头文件,ffmpeg编译产生的库需要的头文件中并没有这些缺少的头文件,那么这些头文件该不该导入,我觉得应该导入,但也需要进行修改,实际上因为我没有导入那些缺少的头文件,也出现了一些undefined的错误。
项目编译时遇到的还有这样的问题:ffmpeg的源码是C语言写的,整个项目都是C项目,按照C的标准,但是NDK进行编译的时候,是使用clang++进行编译的,虽然C和C++语法上接近,曾经我也认为C++是C的一次大升级,但是经过这次学习,我觉得我错了,C就是C,C++就是C++。比如说ffmpeg的源码中变量名有设置成class或template的,不过数量不多,一个个改得过来;但是遇到指针赋值就真的绝了,要知道C语言中允许void指针直接赋值给其他类型的指针,不用强转,而C++中要进行强转,起初我学C的时候还认为,直接把C按这个标准不就行了,但是事实证明我错了,ffmpeg中的指针值赋值全都是没有强转的,我在改了20多个后发现我改不过来,于是一个个撤回后,想着如果能把NDK的编译器改成clang就好了,但是我找不到方法,不过我想起来是可以使用extern C的,于是在include "ffmpeg.h"前后用extern "C"{}包起来,结果不报那些语法错误了。
最后是编译成功,结果在运行的时候崩溃了,log报错是这样:
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "ff_interleaved_golomb_vlc_len" referenced by "/data/app/com.thankvinci.bilipv-i1oNwQACIKGBnxJZtso48Q==/base.apk!/lib/arm64-v8a/libavformat.so"...
定位不到ff_interleaved_golomb_vlc_len,对于这个东西我是很蒙蔽的,我把整个项目导入的头文件和源文件都翻了一遍,没有调用这个函数或者变量的痕迹,甚至没有这个函数或变量的定义。这是一个解题的思路,他问题截止到libavformat.so,可能就是和avformat有关,翻源码比较麻烦,于是我就想到了objdump和nm,由于之前编译的静态库没用上一直放在桌面,我就就近原则用nm工具去查了静态库,结果真就在libavformat.a静态库里面找到了ff_interleaved_golomb_vlc_len,后来用objdump去查动态库,确实就是找不到。找到的过程和结果如下:
./nm /home/thankvinci/桌面/NDKcFFMPEG/ffmpeg-4.2.2/android/armv8-a/lib/libavformat.a >symbol.txt
直接去symbol.txt里面找:
rtpenc_vc2hq.o:
U avpriv_report_missing_feature
U ff_interleaved_dirac_golomb_vlc_code
U ff_interleaved_golomb_vlc_len
U ff_interleaved_ue_golomb_vlc_code
U ff_rtp_send_data
0000000000000000 T ff_rtp_send_vc2hq
U memcpy
我对编译链接还是有一点点理解的,不出意外的话,我会在libavformat目录下找到rtpenc_vc2hq.c源文件,一查还真的有,文件内容里有一条:
#include "libavcodec/golomb.h"
我们找不到的刚好是ff_interleaved_golomb_vlc_len,都有golomb,这应该不是巧合,于是我把libavcodec目录下的golomb.h和golomb.c文件都拷贝到NDK项目的libavcodec目录下,编译运行,果然不报这个错了,,,报了另外一个ff_log2_tab的,是libavcodec.so。好吧,如法炮制,但是这次有点麻烦,在静态文件生成的,应该可以说是链接表吧,里面出现了5次ff_log2_tab,有点难找,最后也不是在文件中找到的,是找到libavutil目录下查log.c时碰巧找到log2_tab的头文件和源文件。最后的结果当然就是跑起来了(猛男落泪)。
标签:ndk,头文件,ffmpeg,golomb,编译,源码,ff,interleaved 来源: https://www.cnblogs.com/thankvincisdaily/p/16193123.html