2019-06-04 AAC编码库:VoAACEncoder动态
代码已上传Github:HaloMartin/VoAACEncoder(https://github.com/HaloMartin/VoAACEncoder),欢迎参阅指点。
背景
AAC是一种比较普遍的音频编码格式,实际应用中经常和H264一起使用来进行音视频的封装。在我司的应用中,将音视频封装成MP4格式时,其中视频使用的是H264编码,可以用ffmpeg库进行编解码;音频使用的是AAC编码,iOS端用的是faac库进行编码,Android端使用的是VoAACEncoder库。
在我司应用中,大致流程如图所示:

在进行封装的时候,视频部分使用的是未解码的H264数据帧直接封装,所以封装时不必进行编码(用程序进行编码也不切实际); 而音频则因为输入设备使用的编码格式的不同,分别使用Speex和G711和两种编码格式,需要先解码为PCM,而后统一编码成AAC,再封装到MP4中。
在这边文章中,只讨论Android上音频的AAC编码这个步骤,iOS目前是前辈从开源网站下载的源码后进行编译使用,较为灵活,可能源码版本很久,不在本篇的讨论范围内。
VoAACEncoder
iOS上的FAAC参考链接:FAAC-1.28(http://www.linuxfromscratch.org/blfs/view/7.7/multimedia/faac.html)
VoAACEncoder库下载地址:https://sourceforge.net/projects/opencore-amr/files/vo-aacenc/。
在Github上有一个开源的项目VoAACEncoder,包含FAAC和VoAACEncoder,从使用者的角度来说,比官方的那些更简单明了,感兴趣的小伙伴也可以从官网下载源码尝试自己封装,也可以从https://github.com/illuspas/VoAACEncoder上直接下载so文件来使用,这里面包含了FAAC和VoAACEncoder两个动态库,对应上面提到的那两个,但是我只使用其中的VoAACEncoder,综合引用文章:VoAACEncoder-贝壳博客所述,VoAACEncoder比FAAC具有更高的效率。
以下是VoAACEncoder的使用方法,很简单:
- 下载并复制libVoAACEncoder.so文件到项目中
- 复制VoAACEncoder.java到指定的包路径(
com.sinaapp.bashell
) - 使用
VoAACEncoder
类中的三个jni接口进行AAC编码
问题
从Android 6.0起,即SDK Version>=23时,系统将会拒绝加载包含text relocations的共享库,而illuspas/VoAACEncoder中直接生成的so文件也有相关问题。
如果你恰好跟我一样,直接使用了libVoAACEncoder.so
,因为要上架到Google Play,被强制要求升级到>=26,则你的App就会在使用该库时崩溃,日志中提示:dlopen failed: "/data/app/com.XXXX/lib/arm/libVoAACEncoder.so" has text relocations
,参考文章:# lib/arm/libVoAACEncoder.so has text relocations问题的解决方案
官方给出了解释,
解决方法:
在Android.mk 中添加LOCAL_LDFLAGS += -fPIC
,重新编译生成so文件,添加代码位置如下:
LOCAL_LDLIBS := -ldl -lc -lz -lm -llog
LOCAL_LDFLAGS += -fPIC
include $(BUILD_SHARED_LIBRARY)
在Terminal上编译过程如图:

- 通过
cd
命令,cd
到VoAACEncoder
的jni目录; - 使用NDK来编译库,但是要注意使用的NDK版本不能高于r15c,否则会出现编译错误,原因如图中
2
所示,VoAACEncoder
支持armeabi
,所以编译的ndk要求低于android-ndk-r15c
; - 正确的编译方法是使用低于
android-ndk-r15c
的NDK进行编译,如图中3
所示。
编译完成后
可在libs
目录找到新生成的so文件,如图

总结
原来illuspas/VoAACEncoder开源的代码有相关的问题,偷懒不想自己编译的话,可以直接使用我的开源项目HaloMartin/VoAACEncoder,相关问题已修复并上传。
参考链接:
# VoAACEncoder-贝壳博客
# lib/arm/libVoAACEncoder.so has text relocations问题的解决方案