編譯前準備
編譯環境:Ubuntu16,可自行下載VMWare最新版并百度永久許可證或在服務器上安裝Ubuntu
ffmpeg源碼:ffmpeg4.2.2
NDK下載:Android NDK r21e
有條件的最好還是在Liunx平臺下編譯吧,Windows平臺下編譯坑更多,文章末尾有Github源碼可自取
開始編譯
1.解壓NDK,執行?unzip android-ndk-r21e-liunx-x86_64.zip
如果提示沒有unzip,執行此命令安裝?sudo apt-get install unzip
2.解壓ffmepg,tar -xvjf ffmpeg-4.2.2.tar.bz2
3.進入ffmpeg4.2.2目錄,修改根目錄下的 configure 文件
搜索?LIB_INSTALL_EXTRA_CMD
?
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
替換為
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
此步驟主要是將so命名為Android通用的so名稱
4.在ffmpeg下創建文件android_build.sh腳本文件,此腳本文件用于配置、執行編譯,根據需求進行配置,網上的配置均有不同,以實際需要為準,將以下代碼copy到android_build.sh腳本文件中,執行?sudo sh android_build.sh
?
#!/bin/bash
API=21
#arm64 x86 x86_64 <----> aarch64 i686 x86_64
ARCH=arm64
ARCH2=aarch64
PREFIX=../out-ffmpeg/$ARCH
#此處路徑替換為當前NDK路徑
TOOLCHAIN=/home/jiang/ffmpeg/android-ndk-r21e-linux-x86_64/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64build()
{#配置各個文件開關及NDK路徑等./configure \--prefix=$PREFIX \--disable-static \--enable-shared \--enable-small \--enable-gpl \--disable-doc \--disable-programs \--disable-avdevice \--enable-cross-compile \--target-os=android \--arch=$ARCH \--cc=$TOOLCHAIN/bin/$ARCH2-linux-android$API-clang \--cross-prefix=$TOOLCHAIN/bin/$ARCH2-linux-android-#清除上次編譯make cleanmake -j4make install
}
#開始編譯
build
android_build.sh腳本文件自取
注:如果編譯過程中出現錯誤(一般是在開頭會有紅色報錯),部分需要安裝其他庫,具體可查閱
5.編譯后會在ffmpeg4.2.2同級目錄下生成out-ffmpeg文件,將out-ffmpeg導出到項目中
Android Studio配置
1.新建一個C++項目
- 將編譯完成后的include頭文件導入到cpp文件中
- 將編譯完成后的lib庫文件導入到libs中
2.配置build.gradle文件
defaultConfig下增加
externalNativeBuild {cmake {cppFlags '-frtti -fexceptions'abiFilters "arm64-v8a","armeabi-v7a"}}
abiFilters是指定當前項目所支持的CPU架構,一般來說有arm64-v8a(arm64位)、armeabi-v7a(arm32位)足夠,大部分手機都是這兩種架構之一,要完全兼容可能會導致APP體積增大
注意:如果你的Gradler版本足夠高(大約>5.6.4),無須配置以下項,否則有可能報錯
?
sourceSets {main {jniLibs.srcDirs = ["libs"]}
}
【免費分享】音視頻學習資料包、大廠面試題、技術視頻和學習路線圖,資料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以點擊788280672加群免費領取~
3.配置CMake
由于android早已支持CMake,所以舊的android.mk配置此處不增加
#聲明cmake版本號
cmake_minimum_required(VERSION 3.10.2)#此處導入頭文件目錄
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)#將so庫文件路徑賦值ffmpeg_lib_dir,方便操作
set(ffmpeg_lib_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${ANDROID_ABI})#項目名稱
project("newffmpeg")add_library( newffmpegSHAREDnative-lib.cpp)#初始化log庫
find_library( log-liblog)#江指定的源文件生成鏈接文件
add_library( avutilSHAREDIMPORTED )set_target_properties( avutilPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavutil.so )add_library( swresampleSHAREDIMPORTED )
set_target_properties( swresamplePROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libswresample.so )add_library( avcodecSHAREDIMPORTED )
set_target_properties( avcodecPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavcodec.so )add_library( avfilterSHAREDIMPORTED)
set_target_properties( avfilterPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavfilter.so )add_library( swscaleSHAREDIMPORTED)
set_target_properties( swscalePROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libswscale.so )add_library( avformatSHAREDIMPORTED)
set_target_properties( avformatPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libavformat.so )add_library( postprocSHAREDIMPORTED)
set_target_properties( postprocPROPERTIES IMPORTED_LOCATION${ffmpeg_lib_dir}/libpostproc.so )#將目標文件與庫文件進行鏈接
target_link_libraries( # Specifies the target library.newffmpegavutilswresampleavcodecavfilterswscaleavformatpostproc${log-lib})
若未能鏈接到庫文件,則檢查路徑是否正常(點擊libs路徑左側菜單能正常展開說明路徑正確)
4.測試ffmpeg
在native-lib.cpp中增加或替換代碼,注意JNI路徑替換為你的包名路徑或方法,在Java中調用,如能正常打印出配置信息,說明編譯及導入完成
?
#include <jni.h>
#include <string>
#include <unistd.h>extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavcodec/jni.h>JNIEXPORT jstring JNICALL
Java_cn_jin_newffmpeg_MainActivity_getConfigurations(JNIEnv *env,jobject /* this */) {return env->NewStringUTF(avcodec_configuration());
}
}
遇到的問題
2 files found with path 'lib/arm64-v8a/libavcodec.so' from inputs:
2 files found with path 'lib/arm64-v8a/libavcodec.so' from inputs:- D:\ffmpeg\project\NewFFmpeg\app\build\intermediates\merged_jni_libs\debug\out\arm64-v8a\libavcodec.so- D:\ffmpeg\project\NewFFmpeg\app\build\intermediates\cxx\Debug\2xk41543\obj\arm64-v8a\libavcodec.so
If you are using jniLibs and CMake IMPORTED targets, see
https://developer.android.com/r/tools/jniLibs-vs-imported-targets
解決辦法:此處是由于在build.gradle中配置了jniLibs.srcDirs導致的文件沖突,gradle高版本已經不需要手動指定so庫的路徑,刪除即可
D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so: error adding symbols: File in wrong format clang++: error: linker command failed with exit code 1 (use -v to see invocation)
?
[1/1] Linking CXX shared library D:\ffmpeg\project\FFmpegProject\app\build\intermediates\cxx\Debug\2c676z6h\obj\arm64-v8a\libffmpeg.so
FAILED: D:/ffmpeg/project/FFmpegProject/app/build/intermediates/cxx/Debug/2c676z6h/obj/arm64-v8a/libffmpeg.so
cmd.exe /C "cd . && C:\Users\as230\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android21 --gcc-toolchain=C:/Users/as230/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/as230/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libffmpeg.so -o D:\ffmpeg\project\FFmpegProject\app\build\intermediates\cxx\Debug\2c676z6h\obj\arm64-v8a\libffmpeg.so CMakeFiles/ffmpeg.dir/native-lib.cpp.o -llog D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavfilter.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavformat.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavutil.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libpostproc.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libswresample.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libswscale.so -latomic -lm && cd ."
D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so: error adding symbols: File in wrong format
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
出現動態庫中的問題導致鏈接器命令失敗大概率是兩個原因
- 編譯出來的so有問題,此時不要嘗試,可下載其他已經編譯好的so進行替換,如其他可正常運行則已經說明
- so庫中依賴其他庫文件,其他庫文件未導入或者已導入未進行鏈接,此時應該檢查一下cmake
java.lang.UnsatisfiedLinkError: dlopen failed: library “libxxx.so” not found
此處錯誤是在運行之后出現的,原因是某些已經使用的庫文件沒有鏈接上,應該檢查一下libs和cmkae,基本上能解決
源碼
ffmpeg for android源碼
原文鏈接?ffmpeg for android編譯全過程與遇到的問題