美文网首页Android TipsAndroid进阶之路FFmpeg
Linux下ndk编译移植FFmpeg到Android平台(二)

Linux下ndk编译移植FFmpeg到Android平台(二)

作者: 第八区 | 来源:发表于2018-01-31 21:38 被阅读457次

    在前面的Linux下ndk编译移植FFmpeg到Android平台文章中介绍了如何将最基本的FFmpeg到Android平台。但只是简单的移植了FFmpeg,没有包含x264编码器,并且AAC编码器也只有默认的。在Android平台下使用FFmpeg进行RTMP推流(摄像头推流)中我实际上已经用到了x264编码器,但没有介绍如何将x264集成到FFmpeg中。而本篇文章将解决这个问题,重点讲解如何集成x264和libfdk-aac,当然也会有问题汇总。

    为什么要单独一篇文章来介绍如何去移植FFmpeg、x264和fdk_aac呢?
    万事开头难,第一步很难,但也是最重要的,不怕告诉大家,就仅仅编译这几个东西我足足花了两天时间去踩坑。对于有些编译出现各种问题导致没有成功的兄弟,可能非常的挫伤积极性,打击学习这方面知识的积极性。所以我觉得有必要重点讲解下这个环节

    在进入这是内容之前我要强调一点,一定要注意安装版本,这个安装版本包括linux系统版本、FFmpeg版本、x264版本、libfdk-aac版本、ndk中android-api版本。你可能会因为版本不匹配导致编译出现各种问题,既然我已经把这些坑踩过了,希望大家不要再掉进去

    同步开源库FFmpegSample,里面有我最新编译好的so

    文章围绕以下几点介绍

    • 编译环境
    • x264编译
    • libfdk-aac编译
    • FFmpeg 编译
    • 踩坑历程

    编译环境

    • linux版本 centos 6.8_64位
    [root@iZ94g6hanmqZ include]# lsb_release -a
    LSB Version:    :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
    Distributor ID: CentOS
    Description:    CentOS release 6.8 (Final)
    Release:    6.8
    Codename:   Final
    
    • ndk版本 下载最新即可
      我的安装位置在/usr/local/android/ndk-bundle

    接下来到了真正编译的时候了,注意我做编译的目录在/opt/下,也就是所有的源码都解压在这个目录下

    编译x264

    下载地址下载版本x264-snapshot-20140916-2245-stable.tar

    2.png
    然后解压为x264目录,进入x264目录,新建build_x264.sh内容为:
    #!/bin/bash
    NDK=/usr/local/android/ndk-bundle
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
    PLATFORM=$NDK/platforms/android-16/arch-arm
    PREFIX=./android
    
    function build_one
    {
        ./configure \
            --prefix=$PREFIX \
            --enable-static \
            --disable-shared \
            --enable-pic \
            --disable-asm \
            --disable-cli \
            --host=arm-linux \
            --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
            --sysroot=$PLATFORM
    }
    build_one
    

    然后给文件增加运行权限 chmod +x build_x264.sh。剩下的就是配置编译安装啦。

    ./build_x264.sh
    make -j4
    make install
    

    安装目录就在当前目录下生成android目录,当然库文件和头文件就有了

    drwxr-xr-x 2 root root 4096 Jan 25 15:06 include
    drwxr-xr-x 3 root root 4096 Jan 25 15:06 lib
    

    编译libfdk-aac

    先来几个问题:

      1. 为啥要集成libfdk-aac呢?
        嘿嘿!别着急,这个我会在下篇文章介绍ffmpeg进行AAC编码时候讲到,这里我只讲如何编译。
      1. 为什么不集成libfaac?
        不少尝试过的童鞋会发现,在编译FFmpeg时集成libfaac也就是configure增加--enable-libfaac参数时会提示ffmpeg: remove option for libfaac,Unknown option "--enable-libfaac",因为现在FFmpeg不支持libfaac扩展了。而网上很多比较早期的文章都是讲如何集成libfaac的,所以很多童鞋就比较疑惑。
    3.png

    下面正式进入编译fdk_aac
    下载地址版本选择0.1.4

    4.png
    同样加压到fdk-aac-0.1.4目录,进入目录,新建build_fdk.sh内容为:
    NDK=/usr/local/android/ndk-bundle
    ANDROID_API=android-14
      
    SYSROOT=$NDK_HOME/platforms/$ANDROID_API/arch-arm  
      
    ANDROID_BIN=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/  
      
    CROSS_COMPILE=${ANDROID_BIN}/arm-linux-androideabi-  
       
    ARM_INC=$SYSROOT/usr/include  
      
    ARM_LIB=$SYSROOT/usr/lib  
      
    LDFLAGS=" -nostdlib -Bdynamic -Wl,--whole-archive -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$NDK_HOME/sources/cxx-stl/gnu-libstdc++/libs/armeabi -L$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/arm-linux-androideabi/lib -L$ARM_LIB  -lc -lgcc -lm -ldl  "  
      
    FLAGS="--host=arm-androideabi-linux --enable-static --disable-shared"  
      
    export CXX="${CROSS_COMPILE}g++ --sysroot=${SYSROOT}"  
      
    export LDFLAGS="$LDFLAGS"  
      
    export CC="${CROSS_COMPILE}gcc --sysroot=${SYSROOT}"  
      
    ./configure $FLAGS  --prefix='/opt/fdk-aac-0.1.4/android'  
    

    剩下的就是配置编译安装啦。

    ./build_fdk.sh
    make -j4
    make install
    

    安装目录就在当前目录下生成android目录,当然库文件和头文件就有了

    drwxr-xr-x 2 root root 4096 Jan 25 15:06 include
    drwxr-xr-x 3 root root 4096 Jan 25 15:06 lib
    

    编译FFmpeg

    FFmpeg版本3.2.4 下载地址
    下载完源码解压后,我们进入目录新建build_ffmpeg.sh脚本,内容

    #!/bin/bash
    NDK=/usr/local/android/ndk-bundle
    SYSROOT=$NDK/platforms/android-16/arch-arm/
    PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt  
    TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
    
    function build_one
    {
    ./configure  --prefix=$PREFIX  \
        --enable-shared \
        --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc  \
        --disable-static \
        --disable-doc \
        --disable-ffserver \
        --disable-yasm \
        --enable-cross-compile \
        --enable-gpl \
        --enable-libx264 \
        --enable-decoder=h264 \
        --enable-encoder=libx264 \
        --enable-libfdk-aac \
        --enable-encoder=libfdk_aac \
        --enable-decoder=libfdk_aac \
        --enable-nonfree \
        --cross-prefix="$TOOLCHAIN/bin/arm-linux-androideabi-" \
        --target-os=linux  \
        --arch=arm \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        $ADDITIONAL_CONFIGURE_FLAG
    }
    
    CPU=arm
    PREFIX=$(pwd)/android/$CPU
    ADDI_CFLAGS="-marm -I/opt/x264/android/include -DANDROID -I/opt/fdk-aac-0.1.4/android/include"
    ADDI_LDFLAGS="-L/opt/x264/android/lib -L/opt/fdk-aac-0.1.4/android/lib"
    
    build_one
    

    然后给文件增加运行权限 chmod +x build_ffmpeg.sh。剩下的就是配置编译安装啦。

    ./build_x264.sh
    make -j4
    make install
    

    安装完之后我们最终的so包就生成了。在当前目录下的 ./android/arm下。

    drwxr-xr-x  2 root root 4096 Jan 25 15:23 bin
    drwxr-xr-x 10 root root 4096 Jan 25 15:11 include
    drwxr-xr-x  3 root root 4096 Jan 25 15:23 lib
    drwxr-xr-x  3 root root 4096 Jan 25 15:11 share
    

    我们的动态库就在lib下了

    -rwxr-xr-x 1 root root 12983912 Jan 25 15:23 libavcodec-57.so
    lrwxrwxrwx 1 root root       16 Jan 25 15:23 libavcodec.so -> libavcodec-57.so
    -rwxr-xr-x 1 root root    59384 Jan 25 15:23 libavdevice-57.so
    lrwxrwxrwx 1 root root       17 Jan 25 15:23 libavdevice.so -> libavdevice-57.so
    -rwxr-xr-x 1 root root  1877548 Jan 25 15:23 libavfilter-6.so
    lrwxrwxrwx 1 root root       16 Jan 25 15:23 libavfilter.so -> libavfilter-6.so
    -rwxr-xr-x 1 root root  1956464 Jan 25 15:23 libavformat-57.so
    lrwxrwxrwx 1 root root       17 Jan 25 15:23 libavformat.so -> libavformat-57.so
    -rwxr-xr-x 1 root root   443860 Jan 25 15:23 libavutil-55.so
    lrwxrwxrwx 1 root root       15 Jan 25 15:23 libavutil.so -> libavutil-55.so
    -rwxr-xr-x 1 root root    42276 Jan 25 15:23 libpostproc-54.so
    lrwxrwxrwx 1 root root       17 Jan 25 15:23 libpostproc.so -> libpostproc-54.so
    -rwxr-xr-x 1 root root    91532 Jan 25 15:23 libswresample-2.so
    lrwxrwxrwx 1 root root       18 Jan 25 15:23 libswresample.so -> libswresample-2.so
    -rwxr-xr-x 1 root root   406924 Jan 25 15:23 libswscale-4.so
    lrwxrwxrwx 1 root root       15 Jan 25 15:23 libswscale.so -> libswscale-4.so
    drwxr-xr-x 2 root root     4096 Jan 25 15:23 pkgconfig
    

    这里对脚本做个解释,增加了几个命令。

    • 支持x264扩展
        --enable-libx264 \
        --enable-decoder=h264 \
        --enable-encoder=libx264 \
    
    • 支持fdk_aac扩展
        --enable-libfdk-aac \
        --enable-encoder=libfdk_aac \
        --enable-decoder=libfdk_aac \
    

    要支持fdk_aac必须还加上

        --enable-nonfree \
        --enable-gpl \
    

    最后就是制定x264 fdk_aac的头文件和库文件的目录--extra-cflags加入头文件目录,--extra-ldflags包含库文件目录,也就是

    ADDI_CFLAGS="-marm -I/opt/x264/android/include -DANDROID -I/opt/fdk-aac-0.1.4/android/include"
    ADDI_LDFLAGS="-L/opt/x264/android/lib -L/opt/fdk-aac-0.1.4/android/lib"
    

    到这里我们就完成了整个编译。得到的so库不仅有FFmpeg基础功能,还有x264和fdk_aac的编解码功能


    踩坑历程

    configure FFmpeg提示找不到x264

    看到这个问题,我开始很诧异,我明明都配置正确了,后来查看config日志,提示 找不到什么log2方法。后来发现新版本的x264的config.h中启用了这个方法,所以大家按我选择的版本就没问题啦。

    make FFmpeg 报错

    libavcodec/libx264.c: In function 'x264_frame' :
    libavcodec/libx264.c:282:9 error: 'x264_bit_depth' undeclared(first use in this function)  
                 if(x264_bit_depth>8)     
    
    libavcodec/libx264.c: In function 'x264_init_static':
    libavcodec/libx264.c:892.9 error: 'x264_bit_depth' undeclared(first use in this function)
                 if(x264_bit_depth== 8)  
    

    很明显没有找到x264_bit_depth这个变量。那咋办,还是版本不对应咯。你用的x264,FFmpeg可能不太兼容哦。

    configure FFmpeg是faac不能用

    这个前面已经提到了,FFmpeg已经不再支持libfaac啦。

    编译好的so ,放在android平台下使用时,提示找不到x264.so

    这里要注意,我在编译x264和fdk_aac时全部使用的静态编译,编出来的是静态库。那么最终我编译完FFmpeg后就不需要讲x264的so加入到android应用项目中。如果你是动态编译x264和fdk_aac那么你就得把这两个库的so也加入到android应用项目中。
    注意编译x264和fdk_aac中间的参数--enable-static --disable-shared


    到此所有讲解结束了,先预告下一篇,下一篇将介绍Android平台下使用FFmpeg进行AAC编译。里面会给大家解释为什么要用fdk_aac,而不用默认的AAC编码器。

    相关文章

      网友评论

      • 涛歌哥:博主,我在MAC下没有编过,报错:configure: error: C preprocessor "/lib/cpp" fails sanity check
        See `config.log' for more details
        还有个疑问:
        在你的脚本中有这个路径:
        -L$NDK_HOME/sources/cxx-stl/gnu-libstdc++/libs/armeabi
        我本地是这样的:-L$NDK_HOME/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi
        难道没报错吗?
      • eb15e719394c:博主写的很细致了,但是在我的mac上我发现使用你的脚本会有很多的问题,对这里不甚了解,推荐一个库,https://github.com/mabeijianxi/FFmpeg4Android,这里有很多的脚本,大家可以参考一下~
      • 王学宏:请问大佬一个问题,
        ```
        Makefile:227: recipe for target '.depend' failed
        make: *** [.depend] Error 1
        /home/hong/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc -Wno-maybe-uninitialized -Wshadow -O3 -ffast-math -m64 -Wall -I. -I. --sysroot=/home/hong/Android/Sdk/ndk-bundle/platforms/android-21/arch-x86_64/ -Os -fpic -std=gnu99 -D_GNU_SOURCE -mpreferred-stack-boundary=5 -fPIC -fomit-frame-pointer -fno-tree-vectorize -c -o x264.o x264.c
        x264.c:40:20: fatal error: signal.h: No such file or directory
        #include <signal.h>
        ^
        compilation terminated.
        <builtin>: recipe for target 'x264.o' failed
        make: *** [x264.o] Error 1
        /home/hong/Android/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc -Wno-maybe-uninitialized -Wshadow -O3 -ffast-math -m64 -Wall -I. -I. --sysroot=/home/hong/Android/Sdk/ndk-bundle/platforms/android-21/arch-x86_64/ -Os -fpic -std=gnu99 -D_GNU_SOURCE -mpreferred-stack-boundary=5 -fPIC -fomit-frame-pointer -fno-tree-vectorize -c -o x264.o x264.c
        x264.c:40:20: fatal error: signal.h: No such file or directory
        #include <signal.h>
        ^
        compilation terminated.
        <builtin>: recipe for target 'x264.o' failed
        make: *** [x264.o] Error 1
        ```
        我发现signal.h文件老版本的NDK是在
        ndk-bundle/platforms/android-14/arch-arm/usr/include文件夹目录下

        而现在最新版本的NDK signal.h文件是在
        ndk-bundle-sysroot-usr-include 文件夹目录下,

        哪在配置这个路径的时候SYSROOT=$NDK_HOME/platforms/$ANDROID_API/arch-x86_64 应该怎么写呀,还是按照原来的这样写吗。
        第八区:@王学宏 就是编译x264的时候是吧,看下你的系统版本。我之前在centos7上编译x264也是出现各种问题。这些问题得一个个排查了。
        王学宏:@eric__ 我配置和你的一样,还是报这个错。
        第八区:@王学宏 是的,而且signal.h都是有的呀,如果你编译有问题可以先按照我的脚本,对应上版本,先编出来。之后再研究其他版本的问题。

      本文标题:Linux下ndk编译移植FFmpeg到Android平台(二)

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