準備工具
- Android開發工具AS(需要下載NDK)
- ffmpeg交叉編譯後的動態庫或靜態庫以及標頭檔案
如果你不知道如何編譯ffmpeg請看這篇文章
NDKr20使用clang編譯ffmpeg4.2.2
接入步驟
新建Native C++工程並引入標頭檔案和動態庫:
編寫CMakeLists.txt檔案:
cmake_minimum_required(VERSION 3.4.1)
# 引入FFmpeg的標頭檔案
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
# 方式一
# 引入FFmpeg的庫檔案,設定內部的方式引入,指定庫的目錄是 -L 指定具體的庫-l
# 這種方式方便快捷
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}")
# 方式二
#設定ffmpeg庫所在路徑的變數
#set(FF ${CMAKE_SOURCE_DIR}/${CMAKE_ANDROID_ARCH_ABI})
#add_library(avcodec SHARED IMPORTED)
#set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so)
#
#add_library(avformat SHARED IMPORTED)
#set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FF}/libavformat.so)
#
#add_library(avutil SHARED IMPORTED)
#set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FF}/libavutil.so)
#
#add_library(swscale SHARED IMPORTED)
#set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${FF}/libswscale.so)
#
#add_library(swresample SHARED IMPORTED)
#set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${FF}/libswresample.so)
#
#add_library(avfilter SHARED IMPORTED)
#set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${FF}/libavfilter.so)
#找到包含所有的cpp檔案
file(GLOB allCpp src/main/cpp/*.*)
add_library(
# 生成的庫的名字
flyffmpeg-lib
# 動態庫
SHARED
# 原始檔
${allCpp} )
target_link_libraries( #目標庫
flyffmpeg-lib
# 把ffmpeg的動態庫以來進來
avformat
avcodec
avutil
avfilter
swscale
swresample
# NDK中的log庫
log )
複製程式碼
相關注釋都已經寫的很清楚了,這裡就不再多解析了。ffmpeg就引入進去後,下面我編寫一個簡答的程式碼呼叫一下ffmpeg的相關api測試下是否能正常呼叫。
新建一個native方法獲取ffmpeg的版本號:
public native static String getFFmpegVersion();
複製程式碼
jni相關程式碼:
#include <jni.h>
#include <string>
// 因為ffmpeg是純C程式碼,要在cpp中使用則需要使用 extern "C"
extern "C" {
#include "libavutil/avutil.h"
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_flyer_ffmpeg_FFmpegUtils_getFFmpegVersion(JNIEnv *env, jclass clazz) {
//通過av_version_info()獲取版本號
return env -> NewStringUTF(av_version_info());
}
複製程式碼
通過TextView顯示一下獲取到的版本號:
遇到的問題
- 報錯ffmpeg的相關庫沒有找到
解決方法:檢查你專案的CMakeLists.txt
中的ffmpeg相關庫有沒有正確連結;
檢查build.gradle
中有沒有配置好將相關so打包進去apk的配置:
sourceSets {
main {
//將依賴庫打進apk,否則可能出現找不到庫
jniLibs.srcDirs = ['libs']
}
}
複製程式碼
- 報自定義封裝的so庫找不到
解決方法: 檢查
build.gradle
中是否設定了abiFilters
筆者的環境實驗發現在cmake中設定abiFilters無效,依然會報so無法找到的錯誤,但是在ndk中設定則正常;
externalNativeBuild(){
cmake{
// 為什麼在這裡指定編譯架構會報so庫找不到的錯誤,而在ndk中指定則不會???
// abiFilters "armeabi-v7a" //指定編譯為 armeabi-v7a
}
ndk {
abiFilters "armeabi-v7a"
}
}
複製程式碼
最後如果你對音視訊開發感興趣可掃碼關注,後續我們共同探討,共同進步。