build ffmpeg for Android

前言

最近在学习 Android 的音视频开发,接触到了 FFmpeg,那如何交叉编译 FFmpeg 才能在Android上使用呢?
经过一番考察,我决定使用这样一套环境来进行编译:Linux + NDK + FFmepg source code


编译步骤

1.获取 FFmpeg 源码

http://www.ffmpeg.org/

  1. 解压
  2. 进入源代码所在文件夹,打开configure文件,并修改

修改前

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

修改后

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

这一步的主要目的是生成Android能够使用的 名称-版本.so文件的格式,不然的话生成的是Linux上使用库,Android不能用

2.获取 NDK

这里建议选择 android-ndk-r17c 的版本。这个版本支持gcc编译,后续最新的版本似乎都是clang编译的模式,个人不是很擅长。本文下面所有的描述,都是基于gcc编译的!

[android-ndk-r17c]
20210407220314508.png

3.编写 build for Android 的脚本

参考的一个大佬写的脚本,里面有很多细节的东西,自己会在文章最后再梳理一下。

#!/bin/bash

# Don't forget to install yasm

# Set your own NDK here
NDK=/home/joshua/AndroidNDK/android-ndk-r17c

ARM_PLATFORM=$NDK/platforms/android-14/arch-arm/
ARM_PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

ARM64_PLATFORM=$NDK/platforms/android-14/arch-arm/
ARM64_PREBUILT=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64

X86_PLATFORM=$NDK/platforms/android-14/arch-arm/
X86_PREBUILT=$NDK/toolchains/x86-4.9/prebuilt/linux-x86_64

X86_64_PLATFORM=$NDK/platforms/android-14/arch-arm/
X86_64_PREBUILT=$NDK/toolchains/x86_64-4.9/prebuilt/linux-x86_64



#NDK r17 sysroot inlcude及lib相关移到了根目录,cflag中添加链接
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/arm-linux-androideabi

#生成的so及.h文件路径
BUILD_DIR=$PWD/ffmpeg-android

#ffmpeg版本,后面pushd用,所以要建立第2步正确的目录结构
FFMPEG_VERSION="4.3.2"

function build_one
{
if [ $ARCH == "arm" ]
then
    PLATFORM=$ARM_PLATFORM
    PREBUILT=$ARM_PREBUILT
    HOST=arm-linux-androideabi
elif [ $ARCH == "arm64" ]
then
    PLATFORM=$ARM64_PLATFORM
    PREBUILT=$ARM64_PREBUILT
    HOST=aarch64-linux-android
elif [ $ARCH == "x86_64" ]
then
    PLATFORM=$X86_64_PLATFORM
    PREBUILT=$X86_64_PREBUILT
    HOST=x86_64-linux-android
else
    PLATFORM=$X86_PLATFORM
    PREBUILT=$X86_PREBUILT
    HOST=i686-linux-android
fi

#extra-cflags配置-I$ASM -isysroot $ISYSROOT,否则会报出.h找不到
#pushd ffmpeg-$FFMPEG_VERSION
./configure --target-os=linux \
    --incdir=$BUILD_DIR/include \
    --libdir=$BUILD_DIR/lib/$CPU \
    --enable-cross-compile \
    --arch=$ARCH \
    --cc=$PREBUILT/bin/$HOST-gcc \
    --cross-prefix=$PREBUILT/bin/$HOST- \
    --nm=$PREBUILT/bin/$HOST-nm \
    --sysroot=$PLATFORM \
    --extra-cflags="-I$ASM -isysroot $ISYSROOT -I$BUILD_DIR/include -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $OPTIMIZE_CFLAGS" \
    --enable-gpl \
    --enable-small \
    --extra-ldflags="-L$BUILD_DIR/lib/$CPU" \
    --enable-shared \
    --disable-doc \
    --disable-programs \
    --disable-stripping \
    --disable-symver \
    --disable-static \
    --pkg-config=/usr/bin/pkg-config \
    $ADDITIONAL_CONFIGURE_FLAG

make clean
make -j8
make install
#popd
}

#arm v7vfpv3
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU -D__thumb__ -mthumb"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#arm v7vfp
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
#PREFIX=`pwd`/ffmpeg-android/$CPU-vfp
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#arm v7n
CPU=armv7-a
ARCH=arm
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"
PREFIX=$BUILD_DIR/$CPU
ADDITIONAL_CONFIGURE_FLAG=
build_one
#arm64-v8a
#CPU=arm64-v8a
#ARCH=arm64
#OPTIMIZE_CFLAGS=
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#x86_64
#CPU=x86_64
#ARCH=x86_64
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#x86
#CPU=i686
#ARCH=i686
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

4.执行脚本 ./build_android.sh

5.在ffmpeg-android里可以查看生成的头文件和so库


错误处理

在交叉编译时还遇到了一些这样的问题


报错原因:在ffmpeg里面 有 #define B0 和 int B0 冲突了;
解决方法:libavcodec/aaccoder, hevc_mvs, opus_pvq 中的 B0,xB0, yB0 全都改成 b0, xb0,yb0.


日积月累

1.认识 -isysroot

在build_android.sh里,有这样一个编译参数,抄的大佬的,这里记录一下。

 --sysroot=$PLATFORM \
  --extra-cflags="-I$ASM -isysroot $ISYSROOT -I$BUILD_DIR/include -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $OPTIMIZE_CFLAGS" \

我在使用NDK交叉编译的时候,其实已经发现了NDK和以前使用的SDK不太一样的地方。
一般来说,交叉编译的一个关键位置就是 SYSROOT,在SYSROOT中有交叉编译的头文件lib库。NDK有着自己独特的目录结构,lib库位于 platforms/android-xx里,而头文件却位于sysroot/usr/include/arm-linux-androideabi 下,如下表所示。

分类 头文件位置 lib库位置
普通SDK sysroot sysroot
NDK platforms/android-xx sysroot/usr/include/arm-linux-androideabi

-isysroot -- i(include),定义 头文件 的位置
-sysroot -- 定义 lib库 的位置

2.认识 armv7-a vfp neon等等

#arm v7vfpv3
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU -D__thumb__ -mthumb"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#arm v7vfp
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
#PREFIX=`pwd`/ffmpeg-android/$CPU-vfp
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#arm v7n
CPU=armv7-a
ARCH=arm
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"
PREFIX=$BUILD_DIR/$CPU
ADDITIONAL_CONFIGURE_FLAG=
build_one
#arm64-v8a
#CPU=arm64-v8a
#ARCH=arm64
#OPTIMIZE_CFLAGS=
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#x86_64
#CPU=x86_64
#ARCH=x86_64
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#x86
#CPU=i686
#ARCH=i686
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

在大佬的build_android.sh,他把CPU=armv7-a的这一行分的特别细,但AS中编译生成的 只有x86x86_64arm64-v8aarmv7-a。那么硬浮点or软浮点,vfp or neon,那种编译方式才是 AS 种的 armv7-a呢?

我个人在想,AS 编译出来的 armv7-a 库应该是通用性,编译选项中应该没有那么多弯弯绕绕的选择才对,不然很容易造成不支持的情况。

我又去仔细查了查AS中 compile_commands.json 中,发现了这一段

[
{
  "directory": "D:/AndroidProject/DemoNDK/app/.cxx/cmake/debug/armeabi-v7a",
  "command": "C:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk\\ndk\\21.1.6352462\\toolchains\\llvm\\prebuilt\\windows-x86_64\\bin\\clang++.exe --target=armv7-none-linux-androideabi23 --gcc-toolchain=C:/Users/Administrator/AppData/Local/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/Administrator/AppData/Local/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/windows-x86_64/sysroot  -Dnative_lib_EXPORTS  -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security   -O0 -fno-limit-debug-info  -fPIC   -o CMakeFiles\\native-lib.dir\\native-lib.cpp.o -c D:\\AndroidProject\\DemoNDK\\app\\src\\main\\cpp\\native-lib.cpp",
  "file": "D:\\AndroidProject\\DemoNDK\\app\\src\\main\\cpp\\native-lib.cpp"
}
]

也就是说,在编译 armv7-a 下lib库的时候,在编译选项中只有 "-march=armv7-a"

这个问题,在这里也没得到一个定论,要在以后的学习中多多留意,来探索如何设置armv7-a 库的编译参数,才能让其通用性最好;或是在适当的时候进行适配,来加强性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容