编译适配纯鸿蒙系统的ijkplayer中的ffmpeg库

目前bilibili官方的ijkplayer播放器,是只适配Android和IOS系统的。而华为接下来即将发布纯harmony系统,是否有基于harmony系统的ijkplayer可以使用呢?

鸿蒙版ijkplayer播放器是哪个,如何使用,这个问题,大家可以参考我另一个技术号的文章先行了解一下:鸿蒙版ijkplayer播放器示例工程适配运行

不过上述提到的这个被鸿蒙化的ijkplayer播放器,里面的ffmpeg库是以已经编译好的ffmpeg的动态库集成进去的。对于需要修改ffmpeg代码的人来说,还需要知道如何编译适配harmony系统的ffmpeg库,从而来替代这个鸿蒙版ijkplayer中的ffmpeg库。

因此本文想要讲解的重点是,如何从之前的安卓版的ijkplayer仓库中,将ffmpeg编译出适配harmony系统的动态库。

一、基于openHarmony环境编译开源库

在本文主题正式开始之前,大家也可以通过我另一个技术号的这篇文章,需要先行了解一下如何基于openHarmony环境编译适配harmony系统的动态库:

基于openHarmony环境编译开源库

二、编译前准备

编译之前,需要搭建的编译环境,需要下载的工具等。可以先大致参考之前安卓版本的编译环境,可从这篇文章中先行了解一下编译环境即可:ijkplayer编译流程详解

PS:其中与安卓相关的配置可以不用做。因为对应的是需要下载鸿蒙的编译工具链和文件系统等。

三、修改编译脚本

我们从上述二中的安卓版的ijkplayer仓库中,对主要编译脚本进行修改,来进行适配。

主要需要修改的就是android\contrib\tools下的三个脚本:do-compile-openssl.shdo-compile-ffmpeg.sh和do-detect-env.sh

在修改这3个脚本之前,根据"一"中文章所述,先提前下载好鸿蒙的交叉编译工具和文件系统,并在这3个脚本的编译前置脚本中(compile-openssl.sh和compile-ffmpeg.sh),将交叉工具链和文件系统的路径export出来,或者在全局环境变量/etc/profile配置文件export出来路径,如下:

bash 复制代码
export OHOS_SYSROOT=/home/weekend/openharmony/ohos-sdk/linux/native/sysroot
export OHOS_LLVM=/home/weekend/openharmony/ohos-sdk/linux/native/llvm

OHOS_SYSROOT和OHOS_LLVM变量在后续的脚本中都是需要的。

1、修改do-detect-env.sh

do-detect-env.sh脚本主要用来检测编译环境的,在安卓版本中,会检查安卓sdk版本,ndk之类的。在鸿蒙版本中这些就都不需要了。我将这些都去掉。

然后增加鸿蒙的编译工具链和文件系统的检查,如下:

bash 复制代码
if [ -z "$OHOS_LLVM" ]; then
    echo "You must define OHOS_LLVM before starting."
	echo "sysroot and llvm is necessary.\n"
    exit 1
fi

if [ -z "$OHOS_SYSROOT" ]; then
    echo "You must define OHOS_SYSROOT before starting."
    echo "sysroot and llvm is necessary.\n"
    exit 1
fi

实际上,我在3个脚本的开头处,都会对这个进行检查。

附上完整的修改后的 do-detect-env.sh

bash 复制代码
#! /usr/bin/env bash
#
#--------------------
set -e
UNAME_S=$(uname -s)
UNAME_SM=$(uname -sm)
echo "build on $UNAME_SM"

echo "OHOS_SYSROOT=$OHOS_SYSROOT"
echo "OHOS_LLVM=$OHOS_LLVM"

if [ -z "$OHOS_LLVM" ]; then
    echo "You must define OHOS_LLVM before starting."
	echo "sysroot and llvm is necessary.\n"
    exit 1
fi

if [ -z "$OHOS_SYSROOT" ]; then
    echo "You must define OHOS_SYSROOT before starting."
    echo "sysroot and llvm is necessary.\n"
    exit 1
fi


# try to detect NDK version
export IJK_GCC_VER=4.9
export IJK_GCC_64_VER=4.9
export IJK_MAKE_TOOLCHAIN_FLAGS=
export IJK_MAKE_FLAG=

case "$UNAME_S" in
    Darwin)
        export IJK_MAKE_FLAG=-j`sysctl -n machdep.cpu.thread_count`
    ;;
    CYGWIN_NT-*)
        IJK_WIN_TEMP="$(cygpath -am /tmp)"
        export TEMPDIR=$IJK_WIN_TEMP/

        echo "Cygwin temp prefix=$IJK_WIN_TEMP/"
    ;;
esac

2、修改do-compile-openssl.sh

do-compile-openssl.sh根据"二"中描述,主要是用于编译openssl的。根据上述"一"中的文章所述,主要是需要修改交叉编译工具链,和文件系统。

将安卓NDK和交叉编译工具链相关的去掉,FF_CROSS_PREFIX=aarch64-linux-android这个是安卓的交叉工具链头,用的gcc。修改为export CC 后面跟着鸿蒙的交叉工具链是llvm目录下的clang,然后target=aarch64-linux-ohos,指明是64位的。

bash 复制代码
CLANG=$OHOS_LLVM/bin/clang

export CC="$CLANG $OHOS_CFLAGS"
export CFLAGS="$OHOS_CFLAGS --sysroot=${OHOS_SYSROOT}"

安卓的脚本中有FF_TOOLCHAIN_TOUCH,主要是安卓的ndk中提供的用于交叉编译的一些工具包。在鸿蒙的编译中,这一块就不需要了,直接去掉。就是下面这段是不需要了的:

bash 复制代码
FF_MAKE_TOOLCHAIN_FLAGS=$IJK_MAKE_TOOLCHAIN_FLAGS
FF_MAKE_FLAGS=$IJK_MAKE_FLAG


FF_MAKE_TOOLCHAIN_FLAGS="$FF_MAKE_TOOLCHAIN_FLAGS --install-dir=$FF_TOOLCHAIN_PATH"
FF_TOOLCHAIN_TOUCH="$FF_TOOLCHAIN_PATH/touch"
if [ ! -f "$FF_TOOLCHAIN_TOUCH" ]; then
    $ANDROID_NDK/build/tools/make-standalone-toolchain.sh \
        $FF_MAKE_TOOLCHAIN_FLAGS \
        --platform=$FF_ANDROID_PLATFORM \
        --toolchain=$FF_TOOLCHAIN_NAME
    touch $FF_TOOLCHAIN_TOUCH;
fi

只需要在后面编译的时候,指明CFLAGS=--sysroot=xxx,跟着鸿蒙的文件系统目录。

bash 复制代码
export CFLAGS="$OHOS_CFLAGS --sysroot=${OHOS_SYSROOT}"

为了确保编译,可以将这些关键的编译相关的都export出来,如下:

bash 复制代码
export CC="$CLANG $OHOS_CFLAGS"
export CXX="$CLANGXX $OHOS_CFLAGS"
export AR=${OHOS_AR}
export AS=${OHOS_AS}
export NM=${OHOS_NM}
export STRIP=${OHOS_STRIP}
export RANLIB=${OHOS_RANLIB}
export LD=${OHOS_LD}
export LDFLAGS="--rtlib=compiler-rt -fuse-ld=lld"
export CFLAGS="$OHOS_CFLAGS --sysroot=${OHOS_SYSROOT}"

附上完整的do-compile-openssl.sh供参考,我暂时只保留是arm的32位,64位和x86的64位这三个常用的cpu架构编译。具体如下:

bash 复制代码
#! /usr/bin/env bash
#--------------------
set -e
if [ -z "$OHOS_LLVM" ]; then
    echo "You must define OHOS_LLVM before starting."
	echo "sysroot and llvm is necessary.\n"
    exit 1
fi

if [ -z "$OHOS_SYSROOT" ]; then
    echo "You must define OHOS_SYSROOT before starting."
    echo "sysroot and llvm is necessary.\n"
    exit 1
fi

#--------------------
# common defines
FF_ARCH=$1
if [ -z "$FF_ARCH" ]; then
    echo "You must specific an architecture 'arm, armv7a, x86, ...'.\n"
    exit 1
fi


FF_BUILD_ROOT=`pwd`

FF_BUILD_NAME=
FF_SOURCE=
FF_CROSS_PREFIX=

FF_CFG_FLAGS=
FF_PLATFORM_CFG_FLAGS=

FF_EXTRA_CFLAGS=
FF_EXTRA_LDFLAGS=

# compile
CLANG=$OHOS_LLVM/bin/clang
CLANGXX=$OHOS_LLVM/bin/clang++
OHOS_AR=$OHOS_LLVM/bin/llvm-ar
OHOS_AS=$OHOS_LLVM/bin/llvm-as
OHOS_NM=$OHOS_LLVM/bin/llvm-nm
OHOS_RANLIB=$OHOS_LLVM/bin/llvm-ranlib
OHOS_STRIP=$OHOS_LLVM/bin/llvm-strip
OBJDUMP=$OHOS_LLVM/bin/llvm-objdump
OHOS_LD=$OHOS_LLVM/bin/ld.lld

OHOS_LIBS="-L${OHOS_LLVM}/lib"
OHOS_INCS="-I${OHOS_LLVM}/include"

OHOS_CFLAGS=

#--------------------
echo ""
echo "--------------------"
echo "[*] do detect env"
echo "--------------------"
. ./tools/do-detect-env.sh
FF_MAKE_FLAGS=$IJK_MAKE_FLAG


#----- armv7a begin -----
if [ "$FF_ARCH" = "armv7a" ]; then
    FF_BUILD_NAME=openssl-armv7a
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_PLATFORM_CFG_FLAGS="linux-armv4"
	OHOS_CFLAGS="--target=arm-linux-ohos -march=armv7-a"


elif [ "$FF_ARCH" = "arm64" ]; then
    FF_BUILD_NAME=openssl-arm64
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_PLATFORM_CFG_FLAGS="linux-aarch64"
	OHOS_CFLAGS="--target=aarch64-linux-ohos"
	
elif [ "$FF_ARCH" = "x86_64" ]; then
    FF_BUILD_NAME=openssl-x86_64
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_PLATFORM_CFG_FLAGS="linux-x86_64"
	OHOS_CFLAGS="--target=x86_64-linux-ohos"

else
    echo "unknown architecture $FF_ARCH";
    exit 1
fi


FF_SYSROOT=$OHOS_SYSROOT
FF_PREFIX=$FF_BUILD_ROOT/build/$FF_BUILD_NAME/output

mkdir -p $FF_PREFIX
# mkdir -p $FF_SYSROOT

#--------------------
echo ""
echo "--------------------"
echo "[*] check openssl env"
echo "--------------------"
export CC="$CLANG $OHOS_CFLAGS"
export CXX="$CLANGXX $OHOS_CFLAGS"
export AR=${OHOS_AR}
export AS=${OHOS_AS}
export NM=${OHOS_NM}
export STRIP=${OHOS_STRIP}
export RANLIB=${OHOS_RANLIB}
export LD=${OHOS_LD}
export LDFLAGS="--rtlib=compiler-rt -fuse-ld=lld"
export CFLAGS="$OHOS_CFLAGS --sysroot=${OHOS_SYSROOT}"
export COMMON_FF_CFG_FLAGS=

FF_CFG_FLAGS="$FF_CFG_FLAGS $COMMON_FF_CFG_FLAGS"

#--------------------
# Standard options:
FF_CFG_FLAGS="$FF_CFG_FLAGS zlib-dynamic"
FF_CFG_FLAGS="$FF_CFG_FLAGS no-asm"
FF_CFG_FLAGS="$FF_CFG_FLAGS no-shared"
FF_CFG_FLAGS="$FF_CFG_FLAGS -fPIC"
FF_CFG_FLAGS="$FF_CFG_FLAGS --openssldir=$FF_PREFIX"
FF_CFG_FLAGS="$FF_CFG_FLAGS $FF_PLATFORM_CFG_FLAGS"

#--------------------
echo ""
echo "--------------------"
echo "[*] configurate openssl"
echo "--------------------"
cd $FF_SOURCE
#if [ -f "./Makefile" ]; then
#    echo 'reuse configure'
#else
    echo "./Configure $FF_CFG_FLAGS"
    ./Configure $FF_CFG_FLAGS
#fi

#--------------------
echo ""
echo "--------------------"
echo "[*] compile openssl"
echo "--------------------"
make depend
make $FF_MAKE_FLAGS
make install_sw

#--------------------
echo ""
echo "--------------------"
echo "[*] link openssl"
echo "--------------------"

3、修改do-compile-ffmpeg.sh

这个脚本就是真正编译ffmpeg的了,与"2"中的openssl类似,主要是需要修改交叉编译工具链,和文件系统。

同样的与安卓相关的FF_TOOLCHAIN_TOUCH这一段可以去掉的:

bash 复制代码
FF_TOOLCHAIN_TOUCH="$FF_TOOLCHAIN_PATH/touch"
if [ ! -f "$FF_TOOLCHAIN_TOUCH" ]; then
    $ANDROID_NDK/build/tools/make-standalone-toolchain.sh \
        $FF_MAKE_TOOLCHAIN_FLAGS \
        --platform=$FF_ANDROID_PLATFORM \
        --toolchain=$FF_TOOLCHAIN_NAME
    touch $FF_TOOLCHAIN_TOUCH;
fi

将交叉编译工具链中提供的工具等,都export出来,这些可能有些不一定用到,但是export出来有利无害:

bash 复制代码
CLANG=$OHOS_LLVM/bin/clang
CLANGXX=$OHOS_LLVM/bin/clang++
OHOS_AR=$OHOS_LLVM/bin/llvm-ar
OHOS_AS=$OHOS_LLVM/bin/llvm-as
OHOS_NM=$OHOS_LLVM/bin/llvm-nm
OHOS_RANLIB=$OHOS_LLVM/bin/llvm-ranlib
OHOS_STRIP=$OHOS_LLVM/bin/llvm-strip
OBJDUMP=$OHOS_LLVM/bin/llvm-objdump
OHOS_LD=$OHOS_LLVM/bin/ld.lld

OHOS_LIBS="-L${OHOS_LLVM}/lib"
OHOS_INCS="-I${OHOS_LLVM}/include"

同样的将安卓NDK和交叉编译工具链相关的去掉,以arm的64位为例,FF_CROSS_PREFIX=aarch64-linux-android这个是安卓的交叉工具链头,修改为export CC 后面跟着鸿蒙的交叉工具链是llvm目录下的clang,然后FF_EXTRA_CFLAGS和FF_EXTRA_LDFLAGS需要target=aarch64-linux-ohos,指明是64位的,如下:

bash 复制代码
    FF_EXTRA_CFLAGS="$FF_EXTRA_CFLAGS --target=x86_64-linux-ohos"
    FF_EXTRA_LDFLAGS="$FF_EXTRA_LDFLAGS --target=x86_64-linux-ohos"

还需要将相关的系统所需头文件,lib库等指明,用于后续编译链接使用:

bash 复制代码
 OHOS_LIBS="$OHOS_LIBS -L${OHOS_SYSROOT}/usr/lib/aarch64-linux-ohos"
 OHOS_INCS="$OHOS_INCS -I${OHOS_SYSROOT}/usr/include/aarch64-linux-ohos"

后续会用到CC、LD、AR、STRIP这些,需要都指明一下:

bash 复制代码
export CC=${CLANG}
export LD=${OHOS_LD}
export AR=${OHOS_AR}
export STRIP=${OHOS_STRIP}

在ffmpeg的configure中,需要加上--cc,--ld,--strip,如下:

bash 复制代码
if [ -f "./config.h" ]; then
    echo 'reuse configure'
else
    which $CC
    ./configure $FF_CFG_FLAGS \
        --cc=${CLANG} \
        --ld=${CLANG} \
        --strip=${STRIP} \
        --extra-cflags="$FF_CFLAGS $FF_EXTRA_CFLAGS" \
        --extra-ldflags="$FF_DEP_LIBS $FF_EXTRA_LDFLAGS"
    make clean
fi

然后在最后的CC编译链接成动态库中,需要将刚才的OHOS_LIBS和OHOS_INCS都加上,不然编译链接会报找不到一些系统的基本库之类。同时为了保持跟鸿蒙版ijkplayer中的ffmpeg库名字一致,将库名改为.z.so结尾。(这个貌似是无所谓的)。如下:

bash 复制代码
$CC -lm -lz -shared --sysroot=$FF_SYSROOT -Wl,--no-undefined -Wl,-z,noexecstack $FF_EXTRA_LDFLAGS \
    -Wl,-soname,libqfffmpeg.z.so \
    $FF_C_OBJ_FILES \
    $FF_ASM_OBJ_FILES \
    $OHOS_LIBS \
    $OHOS_INCS \
    $FF_DEP_LIBS \
    -o $FF_PREFIX/libqfffmpeg.z.so

另外在编译过程中发现--enable-asm和--enable-inline-asm打开的话,会编译不过,所以这2个改为disable的:

bash 复制代码
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-asm"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-inline-asm"

附上完整的do-compile-ffmpeg.sh供参考,我暂时只保留是arm的32位,64位和x86的64位这三个常用的cpu架构编译。具体如下:

bash 复制代码
#! /usr/bin/env bash
#
#--------------------
echo "===================="
echo "[*] build ffmpeg and check env $1"
echo "===================="
set -e


#--------------------
# common defines
FF_ARCH=$1
FF_BUILD_OPT=$2
echo "FF_ARCH=$FF_ARCH"
echo "FF_BUILD_OPT=$FF_BUILD_OPT"
if [ -z "$FF_ARCH" ]; then
    echo "You must specific an architecture 'arm, armv7a, x86, ...'."
    echo ""
    exit 1
fi

if [ -z "$OHOS_LLVM" ]; then
    echo "You must define OHOS_LLVM before starting."
	echo "sysroot and llvm is necessary.\n"
    exit 1
fi

if [ -z "$OHOS_SYSROOT" ]; then
    echo "You must define OHOS_SYSROOT before starting."
    echo "sysroot and llvm is necessary.\n"
    exit 1
fi


FF_BUILD_ROOT=`pwd`

FF_BUILD_NAME=
FF_SOURCE=
FF_CROSS_PREFIX=
FF_DEP_OPENSSL_INC=
FF_DEP_OPENSSL_LIB=

FF_DEP_LIBSOXR_INC=
FF_DEP_LIBSOXR_LIB=

FF_CFG_FLAGS=

FF_EXTRA_CFLAGS=
FF_EXTRA_LDFLAGS=
FF_DEP_LIBS=

FF_MODULE_DIRS="compat libavcodec libavfilter libavformat libavutil libswresample libswscale"
FF_ASSEMBLER_SUB_DIRS=


#--------------------
echo ""
echo "--------------------"
echo "[*] do detect env"
echo "--------------------"
. ./tools/do-detect-env.sh
FF_MAKE_FLAGS=$IJK_MAKE_FLAG

# compile
CLANG=$OHOS_LLVM/bin/clang
CLANGXX=$OHOS_LLVM/bin/clang++
OHOS_AR=$OHOS_LLVM/bin/llvm-ar
OHOS_AS=$OHOS_LLVM/bin/llvm-as
OHOS_NM=$OHOS_LLVM/bin/llvm-nm
OHOS_RANLIB=$OHOS_LLVM/bin/llvm-ranlib
OHOS_STRIP=$OHOS_LLVM/bin/llvm-strip
OBJDUMP=$OHOS_LLVM/bin/llvm-objdump
OHOS_LD=$OHOS_LLVM/bin/ld.lld

OHOS_LIBS="-L${OHOS_LLVM}/lib"
OHOS_INCS="-I${OHOS_LLVM}/include"

#----- armv7a begin -----
if [ "$FF_ARCH" = "armv7a" ]; then
    FF_BUILD_NAME=ffmpeg-armv7a
    FF_BUILD_NAME_OPENSSL=openssl-armv7a
    FF_BUILD_NAME_LIBSOXR=libsoxr-armv7a
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=arm --cpu=cortex-a8"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-neon"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-thumb"
	
    OHOS_LIBS="$OHOS_LIBS -L${OHOS_SYSROOT}/usr/lib/arm-linux-ohos"
    OHOS_INCS="$OHOS_INCS -I${OHOS_SYSROOT}/usr/include/arm-linux-ohos"

    FF_EXTRA_CFLAGS="$FF_EXTRA_CFLAGS -march=armv7-a -mcpu=cortex-a8 -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb --target=arm-linux-ohos"
    FF_EXTRA_LDFLAGS="$FF_EXTRA_LDFLAGS -Wl,--fix-cortex-a8 --target=arm-linux-ohos"

    FF_ASSEMBLER_SUB_DIRS="arm"

elif [ "$FF_ARCH" = "arm64" ]; then
    FF_BUILD_NAME=ffmpeg-arm64
    FF_BUILD_NAME_OPENSSL=openssl-arm64
    FF_BUILD_NAME_LIBSOXR=libsoxr-arm64
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=aarch64 --enable-yasm"
	
    OHOS_LIBS="$OHOS_LIBS -L${OHOS_SYSROOT}/usr/lib/aarch64-linux-ohos"
    OHOS_INCS="$OHOS_INCS -I${OHOS_SYSROOT}/usr/include/aarch64-linux-ohos"

    FF_EXTRA_CFLAGS="$FF_EXTRA_CFLAGS --target=aarch64-linux-ohos"
    FF_EXTRA_LDFLAGS="$FF_EXTRA_LDFLAGS --target=aarch64-linux-ohos"

    FF_ASSEMBLER_SUB_DIRS="aarch64 neon"
	
elif [ "$FF_ARCH" = "x86_64" ]; then
    FF_BUILD_NAME=ffmpeg-x86_64
    FF_BUILD_NAME_OPENSSL=openssl-x86_64
    FF_BUILD_NAME_LIBSOXR=libsoxr-x86_64
    FF_SOURCE=$FF_BUILD_ROOT/$FF_BUILD_NAME

    FF_CFG_FLAGS="$FF_CFG_FLAGS --arch=x86_64 --enable-yasm"
	
    OHOS_LIBS="$OHOS_LIBS -L${OHOS_SYSROOT}/usr/lib/x86_64-linux-ohos"
    OHOS_INCS="$OHOS_INCS -I${OHOS_SYSROOT}/usr/include/x86_64-linux-ohos"

    FF_EXTRA_CFLAGS="$FF_EXTRA_CFLAGS --target=x86_64-linux-ohos"
    FF_EXTRA_LDFLAGS="$FF_EXTRA_LDFLAGS --target=x86_64-linux-ohos"

    FF_ASSEMBLER_SUB_DIRS="x86"	

else
    echo "unknown architecture $FF_ARCH";
    exit 1
fi

if [ ! -d $FF_SOURCE ]; then
    echo ""
    echo "!! ERROR"
    echo "!! Can not find FFmpeg directory for $FF_BUILD_NAME"
    echo "!! Run 'sh init-android.sh' first"
    echo ""
    exit 1
fi

FF_SYSROOT=$OHOS_SYSROOT
FF_PREFIX=$FF_BUILD_ROOT/build/$FF_BUILD_NAME/output
FF_DEP_OPENSSL_INC=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_OPENSSL/output/include
FF_DEP_OPENSSL_LIB=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_OPENSSL/output/lib
FF_DEP_LIBSOXR_INC=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_LIBSOXR/output/include
FF_DEP_LIBSOXR_LIB=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_LIBSOXR/output/lib

case "$UNAME_S" in
    CYGWIN_NT-*)
        FF_SYSROOT="$(cygpath -am $FF_SYSROOT)"
        FF_PREFIX="$(cygpath -am $FF_PREFIX)"
    ;;
esac


mkdir -p $FF_PREFIX
# mkdir -p $FF_SYSROOT

#--------------------
echo ""
echo "--------------------"
echo "[*] check ffmpeg env"
echo "--------------------"
export CC=${CLANG}
export LD=${OHOS_LD}
export AR=${OHOS_AR}
export STRIP=${OHOS_STRIP}

FF_CFLAGS="-O3 -Wall -pipe \
    -std=c99 \
    -ffast-math \
    -fstrict-aliasing -Werror=strict-aliasing \
    -Wno-psabi -Wa,--noexecstack \
    -DANDROID -DNDEBUG"

# cause av_strlcpy crash with gcc4.7, gcc4.8
# -fmodulo-sched -fmodulo-sched-allow-regmoves

# --enable-thumb is OK
#FF_CFLAGS="$FF_CFLAGS -mthumb"

# not necessary
#FF_CFLAGS="$FF_CFLAGS -finline-limit=300"

export COMMON_FF_CFG_FLAGS=
. $FF_BUILD_ROOT/config/module.sh


#--------------------
# with openssl
if [ -f "${FF_DEP_OPENSSL_LIB}/libssl.a" ]; then
    echo "OpenSSL detected"
# FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-nonfree"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-openssl"

    FF_CFLAGS="$FF_CFLAGS -I${FF_DEP_OPENSSL_INC}"
    FF_DEP_LIBS="$FF_DEP_LIBS -L${FF_DEP_OPENSSL_LIB} -lssl -lcrypto"
fi

FF_CFG_FLAGS="$FF_CFG_FLAGS $COMMON_FF_CFG_FLAGS"

#--------------------
# Standard options:
FF_CFG_FLAGS="$FF_CFG_FLAGS --prefix=$FF_PREFIX"

# Advanced options (experts only):
FF_CFG_FLAGS="$FF_CFG_FLAGS "
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-cross-compile"
FF_CFG_FLAGS="$FF_CFG_FLAGS --target-os=linux"
FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-pic"
# FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-symver"

if [ "$FF_ARCH" = "x86" ]; then
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-asm"
else
    # Optimization options (experts only):
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-asm"
    FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-inline-asm"
fi

case "$FF_BUILD_OPT" in
    debug)
        FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-optimizations"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-debug"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --disable-small"
    ;;
    *)
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-optimizations"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-debug"
        FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-small"
    ;;
esac

#--------------------
echo ""
echo "--------------------"
echo "[*] configurate ffmpeg"
echo "--------------------"
cd $FF_SOURCE
if [ -f "./config.h" ]; then
    echo 'reuse configure'
else
    which $CC
    ./configure $FF_CFG_FLAGS \
        --cc=${CLANG} \
        --ld=${CLANG} \
        --strip=${STRIP} \
        --extra-cflags="$FF_CFLAGS $FF_EXTRA_CFLAGS" \
        --extra-ldflags="$FF_DEP_LIBS $FF_EXTRA_LDFLAGS"
    make clean
fi

#--------------------
echo ""
echo "--------------------"
echo "[*] compile ffmpeg"
echo "--------------------"
cp config.* $FF_PREFIX
make $FF_MAKE_FLAGS > /dev/null
make install
mkdir -p $FF_PREFIX/include/libffmpeg
cp -f config.h $FF_PREFIX/include/libffmpeg/config.h

#--------------------
echo ""
echo "--------------------"
echo "[*] link ffmpeg"
echo "--------------------"
echo $FF_EXTRA_LDFLAGS

FF_C_OBJ_FILES=
FF_ASM_OBJ_FILES=
for MODULE_DIR in $FF_MODULE_DIRS
do
    C_OBJ_FILES="$MODULE_DIR/*.o"
    if ls $C_OBJ_FILES 1> /dev/null 2>&1; then
        echo "link $MODULE_DIR/*.o"
        FF_C_OBJ_FILES="$FF_C_OBJ_FILES $C_OBJ_FILES"
    fi

    for ASM_SUB_DIR in $FF_ASSEMBLER_SUB_DIRS
    do
        ASM_OBJ_FILES="$MODULE_DIR/$ASM_SUB_DIR/*.o"
        if ls $ASM_OBJ_FILES 1> /dev/null 2>&1; then
            echo "link $MODULE_DIR/$ASM_SUB_DIR/*.o"
            FF_ASM_OBJ_FILES="$FF_ASM_OBJ_FILES $ASM_OBJ_FILES"
        fi
    done
done

$CC -lm -lz -shared --sysroot=$FF_SYSROOT -Wl,--no-undefined -Wl,-z,noexecstack $FF_EXTRA_LDFLAGS \
    -Wl,-soname,libqfffmpeg.z.so \
    $FF_C_OBJ_FILES \
    $FF_ASM_OBJ_FILES \
    $OHOS_LIBS \
    $OHOS_INCS \
    $FF_DEP_LIBS \
    -o $FF_PREFIX/libqfffmpeg.z.so

mysedi() {
    f=$1
    exp=$2
    n=`basename $f`
    cp $f /tmp/$n
    sed $exp /tmp/$n > $f
    rm /tmp/$n
}

echo ""
echo "--------------------"
echo "[*] create files for shared ffmpeg"
echo "--------------------"
rm -rf $FF_PREFIX/shared
mkdir -p $FF_PREFIX/shared/lib/pkgconfig
ln -s $FF_PREFIX/include $FF_PREFIX/shared/include
ln -s $FF_PREFIX/libqfffmpeg.z.so $FF_PREFIX/shared/lib/libqfffmpeg.z.so
cp $FF_PREFIX/lib/pkgconfig/*.pc $FF_PREFIX/shared/lib/pkgconfig
for f in $FF_PREFIX/lib/pkgconfig/*.pc; do
    # in case empty dir
    if [ ! -f $f ]; then
        continue
    fi
    cp $f $FF_PREFIX/shared/lib/pkgconfig
    f=$FF_PREFIX/shared/lib/pkgconfig/`basename $f`
    # OSX sed doesn't have in-place(-i)
    mysedi $f 's/\/output/\/output\/shared/g'
    mysedi $f 's/-lavcodec/-lijkffmpeg/g'
    mysedi $f 's/-lavfilter/-lijkffmpeg/g'
    mysedi $f 's/-lavformat/-lijkffmpeg/g'
    mysedi $f 's/-lavutil/-lijkffmpeg/g'
    mysedi $f 's/-lswresample/-lijkffmpeg/g'
    mysedi $f 's/-lswscale/-lijkffmpeg/g'
done

以上便是最关键的3个脚本的修改,按照上述修改后,便可编译适配纯harmony系统的ffmpeg库。大家可以将我上述附上的3个完整的脚本复制出来跟原本安卓版的脚本进行对比,可以更清晰地知道修改什么地方。

四、编译

修改脚本之后,便可跟安卓一样运行脚本编译。

先编译openssl:

bash 复制代码
./compile-openssl.sh clean
./compile-openssl.sh all

然后编译ffmpeg:

bash 复制代码
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all

编译完成后,在contrib/build下会有对应cpu架构的ffmpeg和openssl产物文件夹。例如我编译arm64的:

在ffmpeg-arm64的output目录下,就有最终编译好的libqfffmpeg.z.so动态库:

亲测替换到鸿蒙版的ijkplayer中,可以正常运行。至此文章结束。

相关推荐
sanzk3 小时前
华为鸿蒙应用开发
华为·harmonyos
SoraLuna8 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析9 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg6689 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
模拟IC攻城狮9 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
lqj_本人9 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人9 小时前
使用 Flutter 绘制一个棋盘
harmonyos
TangKenny10 小时前
计算网络信号
java·算法·华为
岁月小龙10 小时前
如何让ffmpeg运行时从当前目录加载库,而不是从/lib64
ffmpeg·origin·ffprobe·rpath
23zhgjx-NanKon10 小时前
华为eNSP:QinQ
网络·安全·华为