????????上篇中我們已經(jīng)編譯好了ffmpeg的動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù),接下來(lái)我們要在android上使用,網(wǎng)上也有很多例子,把上篇的多個(gè)動(dòng)態(tài)庫(kù)編譯成一個(gè)so庫(kù),我也嘗試過(guò),但是編譯出來(lái)的libffmpeg.so庫(kù)有十多M,而多個(gè)so庫(kù)總共才4M多,相對(duì)來(lái)說(shuō)太大了,而使用多個(gè)so,需要加載太多了so庫(kù)文件,所以我使用靜態(tài)庫(kù)來(lái)生成一個(gè)動(dòng)態(tài)庫(kù),然后再使用這個(gè)動(dòng)態(tài)庫(kù)。
1、創(chuàng)建一個(gè)android項(xiàng)目,支持Cmake,然后將之前編譯好的靜態(tài)庫(kù)分別拷到j(luò)niLibs下如下圖
2、FFmpeg是C開(kāi)發(fā),api比較多,如果使用api來(lái)開(kāi)發(fā)我們要的功能,成本高,費(fèi)時(shí)久,所以我采用的是命令形式,操作很簡(jiǎn)單,在FFmpeg將cmdutils.c 、cmdutils.h 、cmdutils_common_opts.h、 config.h、 ffmpeg.c、 ffmpeg.h、 ffmpeg_filter.c、 ffmpeg_opt.c拷到cpp目錄下,并且將各個(gè)模塊的.h文件過(guò)濾出來(lái)(寫(xiě)個(gè)腳本去把所有的.h文件提取出來(lái),為了android項(xiàng)目編譯的通過(guò),否則會(huì)找不到頭文件),這個(gè)我是參照www.lxweimin.com/p/ceaa286d8aff,如下圖
3、修改文件
找到ffmpeg.c,把int main(int argc, char argv) 改名為 int jxRun(int argc, char argv)
找到ffmpeg.h, 在文件末尾添加函數(shù)申明: int jxRun(int argc, char **argv);然后在return前加上如下代碼即可
nb_filtergraphs =0;progress_avio = NULL;input_streams = NULL;nb_input_streams =0;input_files = NULL;nb_input_files =0;output_streams = NULL;nb_output_streams =0;output_files = NULL;nb_output_files =0;
找到cmdutils.c中的exit_program函數(shù),修改為
在cmdutils.h文件中將exit_program 返回 改成int 并移除掉av_noreturn
創(chuàng)建jni 與java交互的.c文件ffmpeg-pro-lib.c
4、CMakeLists.txt的配置
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
ffmpeg-pro-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cmdutils.c
src/main/cpp/ffmpeg.c
src/main/cpp/ffmpeg_filter.c
src/main/cpp/ffmpeg_opt.c
src/main/cpp/ffmpeg-pro-lib.c )
add_library(
avcodec
STATIC
IMPORTED
)
add_library(
avfilter
STATIC
IMPORTED
)
add_library(
avformat
STATIC
IMPORTED
)
add_library(
avutil
STATIC
IMPORTED
)
add_library(
swresample
STATIC
IMPORTED
)
add_library(
swscale
STATIC
IMPORTED
)
add_library(
avdevice
STATIC
IMPORTED
)
add_library(
avresample
STATIC
IMPORTED
)
add_library(
postproc
STATIC
IMPORTED
)
add_library(
x264
STATIC
IMPORTED
)
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
set_target_properties(
avcodec
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavcodec.a
)
set_target_properties(
avfilter
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavfilter.a
)
set_target_properties(
avformat
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavformat.a
)
set_target_properties(
avutil
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavutil.a
)
set_target_properties(
swresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswresample.a
)
set_target_properties(
swscale
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswscale.a
)
set_target_properties(
avdevice
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavdevice.a
)
set_target_properties(
avresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavresample.a
)
set_target_properties(
postproc
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libpostproc.a
)
set_target_properties(
x264
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libx264.a
)
endif(${ANDROID_ABI} STREQUAL "armeabi-v7a")
if(${ANDROID_ABI} STREQUAL "x86")
set_target_properties(
avcodec
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavcodec.a
)
set_target_properties(
avfilter
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavfilter.a
)
set_target_properties(
avformat
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavformat.a
)
set_target_properties(
avutil
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavutil.a
)
set_target_properties(
swresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswresample.a
)
set_target_properties(
swscale
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswscale.a
)
set_target_properties(
avdevice
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavdevice.a
)
set_target_properties(
avresample
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavresample.a
)
set_target_properties(
postproc
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libpostproc.a
)
set_target_properties(
x264
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libx264.a
)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-warn-shared-textrel")
endif(${ANDROID_ABI} STREQUAL "x86")
include_directories(
src/main/cpp
)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
ffmpeg-pro-lib
swscale
swresample
postproc
avresample
avdevice
avfilter
avformat
avcodec
avutil
x264
# Links the target library to the log library
# included in the NDK.
${log-lib})
由于使用的是靜態(tài)庫(kù),所有鏈接順序不要亂,否則build不過(guò),可以按照我上面的順序。之后就是編寫(xiě)java代碼了,創(chuàng)建一個(gè)java類(lèi)FFmpegNativeHelper
static{
System.loadLibrary("ffmpeg-pro-lib");
}
public static booleancompressVideo(String videoPath,String resultPath){
int ret = ffmpegCmdRun(new String[]{"ffmpeg",
"-i",videoPath,
"-y",
"-c:v","libx264",
"-c:a","aac",
"-crf","25",
"-vf","scale=-1:640",
"-preset","ultrafast",
"-b:v","900k",
"-bufsize","900k",
"-b:a","96k",
resultPath});
if(ret == 0){
return true;
}
}
return false;
}
private static native intffmpegCmdRun(String[] cmd);
上面只是簡(jiǎn)單的測(cè)試命令,你也可以嘗試其它的命令。
生成apk后,只有一個(gè)so庫(kù)文件,另外四個(gè)是我用了第三方播放器加載進(jìn)來(lái)的忽略掉。
視頻壓縮后的結(jié)果8M多壓成了1M多,感覺(jué)還行。
如下:
由于本人一直是從事android開(kāi)發(fā)的,第一次寫(xiě)關(guān)于ffmpeg文章,可能有很多不足之處,希望大家諒解下,如有疑問(wèn),歡迎提出,代碼的話(huà),改天有空上傳到github。
提示:在x86下,請(qǐng)記得替換掉config.h文件(目前這個(gè)config.h文件需要作ABI的區(qū)分),因?yàn)椴煌脚_(tái)下編譯生成的config.h文件不一樣。