ndk

将ffmpeg 移植到android平台 (android st

2017-12-25  本文已影响0人  siqiangli

        上篇中我们已经编译好了ffmpeg的动态库和静态库,接下来我们要在android上使用,网上也有很多例子,把上篇的多个动态库编译成一个so库,我也尝试过,但是编译出来的libffmpeg.so库有十多M,而多个so库总共才4M多,相对来说太大了,而使用多个so,需要加载太多了so库文件,所以我使用静态库来生成一个动态库,然后再使用这个动态库。

1、创建一个android项目,支持Cmake,然后将之前编译好的静态库分别拷到jniLibs下如下图

2、FFmpeg是C开发,api比较多,如果使用api来开发我们要的功能,成本高,费时久,所以我采用的是命令形式,操作很简单,在FFmpeg将cmdutils.c 、cmdutils.h 、cmdutils_common_opts.h、 config.h、 ffmpeg.c、 ffmpeg.h、 ffmpeg_filter.c、 ffmpeg_opt.c拷到cpp目录下,并且将各个模块的.h文件过滤出来(写个脚本去把所有的.h文件提取出来,为了android项目编译的通过,否则会找不到头文件),这个我是参照www.jianshu.com/p/ceaa286d8aff,如下图

3、修改文件

找到ffmpeg.c,把int main(int argc, char argv) 改名为 int jxRun(int argc, char argv)

找到ffmpeg.h, 在文件末尾添加函数申明: 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函数,修改为

在cmdutils.h文件中将exit_program 返回 改成int 并移除掉av_noreturn

创建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})

由于使用的是静态库,所有链接顺序不要乱,否则build不过,可以按照我上面的顺序。之后就是编写java代码了,创建一个java类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);

上面只是简单的测试命令,你也可以尝试其它的命令。

生成apk后,只有一个so库文件,另外四个是我用了第三方播放器加载进来的忽略掉。

视频压缩后的结果8M多压成了1M多,感觉还行。

如下:

由于本人一直是从事android开发的,第一次写关于ffmpeg文章,可能有很多不足之处,希望大家谅解下,如有疑问,欢迎提出,代码的话,改天有空上传到github。

提示:在x86下,请记得替换掉config.h文件(目前这个config.h文件需要作ABI的区分),因为不同平台下编译生成的config.h文件不一样。

上一篇下一篇

猜你喜欢

热点阅读