NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

07-21 1465阅读

1.准备工作

文件下载:

NDK R25b下载地址:Android NDK历史版本下载网址 - 君*邪 - 博客园 (cnblogs.com)

FFmpeg4.4.4 下载地址:https://ffmpeg.org/releases/ffmpeg-4.4.4.tar.xz

环境配置:

本次编译环境是在PC虚拟机中使用Ubuntu18.04

NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

下载好NDK和FFmpeg 之后,复制到Ubuntu下然后解压,为交叉编译做准备

2.交叉编译FFmpeg流程

解压完FFmpeg源码之后,进入源码根目录,新建编译脚本android.sh

NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

新版 ndk 已放弃 gcc,转而使用更高效的 clang,下述脚本以 clang 为例编译 FFmpeg 源码。支持编译armv8-a 和armv7-a,注意修改成你的NDK目录地址

 #!/bin/bash
 # 修改成你的NDK目录
 TOOLCHAIN=/home/marxist/ndk/android-ndk-r25b-linux/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64
 # 最低支持的android sdk版本
 API=21
 function build_android
 {
 echo "Compiling FFmpeg for $CPU"
 ./configure \
  --prefix=$PREFIX \
  --enable-neon \
  --enable-shared \
  --enable-small \
  --disable-vulkan \
  --disable-gpl \
  --disable-postproc \
  --disable-jni \
  --disable-mediacodec \
  --disable-decoder=h264_mediacodec \
  --disable-static \
  --disable-doc \
  --disable-programs \
  --disable-ffmpeg \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-avdevice \
  --disable-symver \
  --enable-cross-compile \
  --cross-prefix=$CROSS_PREFIX \
  --target-os=android \
  --arch=$ARCH \
  --cpu=$CPU \
  --cc=$CC \
  --cxx=$CXX \
  --sysroot=$SYSROOT \
  --extra-cflags="-mno-stackrealign -Os -fpic -mfpu=neon $OPTIMIZE_CFLAGS" \
  --extra-ldflags="$ADDI_LDFLAGS"
  #--disable-debug
  #--disable-stripping
  #--disable-linux-perf
  #--disable-hwaccels
 make clean
 make -j4
 make install
 echo "The Compilation of FFmpeg for $CPU is completed"
 }
 function print_supported_cpus
 {
     echo "Supports the following CPUs:"
     echo "1. armv7-a"
     echo "2. armv8-a"
 }
 function print_usage
 {
     echo "Usage: $0 [CPU]"
     echo "Example: $0 armv7-a"
     print_supported_cpus
 }
 # 传入CPU参数
 CPU=$1
 if [ -z "$CPU" ]; then
     print_usage
     exit 1
 elif [ "$CPU" = "help" ]; then
     print_usage
 elif [ "$CPU" = "armv7-a" ]; then
     ARCH=arm
     CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
     CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
     SYSROOT=$TOOLCHAIN/sysroot
     CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
     PREFIX=$(pwd)/android/$CPU
     ADDI_LDFLAGS=" "
     OPTIMIZE_CFLAGS="-mfloat-abi=softfp -march=$CPU"
     build_android
 elif [ "$CPU" = "armv8-a" ]; then
     ARCH=arm64
     CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
     CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
     SYSROOT=$TOOLCHAIN/sysroot
     CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
     PREFIX=$(pwd)/android/$CPU
     OPTIMIZE_CFLAGS="-march=$CPU"
     build_android
 else
     echo "Unsupported CPU: $CPU"
     print_supported_cpus
 fi

环境设置

  • TOOLCHAIN: 指向 NDK 中包含的 LLVM 工具链的路径。这个路径用于定位编译工具(如 clang)和系统根目录。
  • API: 设置编译目标的最低 Android API 级别。

    函数定义

    1. build_android

      • 打印正在为特定 CPU 架构编译 FFmpeg。
      • 运行 FFmpeg 的 ./configure 脚本来配置编译选项。
      • 调用 make clean 清理之前的构建结果。
      • 使用 make -j4 启动并行编译过程。
      • 调用 make install 将编译结果安装到指定的前缀路径 $PREFIX。
      • 打印完成编译的消息。
      • print_supported_cpus

        • 打印支持的 CPU 类型。
        • print_usage

          • 打印脚本的使用方法。

    主体逻辑

    • 脚本接收一个参数($1),即 CPU 类型。
    • 根据传入的 CPU 类型,设置相关的编译参数:
      • ARCH: 指定目标架构。
      • CC 和 CXX: 指定 C 和 C++ 编译器。
      • SYSROOT: 设置系统根目录。
      • CROSS_PREFIX: 设置交叉编译工具前缀。
      • PREFIX: 指定安装目录。
      • ADDI_LDFLAGS: 设置额外的链接器标志。
      • OPTIMIZE_CFLAGS: 设置针对特定 CPU 优化的编译标志。
      • 调用 build_android 函数开始编译流程。

        详细配置参数(./configure)

        • --prefix=$PREFIX: 指定安装路径。
        • --enable-neon, --enable-shared, --enable-small: 启用 ARM NEON 指令集支持,生成共享库,优化库大小。
        • --disable-...: 禁用多个功能,如 Vulkan, GPL 功能,文档生成等。
        • --enable-cross-compile: 启用交叉编译模式。
        • --cross-prefix=$CROSS_PREFIX: 设置交叉编译前缀。
        • --target-os=android: 设置目标操作系统为 Android。
        • --arch=$ARCH: 设置目标架构。
        • --cpu=$CPU: 设置目标 CPU。
        • --cc=$CC, --cxx=$CXX: 设置 C 和 C++ 编译器。
        • --sysroot=$SYSROOT: 设置系统根目录。
        • --extra-cflags: 设置额外的编译标志,主要用于性能优化和适应特定硬件。
        • --extra-ldflags: 设置额外的链接标志。

          编译成功之后,在源码目录的android文件夹生成目标CPU的so库和相关的头文件,libavcodec.so libavformat.so libswresample.so libavfilter.so libavutil.so

          NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

          如果需要其他的so 注释掉编译脚本的disable 就能生成对应的其他库

          3.Android项目集成FFmpeg库

          在项目main文件夹新建 ThirdLib文件夹,根据需求添加不同CPU架构下的so库,这里主要是添加了arm64v8-a的库(在ThirdLib文件夹新建arm64-v8a 文件夹,方便与CMakeLists.txt做对应)

          在cpp文件夹新建include文件夹,将FFmpeg头文件放入进去,头文件编译的时候会生成。

          NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

          项目目录层级如上图所示,ThirdLib文件夹与cpp文件夹同一目录,include文件夹与CMakeLists.txt同一目录。如果所有设置都与我一致,就可以直接copy CMakeLists.txt

          接下来就是配置CMakeLists.txt

          引入FFmpeg 头文件,添加FFmpeg相关的库

          # Include directories
          include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
          add_library(avcodec SHARED IMPORTED)
          set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavcodec.so)
          add_library(avfilter SHARED IMPORTED)
          set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavfilter.so)
          add_library(avformat SHARED IMPORTED)
          set_target_properties(avformat PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavformat.so)
          add_library(avutil SHARED IMPORTED)
          set_target_properties(avutil PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libavutil.so)
          add_library(swresample SHARED IMPORTED)
          set_target_properties(swresample PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libswresample.so)
          add_library(swscale SHARED IMPORTED)
          set_target_properties(swscale PROPERTIES IMPORTED_LOCATION
                  ${CMAKE_SOURCE_DIR}/../ThirdLib/arm64-v8a/libswscale.so)
          

          编译的时候链接库, firstjni是我的项目名称,不同项目名称自动生成不同的名字,主要是添加五个库

          #编译链接库
          target_link_libraries( # Specifies the target library.
                  firstjni
                  avcodec
                  avfilter
                  avformat
                  avutil
                  swresample
                  swscale
                  # Links the target library to the log library
                  # included in the NDK.
                  ${log-lib})
          

          4.示例代码,获取FFmpeg版本

          在MainActivity生成JNI函数接口

           public native String getFFMpegVersion();
          

          使用Android Studio自动创建相应的c++实现

          native-lib.cpp 引入FFmpeg头文件

          extern "C"{
          #include 
          }
          

          实现接口,获取FFMpeg当前版本

          extern "C"
          JNIEXPORT jstring JNICALL
          Java_com_marxist_firstjni_MainActivity_getFFMpegVersion(JNIEnv *env, jobject thiz) {
              // TODO: implement getFFMpegVersion()
              const char *ffmpeg_version = av_version_info();
              return env->NewStringUTF(ffmpeg_version);
          }
          

          效果如图: 输出了4.4.4

          NDK R25b 交叉编译FFMpeg4,项目集成,附库下载地址

          5.资源下载

          提供armv7 和 armv8两个版本

          编译平台:NDK R25b

          FFmpeg版本: 4.4.4

          链接:https://pan.baidu.com/s/1PH6bVRv8_0hda-VjesoRyw

          提取码:c0rc

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]