想在Android下实现PCM编码为AAC,已经用Android硬编码实现过AAC编码,但想了解一下FAAC这个库,比较一下两者的差异。
FAAC是开源的C语言库,查了一下网络上的文章,在Linux上编译FAAC,大多数都是编写一个脚本build_android.sh
,脚本里是用make编译,最终只有一个平台的共享库so或者静态库a文件。如:【AAC在Linux下编译】
而Android上使用共享库一般会有如下几个平台:
1 | ├── arm64-v8a |
所以借着FAAC,记录一下Android如何通过NDK使用开源C/C++库。
现在NDK有两种方式编译C/C++库:
- ndk-build
- cmake
根据我的理解,两者的不同之处在于:
ndk-build
构建的库,编译好的so
文件,加上include
目录下的头文件,就可以使用了,不需要再面对开源库繁琐的源码了。但要在Android项目中使用,你还得创建一个NDK项目,通过JNI调用,所以最后你的项目会有两个so
库文件(开源库 + JNI库)。cmake
构建,现在创建一个NDK项目,默认就是用cmake,直接把C/C++库的源文件放到cpp目录下,记录到CMakeLists.txt
,直接通过JNI调用库include的接口就行,最后项目就只有一个so
库文件 (这种方式必须有JNI,否则编译不过)。
那么如何选择?
我觉得两种都可以,不必纠结,但一般源文件多的C/C++库建议用 ndk-build
,不用频繁的编译C/C++代码,拖慢编译速度,但如果你没有ndk-build的环境(第一次构建),配置这个环境也是相当的麻烦。而小项目,如FAAC,则用cmake构建会比较方便,一次就可以把FAAC编译好,并且可以通过JNI将FAAC接口转为Java的。
A. ndk-build编译预构建库
由于之前学NDK有保留一个Demo LearnAndroidAndLibrary\NdkTestLibrarySo
项目,所以直接借鉴Demo的配置文件:Android.mk
、 Application.mk
,本次直接拷贝过来做一些小的修改。
一. ndk-build编译faac
我这边运行的环境是:Ubuntu, G++, Java8(加入环境变量),Android SDK(加入环境变量) , NDK19 (加入环境变量)。
- 下载源码
1
2
3$ wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
$ tar -zxvf faac-1.28.tar.gz
$ cd faac-1.28 - 配置项目环境
1
2
3$ mkdir jni
$ cp include jni/
$ cp libfaac jni/ # 猜的,应该只需要libfaac这些源码 - 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18$ cd jni
$ find -name *.c
./libfaac/kiss_fft/kiss_fftr.c
./libfaac/kiss_fft/kiss_fft.c
./libfaac/ltp.c
./libfaac/util.c
./libfaac/aacquant.c
./libfaac/psychkni.c
./libfaac/bitstream.c
./libfaac/tns.c
./libfaac/backpred.c
./libfaac/midside.c
./libfaac/fft.c
./libfaac/frame.c
./libfaac/huffman.c
./libfaac/channels.c
./libfaac/filtbank.c
$
Android.mk
内容是拷贝其他开源库的,这里只修改两个内容
- 源码 .c 文件列表
- lib名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33$ vim Android.mk
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
# 1. 贴进来所有的c文件
LOCAL_SRC_FILES:= \
libfaac/kiss_fft/kiss_fftr.c \
libfaac/kiss_fft/kiss_fft.c \
libfaac/ltp.c \
libfaac/util.c \
libfaac/aacquant.c \
libfaac/psychkni.c \
libfaac/bitstream.c \
libfaac/tns.c \
libfaac/backpred.c \
libfaac/midside.c \
libfaac/fft.c \
libfaac/frame.c \
libfaac/huffman.c \
libfaac/channels.c \
libfaac/filtbank.c \
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog
#LOCAL_SHARED_LIBRARIES := \
# libcutils
LOCAL_MODULE:= libfaac # 2. 修改库的名称
LOCAL_CPPFLAGS := -O2 -fexceptions -DHAVE_SOCKLEN_T -DHAVE_STRUCT_IOVEC -Wno-write-strings
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
Application.mk
不需要修改
1 | $ vim Application.mk |
APP_STL stlport_static is no longer supported. Please switch to either c++_static or c++_shared.
二. 编译
在 faac-1.28/jni
目录下执行
1 | $ ndk-build |
编译成功
1 | $ tree ../libs/ |
三. 使用预构建库
- include/faaccfg.h faac.h
- libfaac.so
参考: [【Android Ndk使用预构建库】](../Android Ndk使用预构建库)
TODO: 刚编译完,还没有时间在Android上测试这个库是否能跑。
B. cmake 编译 faac
这个就比较简单,用 Android Studio 创建一个NDK的Android项目,将libfaac源码放进去,include放进去,剩下的就是和使用预构建库一样了:通过默认的JNI接口 native-lib.cpp调用 include的接口,在通过Java层调用 native-lib.cc就可以使用fAAC了,有空在记录一下这个过程。