ffmpeg 编译 Android 动态库,静态库
1. 环境
-
编译系统环境
-
win10 自带Ubuntu 子系统(linux)
-
执行如下命令安装 一些工具
-
apt-get install yasm apt-get install nasm apt-get install pkg-config
-
-
-
ndk版本 r20b
-
下载 android-ndk-r20b-linux-x86_64.zip
-
# 1 执行scp命令 将下载下来的ndk 文件复制到 linux 子系统中 比如我安装再子系统的/usr/bin位置 scp -r [/mnt/ndk路径] [要放在linux子系统中的位置] # 2 执行unzip 来解压 ndkzip unzip android-ndk-r20b-windows-x86_64.zip # 3 配置 ndk路径 执行如下命令 vim /etc/profile # 打开配置文件 按i 进入编辑模式 # 4 在文件最后配置path处 添加ndk配置 按ESC 输入:WQ 保存并退出 export NDK=/usr/bin/android-ndk-r20b export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$NDK:$PATH # 5 执行如下命令 立即 更新配置 source /etc/profile
-
-
可选最新ndk版本 在配置文件中注意对应路径即可(比如r17b 之后不支持mips 等区别)
-
-
ffmpeg 版本 4.0.2
-
-
# 如上述ndk # 1 scp 命令 复制 ffmpeg 到 linux 子系统 scp -r [/mnt/ffmpeg存在windows目录] [要放在linux子系统中的位置] # 2 执行tar 解压缩命令 解压ffmpeg 压缩包 tar -jxvf ffmpeg-4.2.2.tar.bz2 # 3 cd 命令进入到ffmpeg 目录下 cd [ffmpeg 路径] # 执行 如下命令 生成一些编译时需要的文件 ./configure --disable-x86asm
-
-
当然可官网选最新版本或者稳定版
-
2 编译ffmpeg
-
编写 编译脚本
build_ffmpeg.sh
内容如下-
#!/bin/bash export NDK=/usr/bin/android-ndk-r20b #这里配置先你的 NDK 路径 TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64 function build_android { ./configure \ --prefix=$PREFIX \ --enable-neon \ --enable-hwaccels \ --enable-gpl \ --disable-postproc \ --disable-debug \ --enable-small \ --enable-jni \ --enable-mediacodec \ --enable-decoder=h264_mediacodec \ --enable-static \ --enable-shared \ --disable-doc \ --enable-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 $OPTIMIZE_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" make clean make -j16 make install echo "============================ build android arm64-v8a success ==========================" } #arm64-v8a -> arm64-v8a ARCH=arm64 CPU=armv8-a API=21 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 -> armeabi-v7a # ARCH=arm # CPU=armv7-a # API=21 # 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 #i686 -> x86 # ARCH=x86 # CPU=i686 # API=21 # 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 -mno-stackrealign" # build_android # #x86-64 -> x86-64 # ARCH=x86_64 # CPU=x86_64 # API=21 # 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=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel" # build_android #armv5-a ->armeabi r20b ndk 里没有armv5 # ARCH=arm # CPU=armv5te # API=21 # CC=$TOOLCHAIN/bin/armv-linux-androideabi$API-clang # CXX=$TOOLCHAIN/bin/armv-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="-march=$CPU" # build_android
-
--enable-static \ # 编译静态库 --enable-shared \ # 编译动态库 我们这里都编译 PREFIX=$(pwd)/android/$CPU # 输出路径 当前目录下android 以cpu为子文件夹的位置
-
-
执行scp 命令将
build_ffmpeg.sh
复制到linux子系统中ffmpeg安装目录下-
执行 如下命令开始编译 等待编译结束即可
-
./buildFfmpeg
-
编译结束后会在当前目录的android目录下根据cpu架构生成的目录
- 其中
include
下 为头文件 -
lib
下为编译好的库
- 其中
-
-
3.导入android项目中使用
由于ffmpeg 是c,c++ 编译的要使用 我们需要使用ndk 所以新建项目需要支持 native 这里我们打印下版本号 ----- 步骤如下
-
新建支android项目 player Phone and table 中选择 Native c++
-
将main->cpp 目录下的CMakeLists.txt 文件复制到 main 目录下
- 这一步是方便CMakeLists.txt 中设置库路径
-
将第二步编译好的include文件夹复制到cpp目录下
- 这一步将头文件复制到项目中
-
main 目录下新建jniLibs 将 对应架构的ffmpeg 的 静态文件 复制到该文件夹下
- 导入静态库
-
配置cmake
-
指定头文件路径
-
指定静态库路径
-
连接静态库
-
具体配置文件如下
-
cmake_minimum_required(VERSION 3.10.2) # Declares and names the project. set(CMAKE_VERBOSE_MAKEFILE on) project("player") add_library( # Sets the name of the library. player # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). cpp/native-lib.cpp) # 引入当前头文件 include_directories(${CMAKE_SOURCE_DIR}/cpp/include) #打印当前 cmakeLists 的路径 message("当前cmakel路径: ${CMAKE_SOURCE_DIR} \n cpu架构:${CMAKE_ANDROID_ARCH_ABI}") #设置C++ 编译 -L 设置库路径 -L设置的路径与下面的link_directories 应该类似 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}") #指定静态库或动态库的搜索路径 该指令的作用主要是指定要链接的库文件的路径 # 自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。 link_directories( ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI} ) find_library( log-lib log) #将指定的静态库连接到可执行文件上 target_link_libraries( player avformat avcodec avfilter avutil swresample swscale ${log-lib})
-
-
在MainActivity中声明native函数
-
public native String stringFromJNI();
-
-
在native-lib.cpp中实现
-
#include <jni.h> #include <string> //由于 FFmpeg 库是 C 语言实现的,我们这里是c++文件,所以要告诉编译器按照 C 的规则进行编译 //导入 version头文件 extern "C" { #include "libavformat/version.h" } extern "C" JNIEXPORT jstring JNICALL Java_com_example_player_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; // 读取version return env->NewStringUTF(AV_STRINGIFY(LIBAVFORMAT_VERSION)); }
-
-
在MainActivity 中调用
-
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // 调用native 方法获取版本信息 TextView tv = binding.sampleText; tv.setText(stringFromJNI()); }
-
-
图就不加了 代码库在下面的连接里
- 代码地址
- 参考 https://www.jianshu.com/p/0792f6bbc9f6