Привет, Хабралюди!
В процессе работы с Android NDK я столкнулся с проблемой сборки уже существующих Linux библиотек на Android NDK. Так как материала не слишком много в этой статье поделюсь своим опытом. В Андроиде я новичек, так что если найдете ошибки — пишите:)
Чтобы пример был не самым простым и при том полезным — возьмём библиотеку libFLAC. Этот даст возможность декодировать .flac файлы. По данному мануалу, я надеюсь, соберутся большинство других библиотек.
Кроме неё нам понадобится:
Создаём стандартный Android проект, в нем создаём папку jni и распаковываем туда libogg, libvorbis, libflac.
Приступим к первому этапу. Для сборки я использовал такой скрипт:
Для libVorbis придется его немного изменить:
LDFLAGS будет таким:
а LIBS:
Для libflac изменим добавим в libs -lvorbis.
Рассмотрим структуру скрипта по порядку. Строка export CC — путь к компилятору Android NDK. Тут: export LDFLAGS можем задавать директории, где искать библиотеки, а в LIBS подключать их. В этой строке: export CPPFLAGS подключаем headers дополнительных библиотек.
Выполняете нужные скрипты в корне каждой из библиотек. После сборки, если все прошло успешно вы получаете библиотеки, которые уже можно компилировать на NDK.
Итак, для начала создадим 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 в тех же папках.
В Makefile.am ищем строки:
libogg_la_SOURCES = framing.c bitwise.c — это все что нам надо. Получаем стандартный Android.mk вида:
Думаю тут объяснять ничего не надо. Идём дальше.
Тут тоже все просто. Находим строку: libvorbis_la_SOURCES и подулючаем все файлы, что там есть. Получаем такой Android.mk:
Процесс тот же, но файлов намного больше и они в поддиректориях. Я решил все что есть собрать в одну библиотеку, чтоб было проще, поэтому получил такой скрипт:
И последнее:
Выполняем ndk-build (этот скрипт находится в папке NDK) и видим что все компилируется, но flac даёт следующую ошибку:
Проблема в том, что константа VERSION определена в makefile, который мы не подключали. Самым простым выходом я вижу создать эту константу в самом format.c вот так:
Все теперь ошибок нет. При компиляции получаем:
В каталогах должны появится такие файлы и папки:
Теперь осталось последнее — протестировать все ли работает. Я переделал на скорую руку из стандартных примеров декодирования аудио через 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.
Вот исходники всего проекта:
исходники
Удачи!
В процессе работы с 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
В каталогах должны появится такие файлы и папки:
Теперь осталось последнее — протестировать все ли работает. Я переделал на скорую руку из стандартных примеров декодирования аудио через 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.
Вот исходники всего проекта:
исходники
Удачи!