16

我正在尝试编译 opus 音频编解码器 ( http://www.opus-codec.org/downloads/ ) 以在 Android 应用程序中使用。我正在使用 Android NDK(版本 6)来编译我的库。到目前为止,我必须为我的应用程序编译的本机 C 库非常简单,我已经能够将我的 Android.mk 文件基于 jni,主要基于教程或其他示例。但是,Opus 的编译看起来要复杂一些。tar.gz 存档包含一个用于为 Windows 编译库的解决方案文件,它还包含一些用于标准 Unix 实现的 Makefile,但是将这些文件转换为 Android.mk makefile 以供 Android NDK 使用有点挑战。

我已经搜索过,但一直无法找到用于编译 libopus 的 Android makefile 的在线版本。有人可以将我链接到这样的makefile吗?或者,我可能会遗漏一些更简单的东西?是否可以使用 Automake 或某种转换器从 tar.gz 中已包含的 unix makefile 为我生成 Android.mk 文件?

4

4 回答 4

13

以下是最终为我工作的 Android.mk 生成文件。我希望这也可以在将来对其他人有所帮助。请注意,在 Opus 存档中包含的 unix makefile 中,是否使用固定或浮动丝绸源的决定被定义为“ifdef”,而这里我使用的是“固定”。(使用“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)
于 2013-07-28T14:29:02.893 回答
11

重要编辑 图像可能不是最新的,但该作品已在以下版本上进行了测试:

  • 作品1.1
  • 作品1.1.2

@praneetloke 解决方案的更新版本(适用于opus-1.1.2 )。一种带有一些附加功能的不同方法。首先下面是我要使用的结构(我打算使用更多的库,所以我把 opus 放在它自己的子文件夹中。)Opus JNI 的文件夹结构

其次,我在opus-1.1.2Android.mk文件夹中有一个根文件和一个根文件。

这是根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.mkopus-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文件夹中的样子:

整个 Opus 文件夹结构

对原始来源的唯一接触是添加Android.mk文件。什么都没有删除。

这样我就可以像使用单独的库一样使用和更新 opus。


这是为那些想要在 android 中编译和使用 opus 的人准备的额外内容;包装器来源,部分:

#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
于 2015-06-26T11:54:57.920 回答
3

编辑:只需使用上面接受的答案的解决方案,原始链接已失效,而且它与我回答时接受的答案基本相同。

这是一个,可能有点过时(它使用作品 0.9.14):

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

不过,在编译库之后,您将编写一些 JNI 包装器......

于 2013-07-28T01:35:41.730 回答
3

感谢@Stanley,我能够通过稍微调整他的解决方案成功地创建一个共享库。我还不知道拥有静态库与共享库相比是否有优势。我只知道我需要一个用于 JNI 包装器的共享库。这就是我所拥有的。注意定点的编译器标志。没有这些,定点模式的编译将失败。

celt_sources.mk首先将,silk_sources.mkopus_sources.mk从 opus 源 tarball复制到您的 jni 目录。将这些文件添加到您的Android.mk文件中将添加不同的变量,您可以根据构建的类型使用这些变量来包含源文件。这也是作品构建过程所做的。

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's solution
include $(BUILD_SHARED_LIBRARY)

这是我的作品库的项目结构。

项目结构

于 2015-01-12T04:13:22.443 回答