文章耽擱了兩星期了,可能很多老鐵已經忘了,上一篇文章的內容了,不妨回顧一下,以前的文章裏面就簡單的說起了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,添加背景音樂,視頻畫面剪切...有想要了解的也能夠在留言中說起。我會作相關方面的調研,