2013-07-25 13 views
12

Ich versuche, den Opus Audio Codec (http://www.opus-codec.org/downloads/) für die Verwendung in einer Android-Anwendung zu kompilieren. Ich verwende Android NDK (Release 6), um meine Bibliotheken zu kompilieren. Bis jetzt waren die nativen C-Bibliotheken, die ich für meine Anwendung kompilieren musste, ziemlich einfach und ich konnte meine Android.mk-Dateien in jni hauptsächlich auf Tutorials oder anderen Beispielen basieren. Die Zusammenstellung von Opus scheint jedoch etwas komplexer zu sein. Das tar.gz-Archiv enthält eine Lösungsdatei zum Kompilieren der Bibliotheken für Windows und enthält auch einige Makefiles für eine Standard-Unix-Implementierung, aber das Übersetzen in ein Android.mk-Makefile zur Verwendung durch das Android-NDK ist eine kleine Herausforderung.Makefile benötigt für die Kompilierung des Opus Codec für Android

Ich habe gesucht, konnte aber keine Online-Version für das Android Makefile finden, um libopus zu kompilieren. Kann mich jemand vielleicht mit einem solchen Makefile verbinden? Alternativ könnte ich etwas einfacheres verpassen? Ist es vielleicht möglich, Automake oder irgendeine Art von Konverter zu verwenden, um vielleicht die Datei Android.mk für mich aus dem Makefile zu generieren, das bereits in tar.gz enthalten ist?

Antwort

12

Das folgende ist das Android.mk makefile, das schließlich für mich arbeitete. Ich hoffe, dies kann auch in Zukunft anderen helfen. Beachten Sie, dass in dem Unix-Makefile, das im Opus-Archiv enthalten ist, die Entscheidung, ob die festen oder float-seitigen Quellen verwendet werden, als "ifdef" definiert ist, während ich hier "fest" verwende. (Zur Nutzung „float“ einfach wäre - einfach aktualisieren, um die Pfade „Seide/fixed“, um „Seide/float“ und aktualisieren Sie die 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

Warum es nicht zurück zu den Opus-Leuten beitragen? – Samveen

+0

Gute Idee. Wird besorgt. – Stanley

+1

Hey Stanley, Wurde dies jemals einer offiziellen Opus-Veröffentlichung hinzugefügt? Für welche Version von Opus wurde dieses Makefile erstellt? Haben Sie ein aktualisiertes Makefile für v1.1? –

2

EDIT: Verwenden Sie einfach die Lösung der angenommenen Antwort oben, die ursprüngliche Verbindung ist tot und es ist im Grunde das gleiche wie die angenommene Antwort zu der Zeit, als ich antwortete.

Hier ist einer, vielleicht ein wenig veraltet (es verwendet Opus 0.9.14):

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

Sie sind einige JNI-Wrapper zu schreiben, nachdem die Bibliothek bekommen, obwohl zu kompilieren, ...

+0

Danke, das half setzt mich auf dem richtigen Weg. Ich habe ein paar Linker-Fehler, wenn ich den libopus-Teil des Makefile benutze, mit dem ich verlinke, also musste ich es ändern. Ich bin upvoting, weil der Link hilfreich war, um zu zeigen, dass cel-, silk- und opus-Quellen in einer einzigen Kompilierung verknüpft werden können und nicht zuerst separat in verschiedene Module kompiliert werden müssen. – Stanley

+0

Wer kann diese JNI-Schnittstelle von Android aus anrufen? Ich möchte die Stimme aufnehmen, aber ich weiß nicht, wie man die Opus-Funktionen benutzt, um die Stimme aufzunehmen und in einer Datei zu speichern. – brucenan

+0

@brucenan Sie möchten Audio-Samples mit [Java API] (http://developer.android.com/reference/android/media/AudioRecord.html) aufnehmen und dann das aufgezeichnete Array von Samples zum Codieren in C-Realm übergeben. Für diesen Teil müssen Sie die Wrapper selbst schreiben, da es offensichtlich ist, dass Opus momentan keine Java-Unterstützung hat. Hoffentlich ist es einfach, solche Wrapper gemäß der [libopus-API-Dokumentation] zu schreiben (http://www.opus-codec.org/docs/html_api-1.1.0/index.html); Achten Sie darauf, es zu überprüfen. Anschließend kann die Datei nach Abschluss der Codierung vollständig in Java geschrieben werden. Hoffe das hilft! –

2

Dank @Stanley konnte ich ein schaffen. Ich weiß nicht, ob es eine statische Bibliothek oder eine gemeinsam genutzte Bibliothek gibt, aber ich weiß nur, dass ich eine gemeinsame Bibliothek für den JNI-Wrapper brauche haben. Beachten Sie die Compiler-Flags für festen Punkt. Ohne diese die Kompilierung für festen Punkt-Modus fehl.

kopieren Sie die celt_sources.mk, silk_sources.mk und opus_sources.mk aus dem opus Quellkodearchivs zu Ihrem jni Verzeichnis. Bringen Wenn Sie diese Dateien in Ihre Datei Android.mk einfügen, werden verschiedene Variablen hinzugefügt, die Sie verwenden können, um Quelldateien basierend auf dem Typ des Builds einzubeziehen. Dies ist auch der Prozess des Opus-Builds.

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) 

Hier ist meine Projektstruktur für die Opus-Bibliothek.

Project structure

+0

Es scheint gut für ARM zu funktionieren, aber nicht so sehr für x86. Weißt du wie ein Makefile für x86 aussehen würde? – Buddy

+0

Was war das Problem, das Sie hatten? – praneetloke

+0

Oh ...Es scheint jetzt zu funktionieren, es gab ein Problem mit meinem Code. Ich habe es zusammen mit opusfile kompiliert und las die Datei mit [op_read()] (https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/group__stream__decoding. html # ga963c917749335e29bb2b698c1cb20a10). Es scheint mit '_buf_size/2' auf x86 zu funktionieren, aber es stürzt mit einem segfault ab, wenn ich' _buf_size' einfach als 'jint' übergebe (funktioniert gut auf ARM). Ich habe das in Code bemerkt, der von einer anderen Person geschrieben wurde, aber ich kenne den Grund für dieses Verhalten nicht. Warum muss ich die Puffergröße durch 2 teilen? Der Stream ist Mono, BTW. – Buddy

9

WICHTIG EDIT Die Bilder möglicherweise nicht auf dem neuesten Stand sein, aber die Arbeit wurde unter Versionen getestet:

  • opus-1.1
  • opus-1.1.

Eine aktualisierte Version (funktioniert für opus-1.1.2) von @ praneetloke-Lösung. Eine Art anderer Ansatz mit einigen Extras. Zunächst einmal unten ist meine Struktur zu verwenden (ich sollte mehr Bibliotheken verwenden, so dass ich Opus in seinem eigenen Unterverzeichnis.) folder structor for opus JNI

Zweitens habe ich eine Wurzel Android.mk Datei und sie in den Ordner opus -1.1.2. Hier

ist die Wurzel Android.mk Datei:

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 Datei im opus-1.1.2 Ordner unter:

#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) 

Dies ist, wie es aussieht innen OPUS 1.1.2 Ordner:

Whole Opus Folder structure

Die einzige Berührung zu den Originalquellen ist das Hinzufügen einer Android.mk Datei. Nichts entfernt.

Auf diese Weise kann ich Opus wie eine separate Bibliothek verwenden und aktualisieren.


Hier ist die Extras für diejenigen, die Opus in Android kompilieren und verwenden möchten; Wrapper Quelle, teilweise:

#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 Datei (optional)

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

Sehr hilfreich, danke! Ich habe auch eines, das deinem und den oben genannten ähnlich ist, um einen libopus.so für armeabi zu bauen. Wie auch immer, ich habe mich gefragt, ob Sie auch eine armee-v7a-Version entwickelt haben? – leenephi

+1

@leenephi Ich bin mir nicht sicher, aber 'APP_ABI: = all' in' Application.mk' wird eine Menge .so-Datei erzeugen. Wenn Sie nur armeabi und armeabi-v7a wollen, können Sie 'APP_ABI: = armeabi armeabi-v7a' verwenden. Ich habe keine anderen .so-Dateien getestet. – guness

+0

Zieh mich raus! Thank u! ~ – funs

Verwandte Themen