正文
1 mac下编译so
我用了大半天的时候,各种测试,各种不行。最终上天有眼让我找到了正确的脚本,亲测可用。https://www.jianshu.com/p/0a7f3175c1b9
1)环境:
操作系统:macos 10.14.1
我的是下的最新的ffmpeg ffmpeg-4.1.4
下载了ndk : android-ndk-r14b
2)ffmpeg 需要用configure先刷一遍
先下载最新版
运行configure
添加–disable-x86asm继续运行
。。。省略一干操作
这时候会生成ffbuild/config.mak等后续需要的东东
3)接着就是按照这篇文章来了
https://www.jianshu.com/p/0a7f3175c1b9
注意修改为自己的配置
最后执行
2 测试使用
1-1)as创建一个支持c++编译的项目,这个前面的文章说过了这里就不提了
1-2)在app/src/main目录下创建jnilibs目录把相关so文件拷贝进来,这里我要常用的四个
1-3)拷贝头文件到cpp下
1-4)配置CMakeLists
就是指定so的位置,以及它的头文件位置即可
1-5) 指定一下jniLibs.srcDirs,这个是给gradle用的,作用是执行安卓代码时调用。
上面指定目录是给cmake用的,作用是编译C代码时调用,这个不要弄混了。
以上,so导入项目的工作就完成了,接下来是第二大块,开发cpp
2-1)jni开发
方便起见,就在自动生成的文件中写入
注意:这里的#include “libavcodec/avcodec.h” 一定要写到extern "C"里面,否则会报错
error: undefined reference to ‘avcodec_configuration()’
2-2)在CmakeLists中将引用的库添加进来
2-3)设置编译的版本
2-4)在java中使用
2-5) run后发现闪退,找不到libavcodec,用包分析器看下
果然没有打进来,前面已经设置了
结果发现
这里写错了,给改成jniLibs,CMakeLists中的路径也得同步。
最终就顺利调用了。
3 网络流补充说明
这个版本设置了 --disable-network,所以我通过网络流获取rtsp流的时候不能正常读取。如果去掉的话,会发生一个错误。
ffmpeg 4.1版本 error: request for member ‘s_addr’ in something not a 。。。
将ndk更新为r17c可以解决这个问题。
4 硬解码补充说明
ffmpeg需要在编译过程就配置好解码器,以便后面调用。发现4.1版本ffmpeg中的decoders只有
没有包含硬解的h264_mediacodec等解码器。
实验证明,并不是不包含,而是大家没有把它放出来
- 编辑ffbulid->config.mak文件
2)搜索CONFIG_H264_MEDIACODEC_DECODER,将前面的!去掉,!代表了非
3)删掉config.h头文件待会让它重新生成
4)再次执行安卓编译脚本,这次大家就能顺利见着它了
昨晚熬到2点半没解决的问题,今天神乎其技的解决了。
5)底层c调用硬解码器:
pCodec = avcodec_find_decoder_by_name("h264_mediacodec");//h264硬解码
if(!pCodec){
LOGD("get h264_mediacodec failed:%s",pCodec);
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoIndex]->codecpar);
pCodecCtx->thread_count = 8;
int re = -1;
re = avcodec_open2(pCodecCtx, NULL, NULL);
if (re < 0){
LOGD("open failed = %s",av_err2str(re));
return -1;
}
接着,新版硬解接口都变了,用的:
参考这篇文章,讲的很好,了解其原理
https://www.cnblogs.com/TaigaCon/p/10041926.html
最后,利用surface显示的问题可以参考这篇文章,写的很好
https://www.jianshu.com/p/4b60cea7fa85