Pull to refresh

Сборка open-source библиотек на Android NDK

Reading time5 min
Views18K
Привет, Хабралюди!

В процессе работы с Android NDK я столкнулся с проблемой сборки уже существующих Linux библиотек на Android NDK. Так как материала не слишком много в этой статье поделюсь своим опытом. В Андроиде я новичек, так что если найдете ошибки — пишите:)

Чтобы пример был не самым простым и при том полезным — возьмём библиотеку libFLAC. Этот даст возможность декодировать .flac файлы. По данному мануалу, я надеюсь, соберутся большинство других библиотек.

Кроме неё нам понадобится:
  • Android NDK, r5b (http://developer.android.com/sdk/ndk/index.html)
  • libOgg (http://www.xiph.org/downloads/)
  • libVorbis (там же, где и libOgg).

Создание проекта


Создаём стандартный Android проект, в нем создаём папку jni и распаковываем туда libogg, libvorbis, libflac.

Сборка



Приступим к первому этапу. Для сборки я использовал такой скрипт:

PREBUILT=/home/user/android-ndk-r5b/toolchains/arm-eabi-4.4.0
PLATFORM=/home/user/android-ndk-r5b/platforms/android-3/arch-arm

export CC="/home/user/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin/arm-eabi-gcc"
export CFLAGS="-fPIC -DANDROID -nostdlib"
export ANDROID_ROOT="/home/user/android-ndk-r5b"
export LDFLAGS="-Wl,-rpath-link=$ANDROID_ROOT/platforms/android-3/arch-arm/usr/lib/ -L$ANDROID_ROOT/platforms/android-3/arch-arm/usr/lib/"

export CPPFLAGS="-I$ANDROID_ROOT/platforms/android-3/arch-arm/usr/include/"
export LIBS="-lc "
./configure --host=arm-eabi 


Для libVorbis придется его немного изменить:
LDFLAGS будет таким:
export LDFLAGS="-Wl,-rpath-link=$ANDROID_ROOT/build/platforms/android-3/arch-arm/usr/lib/ -L$ANDROID_ROOT/build/platforms/android-3/arch-arm/usr/lib/ -L../../libs/armeabi/"

а LIBS:
export LIBS="-lc -logg"


Для libflac изменим добавим в libs -lvorbis.

Рассмотрим структуру скрипта по порядку. Строка export CC — путь к компилятору Android NDK. Тут: export LDFLAGS можем задавать директории, где искать библиотеки, а в LIBS подключать их. В этой строке: export CPPFLAGS подключаем headers дополнительных библиотек.

Выполняете нужные скрипты в корне каждой из библиотек. После сборки, если все прошло успешно вы получаете библиотеки, которые уже можно компилировать на NDK.

Подготовка Android.mk



Итак, для начала создадим Android.mk, вида:
include $(all-subdir-makefiles)
В папках: jni, jni/libogg, jni/libflac, jni/libvorbis
Этот скрипт означает, что будут подключены все Android.mk в поддиректориях.

Для создания Android.mk в папках jni/libogg/src, jni/libvorbis/lib, jni/libflac/src будем использовать все Makefile.am в тех же папках.
jni/libogg/src

В Makefile.am ищем строки:
libogg_la_SOURCES = framing.c bitwise.c — это все что нам надо. Получаем стандартный Android.mk вида:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := libogg

LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/../include/

LOCAL_SRC_FILES := framing.c bitwise.c

include $(BUILD_SHARED_LIBRARY)
  #В данном примере собираем динамические библиотеки

Думаю тут объяснять ничего не надо. Идём дальше.
jni/libvorbis/lib

Тут тоже все просто. Находим строку: libvorbis_la_SOURCES и подулючаем все файлы, что там есть. Получаем такой Android.mk:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libvorbis

LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../../libogg/include
  #Подключаем headers libogg

LOCAL_SRC_FILES := mdct.c smallft.c block.c envelope.c window.c lsp.c \
			lpc.c analysis.c synthesis.c psy.c info.c \
			floor1.c floor0.c\
			res0.c mapping0.c registry.c codebook.c sharedbook.c\
			lookup.c bitrate.c\

LOCAL_SHARED_LIBRARIES := libogg	#Тут подключаем требуемые библиотеки


LOCAL_LDLIBS := -ldl -lGLESv1_CM -llog

include $(BUILD_SHARED_LIBRARY)

jni/libflac/src

Процесс тот же, но файлов намного больше и они в поддиректориях. Я решил все что есть собрать в одну библиотеку, чтоб было проще, поэтому получил такой скрипт:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libFLAC

LOCAL_C_INCLUDES := $(LOCAL_PATH)/libFLAC/include/ \
$(LOCAL_PATH)/../include/ \
$(LOCAL_PATH)/../../libogg/include/ \
$(LOCAL_PATH)/../../vorbis/include/ \
$(LOCAL_PATH)/share/include/ \
$(LOCAL_PATH)/share/utf8/ \
$(LOCAL_PATH)/../include/ \
$(LOCAL_PATH)/../include/share/ \
$(LOCAL_PATH)/share/replaygain_synthesis/include/ \
$(LOCAL_PATH)/../../libogg/include/ \
$(LOCAL_PATH)/../../vorbis/include/ \
$(LOCAL_PATH)/metaflac/include/ \
$(LOCAL_PATH)/../include/ \
$(LOCAL_PATH)/../include/share \
$(LOCAL_PATH)/../../libogg/include/ \
$(LOCAL_PATH)/../../vorbis/include/ \
$(LOCAL_PATH)/flac/ \
$(LOCAL_PATH)/../include/ \
$(LOCAL_PATH)/../../libogg/include/ \
$(LOCAL_PATH)/../../vorbis/include/ \

LOCAL_SRC_FILES := libFLAC/bitmath.c \
	libFLAC/bitreader.c \
	libFLAC/bitwriter.c \
	libFLAC/cpu.c \
	libFLAC/crc.c \
	libFLAC/fixed.c \
	libFLAC/float.c \
	libFLAC/format.c \
	libFLAC/lpc.c \
	libFLAC/md5.c \
	libFLAC/memory.c \
	libFLAC/metadata_iterators.c \
	libFLAC/metadata_object.c \
	libFLAC/stream_decoder.c \
	libFLAC/stream_encoder.c \
	libFLAC/stream_encoder_framing.c \
	libFLAC/window.c \
              libFLAC/ogg_decoder_aspect.c \
	libFLAC/ogg_encoder_aspect.c \
	libFLAC/ogg_helper.c \
	libFLAC/ogg_mapping.c \
              share/getopt/getopt.c share/getopt/getopt1.c  \
              share/grabbag/cuesheet.c \
	share/grabbag/file.c \
	share/grabbag/picture.c \
	share/grabbag/replaygain.c \
	share/grabbag/seektable.c \
              share/replaygain_analysis/replaygain_analysis.c \
              share/replaygain_synthesis/replaygain_synthesis.c \
              share/utf8/charset.c share/utf8/iconvert.c share/utf8/utf8.c \
              metaflac/main.c \
	metaflac/operations.c \
	metaflac/operations_shorthand_cuesheet.c \
	metaflac/operations_shorthand_picture.c \
	metaflac/operations_shorthand_seektable.c \
	metaflac/operations_shorthand_streaminfo.c \
	metaflac/operations_shorthand_vorbiscomment.c \
	metaflac/options.c \
	metaflac/usage.c \
	metaflac/utils.c \
              flac/analyze.c \
	flac/decode.c \
	flac/encode.c \
	flac/foreign_metadata.c \
	flac/local_string_utils.c \
	flac/utils.c \
	flac/vorbiscomment.c \

LOCAL_SHARED_LIBRARIES := libogg libvorbis

LOCAL_LDLIBS := -ldl -lGLESv1_CM -llog

include $(BUILD_SHARED_LIBRARY)

И последнее:

NDK BUILD



Выполняем ndk-build (этот скрипт находится в папке NDK) и видим что все компилируется, но flac даёт следующую ошибку:
/home/user/workspace/w/testOGG/jni/flac-1.2.1/src/libFLAC/format.c:60: error: 'VERSION' undeclared here (not in a function)
/home/user/workspace/w/testOGG/jni/flac-1.2.1/src/libFLAC/format.c:66: error: expected ',' or ';' before 'VERSION'
make: *** [/home/user/workspace/w/testOGG/obj/local/armeabi/objs/FLAC/libFLAC/format.o] Ошибка 1

Проблема в том, что константа VERSION определена в makefile, который мы не подключали. Самым простым выходом я вижу создать эту константу в самом format.c вот так:
#define VERSION "1.2.1"
Все теперь ошибок нет. При компиляции получаем:
Install : libFLAC.so => libs/armeabi/libFLAC.so
Install : libogg.so => libs/armeabi/libogg.so
Install : libvorbis.so => libs/armeabi/libvorbis.so

В каталогах должны появится такие файлы и папки:
image
Теперь осталось последнее — протестировать все ли работает. Я переделал на скорую руку из стандартных примеров декодирования аудио через libflac. Декодировал из flac файла в wav. Так как код скрипт великоват вы можете протестировать работу на этом apk:тестовый apk файл
(чтоб все сработало, надо чтоб в sdcard был файл output.flac с:
05-20 14:18:42.783: INFO/FLAC(427): sample rate: 44100 Hz
05-20 14:18:42.783: INFO/FLAC(427): channels: 2 Hz
05-20 14:18:42.783: INFO/FLAC(427): bits: 16 Hz, он будет перекодирован в test2.wav. При работе программы ничего писать не будет (только в логи). Протестировано на эмуляторе, HTC Wildfire и Samsung galaxy tab (везде Android 2.2). Процесс занял не более минуты при работе с 20 мегабайтным flac файлом. По окончанию работы отобразится Hello world.
Вот исходники всего проекта:
исходники
Удачи!
Tags:
Hubs:
+28
Comments7

Articles

Change theme settings