做Android UI 方面的开发已经3年多了,感觉遇到了瓶颈,后期打算往音视频方面发展,恰好最近公司不忙,编译了下音视频领域常用的几个开源库,特此记录,分享出来,希望能帮助到有用到这些开源库的网友们~
由于版权的原因,现在ffmpeg库默认是不支持视频x264格式,音频aac格式,音频mp3格式的编码的,仅支持上述格式的解码(可通过 命令 ffmpeg -codecs 查看支持的音视频编解码格式);所以才有后面这些库的集成工作需要做;网上其实也有这些开源库的编译脚本,不过比较零散,我这里再统一整理出来一份:先编译x264,第二步编译aac,第三步编译lame,最后再编译ffmpeg(其中ffmpeg编译出来的动态库有好几个,再加上前三步编译出来的三个静态库,最终编译为一个libffmpeg.so共享库)
后面的编译脚本中会用到一些环境变量,网友注意要替换成自己系统中的路径
NDK路径:NDK=/opt/software/android-ndk-r14b
Android版本:$NDK/platforms/android-19/arch-arm(你可以采用自己的)
编译后库的CPU目标平台是arm-v7a(你可以将编译的目标平台变成你自己的)
x264和aac以及lame这几个较轻的开源库的静态库生成路径最好和ffmpeg的设置得一样,因为它们最终都是要和ffmpeg编译出来的8个静态库打包成一个的
编译环境 | Linux:Ubuntu 12.04.2 NDK:android-ndk-r14b |
ffmpeg-4.1.3 | http://ffmpeg.org/download.html |
x264-20180212-2245 | http://download.videolan.org/x264/snapshots/x264-snapshot-20180212-2245-stable.tar.bz2 |
aac-0.1.6 | https://jaist.dl.sourceforge.net/project/opencore-amr/fdk-aac/ |
lame-3.100 | https://sourceforge.net/projects/lame/files/lame/3.100/ |
x264源码编译:最终生成有头文件 (include文件夹下的 x264_config.h x264.h)和静态库文件 (lib文件夹下的 libx264.a)头文件和库文件 都是在最后打包成为一个共享库libffmpeg.so要用到的 ,后面的几个库编译后生成的文件类似就不再赘述
#!/bin/bash
export NDK=/opt/software/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-19/arch-arm
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
#x264库的生成路径(建议和ffmpeg库的生成路径配置得一样,因为最后生成的静态库都会和ffmpeg的库打包为一个,如果配置得不一致就得手动拷贝到一起了-- 我是手动拷贝的)
export PREFIX=/home/xpzhi/x264-snapshot-20180212-2245-stable/install
function build_one
{
./configure \
--prefix=$PREFIX \
--host=arm-linux \
--enable-pic \
#生成的是.a结尾的静态库 .so结尾的是共享库
--enable-static \
--disable-cli \
--cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT
}
build_one
make
make install
aac源码编译:
NDK_HOME=/opt/software/android-ndk-r14b
ANDROID_API=android-19
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++/4.9/libs/armeabi-v7a -L$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/arm-linux-androideabi/lib -L$ARM_LIB -lc -lgcc -lm -ldl "
#enable-static --disable-shared生成的.a静态库,不是.so的共享库
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 \
#aac库的生成路径 建议和ffmpeg最终生成的库配置得一起 否则最终合并的时候就得手动拷贝了--
--prefix='/home/xpzhi/fdk-aac-0.1.6/install'
lame源码编译:
NDK_HOME=/opt/software/android-ndk-r14b
ANDROID_API=android-19
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-
export PATH=$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools
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.8/prebuilt/linux-x86_64/arm-linux-androideabi/lib -L$ARM_LIB -lc -lgcc -lm -ldl "
FLAGS="--host=arm-linux --enable-static --disable-shared"
export CXX="${CROSS_COMPILE}g++ --sysroot=${SYSROOT}"
export LDFLAGS="$LDFLAGS"
export CC="${CROSS_COMPILE}gcc --sysroot=${SYSROOT}"
CPU=armv7-a
./configure $FLAGS \
--prefix=$(pwd)/android/$CPU
ffmpeg源码编译:
对于x264库 要增加编译配置参数 --enable-encoder=libx264 --enable-libx264
对于aac库 要增加编译配置参数 --enable-encoder=libfdk_aac --enable-decoder=libfdk_aac --enable-libfdk-aac --disable-encoder=aac(表示针对aac格式的音频,禁用ffmpeg默认的编码库 aac 采用libfdk-aac库进行编码)
对于lame库 要增加编译配置参数 --enable-libmp3lame
--extra-cflags="-I${PREFIX}/include" 表示引入第三方库(x264和aac以及lamp)的头文件路径
--extra-ldflags="-L${PREFIX}/lib" 表示引入第三方库(libx264.a和 libfdk-aac.a 以及 libmp3lame.a)的路径
#!/bin/bash
set -x
export NDK=/opt/software/android-ndk-r14b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-19/arch-arm
export CPU=armv7-a
export PREFIX=/home/xpzhi/ffmpeg-4.1.3/install
#路径必须要存在
#export TMPDIR=/home/temp
build_one(){
./configure --target-os=linux --prefix=$PREFIX --enable-cross-compile --enable-runtime-cpudetect --disable-asm --arch=arm --cc=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-gcc --cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- --disable-stripping --nm=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-nm --sysroot=$PLATFORM --enable-gpl --enable-libmp3lame --disable-shared --enable-static --enable-nonfree --enable-version3 --enable-small --disable-iconv --disable-encoders --disable-muxers --enable-muxer=mov --enable-muxer=ipod --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi --disable-decoders --enable-encoder=libx264 --enable-libx264 --enable-encoder=libfdk_aac --enable-decoder=libfdk_aac --enable-libfdk-aac --disable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 --disable-demuxers --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpc --enable-demuxer=mov --disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 --disable-protocols --enable-protocol=file --disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb --disable-indevs --enable-zlib --disable-outdevs --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-debug --extra-cflags="-I${PREFIX}/include" --extra-ldflags="-L${PREFIX}/lib -dynamic-linker=/system/bin/linker -lm -llog -lc"
}
build_one
make
make install
最后将前面几步编译出来的静态库编译为一个libffmpeg.so动态库:
就是将ffmpeg的静态库 libavcodec.a libavfilter.a libswresample.a libavformat.a libavutil.a libswscale.a libpostproc.a libavdevice.a 和 libx264.a libfdk-aac.a libmp3lame.a等第三方库 打包成为一个,注意保证这些库能找到(最好自己命令验证下这些路径),最终的库的路径是 /home/xpzhi/ffmpeg-4.1.3/install/libffmpeg.so (库的名字可以随意更改)
#!/bin/bash
set -x
export NDK=/opt/software/android-ndk-r14b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-19/arch-arm
export CPU=armv7-a
export PREFIX=/home/xpzhi/ffmpeg-4.1.3/install
$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/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 libpostproc/libpostproc.a libavdevice/libavdevice.a ${PREFIX}/lib/libx264.a ${PREFIX}/lib/libfdk-aac.a ${PREFIX}/lib/libmp3lame.a -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker $PREBUILT/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a
=====================更新编译和开发过程中遇到的坑=======================
1.libavcodec.a(mpegvideodata.o): error adding symbols: File in wrong format
这个错误是在生成64位动态库的时候出现的,32位的库其实我已经生成成功了,然后为了获得更好的兼容性,我是想再生成一遍64位的库,但是却忘记清理编译的临时文件了--,忘记了 make clean命令,因为在编译过程中会产生很多临时文件如XXX.s XXX.o等,编译64位的动态库却使用32位的临时文件自然就会报格式错误,这里再附带上检查临时文件的到底是32位还是64的方法 可以通过命令 objdump -p libavcodec.a ;要注意编译新的架构平台的库时注意make clean 清理 临时文件
参考博客:https://blog.csdn.net/nxstack/article/details/77926447
2.libavformat/udp.c: In function 'udp_set_multicast_sources':
libavformat/udp.c:290:28: error: request for member 's_addr' in something not a structure or union
mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
遇到这种编译错误的概率蛮大的,网上一般都说是NDK的版本问题,个人感觉不像,因此参考下面的博客修改了下源码再编译就通过了~
参考博客:https://blog.csdn.net/nxstack/article/details/77926447
3.将编译出来的库移植到Android平台后,进行音视频的编解码,发现编解码的速度特别的慢
后来咨询了下专业多媒体的同事才发现,可以开启硬解码,仅使用FFmpeg编解码是属于软解码,Android设备的CPU本身就具有解码功能,这里附带上编译ffmpeg开启硬解码的相关参数:
--enable-jni --enable-mediacodec --enable-decoder=h264_mediacodec --enable-hwaccels --enable-decoder=hevc_mediacodec --enable-decoder=mpeg4_mediacodec --enable-decoder=vp8_mediacodec --enable-decoder=vp9_mediacodec --enable-version3 另外 --target-os=android 目标平台选择Android 不能再是Linux 网上资料据说3.1版本以后才支持h264的硬解码,4.0+又不支持了,还是说参数设置的有问题?请遇到的童靴们帮忙指点下!
ffmpeg3.1版本硬解码的实现:https://blog.csdn.net/lakebobo/article/details/79619584
实现硬解码的方法:https://blog.csdn.net/zhangpengzp/article/details/88943867
软解码和硬解码的区别:https://blog.csdn.net/u010072711/article/details/52413766