侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 41 篇文章
  • 累计创建 27 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Ffmpeg7.1.1编译环境搭建 | Android Ndk

慢行的骑兵
2021-09-03 / 0 评论 / 0 点赞 / 882 阅读 / 2,389 字

一.环境与下载资源

1.1.环境:Linux虚拟机,Ubuntu 20.04.6

1.2.下载资源

二.配置NDK环境变量

  • NDK是有多个位置可以配置环境变量的,我们选择修改~/.bashrc即可

  • 执行命令:vim ~/.bashrc,添加如下信息(添加完成通过wq进行保存,需要对vim有一点点了解):

# 在文件末尾添加 ndk环境变量(/home/jack/android-ndk-r26根据pwd命令查看)
export NDKROOT=/home/jack/android-ndk-r26
export PATH=$NDKROOT:$PATH
  • 执行命令:source ~/.bashrc
  • 接着通过ndk-build检测环境变量是否配置成功
jack@jack-pc:~$ ndk-build
Android NDK: Could not find application project directory !    
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.    
/home/jack/android-ndk-r26/build/core/build-local.mk:151: *** Android NDK: Aborting    . Stop.

三.修改configure文件

  • configure位于/home/jack/ffmpeg-7.1.1中,将文件复制下来,再修改,然后替换

    • 由于编译出来的动态库文件名的版本号在.so之后(例如“libavcodec.so.5.100.1”),而Android平台不能识别这样的文件名,所以需要修改这种文件名。
  • 修改的信息如下

    • configure的文件内容比较多,通过notepad++搜索# build settings,大概是4100多行的位置
# 将ffmpeg-7.1.1目录中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)'

四.安装yasm的汇编编译器

  • 执行命令:apt install yasm -y
  • 如果不安装,在执行后面编写的编译脚本时可能会存在报错
nasm/yasm not found or too old. Use --disable-x86asm for a crippled build

五.编写编译脚本

  • 如取名为build_android.sh,将一下内容复制进去即可,将文件放到ffmpeg-7.1.1目录中

    • 注意
      • 一共可以编译4个平台的,需要编译几个平台,自行设置。
  • 以下是错误的脚本,正确的脚本文件在6.3中,保留是为了记录遇到的坑。

    #!/bin/bash
    NDK=/home/jack/android-ndk-r26
    #工具链路径,根据系统调整
    TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
    #目标 Android API 级别,即兼容性:编译出的 FFmpeg 库最低可运行在 Android 8.0 及以上设备
    API=26

    function build_android
    {
    echo "Compiling FFmpeg for $CPU"
    ./configure \
        #设置安装路径
        --prefix=$PREFIX \
        --enable-neon \
        # 禁用硬件加速
        --disable-hwaccels \
        # 禁用 GPL 代码(使用 LGPL)
        --disable-gpl \
        # 禁用后期处理
        --disable-postproc \
        # 生成动态库
        --enable-shared \
        # 启用 JNI 支持
        --enable-jni \
        # 禁用 MediaCodec
        --enable-mediacodec \
        #启用 H264 硬件解码
        --enable-decoder=h264_mediacodec \
        # 不生成静态库
        --disable-static \
        # 不构建文档
        --disable-doc \
        # 不构建 ffmpeg 命令行工具
        --disable-ffmpeg \
        # 不构建 ffplay
        --disable-ffplay \
        # 不构建 ffprobe
        --disable-ffprobe \
        # 禁用 avdevice 模块
        --disable-avdevice \
        # 禁用符号版本控制
        --disable-symver \
        # 交叉编译工具前缀
        --cross-prefix=$CROSS_PREFIX \
        #要编译的目标系统是Android
        --target-os=android \
        # 目标架构(如 arm64)
        --arch=$ARCH \
        # 目标 CPU 型号(如 armv8-a)
        --cpu=$CPU \
        #配置c编译器
        --cc=$CC \
        --cxx=$CXX \
        #允许是一个交叉编译
        --enable-cross-compile \
        # 系统根目录
        --sysroot=$SYSROOT \
        # 额外 C 编译选项
        --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
        # 额外链接选项
        --extra-ldflags="$ADDI_LDFLAGS" \
        $ADDITIONAL_CONFIGURE_FLAG
    make clean
    make
    make install
    echo "The Compilation of FFmpeg for $CPU is completed"
    }

    #armv8-a
    # 架构类型
    ARCH=arm64
    # CPU 指令集
    CPU=armv8-a
     # C 编译器路径
    CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
    # C++ 编译器路径
    CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
    # 系统库路径
    SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
    # 工具前缀
    CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
    # 安装路径(当前目录下的 android/armv8-a)
    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
  • 设置编译脚本的权限
    • 命令:chmod 777 build_android.sh

六.测试交叉编译效果

  • 执行命令:./build_android.sh

6.1.出现报错

jack@jack-pc:~/ffmpeg-7.1.1$ ./build_android.sh
bash: ./build_android.sh: /bin/bash^M: bad interpreter: No such file or directory
  • 处理方案,依次执行;

    • sudo apt install dos2unix
    • dos2unix build_bash.sh
  • 效果如下:
    1751439976832

6.2.脚本文件执行完毕,出现报错信息,同时没有看到生成的android目录

mkdir: cannot create directory ‘/usr/local/share/man/man1’: Permission denied
make: *** [doc/Makefile:129: install-man] Error 1
  • 注意:要加上sudo,即需要执行命令:sudo ./build_android.sh

6.3.使用最新的脚本文件,加上sudo进行编译

#!/bin/bash
NDK=/home/jack/android-ndk-r26
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
API=26

function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure \
    --prefix=$PREFIX \
    --enable-shared \
	--disable-static \
	--disable-doc \
	--disable-programs \
	--disable-avdevice \
	--disable-avfilter \
	--disable-postproc \
	--disable-symver \
	--disable-static \
	--disable-ffmpeg \
	--disable-ffplay \
	--disable-ffprobe \
	--disable-hwaccels \
	--disable-gpl \
    --target-os=android \
    --arch=$ARCH \
    --cpu=$CPU \
    --cc=$CC \
    --cxx=$CXX \
    --enable-cross-compile \
    --sysroot=$TOOLCHAIN/sysroot \
    --cross-prefix=$CROSS_PREFIX \
	--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
	$ADDITIONAL
	
	make clean
	make -j12
	make install
	echo "The Compilation of FFmpeg for $CPU is completed"
}

echo "Begining Compiling FFmpeg for $CPU with ========= neon ========"
#armv8-a
# 架构类型
ARCH=arm64
# CPU 指令集
CPU=armv8-a
# C 编译器路径
CC=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang
# C++ 编译器路径
CXX=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang++
# 安装路径(当前目录下的 android/armv8-a)
PREFIX=$(pwd)/android/$CPU-neon-hard
# 工具前缀。根据实践以及deepseek查询(待实践中验证其正确性):设置 cross-prefix(注意现在使用 llvm 工具链),llvm- 前缀会自动处理 ar、strip 等工具,故后面省略 --strip=$TOOLCHAIN/bin/llvm-strip \
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
# 优化编译选项
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU "
ADDITIONAL="--enable-asm \
	--enable-neon \
	--enable-jni \
	--enable-mediacodec \
	--enable-decoder=h264_mediacodec \
	--enable-hwaccel=h264_mediacodec"
build_android

echo "Begining Compiling FFmpeg for $CPU without ========= neon ========"
#armv8-a
# 架构类型
ARCH=arm64
# CPU 指令集
CPU=armv8-a
# C 编译器路径
CC=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang
# C++ 编译器路径
CXX=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang++
# 安装路径(当前目录下的 android/armv8-a)
PREFIX=$(pwd)/android/$CPU
# 工具前缀。根据实践以及deepseek查询(待实践中验证其正确性):设置 cross-prefix(注意现在使用 llvm 工具链),llvm- 前缀会自动处理 ar、strip 等工具,故后面省略 --strip=$TOOLCHAIN/bin/llvm-strip \
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
# 优化编译选项
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
ADDITIONAL=""
build_android

echo "==================================================================="
#armv7-a
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi${API}-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi${API}-clang++
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
ADDITIONAL=""
build_android

echo "==================================================================="
#x86
ARCH=x86
CPU=x86
CC=$TOOLCHAIN/bin/i686-linux-android${API}-clang
CXX=$TOOLCHAIN/bin/i686-linux-android${API}-clang++
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
ADDITIONAL=""
build_android

echo "==================================================================="
#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++
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"
ADDITIONAL=""
build_android

6.4.查看编译结果

编译效果

  • 脚本文件是写了要生成5个的,但是最后两个跟x86相关的并未生成。查到的报错信息如下:
/home/jack/android-ndk-r26/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android26-clang is unable to create an executable file

/home/jack/android-ndk-r26/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android26-clang is unable to create an executable file
  • 在NDK对应的文件夹中能找到提到的两个文件,但是为什么没有生成跟x86相关的具体原因不清楚,有知道的同学欢迎指出。

七.遇到的2个问题

7.1.问题1:不产生指定的android文件

  • 原因:没有正确地去添加注释,将build_android函数中的注释去掉

7.2.CROSS_PREFIX配置错误

  • 更改了ndk的版本,对应的CROSS_PREFIX需要做更改,借助了deepseek对CROSS_PREFIX进行赋值,不过具体需要实践才能验证其正确性。

八.总结

  • Ffmpeg交叉编译,实践起来遇到的问题还是比较多的,其中脚本的编写还是存在一定的难度,版本需求等不同编写的内容差异可能比较大。
0

评论区