编译ffmpeg安卓库(clang篇),含armeabi-v7a , arm64-v8a, x86, x86_64
安卓新的NDK编译工具替换成了clang,所以之前的编译脚本需要做相应调整,本文总结了编译过程中遇到的诸多问题,如果编译过程中遇到问题,或编出的库不符合需求,可参考后面的问题总结,希望能帮到你
环境
编译环境:win10 + msys2
DNK版本:android-ndk-21.2.6472646/ android-ndk-21.0.6113669/android-ndk-r20
ffmpeg版本: ffmpeg3.3.9/ffmpeg4.3.1
使用本文的编译脚本,测试了linux和window10,android-ndk-21.2.6472646/ android-ndk-21.0.6113669/android-ndk-r20,编译了 ffmpeg3.3.9/ffmpeg4.3.1,都能成功编译
环境搭建
网上许多安装类unix运行环境都需要翻墙,要么安装速度很慢,本文使用国内源不需要翻墙,如果你安装了其他的类unix运行环境(如cywin, MinGW),理论上应该是可以直接进入后面的编译步骤的,不过我没尝试过
1、msys2安装
在清华大学镜像网站下载并安装 msys2 最新版本 ,此外还有中科大,北京理工大学, 上海交大等镜像源,64位系统建议下载x86_64版本,安装一路点击下一步就行
2、msys2配置
将默认源地址替换为清华大学镜像地址,类似于Ubuntu设置镜像源,这样安装其他工具速度会快很多,配置步骤如下
见清华大学镜像网站msys2帮助文档,我下载的最新版本默认有许多国内镜像源在配置文件中,其他镜像源的没有试过,建议把国内的源放前面,我的配置顺序如下
#清华大学
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686/
#中科大
Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686/
#北京理工大学
Server = http://mirror.bit.edu.cn/msys2/mingw/i686/
Server = https://mirror.selfnet.de/msys2/mingw/i686/
#上海交大
Server = https://mirrors.sjtug.sjtu.edu.cn/msys2/mingw/i686/
Server = https://mirror.yandex.ru/mirrors/msys2/mingw/i686/
Server = https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/
Server = https://www2.futureware.at/~nickoe/msys2-mirror/mingw/i686/
配置完打开安装路径下msys2.exe(或按win键在程序列表中打开),执行 pacman -Sy
刷新软件包数据即可。
然后执行安装路径下msys2_shell.cmd打开msys终端,执行"pacman -Syuu"命令,中途可能会提示关闭终端,此时关闭msys,重新 打 开,再次执行"pacman -Syuu"命令,更新软件包
这里顺便附一个pacman包管理工具命令开始编译
3、安装make
在msys2终端执行pacman -S make,安装make工具
pacman -S make
编译ffmpeg
msys2安装目录下打开mingw64.exe, 切换到ffmpeg源码路径,windows D:盘被挂载为/d/,以此类推,可用 df -h命令确认,不过盘符占用比较多时相应可能比较慢
新建一个buid.sh,将以下内容粘贴到文本,根据需求替换前三个变量,如果使用windows文本编辑器,切记保存为unix格式,否则可能会由于结束符不一致问题,报有语法错误,脚本加了一些辅助调试信息,和交互选项,所以比较长,将脚本保存到ffmpeg源码路径下,执行./build 5 ,可编译armeabi-v7a , arm64-v8a, x86, x86_64 所有动态和静态库,如果只编译某个版本的库执行./build可以看到编译选择,选择相应版本编号即可,输出路径下build.log可跟踪编译情况
#!/bin/bash#ffmpeg 版本
FFMPEG_VERSION=4.3.1
#NDK 路径, 根据情况替换
export NDK=/d/Green_Sorft/Android/Sdk/ndk/21.2.6472646
#编译输出路径 根据需求替换替换,默认在脚本上级目录ffmpeg_for_android目录下
OUT_DIR="`dirname $PWD`/ffmpeg_for_android/ffmpeg_${FFMPEG_VERSION}_lib"
#编译工具路径,linux版本需根据情况替换
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/windows-x86_64export TMPDIR=$OUT_DIR/tmp
mkdir -p $TMPDIR
#将ndk下yasm所在路径添加到PATH环境变量
PATH=$PATH:$TOOLCHAIN/bin
#创建/清空编译日志
> $OUT_DIR/build.logfunction build_start() {echo "build FFmpeg for $ABI"./configure \--prefix=$OUT_DIR/$ABI \--disable-gpl \--enable-shared \--enable-static \--disable-doc \--disable-programs \--disable-avdevice \--disable-doc \--disable-symver \--cross-prefix=$CROSS_PREFIX \--target-os=android \--enable-cross-compile \--arch=$ARCH \--cpu=$CPU \--cc=$CC \--cxx=$CXX \--sysroot=$TOOLCHAIN/sysroot \--extra-cflags="-Os -fPIC $OPTIMIZE_CFLAGS" \configRet=$?echo "* config for $ABI ret:$configRet" >> $OUT_DIR/build.logif [ $configRet -eq 0 ]; thenecho "start make $ABI"make cleanmake -j64makeRet=$?echo "* make for $ABI return:$makeRet" >> $OUT_DIR/build.logif [ $makeRet -eq 0 ]; thenmake installmv_libsfielseecho "The config of FFmpeg for $ABI is failded"echo "* config for $ABI failed !!" >> $OUT_DIR/build.logfiecho "The Compilation of FFmpeg for $ABI is completed"echo "*************************" >> $OUT_DIR/build.log
}function mv_libs() {mkdir -p $OUT_DIR/shared-libs/$ABImv $OUT_DIR/$ABI/lib/*.so $OUT_DIR/shared-libs/$ABImkdir -p $OUT_DIR/static-libs/$ABImv $OUT_DIR/$ABI/lib/*.a $OUT_DIR/static-libs/$ABIcp -rf $OUT_DIR/$ABI/include $OUT_DIR/cp -rf $OUT_DIR/$ABI/share/ffmpeg/examples $OUT_DIR/rm -rf $OUT_DIR/$ABI/
}#armv8-a aarch64
function build_arm64() {API=21ABI=arm64-v8aARCH=arm64CPU=armv8-aCC=$TOOLCHAIN/bin/aarch64-linux-android$API-clangCXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-OPTIMIZE_CFLAGS="-march=$CPU"echo "* buidl for $ABI start !!" >> $OUT_DIR/build.logbuild_startecho "* buidl for $ABI end !!" >> $OUT_DIR/build.logecho "*************************" >> $OUT_DIR/build.log
}#armv7-a
function build_arm() {API=16ABI=armeabi-v7aARCH=armCPU=armv7-aCC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clangCXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-OPTIMIZE_CFLAGS="-march=$CPU -mfloat-abi=softfp -mfpu=vfp -marm"echo "* buidl for $ABI start !!" >> $OUT_DIR/build.logbuild_startecho "* buidl for $ABI end !!" >> $OUT_DIR/build.logecho "*************************" >> $OUT_DIR/build.log
}#x86 i686
function build_x86() {API=16ABI=x86ARCH=x86CPU=x86CC=$TOOLCHAIN/bin/i686-linux-android$API-clangCXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -mno-stackrealign"echo "* buidl for $ABI start !!" >> $OUT_DIR/build.logbuild_startecho "* buidl for $ABI end !!" >> $OUT_DIR/build.logecho "*************************">> $OUT_DIR/build.logecho "">> $OUT_DIR/build.log
}#x86_64
function build_x86_64() {API=21ABI=x86_64ARCH=x86_64CPU=x86-64CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clangCXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"echo "* buidl for $ABI start !!" >> $OUT_DIR/build.logbuild_startecho "* buidl for $ABI end !!" >> $OUT_DIR/build.logecho "*************************">> $OUT_DIR/build.log
}function read_opt()
{echo ""echo "please select onece"echo " 1、build for ABI=armeabi-v7a CPU=armv7-a"echo " 2、build for ABI=arm64-v8a CPU=armv8-a"echo " 3、build for ABI=x86 CPU=x86"echo " 4、build for ABI=x86_64 CPU=x86_64"echo " 5、build all"echo ""echo "input:"read option
}option=$1
if [ "$option" = "" ];thenread_opt
fiif [ "$option" = "1" ];thenecho "start build ABI=arm64-v8a CPU=armv8-a"build_arm64
elif [ "$option" = "2" ];thenecho "start build ABI=armeabi-v7a CPU=armv7-a"build_arm
elif [ "$option" = "3" ];thenecho "start build ABI=x86 CPU=x86"build_x86
elif [ "$option" = "4" ];thenecho "start build ABI=x86_64 CPU=x86_64"build_x86_64
elif [ "$option" = "5" ];thenecho "start build all"build_arm64build_armbuild_x86build_x86_64
elseecho "invalid input"
firm -rf $TMPDIR
问题总结
1、编译x86cpu时内联汇编报错
In file included from libswscale/x86/rgb2rgb.c:102:
libswscale/x86/rgb2rgb_template.c:1666:13: error: inline assembly requires more registers than available
"mov %4, %%"FF_REG_a"\n\t"
^
提供了一下4个解决方案
1、禁用asm,在ffmpeg configure选项中添加--disable-asm禁用汇编,不过可能会影响运行效率
2、在修改ffmpeg路径下config.h,将HAVE_EBP_AVAILABLE 设置为0 #define HAVE_EBP_AVAILABLE 0
3、这是ndk低版本编译链中才存在的问题,可用24及以上版本编译链,及将脚本中x86_build中的API设置为24及以上(可能会影响兼容性)
4、(推荐)在configure --extra-cflags选项中添加 -mno-stackrealign编译选项
2、使用ffmpeg动态库,编译时提示找不到动态库
在app下build.gradle 文件android内添加如下代码
sourceSets.main{jniLibs.srcDirs=['libs']
}
3、使用模拟器调试时,提示java.lang.UnsatisfiedLinkError: dlopen failed: "xxx.so" has text relocations(https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-Enforced-for-API-level-23)
模拟器基本都是x86cpu,网上说只有6.0以上才有这个问题,网上的方案都是把aap下build.gradle中的targetSdkVersion设置为23以下,但是我用模拟器调试时似乎不能这么操作,修改后编不出APK,我不是搞安卓framework的,应用相关的不是很清楚,所以我直接使用静态库了,或者使用手机
4,提示找不到ysam或版本过低
首先在msys终端输入yasm,看是否有这个命令,如果提示找不到命令,则在脚本中将ndk中android-ndk-r20\toolchains\llvm\prebuilt\windows-x86_64\bin\yasm添加到PATH环境变量中,PATH=$PATH:$TOOLCHAIN/bin ,如果有yasm,则用whereis yasm命令,找到电脑中的yasm,将其重命名(记得改回去)或直接删除,然后将ndk的yasm添加到path环境变量
5、在编译armv7-a时,汇编文件报错
libswscale/arm/rgb2yuv_neon_common.S:251:11: error: unexpected token in argument list
CO_BV .dn d2.s16[2]
^
<instantiation>:4:5: error: invalid instruction
vmul y16x16_l, n16x16_l, CO_RY
^
我在编译ffmpeg4.3.1时没有这个问题,但是编译ffmpeg3.3.9时报错,简单粗暴的操作就是在ffmpeg configure选项中添加--disable-asm禁用汇编,但是我们要斯文一点,可以选择只禁用neon,即在armv7-a的ffmpeg configure选项中加入--disable-neon
6、将ffmpeg所有的库编译为一个libffmpeg.so库
目前只编译出静态库,动态库编译编译过程遇到了些问题,后面尝试解决
https://blog.csdn.net/mvp_Dawn/article/details/109136921
编译ffmpeg安卓库(clang篇),含armeabi-v7a , arm64-v8a, x86, x86_64相关推荐
- VC使用mingw32编译ffmpeg静态库所需文件(一),ffmpegshim.c
VC使用mingw32编译ffmpeg静态库所需文件(一),ffmpegshim.c 哈哈,这是我从一些项目里面看到的,这些函数是ffmpeg.a缺少的函数.估计大家会用得上. 当然我移植的的项目都不 ...
- MinGW下编译ffmpeg静态库给Visual C++使用
首先推荐 http://ffmpeg.zeranoe.com/builds/, 这里已经有编译好的动态连接库.可惜上面没静态链接库.我也试过 DLL2Lib, 但是无法连接LIBCMT库,只能使用MS ...
- 【Android 音视频开发打怪升级:FFmpeg音视频编解码篇】一、FFmpeg so库编译
转自:https://juejin.im/post/5e130df55188253a8b42ebac 目录 一.Android音视频硬解码篇: 1,音视频基础知识 2,音视频硬解码流程:封装基础解码框 ...
- ffmpeg自学路(一)用ubantu编译支持android的ffmpeg支持库,感谢韩曙亮
非常感谢韩曙亮的帮助,特以此篇记录编译过程. 韩兄相关文章的对应地址:https://blog.csdn.net/shulianghan/article/details/104351312 / 开始正 ...
- AndroidNDK工程FFmpeg(一)-- Android使用FFmpeg--Shell脚本编写与执行编译FFmpeg库
FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计 算机程序.FFmpeg 是一个多媒体视频处理工具,有非常强大的功能包括视频采集功能. 视频格式转换.视频抓图.给视频加水印 ...
- Android NDK开发之旅29 云服务器Ubuntu下搭建NDK环境,并编译FFmpeg
###前言 因为在Linux环境下编译FFmpeg生成库和头文件下比较方便,所以接下来主要操作在Linux环境下进行.但是对于Android NDK 开发新手来说,自己电脑配置Ubuntu Linux ...
- 【Android FFMPEG 开发】Android Studio 工程配置 FFMPEG ( 动态库打包 | 头文件与函数库拷贝 | CMake 脚本配置 )
文章目录 I . FFMPEG 交叉编译后的函数库及头文件 II . FFMPEG 静态库打包动态库 ( 仅做参考 ) III . 创建 Android Studio 工程 IV . FFMPEG 头 ...
- Android 编译FFmpeg x264
1. Android FFmpeg开发基本流程 (1)X264/FFmpeg + NDK编译 (2)ffmpeg.so + 编解码C代码 (3)Android.mk 编译 (4)JNI (5) ...
- 【Android 安装包优化】动态库打包配置 ( “armeabi-v7a“, “arm64-v8a“, “x86“, “x86_64“ APK 打包 CPU 指令集配置 | NDK 完整配置参考 )
文章目录 一.动态库打包配置 二.NDK 完整配置参考 三.参考资料 一.动态库打包配置 在 build.gradle 构建脚本中 , 配置 ndk 编译的动态库 CPU 架构类型 ; 在 " ...
- linux编译ffmpeg成so,「ffmpeg」一 mac 环境下编译ffmpeg,生成so库文件
1.下载ffmpeg源码,官网,我这里直接采用git 方式下载: 下载ffmpeg.png 终端输入git命令: 静静等待~ 最后下载的版本为3.4.6 . image.png 这里注意一下,刚开始我 ...
最新文章
- TensorFlow框架--Keras
- C# 使用AggregateException 信息
- apache服务器工作原理,Apache服务器的原理简介
- 一个U盘走天下,装机大神撩妹的不二之选
- app error login.php,如何解决uniapp登录错误提示问题
- nefu 984 我是一个粉刷匠
- 文件异步加载读取 php,js文件的异步加载的方法总结(附代码)
- 炫酷流光个人主页源码分享及在线部署教程
- 车规SoC芯片厂商征战功能安全,谁是最佳助力者?
- 广告管理系统的UML分析与设计
- Word文档打印又出新方法!Spire.Doc全新代码让文档更清晰
- 数字黑洞java,java解决数字黑洞问题
- iOS app上架app store流程详解
- c语言水王争霸链表,水王争霸(water)
- c语言ifi=1 2,第1部分_C语言程序设计练习一全解.doc
- 阿里云部署Java网站和微信开发调试心得技巧(下)
- Python 打字小游戏开发,来体验不一样的打字游戏乐趣(第二篇)
- JS中find()和findIndex()
- 计算机基础知识试题答案6,计算机基础知识试题及答案
- CSDN-MarkDown编辑器的姿势大全