FFMPEG(一)华为云linux下编译ffmpeg for Android

一、下载

1.下载NDK

   1.1 创建好目录结构

华为云Ubuntu linux默认进来是在root根目录下,我们使用mkdir android命令创建一个android文件夹,然后cd android进入android文件夹下,再mkdir NDK创建一个目录,最终下载存放ndk的目录是/root/android/NDK。

   1.2 下载NDK

进入/root/android/NDK目录, 使用如下命令下载NDK:

wget -O ndkR21.zip https://dl.google.com/android/repository/android-ndk-r21-linux-x86_64.zip

我下载的是2020年6月29日最新的NDK版本,最终保存的文件路径是/root/android/NDK/ndkR21.zip

  1.3 解压NDK压缩包

使用unzip ndkR21.zip 命令解压zip文件,最终的android NDK的主路径是 /root/android/NDK/android-ndk-r21d  其中android-ndk-r21d为解压出来的文件夹名

2.下载ffmpeg

  2.1 创建好存放目录

  使用cd命令进入android目录下,我们使用mkdir ffmpeg命令创建一个ffmpeg文件夹.最终下载并保存ffmpeg源码的目录将是/root/android/ffmpeg

  2.2 下载ffmpeg

我下载的是2020年6月14日的官网版本V4.2.3

cd ffmpeg进入ffmpeg文件夹,使用如下命令

wget https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2

压缩包存放路径是/root/android/ffmpeg/ffmpeg-snapshot.tar.bz2

 2.3 解压ffmpeg压缩包

cd命令 进入ffmpeg目录,使用tar命令解压tar.bz2文件。

tar xvf ffmpeg-snapshot.tar.bz2 命令解压源码。其中xvf中的x表示解压,v表示输出解压过程信息,f表示文件。

最终ffmpeg源码的路径是:root/android/ffmpeg/ffmpeg-4.2.3

二.  配置环境和编译

 1. 配置NDK环境变量

登录你的linux服务器,打开root目录,输入命令:

vim ~./bashrc 打开这个文件,配置NDK_ROOT环境变量。如果bashrc这个文件找不到,请使用ls -a命令列出bashrc这个文件,因为有时候这个文件是隐藏的。

如上图在文件的末尾,插入红色框起来的两句代码。

我的ndk下载解压后的文件夹存放在/root/android/NDK/android-ndk-r21d   

这样配置后,我们就可以在shell脚本里直接使用NDK_ROOT这个变量来代替冗长的NDK存放路径了。

 2.  编译ffmpeg解码库

注意,最新的ffmpeg编译for android,不再使用gcc++编译器了,而是使用clang编译,因此以下脚本也是针对最新版的NDK(21rd及以上)和ffmpeg(4.2.3及以上)的。

2.1 编译64位 armv8-a架构下的静态库和so动态库

2.1.1 编写脚本

cd 命令打开到 root/android/ffmpeg/ffmpeg-4.2.3 源码目录下,使用vim build.sh创建一个文件,输入以下脚本:

#!/bin/bash
make clean
API=21
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$API -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -marm -march=$CPU -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES=" -isystem $NDK_ROOT/sources/android/support/include"
ADDI_LDFLAGS="";
 
function build_android
{
echo "Compiling FFmpeg for $CPU and path is $NDK_ROOT"
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--enable-static \
--enable-shared \
--disable-encoders \
--disable-avdevice \
--disable-muxers \
--disable-filters \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC
--cxx=$CXX
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot/" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG 
make clean
make 
make install
echo "The Compilation of FFmpeg for $CPU is completed and ndk path is $NDK_ROOT"
}
ARCH=arm64
CPU=armv8-a
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
build_android

以上脚本可编译出供android 64位armv8-a CPU架构下使用的静态解码库和动态解码库(解码包括视频和音频解码),主要用于制作播放器来播放网络上的点播视频,播放网红直播等,到时候我们优先使用静态库,动态库会增大APK安装包大小。

脚本中各配置项的注解如下,供大家参考学习:

#!/bin/bash
make clean
API=21
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$API -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -marm -march=$CPU -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES=" -isystem $NDK_ROOT/sources/android/support/include"
ADDI_LDFLAGS="";
 
function build_android
{
echo "Compiling FFmpeg for $CPU and path is $NDK_ROOT"
./configure \
--prefix=$PREFIX \
--enable-small \       #编译出来的库文件小
--disable-programs \   #不编译命令行程序,即不能用cmd命令来让编解码器执行或调用其它功能。
--enable-static \      #编译静态库,即.a文件
--enable-shared \      #编译动态库
--disable-encoders \   #禁止掉编码器,因为我们将要做一个播放器,只需解码器
--disable-avdevice \   #将不编译libavdevice库,这个库用于读取摄像头设备的图像数据。
--disable-muxers \     #禁止封装音视频,因为我们要做的是播放器,是解封装
--disable-filters \    #禁止FFmpeg filter,filter提供了很多音视频特效处理的功能,比如视频缩放、截取、翻转、叠加等,相当于视频剪辑,这里我们将要做的是播放器,故不需要。
--cross-prefix=$CROSS_PREFIX \    #交叉编译前缀为:$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android- 即引入这个bin目录下的以aarch64-linux-android为前缀的交叉编译器相关的命令,aarch64是用clang编译arm64架构下的库
--target-os=android \             #为android系统编译ffmpeg
--arch=$ARCH \                    #cpu架构为arm 64位
--cpu=$CPU \                      #cpu指令集为armv8-a,它主要支持64位处理器,又向下兼容32位,更适合现在主流的64为CPU的手机,执行速度快。
--cc=$CC                          #指定用于编译C语言的编译器为$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
--cxx=$CXX                        #指定用于编译C++语言的编译器为$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
--enable-cross-compile \  #启用交叉编译,必须,因为要在linux PC环境下编译出能在android嵌入式系统下使用的so库,所以必须要用交叉编译,从一个平台编译出另一个平台(这里为android)可以使用的so库
--sysroot=$SYSROOT \      #指定逻辑目录,将在SYSROOT目录的usr文件夹下搜索NDK环境自带的头文件和库
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot/" \   #-isysroot指定头文件的搜索目录为$NDK_ROOT/sysroot/
--extra-ldflags="$ADDI_LDFLAGS" \                 #设置要链接的目标库的存放目录,如ffmpeg将来要集成X264、AAC等音视频第三方库。目前不需要这些,此变量ADDI_LDFLAGS的值为空,我们用ffmpeg自带的音视频解码器进行播放视频。
$ADDITIONAL_CONFIGURE_FLAG
make clean
make 
make install
echo "The Compilation of FFmpeg for $CPU is completed and ndk path is $NDK_ROOT"
}

#自定义变量
ARCH=arm64
CPU=armv8-a
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
build_android    #调用build_android函数,执行编译ffmpeg

2.1.2 执行脚本,编译成功

cd 进入ffmpeg-4.2.3 , 使用 ./build.sh命令执行2.1.1中书写的脚本。

整个编译过程,10分钟内吧,你可以去喝杯茶。

编译成功后,进入cd ffmpeg-4.2.3/android/armv8-a目录,就可以看到生成了如下3个目录,如下图:

其中lib里就存放的我们编译的目标库(静态和动态都)

cd lib命令打开lib文件夹,然后ls命令查看里面的内容如下:

 其中libavcodec.a,libavfilter.a, libavformat.a, libavutil.a, libswresample.a,libswscale.a为静态库

对应的libavcodec.so,libavfilter.so, libavformat.so, libavutil.so, libswresample.so,libswscale.so为动态库。

2.2 编译32位CPU armv7-a架构下的静态库和so动态库

类似于编译armv8-a 64位CPU架构下的脚本,只是把CPU相关的参数换成了armv7-a 32位,还有交叉编译前缀都换成了arm-linux-androideabi。

2.2.1 编写脚本如下:

#!/bin/bash
make clean
API=21
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$API -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -marm -march=$CPU -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES=" -isystem $NDK_ROOT/sources/android/support/include"
ADDI_LDFLAGS="";
 
function build_android
{
echo "Compiling FFmpeg for $CPU and path is $NDK_ROOT"
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--enable-static \
--enable-shared \
--disable-encoders \
--disable-avdevice \
--disable-muxers \
--disable-filters \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC
--cxx=$CXX
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot/" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG 
make clean
make 
make install
echo "The Compilation of FFmpeg for $CPU is completed and ndk path is $NDK_ROOT"
}
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
build_android

2.2.2  执行脚本,编译成功

 

 android目录下多了一个armv7-a目录,里面内容同armv8-a一样,只不过是32位的库。

2.3 合并脚本

我们可以把编译64位与32位的脚本融为一体,脚本如下:

#!/bin/bash
make clean
API=21
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$API -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -marm -march=$CPU -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES=" -isystem $NDK_ROOT/sources/android/support/include"
ADDI_LDFLAGS="";
CPU_V7=armv7-a
CPU_V8=armv8-a

function build_android
{

	if [ $CPU = $CPU_V7 ]
	then
	     echo " FLAGS=$FLAGS,CROSS_PREFIX=$CROSS_PREFIX"	   
	else
	   FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$API -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -marm -march=$CPU -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
	   echo " FLAGS=$FLAGS,CROSS_PREFIX=$CROSS_PREFIX"	   
	fi
	
echo "Compiling FFmpeg for $CPU and path is $NDK_ROOT"
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--enable-static \
--enable-shared \
--disable-encoders \
--disable-avdevice \
--disable-muxers \
--disable-filters \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC
--cxx=$CXX
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot/" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG 
make clean
make 
make install
echo "The Compilation of FFmpeg for $CPU is completed and ndk path is $NDK_ROOT"
}
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
build_android


ARCH=arm64
CPU=armv8-a
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
build_android

3. 如何将编译成功的linux库文件下载到本地windows系统里。

安装WinSCP软件。打开软件,输入用户名,我这里是root, 登录密码(linux服务器登录密码),然后填写服务器IP地址(我的华为云服务器IP).最后点登录按钮。你会发现WinSCP的资源管理器里全是linux服务器上的文件了,可以在文件的右键菜单里选择下载。

总结:

OK,今天先到这里,其实我们也不用学这些,因为现在视频直播,点播,编码压缩,解码等都使用的是第三方SDK,比如腾讯直播,网易直播,七牛等第三方SDK,不过这些SDK都是基于ffmpeg来做的并且是收费的,如果你们公司需要自主研发不想花钱,那你的知识就派上用场了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冉航--小虾米

希望得到您的鼓励和交流

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值