Shell生成支持x264的ffmpeg安卓全平台so

安卓 FFmpeg系列

第一章 Ubuntu生成ffmpeg安卓全平台so
第二章 Windows生成ffmpeg安卓全平台so
第三章 生成支持x264的ffmpeg安卓全平台so(本章)


文章目录


前言

前两张实现了ffmpeg全平台so的生成,但是ffmpeg依赖的第三方库是需要另外编译的,所以本章将提供编译x264库并加入ffmpeg的方法。本章提供的脚本在ubuntu以及windows的wsl、msys2都适用。


一、实现步骤

定义交叉编译相关变量

bash 复制代码
#ndk api版本 -可配置
API=24
#cpu 架构 -可配置 :armv7-a、armv8-a、i686、x86-64
CPU=x86-64
#msys则可设置为windows
OS=linux
#需要ANDROID_NDK_HOME指定ndk目录
TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$OS-x86_64
echo $TOOLCHAIN
SYSROOT=$TOOLCHAIN/sysroot
PREFIX=$(pwd)/output/ffmpeg${FFMPEG_VERSION}/${API}/${CPU}
PACKAGE_PREFIX=$PACKAGE_SOURCE_DIR/.output/${API}/${CPU}
export CC=${CROSS_PREFIX}clang
export CXX=${CROSS_PREFIX}clang++
case $CPU in
armv7-a)
  ARCH=arm
  CROSS_PREFIX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-
  ;;
armv8-a)
  ARCH=arm64
  CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android$API-
  ;;
i686)
  ARCH=x86
  CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android$API-
  FFMPEG_EXTRA_CONFIGURE_FLAGS=--disable-asm
  ;;
x86-64)
  ARCH=x86_64
  CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android$API-
  ;;

1、下载x264源码

bash 复制代码
 wget https://code.videolan.org/videolan/x264/-/archive/master/x264-master.tar.bz2
 tar -xf $PACKET_X264.tar.bz2

2、交叉编译生成.a

在x264源码目录执行如下操作。其中X264_OUTPUT_DIR 为输出目录,ARCH为cpu架构

bash 复制代码
./configure \
    --prefix=$X264_OUTPUT_DIR \
    --enable-static \
    --enable-pic \
    --host=$ARCH-linux \
    --disable-opencl \
    --disable-cli \
    --cross-prefix=$CROSS_PREFIX \
    --sysroot=$SYSROOT \
    FFMPEG_EXTRA_CONFIGURE_FLAGS
bash 复制代码
make -j$(nproc) 
bash 复制代码
make install

3、加入x264配置

bash 复制代码
FFMPEG_EXTRA_CFLAGS="$FFMPEG_EXTRA_CFLAGS -I$X264_OUTPUT_DIR/include"
FFMPEG_EXTRA_LDFLAGS="$FFMPEG_EXTRA_LDFLAGS -L$X264_OUTPUT_DIR/lib"
FFMPEG_EXTRA_CONFIGURE_FLAGS="$FFMPEG_EXTRA_CONFIGURE_FLAGS --enable-encoder=libx264 --enable-libx264"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$X264_OUTPUT_DIR/lib/pkgconfig"

4、编译ffmpeg

bash 复制代码
 ./configure --target-os=android \
    --prefix=$PREFIX \
    --arch=$ARCH \
    --cpu=$CPU \
    --cc=$CC \
    --cxx=$CXX \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --enable-gpl \
    --cross-prefix=$CROSS_PREFIX \
    --enable-cross-compile \
    --enable-jni \
    --enable-mediacodec \
    --enable-decoder=h264_mediacodec \
    --enable-decoder=hevc_mediacodec \
    --enable-decoder=vp8_mediacodec \
    --enable-decoder=vp9_mediacodec \
    --enable-decoder=mpeg2_mediacodec \
    --enable-decoder=mpeg4_mediacodec \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic -DVK_ENABLE_BETA_EXTENSIONS=0 -march=$CPU $FFMPEG_EXTRA_CFLAGS" \
    --extra-ldflags="$FFMPEG_EXTRA_LDFLAGS" \
    --pkg-config="pkg-config --static" \
    $SHARED_OR_STATIC_FLAG \
    $FFMPEG_EXTRA_CONFIGURE_FLAGS
bash 复制代码
make -j$(nproc)
bash 复制代码
make install

二、完整代码

下列代码可以在ubuntu、wsl ubuntu、msys2中执行。无需任何额外操作,只需调用脚本即可生成so。可以指定cpu、安卓api、以及ffmpeg版本号。如果没有指定ANDROID_NDK_HOME会自动下载ndk,x264源码也会自动下载以及ffmpeg源码也会自动下载,然后自动生成so。同时还会生成ffmpeg.so,是ffmpeg可执行程序,笔者将其生成了so,其内包含的main符号可以直接调用,以输入命令行
注:合并所有库到libffmpeg.so的方式本文暂不提供。

下列代码可复制保存为build.sh直接执行。

bash 复制代码
set -e
show_usage() {
  echo "usage:
      -p is cpu (armv7-a、armv8-a、i686、x86-64) 
      -a is android api number
      -f is ffmpeg version
      -h is help
   "
}
#ffmpeg版本 -可配置
FFMPEG_VERSION=4.3.6
#ndk api版本 -可配置
API=24
#cpu 架构 -可配置 :armv7-a、armv8-a、i686、x86-64
CPU=x86-64
while getopts "p:a:f:h" arg; do
  case $arg in
  p)
    CPU=$OPTARG
    ;;
  a)
    API=$OPTARG
    ;;
  f)
    FFMPEG_VERSION=$OPTARG
    ;;
  h)
    show_usage
    exit 1 
    ;;
  ?)
    echo "unkonw argument"
    show_usage
    exit 1
    ;;
  esac
done
OS=$(uname -o)
echo $OS
if [ $OS == "Msys" ]; then
  OS="windows"
  NDK_URL="https://googledownloads.cn/android/repository/android-ndk-r26d-windows.zip"
  NDK_SHA1="c7ea35ffe916082876611da1a6d5618d15430c29"
else
  OS="linux"
  NDK_URL=" https://googledownloads.cn/android/repository/android-ndk-r26d-linux.zip"
  NDK_SHA1="fcdad75a765a46a9cf6560353f480db251d14765"

fi
echo "************************************Build Info*********************************"
echo "Host os :$OS"
echo "Target cpu :$CPU"
echo "Android api :$API"
echo "FFmpeg version :$FFMPEG_VERSION"
echo "************************************Build Info End*****************************"
PACKAGE_SOURCE_DIR=$(pwd)/.package
#下载NDK
if [ ! -d "$PACKAGE_SOURCE_DIR" ]; then
  mkdir $PACKAGE_SOURCE_DIR
fi
if [ ! -d "$ANDROID_NDK_HOME" ]; then
  pushd $PACKAGE_SOURCE_DIR
  if [ ! -d "ndk" ]; then
    if [ -e "ndk.zip" ]; then
      sha1=$(sha1sum ndk.zip)
    fi
	sha1=($sha1)
    echo "${sha1[0]}"
    if [ "$sha1" != "$NDK_SHA1" ]; then
      if [ -e "ndk.zip" ]; then
        rm ndk.zip
      fi
      echo ndk Downloading...
      wget $NDK_URL -O ndk.zip
	  exit 1
    fi
    if [ -d "ndk" ]; then
      rm -rf ndk
    fi
    unzip ndk.zip -d ndk
  fi
  ANDROID_NDK_HOME=$PACKAGE_SOURCE_DIR/ndk/$(ls ndk)
  popd
fi
#下载NDK -end
TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/$OS-x86_64
echo $TOOLCHAIN

SYSROOT=$TOOLCHAIN/sysroot
case $CPU in
armv7-a)
  ARCH=arm
  CROSS_PREFIX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-
  USR_LIB=$SYSROOT/usr/lib/armv7a-linux-androideabi/$API
  ;;
armv8-a)
  ARCH=arm64
  CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android$API-
  USR_LIB=$SYSROOT/usr/lib/aarch64-linux-android/$API
  ;;
i686)
  ARCH=x86
  CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android$API-
  USR_LIB=$SYSROOT/usr/lib/i686-linux-android/$API
  FFMPEG_EXTRA_CONFIGURE_FLAGS=--disable-asm
  ;;
x86-64)
  ARCH=x86_64
  CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android$API-
  USR_LIB=$SYSROOT/usr/lib/x86_64-linux-android/$API
  ;;
esac
PREFIX=$(pwd)/output/ffmpeg${FFMPEG_VERSION}/${API}/${CPU}
PACKAGE_PREFIX=$PACKAGE_SOURCE_DIR/.output/${API}/${CPU}
export CC=${CROSS_PREFIX}clang
export CXX=${CROSS_PREFIX}clang++
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
#x264
pushd $PACKAGE_SOURCE_DIR
PACKET_X264=x264-master
X264_OUTPUT_DIR=$PACKAGE_PREFIX/x264
FFMPEG_EXTRA_LINK_LIBRARY="$FFMPEG_EXTRA_LINK_LIBRARY $X264_OUTPUT_DIR/lib/libx264.a"
FFMPEG_EXTRA_CFLAGS="$FFMPEG_EXTRA_CFLAGS -I$X264_OUTPUT_DIR/include"
FFMPEG_EXTRA_LDFLAGS="$FFMPEG_EXTRA_LDFLAGS -L$X264_OUTPUT_DIR/lib"
FFMPEG_EXTRA_CONFIGURE_FLAGS="$FFMPEG_EXTRA_CONFIGURE_FLAGS --enable-encoder=libx264 --enable-libx264"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$X264_OUTPUT_DIR/lib/pkgconfig"
if [ ! -e "$X264_OUTPUT_DIR/lib/libx264.a" ]; then
  if [ ! -d "$PACKET_X264" ]; then
    echo x264 Downloading...
    wget https://code.videolan.org/videolan/x264/-/archive/master/x264-master.tar.bz2
    tar -xf $PACKET_X264.tar.bz2
  fi
  if [ "$ARCH" != "x64" ]; then
    PACKET_X264_EXTRA_CONFIGURE_FLAG="--disable-asm"
  fi
  echo x264 Configuring...
  pushd $PACKET_X264
  ./configure \
    --prefix=$X264_OUTPUT_DIR \
    --enable-static \
    --enable-pic \
    --host=$ARCH-linux \
    --disable-opencl \
    --disable-cli \
    --cross-prefix=$CROSS_PREFIX \
    --sysroot=$SYSROOT \
    $PACKET_X264_EXTRA_CONFIGURE_FLAG
  echo x264 Building...
  if [ -e "Makefile" ]; then
    make clean
  fi
  make -j$(nproc) -s
  echo x264 Installing...
  make install
  popd
  popd
fi
#x264 -end
#ffmpeg
pushd $PACKAGE_SOURCE_DIR
FFMPEG_SOURCE_DIR=$(pwd)/ffmpeg$FFMPEG_VERSION
if [ ! -d "$FFMPEG_SOURCE_DIR" ]; then
  echo ffmpeg Downloading...
  git clone -b n$FFMPEG_VERSION --depth 1 https://git.ffmpeg.org/ffmpeg.git $FFMPEG_SOURCE_DIR
  tar -xf $PACKET_X264.tar.bz2
fi
pushd $FFMPEG_SOURCE_DIR
build_ffmpeg() {
  #./configure -h
  # echo ffmpeg surport decoders...
  # ./configure --list-decoders
  # echo ffmpeg surport hwaccels...
  # ./configure --list-hwaccels
  echo ffmpeg Configuring...
  ./configure --target-os=android \
    --prefix=$PREFIX \
    --arch=$ARCH \
    --cpu=$CPU \
    --cc=$CC \
    --cxx=$CXX \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --enable-gpl \
    --cross-prefix=$CROSS_PREFIX \
    --enable-cross-compile \
    --enable-jni \
    --enable-mediacodec \
    --enable-decoder=h264_mediacodec \
    --enable-decoder=hevc_mediacodec \
    --enable-decoder=vp8_mediacodec \
    --enable-decoder=vp9_mediacodec \
    --enable-decoder=mpeg2_mediacodec \
    --enable-decoder=mpeg4_mediacodec \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic -DVK_ENABLE_BETA_EXTENSIONS=0 -march=$CPU $FFMPEG_EXTRA_CFLAGS" \
    --extra-ldflags="$FFMPEG_EXTRA_LDFLAGS" \
    --pkg-config="pkg-config --static" \
    $SHARED_OR_STATIC_FLAG \
    $FFMPEG_EXTRA_CONFIGURE_FLAGS
  echo ffmpeg Building...
  if [ -e "Makefile" ]; then
    make clean
  fi
  make -j$(nproc)
  echo ffmpeg Installing...
  make install
}
# SHARED_OR_STATIC_FLAG="--disable-shared --enable-static"
# echo "ffmpeg build static library"
# build_ffmpeg
SHARED_OR_STATIC_FLAG="--enable-shared  --disable-static"
echo "ffmpeg build shared library"
build_ffmpeg
$CC -shared -fPIC \
  $(find $FFMPEG_SOURCE_DIR/fftools -name '*.c' -and -not -name 'ffplay.c' -and -not -name 'ffprobe.c' -and -not -name 'ffplay_renderer.c' -and -not -name 'ffmpeg_qsv.c' -and -not -name 'ffmpeg_videotoolbox.c') \
  -I$FFMPEG_SOURCE_DIR -lm \
  $(find $PREFIX/lib -name "*.so" -and -not -name 'ffmpeg.so' -type f -print) \
  -o $PREFIX/lib/ffmpeg.so
popd
popd
echo "Generated files in: $PREFIX"
#ffmpeg -end

三、生成好的包

已加入第二章生成好的包里。


四、使用示例

1、基本用法

创建一个ffmpeg-android目录,将完整代码复制保存为build.sh

(1)查看用法

bash 复制代码
./build.sh -h

(2)确认ffmpeg版本

ffmpeg版本参考:https://git.ffmpeg.org/ffmpeg.git 去掉前缀n

(3)生成so

生成全平台、api24、ffmpeg6.1.1的so

arm

bash 复制代码
./build.sh -p armv7-a -a 24 -f 6.1.1

arm64

bash 复制代码
./build.sh -p armv8-a -a 24 -f 6.1.1

x86

bash 复制代码
./build.sh -p i686 -a 24 -f 6.1.1

x64

bash 复制代码
./build.sh -p x86-64 -a 24 -f 6.1.1

生成好的so在build.sh脚本所在目录的output文件夹下

2、ubuntu中使用

wsl、虚拟机都可以。参考第一章安装必要的工具。

bash 复制代码
sudo apt install git unzip
bash 复制代码
./build.sh -p armv7-a -a 24 -f 6.1.1

3、windows msys2中使用

在msys2生成需要参考第二章配置环境,以及安装必要的工具。

bash 复制代码
pacman -S unzip git
bash 复制代码
./build.sh -p armv7-a -a 24 -f 6.1.1

总结

以上就是今天讲述的内容,生成ffmpeg安卓so其实并不难,如果熟悉交叉编译以及shell,编译起来还是比较简单的,尤其是想生成最小或者完整依赖的包,最好还是自己生成。

相关推荐
似霰3 小时前
安卓adb shell串口基础指令
android·adb
fatiaozhang95275 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO6 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师6 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师6 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫7 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白7 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
qq_316837758 小时前
使用ffmpeg 将图片合成为视频,填充模糊背景,并添加两段音乐
ffmpeg·音视频
dpxiaolong8 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo030519879 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android