在前面的Linux下ndk編譯移植FFmpeg到Android平臺(tái)文章中介紹了如何將最基本的FFmpeg到Android平臺(tái)。但只是簡(jiǎn)單的移植了FFmpeg亥宿,沒有包含x264編碼器,并且AAC編碼器也只有默認(rèn)的题诵。在Android平臺(tái)下使用FFmpeg進(jìn)行RTMP推流(攝像頭推流)中我實(shí)際上已經(jīng)用到了x264編碼器拷淘,但沒有介紹如何將x264集成到FFmpeg中。而本篇文章將解決這個(gè)問題茄猫,重點(diǎn)講解如何集成x264和libfdk-aac狈蚤,當(dāng)然也會(huì)有問題匯總。
為什么要單獨(dú)一篇文章來介紹如何去移植FFmpeg划纽、x264和fdk_aac呢脆侮?
萬事開頭難,第一步很難勇劣,但也是最重要的靖避,不怕告訴大家,就僅僅編譯這幾個(gè)東西我足足花了兩天時(shí)間去踩坑比默。對(duì)于有些編譯出現(xiàn)各種問題導(dǎo)致沒有成功的兄弟幻捏,可能非常的挫傷積極性,打擊學(xué)習(xí)這方面知識(shí)的積極性命咐。所以我覺得有必要重點(diǎn)講解下這個(gè)環(huán)節(jié)
在進(jìn)入這是內(nèi)容之前我要強(qiáng)調(diào)一點(diǎn)篡九,一定要注意安裝版本,這個(gè)安裝版本包括linux系統(tǒng)版本醋奠、FFmpeg版本榛臼、x264版本、libfdk-aac版本窜司、ndk中android-api版本沛善。你可能會(huì)因?yàn)榘姹静黄ヅ鋵?dǎo)致編譯出現(xiàn)各種問題,既然我已經(jīng)把這些坑踩過了塞祈,希望大家不要再掉進(jìn)去
同步開源庫(kù)FFmpegSample金刁,里面有我最新編譯好的so 和對(duì)應(yīng)的編譯腳本build_x264.sh
,build_fdk.sh
,build_ffmpeg.sh
文章圍繞以下幾點(diǎn)介紹
- 編譯環(huán)境
- x264編譯
- libfdk-aac編譯
- FFmpeg 編譯
- 踩坑歷程
編譯環(huán)境
- linux版本 centos 6.8_64位 或 CentOS Linux release 7.4.1708 (Core)
[root@iZ94g6hanmqZ include]# lsb_release -a
LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Distributor ID: CentOS
Description: CentOS release 6.8 (Final)
Release: 6.8
Codename: Final
[root@localhost /]# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core)
- ndk版本 android-ndk-r15c
我的安裝位置在/usr/local/app/android-ndk-r15c
接下來到了真正編譯的時(shí)候了
編譯x264
下載地址下載版本x264-snapshot-20140916-2245-stable.tar
然后解壓為x264目錄,進(jìn)入x264目錄织咧,新建
build_x264.sh
內(nèi)容為:
#!/bin/bash
#NDK=/usr/local/android/ndk-bundle
NDK=/usr/local/app/android-ndk-r15c
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
PLATFORM=$NDK/platforms/android-16/arch-arm
PREFIX=./android
echo $NDK
echo $TOOLCHAIN
echo $PLATFORM
echo $PREFIX
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-static \
--disable-shared \
--enable-pic \
--disable-asm \
--disable-cli \
--host=arm-linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$PLATFORM \
}
build_one
然后給文件增加運(yùn)行權(quán)限 chmod +x build_x264.sh
胀葱。剩下的就是配置編譯安裝啦。
./build_x264.sh
make -j4
make install
安裝目錄就在當(dāng)前目錄下生成android目錄笙蒙,當(dāng)然庫(kù)文件和頭文件就有了
drwxr-xr-x 2 root root 4096 Jan 25 15:06 include
drwxr-xr-x 3 root root 4096 Jan 25 15:06 lib
編譯libfdk-aac
先來幾個(gè)問題:
- 為啥要集成libfdk-aac呢抵屿?
嘿嘿!別著急捅位,這個(gè)我會(huì)在下篇文章介紹ffmpeg進(jìn)行AAC編碼時(shí)候講到轧葛,這里我只講如何編譯。
- 為啥要集成libfdk-aac呢抵屿?
- 為什么不集成libfaac艇搀?
不少嘗試過的童鞋會(huì)發(fā)現(xiàn)尿扯,在編譯FFmpeg時(shí)集成libfaac也就是configure增加--enable-libfaac
參數(shù)時(shí)會(huì)提示ffmpeg: remove option for libfaac,Unknown option "--enable-libfaac"
,因?yàn)楝F(xiàn)在FFmpeg不支持libfaac擴(kuò)展了焰雕。而網(wǎng)上很多比較早期的文章都是講如何集成libfaac的衷笋,所以很多童鞋就比較疑惑。
- 為什么不集成libfaac艇搀?
下面正式進(jìn)入編譯fdk_aac
下載地址版本選擇0.1.4
同樣加壓到fdk-aac-0.1.4目錄矩屁,進(jìn)入目錄辟宗,新建
build_fdk.sh
內(nèi)容為:
#!/bin/bash
NDK_HOME=/usr/local/app/android-ndk-r15c
ANDROID_API=android-14
SYSROOT=$NDK_HOME/platforms/$ANDROID_API/arch-arm
ANDROID_BIN=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/
CROSS_COMPILE=${ANDROID_BIN}/arm-linux-androideabi-
ARM_INC=$SYSROOT/usr/include
ARM_LIB=$SYSROOT/usr/lib
LDFLAGS=" -nostdlib -Bdynamic -Wl,--whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$NDK_HOME/sources/cxx-stl/gnu-libstdc++/libs/armeabi -L$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/arm-linux-androideabi/lib -L$ARM_LIB -lc -lgcc -lm -ldl "
FLAGS="--host=arm-androideabi-linux --enable-static --disable-shared"
export CXX="${CROSS_COMPILE}g++ --sysroot=${SYSROOT}"
export LDFLAGS="$LDFLAGS"
export CC="${CROSS_COMPILE}gcc --sysroot=${SYSROOT}"
./configure $FLAGS --prefix='/usr/local/app/fdk-aac-0.1.4/android'
剩下的就是配置編譯安裝啦爵赵。
./build_fdk.sh
make -j4
make install
安裝目錄就在當(dāng)前目錄下生成android目錄,當(dāng)然庫(kù)文件和頭文件就有了
drwxr-xr-x 2 root root 4096 Jan 25 15:06 include
drwxr-xr-x 3 root root 4096 Jan 25 15:06 lib
編譯FFmpeg
FFmpeg版本3.2.4 下載地址
下載完源碼解壓后泊脐,我們進(jìn)入目錄先修改configure文件
中的下面四行:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'
替換為:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
這里是修改編譯完成后so文件的文件名格式
新建build_ffmpeg.sh
腳本空幻,內(nèi)容
#!/bin/bash
NDK=/usr/local/app/android-ndk-r15c
SYSROOT=$NDK/platforms/android-16/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure --prefix=$PREFIX \
--enable-shared \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--disable-static \
--disable-doc \
--disable-ffserver \
--disable-yasm \
--enable-cross-compile \
--enable-gpl \
--enable-libx264 \
--enable-decoder=h264 \
--enable-encoder=libx264 \
--enable-libfdk-aac \
--enable-encoder=libfdk_aac \
--enable-decoder=libfdk_aac \
--enable-nonfree \
--cross-prefix="$TOOLCHAIN/bin/arm-linux-androideabi-" \
--target-os=linux \
--arch=arm \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm -I/usr/local/app/x264-snapshot-20140916-2245-stable/android/include -DANDROID -I/usr/local/app/fdk-aac-0.1.4/android/include"
ADDI_LDFLAGS="-L/usr/local/app/x264-snapshot-20140916-2245-stable/android/lib -L/usr/local/app/fdk-aac-0.1.4/android/lib"
build_one
然后給文件增加運(yùn)行權(quán)限 chmod +x build_ffmpeg.sh
。剩下的就是配置編譯安裝啦容客。
./build_x264.sh
make -j4
make install
安裝完之后我們最終的so包就生成了秕铛。在當(dāng)前目錄下的 ./android/arm下。
drwxr-xr-x 2 root root 4096 Jan 25 15:23 bin
drwxr-xr-x 10 root root 4096 Jan 25 15:11 include
drwxr-xr-x 3 root root 4096 Jan 25 15:23 lib
drwxr-xr-x 3 root root 4096 Jan 25 15:11 share
我們的動(dòng)態(tài)庫(kù)就在lib下了
-rwxr-xr-x 1 root root 12983912 Jan 25 15:23 libavcodec-57.so
lrwxrwxrwx 1 root root 16 Jan 25 15:23 libavcodec.so -> libavcodec-57.so
-rwxr-xr-x 1 root root 59384 Jan 25 15:23 libavdevice-57.so
lrwxrwxrwx 1 root root 17 Jan 25 15:23 libavdevice.so -> libavdevice-57.so
-rwxr-xr-x 1 root root 1877548 Jan 25 15:23 libavfilter-6.so
lrwxrwxrwx 1 root root 16 Jan 25 15:23 libavfilter.so -> libavfilter-6.so
-rwxr-xr-x 1 root root 1956464 Jan 25 15:23 libavformat-57.so
lrwxrwxrwx 1 root root 17 Jan 25 15:23 libavformat.so -> libavformat-57.so
-rwxr-xr-x 1 root root 443860 Jan 25 15:23 libavutil-55.so
lrwxrwxrwx 1 root root 15 Jan 25 15:23 libavutil.so -> libavutil-55.so
-rwxr-xr-x 1 root root 42276 Jan 25 15:23 libpostproc-54.so
lrwxrwxrwx 1 root root 17 Jan 25 15:23 libpostproc.so -> libpostproc-54.so
-rwxr-xr-x 1 root root 91532 Jan 25 15:23 libswresample-2.so
lrwxrwxrwx 1 root root 18 Jan 25 15:23 libswresample.so -> libswresample-2.so
-rwxr-xr-x 1 root root 406924 Jan 25 15:23 libswscale-4.so
lrwxrwxrwx 1 root root 15 Jan 25 15:23 libswscale.so -> libswscale-4.so
drwxr-xr-x 2 root root 4096 Jan 25 15:23 pkgconfig
這里對(duì)腳本做個(gè)解釋缩挑,增加了幾個(gè)命令但两。
- 支持x264擴(kuò)展
--enable-libx264 \
--enable-decoder=h264 \
--enable-encoder=libx264 \
- 支持fdk_aac擴(kuò)展
--enable-libfdk-aac \
--enable-encoder=libfdk_aac \
--enable-decoder=libfdk_aac \
要支持fdk_aac必須還加上
--enable-nonfree \
--enable-gpl \
最后就是制定x264 fdk_aac的頭文件和庫(kù)文件的目錄--extra-cflags
加入頭文件目錄,--extra-ldflags
包含庫(kù)文件目錄,也就是
ADDI_CFLAGS="-marm -I/opt/x264/android/include -DANDROID -I/opt/fdk-aac-0.1.4/android/include"
ADDI_LDFLAGS="-L/opt/x264/android/lib -L/opt/fdk-aac-0.1.4/android/lib"
到這里我們就完成了整個(gè)編譯调煎。得到的so庫(kù)不僅有FFmpeg基礎(chǔ)功能镜遣,還有x264和fdk_aac的編解碼功能
踩坑歷程
configure FFmpeg提示找不到x264
看到這個(gè)問題,我開始很詫異士袄,我明明都配置正確了,后來查看config日志谎僻,提示 找不到什么log2方法娄柳。后來發(fā)現(xiàn)新版本的x264的config.h中啟用了這個(gè)方法,所以大家按我選擇的版本就沒問題啦艘绍。
make FFmpeg 報(bào)錯(cuò)
libavcodec/libx264.c: In function 'x264_frame' :
libavcodec/libx264.c:282:9 error: 'x264_bit_depth' undeclared(first use in this function)
if(x264_bit_depth>8)
libavcodec/libx264.c: In function 'x264_init_static':
libavcodec/libx264.c:892.9 error: 'x264_bit_depth' undeclared(first use in this function)
if(x264_bit_depth== 8)
很明顯沒有找到x264_bit_depth這個(gè)變量赤拒。那咋辦,還是版本不對(duì)應(yīng)咯诱鞠。你用的x264挎挖,F(xiàn)Fmpeg可能不太兼容哦。
configure FFmpeg是faac不能用
這個(gè)前面已經(jīng)提到了,FFmpeg已經(jīng)不再支持libfaac啦航夺。
編譯好的so 蕉朵,放在android平臺(tái)下使用時(shí),提示找不到x264.so
這里要注意阳掐,我在編譯x264和fdk_aac時(shí)全部使用的靜態(tài)編譯始衅,編出來的是靜態(tài)庫(kù)。那么最終我編譯完FFmpeg后就不需要講x264的so加入到android應(yīng)用項(xiàng)目中缭保。如果你是動(dòng)態(tài)編譯x264和fdk_aac那么你就得把這兩個(gè)庫(kù)的so也加入到android應(yīng)用項(xiàng)目中汛闸。
注意編譯x264和fdk_aac中間的參數(shù)--enable-static --disable-shared
到此所有講解結(jié)束了,先預(yù)告下一篇艺骂,下一篇將介紹Android平臺(tái)下使用FFmpeg進(jìn)行AAC編譯诸老。里面會(huì)給大家解釋為什么要用fdk_aac,而不用默認(rèn)的AAC編碼器钳恕。