Linux 编译 Android FFmpeg 动态库

为什么新版本的ffmpeg搭配新版本的ndk编译很容易出错呢?

其实关键点主要还是新旧版本ndk中的交叉编译工具不一样导致的。

比如旧版本(r17及之前)的ndk中的编译器用的是gcc,而网上大部分的同类文章中用的也是gcc,

而新版本的ndk文件已经弃用gcc编译器改用clang了,所以照着网上的文章做当然编译不起来。

从谷歌官网,NDK 修订历史记录(https://developer.android.google.cn/ndk/downloads/revision_history

ndk-build 命令在 r13 中默认为使用 Clang。我们将在后续版本中移除 GCC。

在 13b、14b、15c、16b 中均作出了如下说明:

GCC 不再受支持,虽然尚未从 NDK 中移除,但其已不再接收向后移植项。

在17c中:

明确说明GCC 在 r18 移除。

综上所述,ndk 编译至少有两种方案,根据不同的 ndk 版本,我这里列出了不同的解决方案。

根据 GCC 和 Clang 两种编译方式,可以分成 3 种类型

1,完全GCC(r12及其以下版本)(2016.10 以前)

2,GCC 和 Clang 共存(r13,r14,r15,r16,r17)(2016.10~2018.09)

3,完全 Clang(r18及其以上)(2018.09 以后)

方案一,低版本编译:(android-ndk-r12b + ffmpeg 2.x.x)

方案二,过渡版编译:(android-ndk-r14b + ffmpeg 3.xx)

方案三,高版本编译:(android-ndk-r19c + ffmpeg 4.x.x)
备注:r19 之前的版本,NDK 的默认工具链都是独立工具链,r18 是一个比较尴尬的版本,这里就不使用了。

三种方案中,除了编译的 shell 脚本不同外,其他的步骤是相通的。这里就简单的说明下编译步骤。

第一步:配置系统(编译的系统环境:Ubuntu 20.04 LTS )

为了方便操作,这里采用 XShell 进行远程操作。

系统安装过程和 xShell 安装过程省略。

XShell 连接方式:

1、先在Ubuntu系统中获取 ip地址

ifconfig

2、判断SSH服务是否打开

    ps -e|grep ssh

3、打开ssh

    sudo service sshd start

4、如果提示sshd不存在则安装ssh

    sudo apt install openssh-server

5、在xShell 中新建连接,输入Ubuntu的 ip 。

第二步:配置 NDK 系统环境变量

1、先安装 lrzsz 工具,方便上传文件

sudo apt install lrzsz

2、我们先将本地下载好的文件通过 xShell 上传到 linux 。  

a、将 NDK 文件上传到 /usr/ndk 目录

cd /usr
sudo mkdir ndk
cd ndk
sudo rz

然后选择要上传的 ndk 文件即可。

上传完毕后,将 ndk 解压当当前目录。

sudo unzip android-ndk.zip

b、配置环境变量

需要先安装 vim ,这个自行安装

cd ~
vim .bashrc

在 bashrc 文件末尾添加 ndk 路径,根据实际名字填写

export NDKROOT=/usr/ndk/android-ndk-r12b
export PATH=$NDKROOT:$PATH

保存退出(:wq)

c、刷新环境

source .bashrc

d、测试 ndk 环境是否安装成功

ndk-build

弹出类似信息:

Android NDK: Could not find application project directory !    
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.    
/usr/ndk/android-ndk-r12b/build/core/build-local.mk:151: *** Android NDK: Aborting

第三步:上传 FFmpeg 并配置脚本

1、上传 ffmpeg 文件

将 ffmpeg 压缩文件上传到 /usr/ffmpeg-android

cd /usr/
sudo mkdir ffmpeg-android
cd ffmpeg-android/
sudo rz

选择下载好的 ffmpeg 压缩文件,上传完成后解压到当前目录。

sudo tar -xzvf ffmpeg-2.7.7.tar.gz

一般而言,以“.gz”结尾的是以gzip方式进行压缩的,以".bz2"结尾的是以bzip2方式压缩的。

tar命令有5个常用的选项:

1 “c”:表示创建,用来生成文件包;

2 “x”:表示提取,从文件包中提取文件;

3 “z”:使用 gzip 方式进行处理,它与“c”结合就表示压缩,与“x”结合就表示解压缩;

4 “j”:使用 bzip2 方式进行处理,它与“c”结合就表示压缩,与“x”结合就表示解压缩;

5、“v” : 即view,是可视化的意思,想看解压的文件进度就加上v。

6 “f”:表示文件,后面接着一个文件名。

所以,怎样使用tar命令去压缩,解压文件就一目了然了吧,理解了之后很容易记住,以后就不用再查了。

2、进入 解压后的文件目录,创建编译文件

sudo touch build_android.sh
vim build_android.sh

  2.x 的编译脚本(配置文件换行如果前面自动加tab空格要删除)

#!/bin/bash
export NDK_HOME=/usr/ndk/android-ndk-r12b
export PLATFORM_VERSION=android-9
function build
{
echo "start build ffmpeg for $CPU"
./configure --target-os=linux \
--prefix=$PREFIX --arch=$ARCH \
--disable-doc \
--enable-shared \
--disable-static \
--disable-yasm \
--disable-asm \
--disable-symver \
--enable-gpl \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--cross-prefix=$CROSS_COMPILE \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
echo "build ffmpeg for $CPU finished"
}

#arm
ARCH=arm
CPU=arm
PREFIX=$(pwd)/android/$CPU
TOOLCHAIN=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
ADDI_CFLAGS="-marm"
SYSROOT=$NDK_HOME/platforms/$PLATFORM_VERSION/arch-$ARCH/
build

#x86
ARCH=x86
CPU=x86
PREFIX=$(pwd)/android/$CPU
TOOLCHAIN=$NDK_HOME/toolchains/x86-4.9/prebuilt/linux-x86_64
CROSS_COMPILE=$TOOLCHAIN/bin/i686-linux-android-
ADDI_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
SYSROOT=$NDK_HOME/platforms/$PLATFORM_VERSION/arch-$ARCH/
build

将NDK路径替换成自己实际的 ndk 路径,
保存 platforms 和 toolchains 的子目录是存在的,
如果不存在,选择已存在的目录

效果图:

退出请按 Esc ,然后输入 :wq! 强制保存

3.x 的编译脚本(android-ndk-r14b + ffmpeg-3.3.9)

#!/bin/bash
export NDK_HOME=/usr/ndk/android-ndk-r14b
export PLATFORM_VERSION=android-9
function build
{
echo "start build ffmpeg for $ARCH"
./configure --target-os=linux \
--prefix=$PREFIX --arch=$ARCH \
--disable-doc \
--enable-shared \
--disable-static \
--disable-yasm \
--disable-asm \
--disable-symver \
--enable-gpl \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--cross-prefix=$CROSS_COMPILE \
--enable-cross-compile \
--sysroot=$SYSROOT \
--enable-small \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
echo "build ffmpeg for $ARCH finished"
}
#arm
ARCH=arm
CPU=arm
PREFIX=$(pwd)/android/$ARCH
TOOLCHAIN=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
ADDI_CFLAGS="-marm"
SYSROOT=$NDK_HOME/platforms/$PLATFORM_VERSION/arch-$ARCH/
build
#x86
ARCH=x86
CPU=x86
PREFIX=$(pwd)/android/$ARCH
TOOLCHAIN=$NDK_HOME/toolchains/x86-4.9/prebuilt/linux-x86_64
CROSS_COMPILE=$TOOLCHAIN/bin/i686-linux-android-
ADDI_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
SYSROOT=$NDK_HOME/platforms/$PLATFORM_VERSION/arch-$ARCH/
build

效果图如下:

4.x 的编译脚本(android-ndk-r19c + ffmpeg-4.0.6)

r19 编译的最低版本,为了兼容,统一使用 21:

aarch64-linux-android21-clang
armv7a-linux-androideabi16-clang
i686-linux-android16-clang
x86_64-linux-android21-clang

#!/bin/bash
NDK=/usr/ndk/android-ndk-r19c
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/
API=21

function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure \
--prefix=$PREFIX \
--disable-neon \
--disable-hwaccels \
--disable-gpl \
--disable-postproc \
--enable-shared \
--enable-jni \
--disable-mediacodec \
--disable-decoder=h264_mediacodec \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic -mno-stackrealign $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
--disable-asm \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}

#armv8-a
ARCH=arm64
CPU=armv8-a
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android

#armv7-a
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
build_android

#x86
ARCH=x86
CPU=x86
CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
build_android

#x86_64
ARCH=x86_64
CPU=x86-64
CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"
build_android

效果图如下:

问题1:4.x 版本没有生成x86 包
解决方案:

 -mno-stackrealign 

问题2:编译x86版本时,出现如下错误:

解决方案:安装 yasm

sudo apt install yasm

问题3:4.x的x86 在6.0及以上版本报(has text relocations)
解决方案:
--disable-asm \
https://blog.csdn.net/mike_modern/article/details/78762746

3、2.x 和 3.x 的 ffmpeg 还需要修改配置文件,保证生成的 *.so 文件是可用的

vim configure

将 vim 的行号显示出来,方便等下编辑
:set number 回车键确认

搜索要修改的位置
/# build 

然后跳转到 刚才定位的位置 大概 2850 行
:2850 回车键确认

i 进入编辑模式

将需要替换的文字替换

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

修改完成效果如下:

:wq! 保存退出

4、授予执行权限
为了方便,直接将整个目录,及其子文件授予最高权限

cd ..
chmod 777 -R ffmpeg-2.7.7

5、开始编译

cd ffmpeg-2.7.7/
sudo ./build_android.sh

6、将编译好的文件压缩下载到本地

编译完成后可以看到如下目录:

将 根目录下的 android 文件夹, 整个压缩 成 android.zip 然后下载到本地电脑。

在ffmpeg 根目录中

sudo zip -r android.zip android/
sudo sz android.zip

选择保存的目录即可

第四步:将编译好的so 集成到本地项目

省略...

 

 

NDK 下载地址:https://developer.android.google.cn/ndk/downloads/older_releases

FFMPEG 下载地址:http://www.ffmpeg.org/olddownload.html

 XShell下载:https://www.netsarang.com/zh/xshell/

参考:

https://juejin.cn/post/6844903945496690696

https://blog.csdn.net/mvp_dawn/article/details/109125631

ffmpeg ./configure 的相关参数说明:

https://blog.csdn.net/fengsh998/article/details/79443503

 

编译好的资源下载:

android-ffmpeg-4.0.6.zip

android-ffmpeg-3.3.9.zip

android-ffmpeg-2.7.7.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值