Makefile, необходимый для компиляции Opus Codec для Android

Я пытаюсь скомпилировать звуковой кодек opus (http://www.opus-codec.org/downloads/) для использования в приложении для Android. Я использую Android NDK (выпуск 6) для компиляции моих библиотек. До сих пор родные библиотеки C, которые мне пришлось скомпилировать для моего приложения, были довольно простыми, и я смог основать файлы Android.mk в jni в основном на уроках или других примерах. Однако компиляция Opus выглядит несколько более сложной. Архив tar.gz содержит файл решения для компиляции библиотек для Windows, а также содержит некоторые Make файлы для стандартной реализации Unix, но перевод их в make файл Android.mk для использования в Android NDK - это немного сложная задача.

Я искал, но не смог найти онлайн-версию для Android makefile для компиляции libopus. Может ли кто-нибудь связать меня с таким файлом? В качестве альтернативы, я мог бы пропустить что-то более простое? Возможно ли использовать Automake или какой-то конвертер, чтобы, возможно, создать файл Android.mk для меня из make файла unix, который уже включен в tar.gz?

Ответ 1

Ниже приведен файл make.mp3.mk, который в конечном итоге работал у меня. Надеюсь, это может помочь кому-то еще и в будущем. Обратите внимание, что в make файле unix, включенном в архив Opus, решение о том, использовать ли источники с фиксированным или плавающим шелком, определяется как "ifdef", тогда как здесь я использую "fixed". (Использовать "float" было бы просто - просто обновить пути "silk/fixed", чтобы указать на "silk/float" и обновить CFLAGS.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

MY_MODULE_DIR       := opus

LOCAL_MODULE        := $(MY_MODULE_DIR)
LOCAL_SRC_FILES     := \
    $(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/src/*.c*)) \
    $(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/celt/*.c*)) \
    $(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/silk/*.c*)) \
    $(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/silk/fixed/*.c*))
LOCAL_LDLIBS        := -lm -llog
LOCAL_C_INCLUDES    := \
    $(ROOT_DIR)/$(MY_MODULE_DIR)/include \
    $(ROOT_DIR)/$(MY_MODULE_DIR)/silk \
    $(ROOT_DIR)/$(MY_MODULE_DIR)/silk/fixed \
    $(ROOT_DIR)/$(MY_MODULE_DIR)/celt
LOCAL_CFLAGS        := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS    += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CPPFLAGS      := -DBSD=1 
LOCAL_CPPFLAGS          += -ffast-math -O3 -funroll-loops

include $(BUILD_STATIC_LIBRARY)

Ответ 2

ВАЖНОЕ ИЗМЕНЕНИЕ Изображения могут быть не самыми современными, но работа была протестирована в следующих версиях:

  • Opus-1,1
  • опус-1.1.2

Обновленная версия (работает для opus-1.1.2) решения @praneetloke. Какой-то другой подход с некоторыми дополнительными функциями. Прежде всего, это моя структура для использования (я намеревался использовать больше библиотек, поэтому я помещал opus в свою собственную подпапку.) folder structor for opus JNI

Во-вторых, у меня есть файл root Android.mk и один из них внутри папки opus-1.1.2.

Вот корневой файл Android.mk:

LOCAL_PATH := $(call my-dir)
OPUS_DIR            := opus-1.1.2

include $(OPUS_DIR)/Android.mk

include $(CLEAR_VARS)

LOCAL_MODULE        := codec
LOCAL_SRC_FILES     := Opus_jni.cpp
LOCAL_CFLAGS        := -DNULL=0
LOCAL_LDLIBS        := -lm -llog
LOCAL_C_INCLUDES    := $(LOCAL_PATH)/$(OPUS_DIR)/include
LOCAL_SHARED_LIBRARIES := opus
include $(BUILD_SHARED_LIBRARY)

Android.mk файл внутри папки opus-1.1.2 находится ниже:

#Backing up previous LOCAL_PATH so it does not screw with the root Android.mk file
LOCAL_PATH_OLD := $(LOCAL_PATH)
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#include the .mk files
include $(LOCAL_PATH)/celt_sources.mk
include $(LOCAL_PATH)/silk_sources.mk
include $(LOCAL_PATH)/opus_sources.mk

LOCAL_MODULE        := opus

#fixed point sources
SILK_SOURCES += $(SILK_SOURCES_FIXED)

#ARM build
CELT_SOURCES += $(CELT_SOURCES_ARM)
SILK_SOURCES += $(SILK_SOURCES_ARM)
LOCAL_SRC_FILES     := \
$(CELT_SOURCES) $(SILK_SOURCES) $(OPUS_SOURCES)

LOCAL_LDLIBS        := -lm -llog

LOCAL_C_INCLUDES    := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/silk \
$(LOCAL_PATH)/silk/fixed \
$(LOCAL_PATH)/celt

LOCAL_CFLAGS        := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64

LOCAL_CFLAGS        += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT=1 -DDISABLE_FLOAT_API -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF  -DAVOID_TABLES
LOCAL_CFLAGS        +=  -w -std=gnu99 -O3 -fno-strict-aliasing -fprefetch-loop-arrays  -fno-math-errno
LOCAL_CPPFLAGS      := -DBSD=1
LOCAL_CPPFLAGS      += -ffast-math -O3 -funroll-loops

include $(BUILD_SHARED_LIBRARY)

#Putting previous LOCAL_PATH back here
LOCAL_PATH := $(LOCAL_PATH_OLD)

Вот как это выглядит внутри папки opus-1.1.2:

Whole Opus Folder structure

Единственное касание исходных источников - это добавление файла Android.mk. Ничего не удалено.

Таким образом, я могу использовать и обновлять opus так же, как отдельную библиотеку.


Вот дополнительные функции для тех, кто хочет скомпилировать и использовать opus в android; Источник обертки, частично:

#include <jni.h>
#include <android/log.h>
#include <opus.h>

/* Header for class net_abcdefgh_opustrial_codec_Opus */
#ifndef _Included_net_abcdefgh_opustrial_codec_Opus
#define _Included_net_abcdefgh_opustrial_codec_Opus

#define TAG "Opus_JNI"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO  , TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN  , TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG,__VA_ARGS__)
#ifdef __cplusplus
extern "C" {
    #endif
    JNIEXPORT jint JNICALL Java_net_abcdefgh_opustrial_codec_Opus_open
    (JNIEnv *env, jobject thiz){
        ...
        return error;
    }
    JNIEXPORT jint JNICALL Java_net_abcdefgh_opustrial_codec_Opus_decode
    (JNIEnv * env, jobject thiz, jbyteArray jencoded, jint jencodedOffset, jint jencodedLength, jbyteArray jpcm, jint jpcmOffset, jint jframeSize) {
        ...
        return decodedSize;
    }
    JNIEXPORT jint JNICALL Java_net_abcdefgh_opustrial_codec_Opus_encode
    (JNIEnv * env, jobject thiz, jbyteArray jpcm, jint jpcmOffset, jint jpcmLength, jbyteArray jencoded, jint jencodedOffset) {
        ...
        return encodedSize;
    }
    JNIEXPORT void JNICALL Java_net_abcdefgh_opustrial_codec_Opus_close
    (JNIEnv *env, jobject thiz){
        ...
    }
    #ifdef __cplusplus
}
#endif
#endif

Application.mk файл (необязательно)

APP_ABI := all  # mips, armeabi, armeabi-v7a, x86 etc. builds

Ответ 3

РЕДАКТИРОВАТЬ: просто используйте принятое решение для ответа выше, исходная ссылка мертва плюс в основном такая же, как и принятый ответ в то время, когда я ответил.

Вот один, может быть, немного устаревший (он использовал opus 0.9.14):

https://github.com/haxar/mangler/blob/master/android/jni/Android.mk

Вы должны написать некоторые обертки JNI после получения библиотеки для компиляции, хотя...

Ответ 4

Благодаря @Stanley мне удалось создать общую библиотеку, немного изменив ее решение. Я еще не знаю, есть ли преимущество наличия статической библиотеки и общей библиотеки. Все, что я знаю, мне нужна общая библиотека для обертки JNI. Это то, что у меня есть. Обратите внимание на флаги компилятора для фиксированной точки. Без них компиляция завершится неудачно для режима с фиксированной точкой.

Сначала скопируйте celt_sources.mk, silk_sources.mk и opus_sources.mk из архива источника opus в каталог jni. Приведение этих файлов в ваш файл Android.mk приведет к добавлению разных переменных, которые вы можете использовать для включения исходных файлов в зависимости от типа сборки. Это то же, что и процесс сборки opus.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#include the .mk files
include celt_sources.mk
include silk_sources.mk
include opus_sources.mk

MY_MODULE_DIR       := opus

LOCAL_MODULE        := $(MY_MODULE_DIR)

#fixed point sources
SILK_SOURCES += $(SILK_SOURCES_FIXED)

#ARM build
CELT_SOURCES += $(CELT_SOURCES_ARM)
SILK_SOURCES += $(SILK_SOURCES_ARM)
LOCAL_SRC_FILES     := \
$(CELT_SOURCES) $(SILK_SOURCES) $(OPUS_SOURCES)

LOCAL_LDLIBS        := -lm -llog

LOCAL_C_INCLUDES    := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/silk \
$(LOCAL_PATH)/silk/fixed \
$(LOCAL_PATH)/celt

LOCAL_CFLAGS        := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS        += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT=1 -DDISABLE_FLOAT_API -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CPPFLAGS      := -DBSD=1
LOCAL_CPPFLAGS      += -ffast-math -O3 -funroll-loops

#build a shared library not a static one like in Stanley solution
include $(BUILD_SHARED_LIBRARY)

Здесь моя структура проекта для библиотеки opus.

Project structure