Linux下ndk编译移植FFmpeg到Android平台(二)——集成x264和libfdk-aac

在前面的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

《Linux下ndk编译移植FFmpeg到Android平台(二)——集成x264和libfdk-aac》 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的,所以很多童鞋就比较疑惑。

《Linux下ndk编译移植FFmpeg到Android平台(二)——集成x264和libfdk-aac》 3.png

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

《Linux下ndk编译移植FFmpeg到Android平台(二)——集成x264和libfdk-aac》 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编码器。

    原文作者:八度空间X
    原文地址: https://www.jianshu.com/p/1bb2fdb85392
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞