因為畢設項目涉及在安卓手機上處理音視頻胀葱,需要使用OpenCV和FFmpeg庫,所以前段時間一直在找Android如何引入OpenCV和FFmpeg笙蒙,相關(guān)教程在網(wǎng)上可以搜到很多抵屿,但因為教程編寫的時間都很久,很多都存在問題捅位。本文以Opencv-4.5.1和FFmpeg-4.4版本為例轧葛,記錄下Android項目引入兩個音視頻庫的過程。
Opencv-4.5.2
本次教程引入OpenCV的方式:OpenCV Android SDK + OpenCV動態(tài)庫 + JNI(可以同時使用Java和C++進行開發(fā))
開發(fā)環(huán)境:macOS Big Sur-11.2.3 + Android Studio-4.1.2
-
下載相關(guān)工具艇搀。點擊工具欄的SDK Manager尿扯,點擊SDK Tools,選中CMake和NDK(Side by side)焰雕,點擊apply即可下載所需工具
-
新建Android C++工程
-
下載OpenCV-Android-SDK衷笋。下載地址OpenCV Release
-
Android工程引入OpenCV-SDK。點擊 File -> new -> Import Module, 選中 OpenCV-Android-SDK/sdk/java 文件夾矩屁,點擊確定辟宗,就會自動識別處模塊爵赵,導入完成后,會在工程目錄下發(fā)現(xiàn) OpenCV 的庫慢蜓,settings.gradle 文件也會相應改變
-
修改OpenCV庫的SDK版本亚再。點擊 File -> Project Structure- Modules 郭膛,選中OpenCV模塊晨抡,修改SDK版本為你工程對應的SDK版本
APP引入OpenCV依賴。打開app目錄下的build.gradle则剃,添加OpenCV依賴
dependencies {
...
//path后填的之前導入的OpenCV Module名稱
implementation project(path: ':opencv452')
}
此時點擊 File -> Project Structure-Dependencies耘柱,選中app模塊,可以看到已經(jīng)引入opencv452的依賴
-
修改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 目錄下全部內(nèi)容復制到工程目錄/app/src/main/jniLibs 目錄下(jniLibs目錄需要新建)
復制頭文件调煎。將 OpenCV-Android-SDK/sdk/native/jni/include 目錄下全部內(nèi)容復制到 工程目錄/app/libs/include 目錄下
編輯CMakeList.txt。打開/app/src/main/cpp/CMakeLists.txt文件己肮,添加以下內(nèi)容
# 該變量為真時會創(chuàng)建完整版本的Makefile
set(CMAKE_VERBOSE_MAKEFILE on)
#調(diào)用頭文件的具體路徑
include_directories(../../../libs/include)
#增加opencv的動態(tài)庫
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,添加以下內(nèi)容
- 在android {defaultConfig {cmake { … }}}中添加谎僻,具體內(nèi)容見下方代碼
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 {…}中添加娄柳,具體內(nèi)容見下方代碼
//以下為需要添加的代碼
sourceSets {
main {
jni.srcDirs = ['/src/main/cpp']
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
- 初始化OpenCV。
創(chuàng)建BaseApplication或者在MainActivity中初始化艘绍,在onCreate()中調(diào)用
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動態(tài)庫,會極大增加安裝包體積航夺,但好處是可以同時使用Java和C++編程蕉朵,而且使用FFmpeg時也需要使用JNI,此時先引入OpenCV動態(tài)庫阳掐,方便以后FFmpeg的引入始衅。
FFmpeg-4.4
FFmpeg庫需要自己先編譯,再引入安卓項目锚烦。我遇到的最大的問題是編譯FFmpeg的安卓版本觅闽,因為網(wǎng)上的教程主要是使用NDK-20以前的版本進行編譯,而NDK-20前后版本編譯方式有一些差距涮俄,所以一開始總是編譯失敗蛉拙,后來找到一篇文章,按照教程終于編譯成功彻亲。
編譯Android版本的FFmpeg
開發(fā)環(huán)境:macOS Big Sur-11.2.3 + Android Studio-4.1.2 + NDK-r22
使用homebrew安裝yasm孕锄、pkg-config吮廉、gcc
下載FFmpeg和NDK嘹害,官網(wǎng)下載Download FFmpeg和NDK官網(wǎng)下載NDK
在FFmpeg文件夾下新建build_android.sh文件路召,文件內(nèi)容如下
#!/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 ..
}
# 根據(jù)自己需要的 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}/android/$OUTPUT_FOLDER"
# LIB_DIR="${PWD}/android/libs/$OUTPUT_FOLDER"
# OPTIMIZE_CFLAGS="-march=$CPU"
# build_android
# }
# ## armv7-a
# function v7() {
# source "config-env.sh"
# OUTPUT_FOLDER="armeabi-v7a"
# ARCH="arm"
# CPU="armv7-a"
# TOOL_CPU_NAME=armv7a
# TOOL_PREFIX="$TOOLCHAIN/bin/arm-linux-androideabi"
# CC="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang"
# CXX="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++"
# SYSROOT="$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
# PREFIX="${PWD}/android/$OUTPUT_FOLDER"
# LIB_DIR="${PWD}/android/libs/$OUTPUT_FOLDER"
# OPTIMIZE_CFLAGS="-march=$CPU"
# build_android
# }
# ## x86
# function x86() {
# source "config-env.sh"
# OUTPUT_FOLDER="x86"
# ARCH="x86"
# CPU="x86"
# TOOL_CPU_NAME="i686"
# 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}/android/$OUTPUT_FOLDER"
# LIB_DIR="${PWD}/android/libs/$OUTPUT_FOLDER"
# OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
# build_android
# }
## x86_64
function x86_64() {
source "config-env.sh"
OUTPUT_FOLDER="x86_64"
ARCH="x86_64"
CPU="x86-64"
TOOL_CPU_NAME="x86_64"
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}/android/$OUTPUT_FOLDER"
LIB_DIR="${PWD}/android/libs/$OUTPUT_FOLDER"
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
}
# 簡單使用說明
if [ -z $1 ]; then
echo "Usage:"
echo " $0 all"
echo " $0 armv8"
echo " all support cpu :armv7 armv8 x86 x86_64"
exit -1
fi
# 檢測構(gòu)建全部
HAVE_ALL=0
for arg in $@; do
if [ "$arg" == 'all' ]; then
HAVE_ALL=1
fi
done
if [ $HAVE_ALL -eq 1 ]; then
x86
x86_64
v8
v7
exit 0
fi
# 根據(jù)輸入?yún)?shù)檢測構(gòu)建哪種cpu
for arg in $@; do
if [ "$arg" == 'x86' ]; then
x86
fi
if [ "$arg" == 'x86_64' ]; then
x86_64
fi
if [ "$arg" == 'armv8' ]; then
v8
fi
if [ "$arg" == 'armv7' ]; then
v7
fi
done
# 當前NDK版本為r22b, ffmpeg版本為4.4
# 在原作者基礎上有修改
# 1\. API等級是30
# 2\. 4.4 版本并不需要手動修改ffmpeg的configure文件,因為打出來的so文件是沒有版本號的
# 3\. ffmpeg 目錄結(jié)構(gòu)有修改, 所以有一個cd的過程
# 目錄結(jié)構(gòu)
# tree -L 1
# .
# ├── android # 輸出目錄
# ├── build_ffmpeg_android.sh # 腳本
# ├── config-env.sh # 選項
# └── ffmpeg-4.3.1 # ffmpeg 目錄
# 編譯選項可以使用 ./configure -h 查看, 可以根據(jù)自己的需求開啟或關(guān)閉編解碼支持, 會顯著降低so大小
# 本選項編譯出的文件文件尺寸如下:
# ll android/libs/arm64-v8a
# total 11624
# -rwxr-xr-x 1 caijinglong staff 3.9M 7 26 16:28 libavcodec.so
# -rwxr-xr-x 1 caijinglong staff 106K 7 26 16:28 libavfilter.so
# -rwxr-xr-x 1 caijinglong staff 771K 7 26 16:28 libavformat.so
# -rwxr-xr-x 1 caijinglong staff 443K 7 26 16:28 libavutil.so
# -rwxr-xr-x 1 caijinglong staff 82K 7 26 16:28 libswresample.so
# -rwxr-xr-x 1 caijinglong staff 398K 7 26 16:28 libswscale.so
# 如果想要和ijkplayer那樣將所有so合并為一個libffmpeg.so庫,可以看下面的說明
# 說是合并,實際上so是不支持合并的, 需要編譯出.a靜態(tài)庫而不是so動態(tài)庫, 然后將多個靜態(tài)庫合并為一個so, 然后用TOOLCHAIN中的gcc命令進行合并
# gcc -shared -o -Wl --whole-archive avcodec.a avfilter.a other.a -Wl,--no-whole-archive
- 在FFmpeg文件夾下新建config-env.sh文件往毡,這個環(huán)境是 ijkplayer 的 ffmpeg 配置奖年,文件內(nèi)容如下
#! /usr/bin/env bash
# shell/config.sh
# 這個來自ijkplayer的ffmpeg配置, 會在上面的build腳本中被引入
#--------------------
# Standard options:
export COMMON_FF_CFG_FLAGS=
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --prefix=PREFIX"
# Licensing options:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gpl"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-version3"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-nonfree"
# Configuration options:
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-static"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-shared"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-small"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-runtime-cpudetect"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-gray"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-swscale-alpha"
# Program options:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-programs"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffmpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffplay"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffprobe"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver"
# Documentation options:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-doc"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-htmlpages"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-manpages"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-podpages"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-txtpages"
# Component options:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avdevice"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avcodec"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avformat"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avutil"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swresample"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swscale"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-postproc"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avfilter"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avresample"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-pthreads"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-w32threads"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-os2threads"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-network"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dct"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dwt"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-lsp"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-lzo"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mdct"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-rdft"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fft"
# Hardware accelerators:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-d3d11va"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dxva2"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vaapi"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vdpau"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-videotoolbox"
# Individual component options:
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-everything"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-encoders"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-encoder=png"
# ./configure --list-decoders
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-decoders"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=aac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=aac_latm"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=flv"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h264"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mp3*"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp6f"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=flac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=hevc"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp8"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=vp9"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263i"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=h263p"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mpeg4"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-hwaccels"
# ./configure --list-muxers
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-muxers"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-muxer=mp4"
# ./configure --list-demuxers
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-demuxers"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=aac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=concat"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=data"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=flv"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=hls"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=live_flv"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mov"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mp3"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegps"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegts"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpegvideo"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=flac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=hevc"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=webm_dash_manifest"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mpeg4"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=avi"
# ./configure --list-parsers
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-parsers"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=aac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=aac_latm"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=h264"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=flac"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=hevc"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpeg4"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpeg4video"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parser=mpegvideo"
# ./configure --list-bsf
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-bsfs"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=chomp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=dca_core"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=dump_extradata"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=hevc_mp4toannexb"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=imx_dump_header"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mjpeg2jpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mjpega_dump_header"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mov2textsub"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mp3_header_decompress"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=mpeg4_unpack_bframes"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=noise"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=remove_extradata"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=text2movsub"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=vp9_superframe"
# ./configure --list-protocols
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocols"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=async"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=bluray"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=concat"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=crypto"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=ffrtmpcrypt"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=ffrtmphttp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=gopher"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=icecast"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=librtmp*"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=libssh"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=md5"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=mmsh"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=mmst"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtmp*"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtmp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtmpt"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=sctp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=srtp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=subfile"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=unix"
#
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-devices"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-filters"
# External library support:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-iconv"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-audiotoolbox"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-videotoolbox"
# ...
# Advanced options (experts only):
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cross-prefix=${FF_CROSS_PREFIX}-"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-cross-compile"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --sysroot=PATH"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --sysinclude=PATH"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-os=TAGET_OS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-exec=CMD"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --target-path=DIR"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --toolchain=NAME"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --nm=NM"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --ar=AR"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --as=AS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --yasmexe=EXE"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cc=CC"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cxx=CXX"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --dep-cc=DEPCC"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --ld=LD"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cc=HOSTCC"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cflags=HCFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-cppflags=HCPPFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-ld=HOSTLD"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-ldflags=HLDFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-libs=HLIBS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --host-os=OS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-cflags=ECFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-cxxflags=ECFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-ldflags=ELDFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-libs=ELIBS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --extra-version=STRING"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --optflags=OPTFLAGS"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --build-suffix=SUFFIX"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --malloc-prefix=PREFIX"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --progs-suffix=SUFFIX"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --arch=ARCH"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --cpu=CPU"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-pic"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-sram"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-thumb"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-symver"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-hardcoded-tables"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-safe-bitstream-reader"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-memalign-hack"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-lto"
# Optimization options (experts only):
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-asm"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-altivec"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-amd3dnow"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-amd3dnowext"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mmx"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mmxext"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse2"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse3"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ssse3"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse4"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-sse42"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avx"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fma4"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv5te"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv6"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-armv6t2"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vfp"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-neon"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vis"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-inline-asm"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-yasm"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mips32r2"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsdspr1"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsdspr2"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-mipsfpu"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-fast-unaligned"
# Developer options (useful when working on FFmpeg itself):
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-coverage"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-debug"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-debug=LEVEL"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-optimizations"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-extra-warnings"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-stripping"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --assert-level=level"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-memory-poisoning"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --valgrind=VALGRIND"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-ftrapv"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --samples=PATH"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-xmm-clobber-test"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-random"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-random"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-random=LIST"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-random=LIST"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --random-seed=VALUE"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bzlib"
-
從終端進入FFmpeg文件目錄搭幻,執(zhí)行腳本
chmod +x build_android.sh
修改腳本執(zhí)行權(quán)限./build_android.sh all
運行腳本編譯過程中會提示clang等執(zhí)行軟件不安全堪藐,在Mac的設置-安全性與隱私-通用選項中點擊允許即可
編譯完成后旭咽,在FFmpeg文件夾中會生成一個android文件夾幼苛,其中.so文件就是編譯好的庫
Android工程引入FFmpeg
新建C++項目或者使用上文OpenCV項目
將FFmpeg文件夾中的android/libs對應CPU型號的.so文件大咱,復制到安卓工程app/src/main/jniLibs/對應CPU型號的文件夾內(nèi)
-
修改build.gradle文件
- 在android {defaultConfig {cmake { … }}}中添加恬涧,具體內(nèi)容見下方代碼
defaultConfig {
applicationId "com.bupt.compose3dvideo"
minSdkVersion 25
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
//以下為需要添加的代碼
//可選 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
abiFilters 'x86', 'armeabi-v7a'
}
}
}
- 在android {…}中添加,具體內(nèi)容見下方代碼
//以下為需要添加的代碼
sourceSets {
main {
jni.srcDirs = ['/src/main/cpp']
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
- 編輯CMakeList.txt碴巾。打開/app/src/main/cpp/CMakeLists.txt文件溯捆,添加以下內(nèi)容
add_library(avcodec
SHARED
IMPORTED)
# 注意,IMPORTED_LOCATION是引入.so文件的路徑厦瓢,此路經(jīng)必須正確
set_target_properties(avcodec
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavcodec.so)
add_library(avformat
SHARED
IMPORTED)
set_target_properties(avformat
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavformat.so)
add_library(avutil
SHARED
IMPORTED)
set_target_properties(avutil
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavutil.so)
add_library(swresample
SHARED
IMPORTED)
set_target_properties(swresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswresample.so)
add_library(swscale
SHARED
IMPORTED)
set_target_properties(swscale
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswscale.so)
add_library(avfilter
SHARED
IMPORTED)
set_target_properties(avfilter
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavfilter.so)
- 在com/bupt/opencvandffmpeg目錄下新建jni文件夾提揍,新建FFmpegCmd類,實現(xiàn)FFmpeg函數(shù)的調(diào)用煮仇,類內(nèi)容如下:
object FFmpegCmd {
private external fun run(cmdLen: Int, cmd: Array<String>): Int
external fun test(): String?
fun run(cmd: Array<String>): Int {
return run(cmd.size, cmd)
}
init {
System.loadLibrary("avutil")
System.loadLibrary("avcodec")
System.loadLibrary("swresample")
System.loadLibrary("avformat")
System.loadLibrary("swscale")
System.loadLibrary("avfilter")
}
}
之后就可以調(diào)用FFmpegCmd類中的函數(shù)劳跃。
// 這里記錄一下普通JNI使用方式:
// 1\. 在 Java 層編寫 native 方法
// 2\. 使用 javah -jni 生成本地接口
// 3\. 在 C++ 層實現(xiàn)接口
// 4\. 在 Java 層調(diào)用 native 方法
總結(jié)
雖然成功引入了Opencv和FFmpeg庫,但是仍存在很多問題欺抗,首先就是引入庫文件后導致安裝包體積過大的問題售碳,以后有待優(yōu)化;其次是安卓JNI的使用問題绞呈,因為是使用C++編程贸人,對于C++我還不是很熟悉,需要繼續(xù)學習佃声。
在成功引入Opencv和FFmpeg庫之前艺智,每次遇到error都讓我很焦躁,因為覺得按照網(wǎng)上教程的步驟來一定會成功圾亏,然而不斷的error讓我有想砸鼠標的沖動十拣,幸好在查找資料、學習進步的過程中不斷積累經(jīng)驗志鹃,總結(jié)之前失敗的原因夭问,最終成功引入Opencv和FFmpeg庫,所以寫下這邊文章以記錄自己成功的經(jīng)驗曹铃$智鳎總結(jié)的經(jīng)驗就是一定要耐心查找資料,而且要了解這些開源庫各版本之間編譯或者使用的區(qū)別,如果遇到編譯error秘血,可以直接復制error信息上網(wǎng)查找解決方案味抖,一步一步來最后終會成功!
參考資料: