美文网首页
Android Studio 3.3.1 下FFMPEG-3.4

Android Studio 3.3.1 下FFMPEG-3.4

作者: 水清波 | 来源:发表于2019-04-15 10:59 被阅读0次

    ffmpeg编译的文章很多了,理论上没必要写了,可是架不住Android Studio在不断升级,Android Studio 3.3.1版本,这个版本不允许你只编译arm版本的so库了,所以这个文章目标编译armv7-a。

    为什么要编译armv7-a,百度吧,为了apk大小和兼容性,放armv7-a比较合适。

    ndk 是android-ndk-r14b 从NDK r18b开始删除了gcc,用clang替换了,所以用这套脚本是不能成功的,最后一个支持gcc的版本是r17c。(18开始gcc被删除用一个脚本替换指向到了llvm目录下的clang,由于这个兼容脚本没用19就删除掉了)

    后续更新:使用r20b来编译,请拉到本文最后。

    android-ndk-r14b 放到/usr/ndk/android-ndk-r14b,修改权限。

    在FFMPEG-3.4.5目录下新建build_android.sh,改可执行。

    
    #!/bin/bash
    
    # 设置NDK路径
    
    NDK=/usr/ndk/android-ndk-r14b
    
    # 设置编译针对的平台,可以根据实际需求进行设置
    
    # 当前设置为最低支持android-14版本,arm架构
    
    SYSROOT=$NDK/platforms/android-14/arch-arm
    
    # 设置编译工具链,4.9为版本号
    
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
    
    function build_one
    
    {
    
    ./configure \
    
        --enable-cross-compile \
    
        --enable-shared \
    
        --disable-static \
    
        --disable-doc \
    
        --disable-ffmpeg \
    
        --disable-ffplay \
    
        --disable-ffprobe \
    
        --disable-ffserver \
    
        --disable-avdevice \
    
        --disable-doc \
    
        --disable-symver \
    
        --prefix=$PREFIX \
    
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    
        --target-os=android \
    
        --arch=arm \
    
        --sysroot=$SYSROOT \
    
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    
    $ADDITIONAL_CONFIGURE_FLAG
    
    make clean
    
    make
    
    make install
    
    }
    
    # 设置编译后文件的输出目录
    
    CPU=armv7-a
    
    PREFIX=$(pwd)/android/$CPU
    
    ADDI_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
    
    build_one
    
    

    后面就可以用这个脚本编译了,编译20分钟左右,看你的CPU速度了,多核cpu的可以把倒数第8行的make 改make -j4 多进程跑,加速。

    这个里面比较容易出错的地方就是,如果你按网上以前的教程,那些教程都是教你编译arm版本的,机械替换arm到armv7-a 是不能成功的,关键就在于 --extra-cflags里ADDI_CFLAGS 这个flag的设置,设置好了就可以编译成功,在当前目录下的android里,脚本已经设置过了,所以只有so、头文件、例子。

    as截图

    CPP下新建inlude把头文件拷贝过来,新建jniLibs/armeabi-v7a把so拷贝过来。

    还是android studio 3.3.1的改动,CMakeLists改到CPP目录下了,所以层级目录就是以cpp为工程目录,又是一个坑人的地方。

    
    # 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)
    
    set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs)
    
    message("JNI_LIBS_DIR:"${JNI_LIBS_DIR})
    
    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(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)
    
    include_directories(./include)
    
    aux_source_directory(. NATIVE_SRC)
    
    # Creates and names a library, sets it as either STATIC
    
    # or SHARED, and provides the relative paths to its source code.
    
    # You can define multiple libraries, and CMake builds them for you.
    
    # Gradle automatically packages shared libraries with your APK.
    
    add_library(# Sets the name of the library.
    
            native-lib
    
            # Sets the library as a shared library.
    
            SHARED
    
            # Provides a relative path to your source file(s).
    
    #        native-lib.cpp)
    
            ${NATIVE_SRC})
    
    # Searches for a specified prebuilt library and stores the path as a
    
    # variable. Because CMake includes system libraries in the search path by
    
    # default, you only need to specify the name of the public NDK library
    
    # you want to add. CMake verifies that the library exists before
    
    # completing its build.
    
    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)
    
    find_library(android-lib
    
            android )
    
    # Specifies libraries CMake should link to your target library. You
    
    # can link multiple libraries, such as libraries you define in this
    
    # build script, prebuilt third-party libraries, or system libraries.
    
    target_link_libraries(# Specifies the target library.
    
            native-lib
    
    avutil
    
    swresample
    
    swscale
    
    avcodec
    
    avformat
    
    avfilter
    
            ${android-lib}
    
            # Links the target library to the log library
    
    # included in the NDK.
    
            ${log-lib})
    
    

    CMakeLists 的内容如上

    native-lib.cpp

    导入

    extern "C" {
    
    #include "include/libavcodec/avcodec.h"
    
    #include "include/libavfilter/avfilter.h"
    
    #include "include/libswscale/swscale.h"
    
    #include "include/libavformat/avformat.h"
    
    #include "include/libavutil/avutil.h"
    
    #include "include/libswresample/swresample.h"
    
    }
    

    activity里导入库

    
    companion object {
    
        // Used to load the 'native-lib' library on application startup.
    
        init {
    
    System.loadLibrary("native-lib")
    
    }
    
    }
    
    

    还有一个设置,指定模块只编译armeabi-v7a,因为我们编译的native-lib依赖的so都是arm-v7a格式的,在XXX.gradle设置。

    defaultConfig {
    //skip
            externalNativeBuild {
                cmake {
                    cppFlags "-std=c++11"
                }
                ndk {
                    abiFilters  'armeabi-v7a'
                }
            }
        }
    

    主要是讲和以前版本的不同,看不懂请找几个老版本的参考,有一些博客明明编译的是arm版本,直接集成到armv7a里使用,我也不确定这样有没有问题,v7a的体积会相对小一点,也是个优点了。

    更新NDK r20B的编译方法

    在17之后,18开始就删除了gcc,上面的脚本指定到gcc编译器是没有用的。
    18的gcc编译器,是一个指向clang的脚本,根本没用,在19干脆就删掉了这个脚本。
    18和19的clang编译器那边结构还不一样,clang需要指定编译器的脚本名,因为脚本是由platform+后缀+api版本来编写的,所以还是直接用最新的20b版本好了,使用18版本需要你自己配bulid脚本。

    总结:要么17c使用gcc编译,要么直接20b配clang,别搞18版本浪费时间

    换了R20B后发现,再编译3.3.1有编译错误了,可能是需要更新ffmpeg版本了,测试了一下3.4.7、4.1都是可以的。直接上脚本了,clang需要配置的就是cc、ld、cxx这3个在config的默认脚本里是用cross-prefix做前缀,需要修改名字。
    这是由于,在/usr/ndk/android-ndk-r20b/toolchains/llvm/prebuilt/linux-x86_64/bin
    目录里起名相当混乱

    -rwxr-xr-x  1 jack jack      187 10月 17 15:43 aarch64-linux-android21-clang*
    -rwxr-xr-x  1 jack jack      191 10月 17 15:43 aarch64-linux-android21-clang++*
    ...
    -rwxr-xr-x  1 jack jack   817728 10月 17 15:34 arm-linux-androideabi-addr2line*
    -rwxr-xr-x  1 jack jack   845832 10月 17 15:34 arm-linux-androideabi-ar*
    -rwxr-xr-x  1 jack jack  1436624 10月 17 15:34 arm-linux-androideabi-as*
    ...
    -rwxr-xr-x  1 jack jack      190 10月 17 15:43 armv7a-linux-androideabi16-clang*
    -rwxr-xr-x  1 jack jack      194 10月 17 15:43 armv7a-linux-androideabi16-clang++*
    ...
    -rwxr-xr-x  1 jack jack      199 10月 17 15:43 i686-linux-android16-clang*
    -rwxr-xr-x  1 jack jack      203 10月 17 15:43 i686-linux-android16-clang++*
    

    clang的名字是用PLATFORM+api+clang,负责clang和clang++的脚本名
    但是cross-prefix又是$ARCH-linux-androideabi,负责剩下的通用编译工具名
    都要对应好,都不能出错。

    --ld=$TOOLCHAIN/$TARGET$API-clang 
    

    这行没有错。

    最后记得make install

    #!/bin/bash
    
    export NDK=/usr/ndk/android-ndk-r20b
    export API=21
    # arm aarch64 i686 x86_64
    export ARCH=arm
    # armv7a aarch64 i686 x86_64
    export PLATFORM=armv7a
    export TARGET=$PLATFORM-linux-androideabi
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
    #正确的sysroot
    export SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
    export CPU=$PLATFORM
    export PREFIX=./android/armeabi-v7a2
    export CFLAG="-D__ANDROID_API__=$API -Os -fPIC -DANDROID "
    
    ./configure \
    --prefix=$PREFIX \
    --cc=$TOOLCHAIN/$TARGET$API-clang \
    --ld=$TOOLCHAIN/$TARGET$API-clang \
    --cxx=$TOOLCHAIN/$TARGET$API-clang++ \
    --target-os=android  \
    --arch=$ARCH \
    --cpu=$PLATFORM \
    --cross-prefix=$TOOLCHAIN/$ARCH-linux-androideabi- \
    --disable-asm \
    --enable-cross-compile \
    --enable-shared \
    --disable-doc \
    --enable-runtime-cpudetect \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-decoders \
    --disable-encoders \
    --disable-devices \
    --enable-gpl --enable-nonfree --enable-version3 --disable-iconv \
    --enable-jni \
    --enable-mediacodec \
    --disable-decoders --enable-decoder=vp9 --enable-decoder=h264 --enable-decoder=mpeg4 --enable-decoder=aac \
    --disable-encoders --enable-encoder=vp9_vaapi --enable-encoder=h264_nvenc --enable-encoder=h264_v4l2m2m --enable-encoder=hevc_nvenc \
    --disable-demuxers --enable-demuxer=rtsp --enable-demuxer=rtp --enable-demuxer=flv --enable-demuxer=h264 \
    --disable-muxers --enable-muxer=rtsp --enable-muxer=rtp --enable-muxer=flv --enable-muxer=h264 \
    --disable-parsers --enable-parser=mpeg4video --enable-parser=aac --enable-parser=h264 --enable-parser=vp9 \
    --disable-protocols --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=tcp --enable-protocol=udp \
    --disable-bsfs \
    --disable-indevs \
    --disable-outdevs \
    --disable-filters \
    --disable-postproc \
    --sysroot=$SYSROOT \
    --extra-cflags="$CFLAG" \
    --extra-ldflags=""
    

    相关文章

      网友评论

          本文标题:Android Studio 3.3.1 下FFMPEG-3.4

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