macos NDK 交叉编译X264

macos NDK 交叉编译X264

x264是一个开源的H.264/MPEG-4 AVC视频编码函数库,是最好的有损视频编码器之一。 它将作为我们直播数据的视频编码库。

FFmpeg中同样实现了H.264的编码,同时FFmpeg也能够集成X264。本次我们将直接使用X264来进行视 频编码而不是FFmpeg

[X264 主页]

X264 主页

Source

The latest x264 source code is available through git repository:

# git clone https://code.videolan.org/videolan/x264.git

You can browse the source on-line.

ls

存在configure,这时候我们第一反应一定是执行help

./configure --help

Usage: ./configure [options]

Help:
  -h, --help               print this message

Standard options:
  --prefix=PREFIX          install architecture-independent files in PREFIX
                           [/usr/local]
  --exec-prefix=EPREFIX    install architecture-dependent files in EPREFIX
                           [PREFIX]
  --bindir=DIR             install binaries in DIR [EPREFIX/bin]
  --libdir=DIR             install libs in DIR [EPREFIX/lib]
  --includedir=DIR         install includes in DIR [PREFIX/include]
  --extra-asflags=EASFLAGS add EASFLAGS to ASFLAGS
  --extra-cflags=ECFLAGS   add ECFLAGS to CFLAGS
  --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS
  --extra-rcflags=ERCFLAGS add ERCFLAGS to RCFLAGS

Configuration options:
  --disable-cli            disable cli
  --system-libx264         use system libx264 instead of internal
  --enable-shared          build shared library
  --enable-static          build static library
  --disable-bashcompletion disable installation of bash-completion script
  --enable-bashcompletion  force installation of bash-completion script
  --bashcompletionsdir=DIR install bash-completion script in DIR [auto]
  --disable-opencl         disable OpenCL features
  --disable-gpl            disable GPL-only features
  --disable-thread         disable multithreaded encoding
  --disable-win32thread    disable win32threads (windows only)
  --disable-interlaced     disable interlaced encoding support
  --bit-depth=BIT_DEPTH    set output bit depth (8, 10, all) [all]
  --chroma-format=FORMAT   output chroma format (400, 420, 422, 444, all) [all]

Advanced options:
  --disable-asm            disable platform-specific assembly optimizations
  --enable-lto             enable link-time optimization
  --enable-debug           add -g
  --enable-gprof           add -pg
  --enable-strip           add -s
  --enable-pic             build position-independent code

Cross-compilation:
  --host=HOST              build programs to run on HOST
  --cross-prefix=PREFIX    use PREFIX for compilation tools
  --sysroot=SYSROOT        root of cross-build tree

External library support:
  --disable-avs            disable avisynth support
  --disable-swscale        disable swscale support
  --disable-lavf           disable libavformat support
  --disable-ffms           disable ffmpegsource support
  --disable-gpac           disable gpac support
  --disable-lsmash         disable lsmash support
  • --prefix 设置编译结果输出目录,一般规范都会存在这个参数
  • --exec-prefix 参数表示我们可以借助这个对编译器(gcc/clang)设置选项 「类似javac设置-classpath」
  • --disable-cli 这个配置是关闭编译命令行工具,在Android,是自己编译代码,用不到,也可以不管,倒库的是后不用就好
  • --enable-shared &编译成静态库是动态库.so
  • --enable-static 编译成静态库.a
  • --enable-debug & --enable-gprof & --enable-strip 给编译器传递参数 相当 gcc -g / clang -g
  • --enable-pic 如果编译Android使用的动态库,使用PIC 指令。有的--with-pic. 一些脚本没有提供那么我们可以加上gcc -fPIC 通过 CFLAGS 变量 CFLAGS=“-g -fPIC -xxx" 开启 x264 还给我们提供了跨平台的参数Configuration options: --cross-prefix --cross-prefix=前缀- 那么我们相当于使用“gcc xxx.c” 就会用 “前缀-gcc xxxx.c” 编译 --sysroot 查找库,有点类似-L 使用。但是有区别 --extra-cflags 作为传递给编译器的参数,所以就算有些库没有--extra-cflags配置,我们也可以自己创建变量cFLAGS传参

虽然x264提供了交叉编译配置:--cross-prefix,如--corss-prefix=/NDK/arm-linux-androideabi-
那么则会使用 /NDK/arm-linux-androideabi-gcc 来编译
然而ndk19开始gcc已经被移除,由clang替代。
小常识:一般的库都会使用$CC 变量来保存编译器,我们自己设置CC变量的值为clang。

export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++

mac 脚本

#!/bin/bash
# NDK目录
NDK_ROOT=/Users/jiangbin/Library/Android/sdk/ndk/21.1.6352462
#编译后安装位置 pwd表示当前目录
PREFIX=`pwd`/android/armeabi-v7a
#目标平台版本,我们将兼容到android-21
API=21
#编译工具链目录
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/darwin-x86_64

#小技巧,创建一个AS的NDK工程,执行编译,
#然后在 app/.cxx/cmake/debug(release)/自己要编译的平台/ 目录下自己观察 build.ninja与 rules.ninja

# 虽然x264提供了交叉编译配置:--cross-prefix,如--corss-prefix=/NDK/arm-linux-androideabi-
# 那么则会使用 /NDK/arm-linux-androideabi-gcc 来编译
# 然而ndk19开始gcc已经被移除,由clang替代。
# 小常识:一般的库都会使用$CC 变量来保存编译器,我们自己设置CC变量的值为clang。

export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++


#--extra-cflags会附加到CFLAGS 变量之后,作为传递给编译器的参数,所以就算有些库没有--extra-cflags配置,我们也可以自己创建变量cFLAGS传参
FLAGS="--target=armv7-none-linux-androideabi21 --gcc-toolchain=${TOOLCHAIN}  -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security   -Oz -DNDEBUG  -fPIC "


# echo ${FLAGS}


# prefix: 指定编译结果的保存目录 `pwd`: 当前目录
./configure --prefix=${PREFIX} \
--disable-cli \
--enable-static \
--enable-pic=no \
--host=arm-linux \
--cross-prefix=${TOOLCHAIN}/bin/arm-linux-androideabi- \
--sysroot=${TOOLCHAIN}/sysroot \
--extra-cflags=$FLAGS

make install

编译脚本修改,编译 armeabi-v7a arm64-v8a x86_64

x86编译不成功

脚本文件目录结构如下:

image-20210325141328297

config.sh

#NDK路径
export ANDROID_NDK_ROOT=/Users/jiangbin/Library/Android/sdk/ndk/21.1.6352462

export AOSP_TOOLCHAIN_SUFFIX=4.9

export AOSP_API="android-21"
#目标平台版本,我们将兼容到android-21
API=21

#架构
if [ "$#" -lt 1 ]; then
    THE_ARCH=armv7
else
    THE_ARCH=$(tr [A-Z] [a-z] <<< "$1")
fi

#根据不同架构配置环境变量
case "$THE_ARCH" in
  armv7a|armeabi-v7a)
    TOOLCHAIN_BASE="arm-linux-androideabi"
    TOOLNAME_BASE="arm-linux-androideabi"
    AOSP_ABI="armeabi-v7a"
    AOSP_ARCH="arch-arm"
    HOST="arm-linux-androideabi"
    AOSP_FLAGS="-march=armv7-a -mthumb -mfpu=vfpv3-d16 -mfloat-abi=softfp -Wl,--fix-cortex-a8 -funwind-tables -fexceptions -frtti"
    FF_EXTRA_CFLAGS="-DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 "
    FF_CFLAGS="-O3 -Wall -pipe -ffast-math -fstrict-aliasing -Werror=strict-aliasing -Wno-psabi -Wa,--noexecstack -DANDROID  "
    ;;
  armv8|armv8a|aarch64|arm64|arm64-v8a)
    TOOLCHAIN_BASE="aarch64-linux-android"
    TOOLNAME_BASE="aarch64-linux-android"
    AOSP_ABI="arm64-v8a"
    AOSP_ARCH="arch-arm64"
    HOST="aarch64-linux"
    AOSP_FLAGS="-funwind-tables -fexceptions -frtti"
    FF_EXTRA_CFLAGS=""
    FF_CFLAGS="-O3 -Wall -pipe -ffast-math -fstrict-aliasing -Werror=strict-aliasing -Wno-psabi -Wa,--noexecstack -DANDROID  "
    ;;
  x86)
    TOOLCHAIN_BASE="x86"
    TOOLNAME_BASE="i686-linux-android"
    AOSP_ABI="x86"
    AOSP_ARCH="arch-x86"
    HOST="i686-linux"
    AOSP_FLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -funwind-tables -fexceptions -frtti"
    FF_EXTRA_CFLAGS="-O3 -DANDROID -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -fomit-frame-pointer -march=k8 "
    FF_CFLAGS="-O3 -Wall -pipe -ffast-math -fstrict-aliasing -Werror=strict-aliasing -Wno-psabi -Wa,--noexecstack -DANDROID  "
    ;;
  x86_64|x64)
    TOOLCHAIN_BASE="x86_64"
    TOOLNAME_BASE="x86_64-linux-android"
    AOSP_ABI="x86_64"
    AOSP_ARCH="arch-x86_64"
    HOST="x86_64-linux"
    AOSP_FLAGS="-march=x86-64 -msse4.2 -mpopcnt -mtune=intel -funwind-tables -fexceptions -frtti"
    FF_EXTRA_CFLAGS="-O3 -DANDROID -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -fomit-frame-pointer -march=k8 "
    FF_CFLAGS="-O3 -Wall -pipe -ffast-math -fstrict-aliasing -Werror=strict-aliasing -Wno-psabi -Wa,--noexecstack -DANDROID  "
    ;;
  *)
    echo "ERROR: Unknown architecture $1"
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
    ;;
esac

echo "TOOLCHAIN_BASE="$TOOLCHAIN_BASE
echo "TOOLNAME_BASE="$TOOLNAME_BASE
echo "AOSP_ABI="$AOSP_ABI
echo "AOSP_ARCH="$AOSP_ARCH
echo "AOSP_FLAGS="$AOSP_FLAGS
echo "HOST="$HOST

build_x264.sh

#!/bin/bash

ARCH=$1
#目标平台版本,我们将兼容到android-21
API=21


source config.sh $ARCH
LIBS_DIR=$(cd `dirname $0`; pwd)/libs/libx264
echo "LIBS_DIR="$LIBS_DIR

#echo "ANDROID_NDK_ROOT="$ANDROID_NDK_ROOT

cd x264

PREFIX=$LIBS_DIR/$AOSP_ABI
TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/darwin-x86_64
SYSROOT=${TOOLCHAIN}/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/$TOOLNAME_BASE-


#根据不同架构配置环境变量
case "$THE_ARCH" in
  armv7a|armeabi-v7a)
    export CC=${TOOLCHAIN}/bin/armv7a-linux-androideabi$API-clang
    export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
    ;;
  armv8|armv8a|aarch64|arm64|arm64-v8a)
    export CC=${TOOLCHAIN}/bin/aarch64-linux-android$API-clang
    export CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
    ;;
  x86)
    export CC=${TOOLCHAIN}/bin/i686-linux-android$API-clang
    export CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
    ;;
  x86_64|x64)
    export CC=${TOOLCHAIN}/bin/x86_64-linux-android$API-clang
    export CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
    ;;
  *)
    echo "ERROR: Unknown architecture $1"
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
    ;;
esac

# echo "TOOLCHAIN="$TOOLCHAIN


# echo "CC="$CC
# echo "CXX="$CXX

./configure --prefix=$PREFIX \
--enable-static \
--enable-pic \
--disable-cli \
--host=$HOST \
--cross-prefix=${TOOLCHAIN}/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic" \
--extra-ldflags=""

make clean
make -j4
make install

cd ..

build_x264_all

for arch in armeabi-v7a arm64-v8a x86_64
do
    bash build_x264.sh $arch
done

运行编译

#编译指定平台
bash build_x264.sh armeabi-v7a
#编译全平台
bash build_all_x264.sh
tree                                                                                                                                                                                                                                                                                           ✔  1530  14:18:10
.
└── libx264
    ├── arm64-v8a
    │   ├── include
    │   │   ├── x264.h
    │   │   └── x264_config.h
    │   └── lib
    │       ├── libx264.a
    │       └── pkgconfig
    │           └── x264.pc
    ├── armeabi-v7a
    │   ├── include
    │   │   ├── x264.h
    │   │   └── x264_config.h
    │   └── lib
    │       ├── libx264.a
    │       └── pkgconfig
    │           └── x264.pc
    └── x86_64
        ├── include
        │   ├── x264.h
        │   └── x264_config.h
        └── lib
            ├── libx264.a
            └── pkgconfig
                └── x264.pc

13 directories, 12 files

生成libx264目录结果

x86平台

bash build_x264.sh x86
In file included from ./common/common.h:808:
./common/x86/util.h:134:9: error: inline assembly requires more registers than available
        "movq       (%2), %%mm5 \n"
        ^
./common/x86/util.h:198:9: error: inline assembly requires more registers than available
        "movq       (%2), %%mm5 \n"
        ^
2 errors generated.

加入编译选项

--disable-asm
image-20210325144725914
image-20210325144825587

你可能感兴趣的:(macos NDK 交叉编译X264)