因为毕设项目涉及在安卓手机上处理音视频,需要使用OpenCV和FFmpeg库,所以前段时间一直在找Android如何引入OpenCV和FFmpeg,相关教程在网上可以搜到很多,但因为教程编写的时间都很久,很多都存在问题。本文以Opencv-4.5.1和FFmpeg-4.4版本为例,记录下Android项目引入两个音视频库的过程。
Opencv-4.5.2
本次教程引入OpenCV的方式:OpenCV Android SDK + OpenCV动态库 + JNI(可以同时使用Java和C++进行开发)
开发环境:macOS Big Sur-11.2.3 + Android Studio-4.1.2
- 下载相关工具。点击工具栏的SDK Manager,点击SDK Tools,选中CMake和NDK(Side by side),点击apply即可下载所需工具
![](https://i-blog.csdnimg.cn/blog_migrate/ea6e46764ab032be94753d6eebfe33f4.png)
新建Android C++工程
![](https://i-blog.csdnimg.cn/blog_migrate/0ae375fa1c704607dd0bb5f81bbe3784.png)
下载OpenCV-Android-SDK。下载地址OpenCV Release
![](https://i-blog.csdnimg.cn/blog_migrate/e74240bc3cc3d71ac642b3ee204068b3.png)
Android工程引入OpenCV-SDK。点击 File -> new -> Import Module, 选中 OpenCV-Android-SDK/sdk/java 文件夹,点击确定,就会自动识别处模块,导入完成后,会在工程目录下发现 OpenCV 的库,settings.gradle 文件也会相应改变
修改OpenCV库的SDK版本。点击 File -> Project Structure- Modules ,选中OpenCV模块,修改SDK版本为你工程对应的SDK版本
![](https://i-blog.csdnimg.cn/blog_migrate/2d4906debf10bf5e5c5103442da241c9.png)
APP引入OpenCV依赖。打开app目录下的build.gradle,添加OpenCV依赖
dependencies {
...
//path后填的之前导入的OpenCV Module名称
implementation project(path: ':opencv452')
}
此时点击 File -> Project Structure-Dependencies,选中app模块,可以看到已经引入opencv452的依赖
![](https://i-blog.csdnimg.cn/blog_migrate/ea4f16e032f9c251110cc99630b996f3.png)
修改Opencv模块中的build.gradle设置。
- 首行的
apply plugin: ‘com.android.application’
修改为apply plugin: ‘com.android.library’
- 去掉
defaultConfig {
applicationId "org.opencv"
}
最后Opencv模块中的build.gradle如下图所示:
将 OpenCV-Android-SDK/sdk/native/libs 目录下全部内容复制到工程目录/app/src/main/jniLibs 目录下(jniLibs目录需要新建)
复制头文件。将 OpenCV-Android-SDK/sdk/native/jni/include 目录下全部内容复制到 工程目录/app/libs/include 目录下
编辑CMakeList.txt。打开/app/src/main/cpp/CMakeLists.txt文件,添加以下内容
# 该变量为真时会创建完整版本的Makefile
set(CMAKE_VERBOSE_MAKEFILE on)
#调用头文件的具体路径
include_directories(../../../libs/include)
#增加opencv的动态库
add_library(opencv_lib SHARED IMPORTED)
#建立链接, IMPORTED_LOCATION 后跟的是jniLibs的相对路径
set_target_properties(opencv_lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java4.so)
修改build.gradle。修改app模块下的build.gradle,添加以下内容
- 在android {defaultConfig {cmake { … }}}中添加,具体内容见下方代码
defaultConfig {
applicationId "com.bupt.compose3dvideo"
minSdkVersion 25
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
//以下为需要添加的代码
arguments "-DANDROID_STL=c++_shared"
//可选 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
abiFilters 'x86', 'armeabi-v7a'
}
}
}
在android {…}中添加,具体内容见下方代码
//以下为需要添加的代码
sourceSets {
main {
jni.srcDirs = ['/src/main/cpp']
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
初始化OpenCV。
- 创建BaseApplication或者在MainActivity中初始化,在onCreate()中调用
OpenCVLoader.initDebug()
即可初始化OpenCV - 如果在BaseApplication中初始化,需要手动添加以下代码,MainActivity中已存在,不需手动添加
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
以上就是引入Opencv库的全部步骤,因为同时引入了OpenCV-Android-SDK和OpenCV动态库,会极大增加安装包体积,但好处是可以同时使用Java和C++编程,而且使用FFmpeg时也需要使用JNI,此时先引入OpenCV动态库,方便以后FFmpeg的引入。
FFmpeg-4.4
FFmpeg库需要自己先编译,再引入安卓项目。我遇到的最大的问题是编译FFmpeg的安卓版本,因为网上的教程主要是使用NDK-20以前的版本进行编译,而NDK-20前后版本编译方式有一些差距,所以一开始总是编译失败,后来找到一篇文章,按照教程终于编译成功。
编译Android版本的FFmpeg
开发环境:macOS Big Sur-11.2.3 + Android Studio-4.1.2 + NDK-r22
- 使用homebrew安装yasm、pkg-config、gcc
- 下载FFmpeg和NDK,官网下载Download FFmpeg和NDK官网下载NDK
- 在FFmpeg文件夹下新建build_android.sh文件,文件内容如下
#!/bin/bash
# 修改为你本地NDK目录
NDK=/Users/xxx/android-ndk-r22b
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
API=30
function build_android() {
cd ffmpeg-4.4
echo "Compiling FFmpeg for $CPU"
./configure \
--prefix=$PREFIX \
--libdir=$LIB_DIR \
--enable-shared \
--disable-static \
--enable-jni \
--disable-doc \
--disable-symver \
--disable-programs \
--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" \
--disable-asm \
$COMMON_FF_CFG_FLAGS
make clean
make -j8
make install
echo "The Compilation of FFmpeg for $CPU is completed"
echo "Output library : $LIB_DIR"
cd ..
}
# 根据自己需要的 cpu, 放开对应的注释即可
# ## armv8-a
# function v8() {
# source "config-env.sh"
# OUTPUT_FOLDER="arm64-v8a"
# ARCH=arm64
# CPU="armv8-a"
# TOOL_CPU_NAME=aarch64
# TOOL_PREFIX="$TOOLCHAIN/bin/$TOOL_CPU_NAME-linux-android"
# CC="$TOOL_PREFIX$API-clang"
# CXX="$TOOL_PREFIX$API-clang++"
# SYSROOT="$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
# PREFIX="${PWD}