FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,並能將其轉化爲流的開源計算機程序。它提供了錄製、轉換以及流化音視頻的完整解決方案。
1.環境搭建
操作系統:Ubuntu 16.04 64bit
NDK版本:android-ndk-r14b-linux-x86_64
FFmpeg版本:3.4.2
將NDK和FFmpeg源碼解壓至指定目錄,文中解壓在了Home > ffmpeg目錄下,注意NDK的版本一定要選擇Linux版的,在編譯的時候我就犯了這個錯誤,使用了Windows版的NDK,一直報錯也找不到原因,切記切記!
2.編譯FFmpeg
在ffmpeg-3.4.2目錄下創建build_android.sh編譯腳本,文件名可以隨便取,這個腳本是本文中最關鍵的內容,一起來看下:
#!/bin/bash
# 設置臨時文件夾,需要提前手動創建
export TMPDIR="/home/yangle/ffmpeg/ffmpeg-3.4.2/ffmpegtemp"
# 設置NDK路徑
NDK=~/ffmpeg/android-ndk-r14b
# 設置編譯針對的平臺,可以根據實際需求進行設置
# 當前設置爲最低支持android-14版本,arm架構
SYSROOT=$NDK/platforms/android-14/arch-arm
# 設置編譯工具鏈,4.9爲版本號
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--enable-cross-compile \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--prefix=$PREFIX \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=android \
--arch=arm \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
# 設置編譯後文件的輸出目錄
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
前四項配置按照你本機的實際路徑修改就可以了,注意ffmpegtemp這個臨時文件夾需要提前手動創建,【~/】 在Linux上代表 【/home/用戶名/】,看下build_one這個方法,enable、disable分別代表打開和關閉一些功能,重點看下下面幾個配置:
--enable-shared
--disable-static
編譯動態庫,shared和static的開關是相對的。
--prefix=$PREFIX
CPU=arm
PREFIX=$(pwd)/android/$CPU
設置編譯後文件的輸出目錄,$(pwd)代表當前目錄,所以文件的輸出路徑爲:ffmpeg-3.4.2/android/arm
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-
設置交叉編譯器,按照實際路徑修改就可以了。
--target-os=android
設置編譯針對的系統,網上查到很多資料說編譯前需要修改configure文件,設置這項後就不用修改了,系統會自動爲我們修改,效果一樣。
--arch=arm
設置編譯so庫的架構,當前設置爲arm,可以根據實際需求修改。
--sysroot=$SYSROOT
設置編譯針對的平臺,可以根據實際需求進行設置,當前設置爲最低支持android-14版本,arm架構。
--extra-cflags="-Os -fpic $ADDI_CFLAGS"
ADDI_CFLAGS="-marm"
還沒有完全理解這幾個參數的作用,有知道的同學可以給我留言啊,謝謝!
到這裏,編譯腳本就寫完了,在當前目錄下打開終端窗口,執行腳本,加上管理員權限,以防權限不足:
$ sudo ./build_android.sh
回車提示輸入密碼,密碼不會顯示出來或者顯示成*號,直接輸完然後回車就可以了,看下執行效果:
編譯中:
如果一切順利的話,大概十多分鐘就可以編譯完成:
編譯完成後,在當前目錄下(ffmpeg-3.4.2)會生成一個android目錄,so文件就在android > arm > lib目錄下:
看下生成的so包是做什麼用的:
libavcodec:用於各種類型聲音、圖像編解碼。
libavformat:用於各種音視頻封裝格式的生成和解析,讀取音視頻幀等功能。
libavutil:包含一些公共的工具函數。
libavfilter:提供了各種音視頻過濾器。
libswresample:用於音頻重採樣,採樣格式轉換和混合。
libswscale:用於視頻場景比例縮放、色彩映射轉換。
3.將FFmpeg編譯成一個so文件
在上文中我們成功的編譯了FFmpeg,但是編譯出來的so文件一共有6個,如果覺的使用起來比較麻煩,可以編譯成一個so文件,下面我們來修改下腳本:
#!/bin/bash
# 設置臨時文件夾,需要提前手動創建
export TMPDIR="/home/yangle/ffmpeg/ffmpeg-3.4.2/ffmpegtemp"
# 設置NDK路徑
NDK=~/ffmpeg/android-ndk-r14b
# 設置編譯針對的平臺,可以根據自己的需求進行設置
# 當前設置爲最低支持android-14版本,arm架構
SYSROOT=$NDK/platforms/android-14/arch-arm
# 設置編譯工具鏈,4.9爲版本號
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--enable-cross-compile \
--enable-static \
--disable-shared \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--prefix=$PREFIX \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=android \
--arch=arm \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
# 合併生成的靜態庫
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
}
# 設置編譯後的文件輸出目錄
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
看下和編譯單個so文件的腳本有什麼區別:
生成靜態庫:
--disable-static
--enable-shared
修改爲:
--enable-static
--disable-shared
增加下面的指令,將生成的靜態庫合併成一個動態庫:
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
重點看下下面兩個配置:
-soname libffmpeg.so
指定動態庫,也就是so文件的名稱。
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
設置編譯器的路徑,根據實際路徑進行修改,編譯前一定要檢查一遍路徑是否正確!
腳本中還涉及到一些編譯指令,都可以在網上查到作用,在這裏就不再一一說明了,OK,開始執行編譯腳本:
$ sudo ./build_android_all.sh
編譯完成後,生成的libffmpeg.so就在android > arm目錄下:
4.遇到的問題
NDK路徑錯誤
遇到這個錯誤仔細檢查一遍設置的路徑有沒有問題,我就栽在了這個坑裏:
android文件夾帶鎖
編譯成功後,android文件夾是帶鎖的,執行下面的命令就可以解鎖:
sudo chown 用戶名 android/ -R
5.寫在最後
第一次使用Linux系統和編譯FFmpeg,一直在網上查命令和各種報錯的解決方案,這篇文章前前後後寫了一個多月,如有錯誤的地方,可以給我留言指正,多謝!
文中用到的FFmpeg源碼、編譯腳本以及編譯生成的so文件已經上傳至GitHub,後續還會更新,歡迎Start、Fork!
本篇文章到這裏就結束了,下一篇文章將會繼續介紹如何在Android項目中使用FFmepg,敬請期待!