Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264

ubuntu系统安装就不多说了,问度娘去,相关文章非常多。

本文章着重介绍如何交叉编译ffmpeg以及libx264。

一、下载安装NDK r21e

 进入官方网站,NDK 下载  |  Android NDK  |  Android Developers

 到不受支持的旧版本中卑微的下载r21e版本,不要问为什么卑微,因为支持的版本笔者交叉编译编不过【笑哭】, 如果有大神编过了希望分享一下脚本。

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第1张图片

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第2张图片

下载linux系统的包,并解压到/home/selivert/ndk/android-ndk-r21e。 

 OK,交叉编译器到此就准备好了。

二、下载安装编译x264

到github上  https://code.videolan.org/videolan/x264

 clone或者download随意,源码搞到后放到/home/selivert/x264目录下。

源码有了,接下来就是开始交叉编译了。

先在/home/selivert/x264目录下创建脚本文件x264_build_android.sh

touch x264_build_android.sh

 随后将文件赋予执行权限,此处直接上全部权限

sudo chmod 777 x264_build_android.sh

 文件创建成功,接下来就是执行脚本内容了

#!/bin/bash

export NDK=/home/selivert/ndk/android-ndk-r21e #NDK path
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
export API=21 #对应android sdk版本 

function build_android
{
APP_ABI=$1
  echo "======== > Start build $APP_ABI"
  case ${APP_ABI} in
  armeabi-v7a)
    HOST=armv7a-linux-android
    CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
    ;;
  arm64-v8a)
    HOST=aarch64-linux-android
    CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
    ;;
  esac

./configure \
	--prefix=$PREFIX \
	--disable-cli \
	--enable-shared \
	--enable-pic \
	--enable-static \
	--enable-strip \
	--cross-prefix=$CROSS_PREFIX \
	--sysroot=$SYSROOT \
	--host=$HOST

make clean

make -j4

make install
}

PREFIX=`pwd`/android/armeabi-v7a
SYSROOT=$TOOLCHAIN/sysroot
export TARGET=armv7a-linux-androideabi
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++

build_android armeabi-v7a

PREFIX=`pwd`/android/arm64-v8a
export TARGET=aarch64-linux-android
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++

build_android arm64-v8a

注意修改一下ndk的路径,改成你实际环境路径,随后执行该脚本。

脚本执行完成后会在当前目录下生成android文件夹,内部对应32位与64位编译结果。

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第3张图片

 lib目录下.so文件与.a文件全都有,如不需要.a文件,上述脚本中将 enable-static 改成 disable-static即可。由于不清楚后面编到ffmpeg中用的什么文件,笔者两个都编了。

ps:这样一番操作下来,编出的so后面还跟个尾巴,不能直接给android使用,至于是否影响ffmpeg集成没有试过,笔者在集成到ffmpeg之前先验证了so是否可以正常执行,所以编入ffmpeg之前去掉了尾巴,说一下怎么去掉尾巴:打开x264目录下得configure文件,搜索 libx264.so,删除libx264.so后面的尾巴 ,改两个地方,改完如下

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第4张图片

再重新执行一下脚本,编出来的so就没有尾巴了。 

三、下载安装ffmpeg

ffmpeg官网地址 FFmpeg

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第5张图片

 进入官网就能看到大大的下载按钮,直接点击,会跳转到具体的下载位置。

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第6张图片

 跳转之后选择红框的更多版本。当前官方的最新版本是5.0.1(交叉编译时使用下述的编译脚本无法将三方库编入到结果中,如果不需要编码功能,可选择该版本),此处推荐4.4.2版本。

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第7张图片

 选一个版本下载后解压到指定目录。笔者解压到/home/selivert/ffmpeg。

然后开始准备编译脚本:创建ffmpeg_build_android.sh文件并给上执行权限。

书写脚本内容

#!/bin/bash
# 用于编译android平台的脚本

# NDK所在目录
NDK_PATH=/home/selivert/ndk/android-ndk-r21e # tag1
# macOS 平台编译,其他平台看一下 $NDK_PATH/toolchains/llvm/prebuilt/ 下的文件夹名称
HOST_PLATFORM=linux-x86_64  #tag1
# minSdkVersion
API=21

TOOLCHAINS="$NDK_PATH/toolchains/llvm/prebuilt/$HOST_PLATFORM"
SYSROOT="$NDK_PATH/toolchains/llvm/prebuilt/$HOST_PLATFORM/sysroot"
# 生成 -fpic 与位置无关的代码
CFLAG="-D__ANDROID_API__=$API -Os -fPIC -DANDROID "
LDFLAG="-lc -lm -ldl -llog "

# 输出目录
PREFIX=`pwd`/android
# 日志输出目录
CONFIG_LOG_PATH=${PREFIX}/log
# 公共配置
COMMON_OPTIONS=
# 交叉配置
CONFIGURATION=

build() {
  APP_ABI=$1
  CFLAG264=-I/home/selivert/x264/android/$APP_ABI/include
  LDFLAG264=-L/home/selivert/x264/android/$APP_ABI/lib
  echo "======== > Start build $APP_ABI"
  case ${APP_ABI} in
  armeabi-v7a)
    ARCH="arm"
    CPU="armv7-a"
    MARCH="armv7-a"
    TARGET=armv7a-linux-androideabi
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"

    # 交叉编译工具前缀
    CROSS_PREFIX="$TOOLCHAINS/bin/arm-linux-androideabi-"
    EXTRA_CFLAGS="$CFLAG -mfloat-abi=softfp -mfpu=vfp -marm -march=$MARCH "
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--enable-neon --cpu=$CPU "
    ;;
  arm64-v8a)
    ARCH="aarch64"
    TARGET=$ARCH-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    EXTRA_CFLAGS="$CFLAG"
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS=""
    ;;
  x86)
    ARCH="x86"
    CPU="i686"
    MARCH="i686"
    TARGET=i686-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    #EXTRA_CFLAGS="$CFLAG -march=$MARCH -mtune=intel -mssse3 -mfpmath=sse -m32"
    EXTRA_CFLAGS="$CFLAG -march=$MARCH  -mssse3 -mfpmath=sse -m32 "
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--cpu=$CPU "
    ;;
  x86_64)
    ARCH="x86_64"
    CPU="x86-64"
    MARCH="x86_64"
    TARGET=$ARCH-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    #EXTRA_CFLAGS="$CFLAG -march=$CPU -mtune=intel -msse4.2 -mpopcnt -m64"
    EXTRA_CFLAGS="$CFLAG -march=$CPU -msse4.2 -mpopcnt -m64 "
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--cpu=$CPU "
    ;;
  esac

  echo "-------- > Start clean workspace"

make clean

  echo "-------- > Start build configuration"
  CONFIGURATION="$COMMON_OPTIONS"
  CONFIGURATION="$CONFIGURATION --logfile=$CONFIG_LOG_PATH/config_$APP_ABI.log"
  CONFIGURATION="$CONFIGURATION --prefix=$PREFIX"
  CONFIGURATION="$CONFIGURATION --libdir=$PREFIX/libs/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --incdir=$PREFIX/includes/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --pkgconfigdir=$PREFIX/pkgconfig/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --cross-prefix=$CROSS_PREFIX"
  CONFIGURATION="$CONFIGURATION --arch=$ARCH"
  CONFIGURATION="$CONFIGURATION --sysroot=$SYSROOT"
  CONFIGURATION="$CONFIGURATION --cc=$CC"
  CONFIGURATION="$CONFIGURATION --cxx=$CXX"
  CONFIGURATION="$CONFIGURATION --ld=$LD"
  # nm 和 strip
  CONFIGURATION="$CONFIGURATION --nm=$TOOLCHAINS/bin/llvm-nm"
  CONFIGURATION="$CONFIGURATION --strip=$TOOLCHAINS/bin/llvm-strip"
  CONFIGURATION="$CONFIGURATION $EXTRA_OPTIONS"

  echo "-------- > Start config makefile with $CONFIGURATION --extra-cflags=${EXTRA_CFLAGS}${CFLAG264} --extra-ldflags=${EXTRA_LDFLAGS}${LDFLAG264}"

  ./configure ${CONFIGURATION} \
  --extra-cflags="$EXTRA_CFLAGS$CFLAG264" \
  --extra-ldflags="$EXTRA_LDFLAGS$LDFLAG264"

  echo "-------- > Start make $APP_ABI with -j1"
  make -j1
  echo "-------- > Start install $APP_ABI"
  make install
  echo "++++++++ > make and install $APP_ABI complete."
}

build_all() {
  #配置开源协议声明
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-gpl"
  #目标android平台
  COMMON_OPTIONS="$COMMON_OPTIONS --target-os=android"
  #取消默认的静态库
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-static"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-shared"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-protocols"
  #开启交叉编译
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-cross-compile"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-optimizations"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-debug"
  #尽可能小
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-small"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-doc"
  #不要命令(执行文件)
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-programs"  # do not build command line programs
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffmpeg"    # disable ffmpeg build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffplay"    # disable ffplay build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffprobe"   # disable ffprobe build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-symver"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-network"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-x86asm"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-asm"
  #启用
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-pthreads"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-mediacodec"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-jni"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-zlib"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-pic"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-libx264"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-encoder=libx264"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-encoder=h264"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-muxer=flv"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-encoder=h264"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=mpeg4"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=mjpeg"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=png"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=vorbis"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=opus"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=flac"
  echo "COMMON_OPTIONS=$COMMON_OPTIONS"
  echo "PREFIX=$PREFIX"
  echo "CONFIG_LOG_PATH=$CONFIG_LOG_PATH"
  mkdir -p ${CONFIG_LOG_PATH}
  build "armeabi-v7a"
  build "arm64-v8a"
  #build "x86"
  #build "x86_64"
}

echo "-------- Start --------"
build_all
echo "-------- End --------"

 其中 enable-libx264 与

CFLAG264=-I/home/selivert/x264/android/$APP_ABI/include
LDFLAG264=-L/home/selivert/x264/android/$APP_ABI/lib

声明了要集成x264并指明依赖三方库x264的位置,一个头文件,一个是库文件。

随后执行脚本,等待编译结果。编译成功后,会在当前目录生成android文件夹,其内包含各种编译产出。此处主要关注includes与libs文件夹,内部区分32位和64位结果。此处同样编出了.a(static)和.so(share)文件,读者可根据需要修改脚本只编so或者.a文件

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第8张图片

 至此,适用于安卓平台的集成x264编码器的ffmpeg就编译完成啦,接下来就是使用这个去进行编解码验证了。

怎么验证咱们下期再说,此处先给大家看一下结果。输出的是ffmpeg中名称包含‘6’的编码器

Android FFMPEG编解码实践(一):Ubuntu 22.04 NDK编译FFMPEG+libx264_第9张图片

ok,libx264已经成功编入ffmpeg,大功告成。 

参考资料

​​​​​​window 10 下安装 Ubuntu 22.04 使用 NDK r24 编译FFmpeg 5.1 - 简书

 编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac)_剑西的博客-CSDN博客

编译x264_胡刚2016的博客-CSDN博客_x264 编译

你可能感兴趣的:(FFMPEG,android)