android linux编译FFmpeg 和 x264框架so库

880 阅读2分钟

android linux编译FFmpeg 和 x264框架so库

在学习编译X264的时候找了很多资料都没有编译成功,这里记录一下编译成功的脚本
参考资料点击这里

编译步骤:

  1. 使用NDK生成编译所需要的命令工具集
  2. 编译X264框架
  3. 编译FFmpeg,并加上x264

一、生成命令工具集

找个新的目录新建一个编译脚本文件,例如:vim make_android_toolchain.sh 把下面编辑脚本复制进去(注意要修改NDK目录)

#!/bin/bash
#NDK目录,你要改成自己的ndk解压缩后所在的目录
export NDK_HOME=/home/mirrer/work/ffmpeg/android-ndk-r21e
#生成交叉编译链工具
toolchain=${NDK_HOME}/build/tools/make-standalone-toolchain.sh
#生成交叉编译链保存在当前目录子文件夹android-toolchain
install_root=`pwd`/android-toolchain-r21

#生成32位库最低支持到android4.3,64位库最低支持到android5.0
platforms=(
  "android-18"
  "android-18"
  "android-21"
  "android-18"
  "android-21"
)
#支持以下5种cpu框架
archs=(
  "arm"
  "arm"
  "arm64"
  "x86"
  "x86_64"
)
#cpu型号
abis=(
  "armeabi"
  "armeabi-v7a"
  "arm64-v8a"
  "x86"
  "x86_64"
)
echo $NDK_HOME
echo "安装在目录:$install_root"

num=${#abis[@]}

for ((i=0; i<num; i++))
do
   bash $toolchain --arch=${archs[i]} --platform=${platforms[i]} --abis=${abis[i]} --install-dir=$install_root/${abis[i]}
done

脚本编译完成后会在目录下生成一个android-toolchain-r21目录

2、编译X264库

同样在当前目录下新建一个编译脚本文件,例如:vim android_build_x264.sh 把以下脚本代码复制进去

#!/bin/bash

ROOT=`pwd`/
#配置交叉编译链,未生成交叉编译链请参考https://github.com/cwj2014/android_toolchain
export TOOL_ROOT=$ROOT/android-toolchain-r21
#五种类型cpu编译链  这里我注释了几个  想编译x86架构的把注释打开就行
android_toolchains=(
   "armeabi"
   "armeabi-v7a"
   #"arm64-v8a"
   #"x86"
   #"x86_64"
)
#优化编译项
extra_cflags=(
   "-march=armv5te -msoft-float -D__ANDROID__ -D__ARM_ARCH_5TE__ -D__ARM_ARCH_5TEJ__"
   "-march=armv7-a -mfloat-abi=softfp -mfpu=neon -mthumb -D__ANDROID__ -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__ARM_ARCH_7R__ -D__ARM_ARCH_7M__ -D__ARM_ARCH_7S__ -Wl,--exclude-libs,libgcc_real.a"
   "-march=armv8-a -D__ANDROID__ -D__ARM_ARCH_8__ -D__ARM_ARCH_8A__"
   "-march=i686 -mtune=i686 -m32 -mmmx -msse2 -msse3 -mssse3 -D__ANDROID__ -D__i686__"
   "-march=core-avx-i -mtune=core-avx-i -m64 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt -D__ANDROID__ -D__x86_64__"
)

extra_ldflags="-nostdlib -lc"
#共同配置项,可以额外增加相关配置,详情可查看源文件目录下configure
configure="--disable-cli \
           --enable-static \
           --enable-shared \
           --disable-opencl \
           --enable-strip \
           --disable-cli \
           --disable-win32thread \
           --disable-avs \
           --disable-swscale \
           --disable-lavf \
           --disable-ffms \
           --disable-gpac \
           --disable-lsmash"
#针对各版本不同的编译项
extra_configure=(
   "--disable-asm"
   ""
   ""
   "--disable-asm"
   "--disable-asm"
)
#交叉编译后的运行环境
hosts=(
  "arm-linux-androideabi"
  "arm-linux-androideabi"
  "aarch64-linux-android"
  "i686-linux-android"
  "x86_64-linux-android"
)
#交叉编译工具前缀
cross_prefix=(
  "arm-linux-androideabi-"
  "arm-linux-androideabi-"
  "aarch64-linux-android-"
  "i686-linux-android-"
  "x86_64-linux-android-"
)

#当前目录下x264源文件目录
if [ ! -d "x264" ]
then
    echo "下载x264源文件"
    git clone https://code.videolan.org/videolan/x264.git
fi
SOURCE=x264
#安装文件夹
INSTALL_DIR="x264_install"
#安装路径,默认安装在当前执行目录下的${INSTALL_DIR}
PREFIX=$ROOT/$INSTALL_DIR

n=${#android_toolchains[@]}


cd $ROOT/$SOURCE

for((i=0; i<n; i++))
do
   export PATH=$TOOL_ROOT/${android_toolchains[i]}/bin:$PATH
   echo "开始配置${android_toolchains[i]}版本"
   #交叉编译最重要的是配置--host、--cross-prefix、sysroot、以及extra-cflags和extra-ldflags
   ./configure ${configure} \
               ${extra_configure[i]} \
               --prefix=$PREFIX/${android_toolchains[i]} \
               --host=${hosts[i]} \
               --cross-prefix=${cross_prefix[i]} \
               --sysroot=$TOOL_ROOT/${android_toolchains[i]}/sysroot \
               #--extra-cflags="${extra_cflags[i]}" \  #这里有注释
               --extra-ldflags="$extra_ldflags"
   make clean
   echo "开始编译并安装${android_toolchains[i]}版本"
   make -j4 & make install
done

里面的优化编译项被我注释掉了,原因到最后说 #--extra-cflags="${extra_cflags[i]}" 需要的可以自行打开

3、编译FFmpeg

同样在当前目录下新建编译脚本文件,例如:vim android_build_ffmpeg.sh 把以下脚本代码复制进去(注意脚本编译的FFmpeg 4.1.2版本,可以自行修改版本)

#!/bin/bash

ROOT=`pwd`


if [ ! -d "ffmpeg-4.1.3" ]
then
   # echo "解压ffmpeg-4.1.3源文件"
    wget http://ffmpeg.org/releases/ffmpeg-4.1.3.tar.bz2
    tar -xjvf ffmpeg-4.1.3.tar.bz2
fi

#当前目录下x264源文件目录
SOURCE=ffmpeg-4.1.3

#配置交叉编译链,未生成交叉编译链请参考https://github.com/cwj2014/android_toolchain
export TOOL_ROOT=$ROOT/android-toolchain-r21
#五种类型cpu编译链  需要编译x86架构的可以打开注释
android_toolchains=(
   "armeabi"
   "armeabi-v7a"
#   "arm64-v8a"
#   "x86"
#   "x86_64"
)
#优化编译项
extra_cflags=(
   "-std=gnu11 -march=armv5te -msoft-float -D__ANDROID__ -D__ARM_ARCH_5TE__ -D__ARM_ARCH_5TEJ__"
   "-std=gnu11 -march=armv7-a -mfloat-abi=softfp -mfpu=neon -mthumb -D__ANDROID__ -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__ARM_ARCH_7R__ -D__ARM_ARCH_7M__ -D__ARM_ARCH_7S__"
   "-std=gnu11 -march=armv8-a -D__ANDROID__ -D__ARM_ARCH_8__ -D__ARM_ARCH_8A__"
   "-std=gnu11 -march=i686 -mtune=i686 -m32 -mmmx -msse2 -msse3 -mssse3 -D__ANDROID__ -D__i686__"
   "-std=gnu11 -march=core-avx-i -mtune=core-avx-i -m64 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt -D__ANDROID__ -D__x86_64__"
)

#共同配置项,可以额外增加相关配置,详情可查看源文件目录下configure
#--disable-indev=v4l2  #解决libavdevice/v4l2.c:135:9: error: assigning to 'int (*)(int, unsigned long, ...)'
configure="--enable-gpl \
           --enable-version3 \
           --enable-nonfree \
           --enable-static \
           --enable-shared \
           --enable-small \
           --disable-ffmpeg \
           --disable-doc \
           --disable-htmlpages \
           --disable-manpages \
           --disable-podpages \
           --disable-txtpages \
           --disable-indev=v4l2 \
           --enable-libx264"
#针对各版本不同的编译项
extra_configure=(
   "--disable-asm"
   ""
   ""
   "--disable-asm"
   "--disable-asm"
)
#交叉编译工具前缀
cross_prefix=(
  "arm-linux-androideabi-"
  "arm-linux-androideabi-"
  "aarch64-linux-android-"
  "i686-linux-android-"
  "x86_64-linux-android-"
)

#支持以下5种cpu框架
archs=(
  "arm"
  "arm"
  "arm64"
  "x86"
  "x86_64"
)

#安装文件夹
INSTALL_DIR="ffmpeg_install"
#安装路径,默认安装在当前执行目录下的${INSTALL_DIR}
PREFIX=$ROOT/$INSTALL_DIR

#x264安装目录
X264_INSTALL_DIR=$ROOT/"x264_install"
#libmp3lame安装目录
LAME_INSTALL_DIR=$ROOT/"lame_install"

n=${#android_toolchains[@]}

cd $ROOT/$SOURCE

for((i=0; i<n; i++))
do
   export PATH=$TOOL_ROOT/${android_toolchains[i]}/bin:$PATH
   echo "开始配置${android_toolchains[i]}版本"

   #配置额外库头文件和库文件路径
   #extra_include="-I$X264_INSTALL_DIR/${android_toolchains[i]}/include -I$LAME_INSTALL_DIR/${android_toolchains[i]}/include"
   #extra_lib="-L$X264_INSTALL_DIR/${android_toolchains[i]}/lib -L$LAME_INSTALL_DIR/${android_toolchains[i]}/lib -lc"

   extra_include="-I$X264_INSTALL_DIR/${android_toolchains[i]}/include "
   extra_lib="-L$X264_INSTALL_DIR/${android_toolchains[i]}/lib  -lc"

   #交叉编译最重要的是配置--host、--cross-prefix、sysroot、以及extra-cflags和extra-ldflags
   ./configure ${configure} \
               ${extra_configure[i]} \
               --prefix=$PREFIX/${android_toolchains[i]} \
               --enable-cross-compile \
               --target-os=android \
               --arch=${archs[i]} \
               --cross-prefix=${cross_prefix[i]} \
               --sysroot=$TOOL_ROOT/${android_toolchains[i]}/sysroot \
               --extra-cflags="${extra_cflags[i]} $extra_include" \
               --extra-ldflags="$extra_lib"
   make clean
   echo "开始编译并安装${android_toolchains[i]}版本"
   make -j4 
   make install
done

到此目录下应该有三个脚本文件:

  1. make_android_toolchain.sh
  2. android_build_x264.sh
  3. android_build_ffmpeg.sh

脚本问题没问题的话,现在开始编译

首先把三个脚本增加可以执行权限

chmod +x make_android_toolchain.sh
chmod +x android_build_x264.sh
chmod +x android_build_ffmpeg.sh

然后依次执行三个脚本

./make_android_toolchain.sh
./android_build_x264.sh
./android_build_ffmpeg.sh

编译完成后目录下会生成以下目录,x264_install和ffmpeg_install里面有我们需要的so库和头文件

ffmpeg_x2641.png

ffmpeg_x2642.png

ffmpeg_x2645.png

ffmpeg_x2644.png

ffmpeg_x2643.png

问题

一、默认编译出来的so库会带有后缀,比如xx.so.154这种格式,这种android无法使用;这里需要修改一下configure文件

1、修改x264的configure文件
==============================================
找到下面内容
elif [ "$SYS" = "SunOS" ]; then
        echo "SOSUFFIX=so" >> config.mak
        echo "SONAME=libx264.so.$api" >> config.mak
        echo "SOFLAGS=-shared -Wl,-h,$(SONAME) $SOFLAGS" >> config.mak
    else
        echo "SOSUFFIX=so" >> config.mak
        echo "SONAME=libx264.so.$api" >> config.mak
        echo "SOFLAGS=-shared -Wl,-soname,$(SONAME) $SOFLAGS" >> config.mak
==============================================
修改成:
elif [ "$SYS" = "SunOS" ]; then
        echo "SOSUFFIX=so" >> config.mak
        echo "SONAME=libx264.so" >> config.mak
        echo "SOFLAGS=-shared -Wl,-h,$(SONAME) $SOFLAGS" >> config.mak
    else
        echo "SOSUFFIX=so" >> config.mak
        echo "SONAME=libx264.so" >> config.mak
        echo "SOFLAGS=-shared -Wl,-soname,$(SONAME) $SOFLAGS" >> config.mak


2、修改FFmpeg的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)'

二、我在把x264和ffmpeg导入安卓项目运行的时候报以下错误

ffmpeg_x2646.png

最后把x264编译的时候优化选项给注释掉之后就可以了,#--extra-cflags="${extra_cflags[i]}" 就是这句代码

按照上面流程编译出的so就可以正常使用,需要注意的是使用X264.so库的时候,需要把x264.so库复制到安卓项目中,我之前以为会在ffmpeg中一起打包过去的,我这边测试是需要手动复制过来才行,不然会报找不到x264.so库的错误。