目錄
1.編譯FFmpeg
2.集成到Android Studio
3.遇到的問題
最近項(xiàng)目中用到了視頻播放唯竹,由于Android平臺(tái)硬編解碼存在兼容性問題据德,對不支持3k視頻編解碼的手機(jī)采用軟編碼,因?yàn)橛玫搅薴fmpeg亲善。雖然github上有很多好的視頻相關(guān)的庫,但是開源項(xiàng)目的功能都很多,我們只是用到一部分功能而已犯建,畢竟不是專門做視頻播放器。使用開源的話瓜客,會(huì)引入不必要的資源适瓦。本文主要講將在Mac上編譯ffmpeg生成對應(yīng)的so文件,并引入Android Studio簡單開發(fā)以及記錄過程中遇到的錯(cuò)誤和解決的辦法谱仪。
一.編譯FFmpeg
1.官網(wǎng)下載ffmpeg
最新版本3.4.2(我自己編譯的是3.0.11版本)
2.更改configure文件
默認(rèn)配置文件玻熙,編譯生成的版本號會(huì)加在so的后面,導(dǎo)致Android不能識(shí)別疯攒,雖有我們要去掉后面的版本號
將下載的文件ffmpeg壓縮包解壓到自己要操作的文件目錄嗦随,進(jìn)入一級目錄對configure文件進(jìn)行修改。
將
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)'
3.編寫腳本文件
在一級子目錄下創(chuàng)建build_android.sh腳本文件敬尺,這里的腳本配置armeabi-v7a,arm64-v8a,armeabi,x86_64共4個(gè)平臺(tái)枚尼,可以根據(jù)自己的需要做相應(yīng)的改動(dòng);內(nèi)容如下:
# ndk環(huán)境
export NDK=/Users/fj/Downloads/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-21/arch-arm
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PREFIX=android-build
COMMON_OPTIONS="\
--prefix=android/ \
--target-os=android \ # 指定Android平臺(tái)
--disable-static \
--enable-shared \
--enable-small \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--enable-avresample \
--disable-symver \
--disable-asm \
--disable-armv5te \
"
function build_android {
#armeabi平臺(tái)
./configure \
--libdir=${PREFIX}/libs/armeabi \
--incdir=${PREFIX}/includes/armeabi \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi \
--arch=arm \
--cpu=armv6 \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
#armeabi-v7a平臺(tái)
./configure \
--libdir=${PREFIX}/libs/armeabi-v7a \
--incdir=${PREFIX}/includes/armeabi-v7a \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
#arm64-v8a
./configure \
--libdir=${PREFIX}/libs/arm64-v8a \
--incdir=${PREFIX}/includes/arm64-v8a \
--pkgconfigdir=${PREFIX}/pkgconfig/arm64-v8a \
--arch=aarch64 \
--cpu=armv8-a \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
#armeabi
./configure \
--libdir=${PREFIX}/libs/x86 \
--incdir=${PREFIX}/includes/x86 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86 \
--arch=x86 \
--cpu=i686 \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
#x86_64
./configure \
--libdir=${PREFIX}/libs/x86_64 \
--incdir=${PREFIX}/includes/x86_64 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86_64 \
--arch=x86_64 \
--cpu=x86_64 \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
};
build_android
前三行是配置你的NDK路徑砂吞,改成自己的就可以了署恍。
export PREFIX=$(pwd)/android/$CPU
:指定so生成的目錄,這里這樣寫蜻直,會(huì)在跟目錄下生成一個(gè)build_android文件夾盯质,我們需要的東西就存在在里面。
4. 編譯
cd到ffmpeg一級目錄袭蝗,然后執(zhí)行以下的命令
chmod 777 build_android.sh //改變腳本權(quán)限唤殴,使其能夠運(yùn)行,然后
./build_android.sh //運(yùn)行腳本
等待編譯完成到腥,進(jìn)入一級子目錄下看到生成了一個(gè)build_android文件夾朵逝,內(nèi)容如下:
二.項(xiàng)目集成
- 新建項(xiàng)目,增加C++支持乡范。手動(dòng)創(chuàng)建jniLibs文件夾
-
然后將上一步生成的所有文件復(fù)制到j(luò)niLibs文件夾下面
最終目錄結(jié)構(gòu):
然后修改CMakeLists.txt文件配名,集成so。
cmake_minimum_required(VERSION 3.4.1)
find_library(log-lib log)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp )
set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)
add_library(avutil
SHARED
IMPORTED )
set_target_properties(avutil
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavutil.so )
add_library(swresample
SHARED
IMPORTED )
set_target_properties(swresample
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libswresample.so )
add_library(avresample
SHARED
IMPORTED )
set_target_properties(avresample
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavresample.so )
add_library(swscale
SHARED
IMPORTED )
set_target_properties(swscale
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libswscale.so )
add_library(avcodec
SHARED
IMPORTED )
set_target_properties(avcodec
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavcodec.so )
add_library(avformat
SHARED
IMPORTED )
set_target_properties(avformat
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavformat.so )
add_library( avfilter
SHARED
IMPORTED )
set_target_properties(avfilter
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavfilter.so )
add_library(avdevice
SHARED
IMPORTED )
set_target_properties(avdevice
PROPERTIES IMPORTED_LOCATION
${JNI_LIBS_DIR}/${ANDROID_ABI}/libavdevice.so )
include_directories(${JNI_LIBS_DIR}/includes)
target_link_libraries(native-lib
avutil swresample avresample swscale avcodec avformat avfilter avdevice
${log-lib} )
編寫測試文件:
#include <jni.h>
#include <stdio.h>
#pragma clang diagnostic push
#pragma ide diagnostic ignored "CannotResolve"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
JNIEXPORT jstring JNICALL
Java_com_bysj_myapplication_JNIUtils_getStringFromC(JNIEnv *env, jclass type) {
char info[40000] = {0};
av_register_all();
AVInputFormat *if_temp = av_iformat_next(NULL);
AVOutputFormat *of_temp = av_oformat_next(NULL);
while (if_temp != NULL) {
sprintf(info, "%sInput: %s\n", info, if_temp->name);
if_temp = if_temp->next;
}
while (of_temp != NULL) {
sprintf(info, "%sOutput: %s\n", info, of_temp->name);
of_temp = of_temp->next;
}
return env->NewStringUTF(info);
}
}
#pragma clang diagnostic pop
運(yùn)行結(jié)果如下:
三.遇到的問題
-
開始的時(shí)候編譯的是3.4.2版本晋辆,然后NDK用到的是Android Studio自動(dòng)下載的渠脉,結(jié)果編譯的時(shí)候一直抱如下的錯(cuò)誤:
進(jìn)入NDK目錄查看文件都存在,就是抱一直找不到瓶佳,然后自己去下載了NDK:android-ndk-r16b-darwin-x86_64.zip,然后再去編譯就沒有問題了芋膘。還要記得配置ndk的環(huán)境變量,否則編譯也會(huì)出問題的。
2.在.cpp文件中为朋,在導(dǎo)入包的時(shí)候臂拓,會(huì)報(bào)如下的錯(cuò)誤:
解決方案用C語法:
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}