美文网首页
Mac编译FFmpeg(Android版本)

Mac编译FFmpeg(Android版本)

作者: 匿名用户_bcc3 | 来源:发表于2019-01-28 18:20 被阅读0次

    开发环境

    FFmpeg源码地址:https://github.com/FFmpeg/FFmpeg
    编译环境:

    • macOS Mojava(10.14.2)
    • FFmpeg(tag:n3.4)
    • ndk-r10e

    NDK配置
    vim ~/.bash_profile
    export ANDROID_NDK=/Users/zhouxiang/Library/Android/sdk/android-ndk-r10e
    export PATH=$ANDROID_NDK:$PATH

    修改configure文件

    因为FFmpeg默认编译出来的so的版本号在.so之后(如libavcodec.so.5.100.1),而Android中并不能识别这种格式,
    打开configure文件,所以我们修改下面的配置文件。

    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)'
    

    编写编译脚本

    在FFmpeg目录下创建build_android.sh脚本,并赋予可执行的权限。
    注意脚本中的TMPDIR以及NDK路径,并且需要保证TMPDIR目录是可写入的

    #!/bin/bash
    
    make clean
    # NDK的路径,根据自己的安装位置进行设置
    export TMPDIR=/code/FFmpeg/ffmpeg_compile
    export NDK=/Users/zhouxiang/Library/Android/sdk/android-ndk-r10e
    export SYSROOT=$NDK/platforms/android-21/arch-arm/
    export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
    export CPU=arm
    export PREFIX=$(pwd)/android/$CPU
    export ADDI_CFLAGS="-marm"
    function build_one
    {
    ./configure \
        --prefix=$PREFIX \
        --target-os=linux \
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
        --arch=arm \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
        --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
        --enable-shared \
        --enable-runtime-cpudetect \
        --enable-gpl \
        --enable-small \
        --enable-cross-compile \
        --disable-debug \
        --disable-static \
        --disable-doc \
        --disable-asm \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-ffserver \
        --enable-postproc \
        --enable-avdevice \
        --disable-symver \
        --disable-stripping \
    $ADDITIONAL_CONFIGURE_FLAG
    sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
    sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
    sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
    sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
    sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
    sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
    sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
    sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
    make clean
    # 这里是定义用几个CPU编译,我用4个,一般在5分钟之内编译完成
    make -j4
    make install
    }
    build_one
    

    其中:

    • TMPDIR为编译生成的临时文件存放的目录
    • SYSROOT为so文件支持的最低Android版本的平台目录
    • CPU为指定so文件支持的平台
    • PREFIX为生成的so文件存放目录
    • TOOLCHAIN为编译所使用的工具链目录
    • cross-prefix为编译所使用的工具链文件
    • enable和disable指定了需要编译的项
    • target-os为目标操作系统;

    执行编译脚本

    ./build_android.sh

    如果一切正常,将会在FFmpeg/android/arm/lib目录下看到生成的so文件。

    常见错误

    libavcodec/aaccoder.c: In function 'search_for_ms':
    libavcodec/aaccoder.c:803:25: error: expected identifier or '(' before numeric constant
                         int B0 = 0, B1 = 0;
                             ^
    libavcodec/aaccoder.c:865:28: error: lvalue required as left operand of assignment
                             B0 += b1+b2;
                                ^
    libavcodec/aaccoder.c:866:25: error: 'B1' undeclared (first use in this function)
                             B1 += b3+b4;
                             ^
    libavcodec/aaccoder.c:866:25: note: each undeclared identifier is reported only once for each function it appears in
    make: *** [libavcodec/aaccoder.o] Error 1
    

    解决办法:https://blog.csdn.net/hyjwan/article/details/80384916
    略坑

    编译生成单个so文件

    上面的脚本编译出来的是8个so文件,如果需要使用ffmpeg,就需要把so文件拷贝进去,这也太麻烦了。我们可以打包成一个so,这样引入时将更加方便。具体步骤如下,下面每一个字都是非常重要的,说多了都是泪,网上很多教程都是复制粘贴,根本没有验证!

    Step1还原configure文件

    SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
    LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
    SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
    SLIB_INSTALL_LINKS='$(SLIBNAME)'
    

    还原成

    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)'
    

    Step2修改上面创建的build_android.sh,主要有以下两点:

    • 需要将disable-static enable-shared 修改成 enable-static disable-shared
    • 在make install之后添加打包脚本

    具体脚本如下:

    #!/bin/bash
    
    make clean
    # NDK的路径,根据自己的安装位置进行设置
    export TMPDIR=/Users/zhouxiang/Desktop
    export NDK=/Users/zhouxiang/Library/Android/sdk/android-ndk-r10e
    export SYSROOT=$NDK/platforms/android-21/arch-arm/
    export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
    export CPU=armv7-a
    export PREFIX=$(pwd)/android/$CPU
    export ADDI_CFLAGS="-marm"
    function build_one
    {
    ./configure_before \
        --prefix=$PREFIX \
        --target-os=linux \
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
        --arch=arm \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
        --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
        --disable-shared \
        --enable-runtime-cpudetect \
        --enable-gpl \
        --enable-small \
        --enable-cross-compile \
        --disable-debug \
        --enable-static \
        --disable-doc \
        --disable-asm \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-ffserver \
        --enable-postproc \
        --enable-avdevice \
        --disable-symver \
        --disable-stripping \
    $ADDITIONAL_CONFIGURE_FLAG
    sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
    sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
    sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
    sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
    sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
    sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
    sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
    sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
    make clean
    # 这里是定义用几个CPU编译,我用4个,一般在5分钟之内编译完成
    make -j4
    make install
    
    #打包
    $TOOLCHAIN/bin/arm-linux-androideabi-ld \
        -rpath-link=$SYSROOT/usr/lib \
        -L$SYSROOT/usr/lib \
        -L$PREFIX/lib \
        -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
        $PREFIX/libffmpeg.so \
        libavcodec/libavcodec.a \
        libavdevice/libavdevice.a \
        libavfilter/libavfilter.a \
        libavformat/libavformat.a \
        libavutil/libavutil.a \
        libpostproc/libpostproc.a \
        libswresample/libswresample.a \
        libswscale/libswscale.a \
        -lc -lm -lz -ldl -llog --dynamic-linker=system/bin/linker \
        $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9/libgcc.a
    
    #strip 精简文件
    $TOOLCHAIN/bin/arm-linux-androideabi-strip $PREFIX/libffmpeg.so
    
    echo "编译结束"
    }
    build_one
    

    Step3执行脚本

    编译完成之后会在android-armv7-a目录下生成libffmpeg.so文件


    相关文章

      网友评论

          本文标题:Mac编译FFmpeg(Android版本)

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