美文网首页ndk
将ffmpeg 移植到android平台 (android st

将ffmpeg 移植到android平台 (android st

作者: siqiangli | 来源:发表于2017-12-25 15:48 被阅读0次

            上篇中我们已经编译好了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文件不一样。

    相关文章

      网友评论

        本文标题:将ffmpeg 移植到android平台 (android st

        本文链接:https://www.haomeiwen.com/subject/mbylgxtx.html