FFMPEG - Android NDK编译ffmpeg带openssl

781 阅读1分钟

编译环境

编译openssl

1. 创建openssl编译脚本

下载openssl解压后在openssl根目录新建compile-android-openssl.sh,编辑内容如下

#!/bin/bash

API=21
export NDK=/Users/patrick/CodeLibraries/ndk/android-ndk-r17c

compile() {
    CPU=$1
    PLATFORM=$2
    CPU_ARCH=
    if [[ $CPU = "arm" ]]; then
        CPU_ARCH="armeabi-v7a"
    elif [[ $CPU = "arm64" ]]; then
        CPU_ARCH="arm64-v8a"
    else
        echo "\n======================================================================"
        echo "[*] cpu arch error ..."
        echo "======================================================================\n"
        exit 1
    fi

    echo "\n======================================================================"
    echo "[*] start compile openssl for android $CPU_ARCH ..."
    echo "======================================================================\n"

    echo "\n======================================================================"
    echo "[*] make clean ..."
    echo "======================================================================\n"

    make clean
    rm -rf $(pwd)/android/$CPU_ARCH
    export ANDROID_NDK_HOME=$NDK
    PATH=$ANDROID_NDK_HOME/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64/bin:$PATH

    echo "\n======================================================================"
    echo "[*] configure ..."
    echo "======================================================================\n"

    ./Configure \
        android-$CPU \
        -D__ANDROID_API__=$API \
        --prefix=$(pwd)/android/$CPU_ARCH \
        --openssldir=$(pwd)/android/$CPU_ARCH \
        no-shared no-ssl2 no-ssl3 no-comp no-hw no-engine

    echo "\n======================================================================"
    echo "[*] make ..."
    echo "======================================================================\n"
    make

    echo "\n======================================================================"
    echo "[*] make intall ..."
    echo "======================================================================\n"
    make install

    echo "\n======================================================================"
    echo "[*] openssl compile finished!"
    echo "======================================================================\n"
}

# compile armeabi-v7a
compile arm arm-linux-androideabi

# compile arm64-v8a
compile arm64 aarch64-linux-android

2.执行编译

sh compile-android-openssl.sh

编译完成后在openssl根目录下会生成android/armeabi-v7a和android/arm64-v8a目录 include/openssl里面是头文件, lib里面是动态库.so和静态库.a,根据需要copy使用即可

Screen Shot 2021-10-23 at 3.55.19 PM.png

Screen Shot 2021-10-23 at 3.55.45 PM.png

编译FFmpeg with openssl

1. ffmpeg源码修改

因为ndk版本与ffmpeg版本的兼容问题,编译前需要将ffmpeg中的部分源码进行修改,以解决编译中会出现的错误:

  • 错误1: 修改libavcodec/aaccoder.c 将其中的B0全部改为b0

    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;
    
  • 错误2: 修改libavcodec/hevc_mvs.c 将其中的B0、xB0、yB0全部改为b0、xb0、yb0

    libavcodec/hevc_mvs.c: In function 'derive_spatial_merge_candidates':
    libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function)
                 ((y ## v) >> s->ps.sps->log2_min_pu_size))
                   ^
    libavcodec/hevc_mvs.c:204:14: note: in definition of macro 'TAB_MVF'
         tab_mvf[(y) * min_pu_width + x]
                  ^
    libavcodec/hevc_mvs.c:274:16: note: in expansion of macro 'TAB_MVF_PU'
         (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA))
                    ^
    libavcodec/hevc_mvs.c:368:23: note: in expansion of macro 'AVAILABLE'
         is_available_b0 = AVAILABLE(cand_up_right, B0) &&
    
  • 错误3: 修改libavcodec/opus_pvq.c 将其中的B0全部改为b0

    libavcodec/opus_pvq.c:498:9: error: expected identifier or '(' before numeric constant
         int B0 = blocks;
             ^
    libavcodec/opus_pvq.c:559:12: error: lvalue required as left operand of assignment
             B0 = blocks;
    
  • 修改configure将android的编译器从clang改为gcc

    set_default target_os
    if test "$target_os" = android; then
        cc_default="gcc"
    fi
    

2. 创建带openssl的ffmpeg编译脚本

在ffmpeg源码根目录新建compile-android-ffmpeg-with-openssl.sh,编辑内容如下:

#!/bin/bash

set -e

echo_header_line() {
    echo "\n======================================================================"
}
echo_foot_line() {
    echo "======================================================================\n"
}

ANDROID_API=21
# set ndk root dir
export NDK=/Users/patrick/CodeLibraries/ndk/android-ndk-r17c

compile_android() {

    CPU=$1
    PLATFORM=$2
    CPU_ARCH=
    if [[ $CPU = "arm" ]]; then
        CPU_ARCH="armeabi-v7a"
    elif [[ $CPU = "arm64" ]]; then
        CPU_ARCH="arm64-v8a"
    else    
        echo_header_line
        echo "[*] cpu arch error ..."
        echo_foot_line
        exit 1
    fi

    SYSROOT=$NDK/platforms/android-$ANDROID_API/arch-$CPU
    TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
    CROSS_PREFIX=$TOOLCHAIN/bin/$PLATFORM-
    ISYSROOT=$NDK/sysroot
    ASM=$ISYSROOT/usr/include/$PLATFORM
    PREFIX=$(pwd)/android/$CPU_ARCH

    # 设置编译好的openssl目录
    OPENSSL_DIR=/Users/patrick/CodeLibraries/ffmpeg/openssl-1.1.1l/android/$CPU_ARCH
    export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$OPENSSL_DIR/lib/pkgconfig

    echo_header_line
    echo "[*] ffmpeg compile for android $CPU_ARCH start ..."
    echo_foot_line

    # set config
    FF_CONFIG=
    FF_CONFIG="$FF_CONFIG --target-os=android"
    FF_CONFIG="$FF_CONFIG --prefix=$PREFIX"
    FF_CONFIG="$FF_CONFIG --enable-cross-compile"
    FF_CONFIG="$FF_CONFIG --cross-prefix=$CROSS_PREFIX"
    FF_CONFIG="$FF_CONFIG --enable-static"
    FF_CONFIG="$FF_CONFIG --enable-small"
    FF_CONFIG="$FF_CONFIG --enable-neon"
    FF_CONFIG="$FF_CONFIG --enable-hwaccels"
    FF_CONFIG="$FF_CONFIG --enable-openssl"
    FF_CONFIG="$FF_CONFIG --pkg-config=pkg-config"
    FF_CONFIG="$FF_CONFIG --enable-protocols"
    FF_CONFIG="$FF_CONFIG --disable-shared"
    FF_CONFIG="$FF_CONFIG --disable-doc"
    FF_CONFIG="$FF_CONFIG --disable-ffmpeg"
    FF_CONFIG="$FF_CONFIG --disable-ffplay"
    FF_CONFIG="$FF_CONFIG --disable-ffprobe"
    FF_CONFIG="$FF_CONFIG --disable-avdevice"
    FF_CONFIG="$FF_CONFIG --disable-symver"
    FF_CONFIG="$FF_CONFIG --arch=$CPU"
    FF_CONFIG="$FF_CONFIG --sysroot=$SYSROOT"

    # set cflags
    FF_CFLAGS=
    FF_CFLAGS="$FF_CFLAGS -I$ASM -isysroot $ISYSROOT"
    FF_CFLAGS="$FF_CFLAGS -I$ASM -I$OPENSSL_DIR/include -fPIE -pie"
    FF_CFLAGS="$FF_CFLAGS -D__ANDROID_API__=$ANDROID_API"
    FF_CFLAGS="$FF_CFLAGS -U_FILE_OFFSET_BITS"
    FF_CFLAGS="$FF_CFLAGS -Os -fPIC -DANDROID -Wno-deprecated"

    if [[ $CPU = "arm" ]]; then
        FF_CFLAGS="$FF_CFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -marm"
    elif [[ $CPU = "arm64" ]]; then
        FF_CFLAGS="$FF_CFLAGS -march=armv8-a"
    else    
        echo_header_line
        echo "[*] cpu arch error ..."
        echo_foot_line
        exit 1
    fi
    
    # set ldflags
    FF_LDFLAGS=
    FF_LDFLAGS="$FF_LDFLAGS -L$OPENSSL_DIR/lib -lssl -lcrypto"

    ADDITIONAL_FLAGS=

    echo_header_line
    echo "[*] configure ..."
    echo_foot_line

    ./configure $FF_CONFIG \
        --extra-cflags="$FF_CFLAGS" \
        --extra-ldflags="$FF_LDFLAGS" \
        $ADDITIONAL_FLAGS \

    echo_header_line
    echo "[*] clean output dir ..."
    echo "[*] rm -rf $PREFIX"
    echo_foot_line
    rm -rf $PREFIX

    echo_header_line
    echo "[*] make clean ..."
    echo_foot_line
    make clean

    echo_header_line
    echo "[*] make ..."
    echo_foot_line
    make -j8

    echo_header_line
    echo "[*] make install ..."
    echo_foot_line
    make install

    echo_header_line
    echo "[*] ndk package ..."
    echo_foot_line
    $TOOLCHAIN/bin/$PLATFORM-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 \
        libavfilter/libavfilter.a \
        libavformat/libavformat.a \
        libavutil/libavutil.a \
        libswresample/libswresample.a \
        libswscale/libswscale.a \
        -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
        $TOOLCHAIN/lib/gcc/$PLATFORM/4.9.x/libgcc.a
 
    $TOOLCHAIN/bin/$PLATFORM-strip  $PREFIX/libffmpeg.so
    
    echo_header_line
    echo "[*] ffmpeg compile finished!"
    echo_foot_line

    echo_header_line
    echo "[*] $PREFIX"
    echo_foot_line
}

# compile armeabi-v7a
compile_android arm arm-linux-androideabi
# compile arm64-v8a
compile_android arm64 aarch64-linux-android

4. 编译

sh compile-android-ffmpeg-with-openssl.sh

编译完成后在ffmpeg的根目录下会生成android/armeabi-v7a和android/arm64-v8a目录 .so文件和相关的.h文件就在对应的架构目录下

/Users/patrick/CodeLibraries/ffmpeg-4.4/android/armv7-a

Screen Shot 2021-10-23 at 1.43.35 PM.png