文章耽搁了两星期了,可能很多老铁已经忘了,上一篇文章的内容了,不妨回顾一下,以前的文章里面就简单的说起了FFmpeg的一些简单命令的用法,官方下载不一样平台的静态库,能够直接执行binary 文件来编辑一些音视频文件。我上次只是说了视频画面合成的用法,经过vstack和hstack,来进行合成。此次呢 我将教你们,如何在本身的Android手机上进行视频画面拼接的方法 以及如何经过官方库编译出Android平台的so库及静态库。此次内容可能会不少,也涉及到了不少shell脚本语言的的东西。但愿老铁们耐心看看,绝对会有帮助。html
这个是以前的系列java
原来FFmpeg这么有意思 (一)linux
这里教你们一些骚操做,android
这边主要是为了你们下载版本号相同,根据脚本能够编译成功,否则每一个版本里面可能要修改一些参数 我这里就按照个人环境和你们说一下把git
ubuntu ( Ubuntu 18.10 )github
FFmpeg 官方库(4.0.2) x264 官方库(最新就行)shell
这边已经上传到了github(编译脚本及编译库,脚本通用,可是不一样平台库可能不一样)ubuntu
FFmpeg 官方bash
x264 官方app
我会把编译好的FFmpeg静态库传到github,你们能够直接拿来用。 github下载地址
在咱们的app中若是说想执行二进制文件,必须放在咱们的私有目录下,sdcard只是Android文件系统linker出来的一个文件夹,是没有权限执行二进制文件的,而咱们App的私有目录是能够的。下面我会给出一下代码 仅供你们参考。
二进制的FFmpeg已经上传到了github ,若是有兴趣的同窗能够下载下来,本身的App中跑起来,咱们能够把这个文件放在assets文件夹下,而后App运行的时候把这个文件copy到App的私有目录下
boolean isFileCopied = FileUtils.copyBinaryFromAssetsToData(App.getInstance(),
cpuArchNameFromAssets + File.separator + FileUtils.ffmpegFileName,
FileUtils.ffmpegFileName);
// make file executable
if (isFileCopied) {
if (!ffmpegFile.canExecute()) {
Log.d(BuildInfo.TAG, "FFmpeg is not executable, trying to make it executable ...");
if (ffmpegFile.setExecutable(true)) {
Log.d(BuildInfo.TAG, "FFmpeg is executable");
}
} else {
Log.d(BuildInfo.TAG, "FFmpeg is executable");
}
}
复制代码
上面的代码本身能够编写。我这就不所有贴了。App运行起来后,把这个文件copy到本地,而后调用
ffmpegFile.setExecutable(true)
复制代码
这样就能够执行FFmpeg 了。Android中也提供了执行commend的方法
public static Process run(String[] commandString) {
Process process = null;
try {
process = Runtime.getRuntime().exec(commandString);
String output = Util.convertInputStreamToString(process.getErrorStream());
Log.i("cuieney",output);
} catch (IOException e) {
Log.e(BuildInfo.TAG,"Exception while trying to run: " + commandString+e.toString());
}
return process;
}
复制代码
就是经过调用runtime.exec就能够了 把命令写进去就好。
run({"ffmpeg",""})
复制代码
这样就ok了。成功的话能够在logcat 中看到这些,log太多了 我就没复制
ffmpeg version 4.0.2 Copyright (c) 2000-2018 the FFmpeg developersbuilt with gcc 4.9.x (GCC) 20150123 (prerelease)........
复制代码
我这里根据编译出来的库,完成了一些功能
扫二维码也是能够下载的
关于编译Android 平台的库可能网上有一大堆,反正一搜索,确定有你须要的,这边我主要教你们使用静态库而非动态库,这样你会省了不少不少的麻烦,各类so库的来回粘贴复制,还要写cmakelist文集,配置gradle,对于没怎么玩过FFmpeg的人来讲可能须要搞很长时间,这里我将带给你们另外一种玩法
动态库其实就是编译出来的so库,link到咱们的项目中而后load library 而后经过jni的方式进行操做c上面的东西,这边就是简单归纳一下,那我知道了须要哪些东西了,那咱们接下来就是,编译这个so库,你们能够在网上看到FFmpeg编译出来的有不少so 你要一个一个的把他们放进咱们的项目中。而后cmakelist里面添加东西。这里我教你们把这几个库编译到一个so里面,能够省了你不少麻烦
脚本我这边就把一部分代码贴上去,所有的我放在了github上了(下面这个脚本名称叫作build_ffmpeg_android.sh,能够在我上面的写的地址里找到),我会写一些注释在上面
能够看到下面的 代码中有一个MODULE(主要作一些里面库的enabel 和disable,把须要的库咱们编译进去 不须要的固然是不用了) GENERAL(主要做用是一些参数的设置和额外的库添加)和LIB_TYPE(这个就是设置编译shared仍是static的了)静态库或者动态库
function build
{
pushd ffmpeg
./configure \
--logfile=config.log \
--target-os=android \
--prefix=$PREFIX \
${MODULE} \
${GENERAL} \
${LIB_TYPE} \
--sysroot=$PLATFORM \
--extra-cflags="-fPIE -fPIC -std=c11" \
--extra-ldflags="$flags $shared_flag" \
# essencial for dynamic library
sed -i -E "s/^(#define HAVE_SYSCTL).*/\1 0/" config.h
make clean
make -j$NUM_OF_CORE
make install
popd
}
build
复制代码
这个就是GENERAL的参数
GENERAL=" \ --extra-libs="-lgcc" \ --arch=${ARCH} \ --cc=$PREBUILT/bin/${BIN_PREFIX}-gcc \ --cross-prefix=$PREBUILT/bin/${BIN_PREFIX}- \ --nm=$PREBUILT/bin/${BIN_PREFIX}-nm \ --extra-cflags="-I$X264_INCLUDE" \ --extra-ldflags="-L$X264_LIB" \ "
复制代码
这个是module的参数 只放了一部分,用到的能够enable 用不到的disable 否则编译出来的库很大。那咱们的apk也会相应的很大,能够到github下载原始文件
MODULE=" \ --enable-jni \ --enable-pic \ --enable-gpl \ --enable-zlib \ --enable-yasm \ --enable-small \ --enable-pthreads \ --enable-mediacodec \ --enable-libx264 \ --enable-cross-compile \ --disable-doc \ --disable-ffplay \ --disable-ffprobe \ --disable-network \ --enable-neon --disable-linux-perf \ --enable-encoder=libx264 \ --enable-encoder=aac \ --enable-encoder=mpeg4 \ --enable-encoder=mjpeg \ --enable-encoder=png \ --disable-muxers \ 复制代码
这边脚本里写了一些判断,咱们能够执行脚本的时候 再加个字段就能够编译出咱们须要的静态库,我这边的脚本名字叫作build_ffmpeg_android.sh,因此只要按照下面的命令执行便可
./build_ffmpeg_andori.sh static
复制代码
若是你想编译动态库 只要把static 改为shared便可。
如今的电脑应该编译的很快,执行成功应该能够看到下面的目录,so已经编译出来了
静态库已经出来了
只要把如下的代码添加到编译脚本里面便可。
$TOOLCHAIN/bin/${BIN_PREFIX}-ld \
-rpath-link=$PLATFORM/usr/lib \
-L$PLATFORM/usr/lib \
-L$PREFIX/lib \
-L$X264_LIB \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
$PREFIX/lib/libavcodec.a \
$PREFIX/lib/libavfilter.a \
$PREFIX/lib/libavformat.a \
$PREFIX/lib/libavutil.a \
$PREFIX/lib/libswresample.a \
$PREFIX/lib/libswscale.a \
$X264_ALIB/libx264.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/${BIN_PREFIX}/4.9.x/libgcc.a
复制代码
从上面脚本能够看到 至关于把这些库linker到咱们上面的libffmpeg.so里面。
成功的话能够看到ffmpeg 目录下的Android中看到这个so库
能够看到libffmpeg.so已经出来了
为何用这个库呢,若是说你已经以上步骤都成功了,并且已经运行到Android机上面了,你会发现编码出来的视频文件明显质量不好,不该该说不好,反正确定是本身不满意的结果。说了这么多,你们应该知道这个库的做用了,提升编码质量,为何我在官网下载的pc库会质量很好呢,那是由于他们已经把这个库编进去了并且已经enable。那么咱们这里要作的就是去下载Lib264官方源码,编译出Android平台的 而后把这个库给打进FFmpeg里面。
这个库编译就比较简单了。参数和代码没有那么多,github上面放的脚本名字叫作(build_x264_andorid.sh)你们下载下来就能够用的
若是想编译不一样的版本一样能够经过 后缀shared 或者static 就能够了
LIB_TYPE=${1-static}
echo '@@@#####'${LIB_TYPE}
function build
{
pushd x264
# remove suffix of libx264.so
sed -in 's/so\.\$API/so/g' configure
./configure \
--prefix=./android/$ABI \
--enable-$LIB_TYPE \
--enable-pic \
--host=$BIN_PREFIX \
--cross-prefix=${PREBUILT}/bin/${BIN_PREFIX}- \
--extra-cflags="-fPIC -fPIE -std=c11" \
--sysroot=$PLATFORM
sed -i 's/-f -s/-f/g' ./Makefile
make clean
make -j$NUM_OF_CORE
make install
tree android
popd
}
build
printf "$success" "x264"
复制代码
./build_x264_android.sh shared
复制代码
执行成功应该能够看到下面的目录在x264/android/目录下,so已经编译出来了
上面已经把每一个平台的库都编译好了,那咱们怎么把这两个库合成在一块儿呢,细心的同窗已经看到了,我上面贴脚本的时候已经把代码贴进去了,就是在咱们编译脚本build_ffmpeg_android.sh的时候已经带进去了就是那个GENERAL字段
看看下面的字段cflags 和 ldflags 已经把咱们以前编译的x264编译进去了。
X264_INCLUDE=../x264/android/$ABI/include
X264_LIB=../x264/android/$ABI/lib
X264_ALIB=../x264
复制代码
GENERAL=" \ --extra-libs="-lgcc" \ --arch=${ARCH} \ --cc=$PREBUILT/bin/${BIN_PREFIX}-gcc \ --cross-prefix=$PREBUILT/bin/${BIN_PREFIX}- \ --nm=$PREBUILT/bin/${BIN_PREFIX}-nm \ --extra-cflags="-I$X264_INCLUDE" \ --extra-ldflags="-L$X264_LIB" \ "
复制代码
这个就比较简单了,既然一个平台已经成功,那么其余的改一下 编译平台不就好了。能够在咱们的脚本中修改一些参数便可,
我这边作了一些判断能够在编译脚本前,在咱们的common.sh目录下修改如下ARCH既能够,而后在执行build_ffmpeg_android.sh便可。
#ARCH=arm
ARCH=aarch64
[[ $ARCH = "arm" ]] && \
{ BIN_PREFIX=arm-linux-androideabi; ABI=armeabi-v7a; } || { BIN_PREFIX=aarch64-linux-android; ABI=arm64-v8a; }
NDK=~/Downloads/android-ndk-r14b
PLATFORM=$NDK/platforms/android-21/arch-arm64
PREBUILT=$NDK/toolchains/${BIN_PREFIX}-4.9/prebuilt/linux-x86_64
TOOLCHAIN=$NDK/toolchains/${BIN_PREFIX}-4.9/prebuilt/linux-x86_64
NUM_OF_CORE=$(nproc)
success="${BLACKB}${YELLOWF}build %s success${RESET}\n"
复制代码
以上就是common.sh脚本。只要修改上面的arch参数就行 ,若是要变异arm的话记得把PLATFORM这个参数后面的64去了。
可能上面有说的不清楚的。你们能够在留言中或者私信中 提问。若是上面有说错的地方,你们能够积极的和我说。我会在文章中纠正。
To be continue..... 下回我会带给你们 关于App的一些内容。好比画面拼接,添加logo,添加背景音乐,视频画面剪切...有想要了解的也能够在留言中说起。我会作相关方面的调研,