编译适配纯鸿蒙系统的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中,可以正常运行。至此文章结束。

相关推荐
周胡杰10 小时前
组件导航 (HMRouter)+flutter项目搭建-混合开发+分栏效果
前端·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
bestadc10 小时前
鸿蒙 Core File Kit(文件基础服务)之简单使用文件
harmonyos
SuperHeroWu712 小时前
【HarmonyOS 5】鸿蒙星闪NearLink详解
华为·蓝牙·harmonyos·nearlink·鸿蒙星闪·绿牙
追随远方13 小时前
FFmpeg在Android开发中的核心价值是什么?
android·ffmpeg
积跬步DEV14 小时前
RN 鸿蒙混合开发实践(踩坑)
react native·华为·harmonyos
视频砖家17 小时前
如何设置FFmpeg实现对高分辨率视频进行转码
ffmpeg·音视频·视频编解码·视频转码
繁依Fanyi18 小时前
我的 PDF 工具箱:CodeBuddy 打造 PDFMagician 的全过程记录
java·pdf·uni-app·生活·harmonyos·codebuddy首席试玩官
Huang兄18 小时前
#跟着若城学鸿蒙# web篇-获取定位
harmonyos
yanjiee19 小时前
视频质量分析时,遇到不同分辨率的对照视频和源视频,分辨率对齐的正确顺序。
ffmpeg·音视频
Sleepless_斑马19 小时前
【FFmpeg+SDL】使用FFmpeg捕获屏幕,SDL显示
ffmpeg