2013-07-25 13 views
12

Sto cercando di compilare il codec audio opus (http://www.opus-codec.org/downloads/) per l'utilizzo in un'applicazione Android. Sto usando Android NDK (versione 6) per compilare le mie librerie. Fino ad ora, le librerie C native che ho dovuto compilare per la mia applicazione sono state abbastanza semplici e sono stato in grado di basare i miei file Android.mk in jni principalmente su tutorial o altri esempi. Tuttavia, la compilazione di Opus sembra essere un po 'più complessa. L'archivio tar.gz contiene un file di soluzione per la compilazione delle librerie per Windows e contiene anche alcuni Makefile per un'implementazione Unix standard, ma la loro traduzione in un makefile Android.mk per l'uso con l'NDK di Android è un po 'una sfida.Makefile necessario per compilare Opus Codec per Android

Ho cercato, ma non sono riuscito a trovare una versione online per il makefile Android per compilare libopus. Qualcuno può forse collegarmi a un simile makefile? In alternativa, potrei mancare qualcosa di più semplice? È forse possibile utilizzare Automake o un qualche tipo di convertitore per generare il file Android.mk per me dal makefile unix già incluso in tar.gz?

risposta

12

Quello che segue è il makefile di Android.mk che alla fine ha funzionato per me. Spero che questo possa aiutare qualcun altro in futuro. Prendete nota che nel makefile unix incluso nell'Opus Archive, la decisione se utilizzare le sorgenti di seta fisse o float è definita come "ifdef" mentre qui sto usando "fixed". (Per utilizzare "galleggiare" sarebbe semplice - semplicemente aggiornare i percorsi "di seta/fisso" per puntare a "seta/float" e aggiornare il 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

Perché non contribuire di nuovo alle persone Opus? – Samveen

+0

Buona idea. Andrà bene. – Stanley

+1

Hey Stanley, È mai stato aggiunto a un rilascio ufficiale di opus? Per quale versione di opus era questo makefile? Hai un makefile aggiornato per la v1.1? –

2

MODIFICA: basta usare la soluzione della risposta accettata sopra, il collegamento originale è morto più è fondamentalmente la stessa della risposta accettata al momento in cui ho risposto.

Qui è uno, forse un po 'datato (è stato opus 0.9.14):

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

Sei di scrivere qualche wrapper JNI dopo aver ottenuto la libreria per la compilazione, anche se ...

+0

Grazie, questo mi ha aiutato a impostare in pista. Ho riscontrato alcuni errori di linker quando si utilizzava la parte libopus del makefile a cui si collegava, quindi ho dovuto cambiarla. Sto effettuando l'upvoting perché il link è stato utile per mostrare che le fonti celt, silk e opus possono essere collegate in una singola compilazione e non devono essere prima compilate separatamente in moduli diversi. – Stanley

+0

chissà come chiamare queste interfacce JNI da Android? Voglio registrare la voce, ma non so come usare le funzioni opus per registrare la voce e salvarle su file. – brucenan

+0

@brucenan Si desidera registrare campioni audio usando [l'API Java] (http://developer.android.com/reference/android/media/AudioRecord.html), quindi passare l'array registrato di campioni in C realm per la codifica. Per quella parte devi scrivere tu stesso i wrapper, poiché è ovvio che Opus non ha alcun supporto Java per ora. Si spera che sia semplice scrivere tali wrapper secondo [documentazione API libopus] (http://www.opus-codec.org/docs/html_api-1.1.0/index.html); assicurati di dare un'occhiata Quindi, la scrittura del file può essere eseguita completamente in Java al termine della codifica. Spero che questo ti aiuti! –

2

Grazie a @Stanley, sono stato in grado di creare un. libreria condivisa con successo modificando la sua soluzione un po ', non so ancora se ci sia un vantaggio di avere una libreria statica rispetto a una libreria condivisa.Tutto ciò che so è che ho bisogno di una libreria condivisa per il wrapper JNI. hanno. si notino le flag di compilazione per punto fisso. Senza quelli la compilazione fallirà per la modalità punto fisso.

prima copia del celt_sources.mk, silk_sources.mk e opus_sources.mk dalla sorgente tarball opus alla directory JNI. portare l'inserimento di questi file nel file Android.mk aggiungerà variabili diverse che è possibile utilizzare per includere i file di origine in base al tipo di build. Questo è anche il processo di creazione dell'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's solution 
include $(BUILD_SHARED_LIBRARY) 

Ecco la mia struttura di progetto per la libreria opus.

Project structure

+0

Sembra funzionare bene per ARM, ma non tanto per x86. Sai come sarebbe un makefile per x86? – Buddy

+0

Qual era il problema che stavi avendo? – praneetloke

+0

Oh ...Sembra che funzioni bene ora, c'era un problema con il mio codice. L'ho compilato insieme a opusfile e stavo leggendo il file usando [op_read()] (https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/group__stream__decoding. html # ga963c917749335e29bb2b698c1cb20a10). Sembra funzionare bene con '_buf_size/2' su x86, ma si blocca con un segfault quando ho appena passato' _buf_size' come 'jint' (funziona bene su ARM). L'ho notato nel codice scritto da un'altra persona, ma non conosco il motivo di questo comportamento. Perché devo dividere la dimensione del buffer per 2? Lo stream è mono, btw. – Buddy

9

EDIT IMPORTANTE Le immagini potrebbero non essere aggiornati, ma il lavoro è stato testato su versioni di seguito:

  • opus-1.1
  • opus-1.1.2

Una versione aggiornata (lavora per opus-1.1.2) di @ di praneetloke soluzione. Una sorta di approccio diverso con alcuni extra. Prima di tutto sotto è la mia struttura da utilizzare (avevo intenzione di utilizzare più librerie, così ho messo opus nella propria sottocartella.) folder structor for opus JNI

In secondo luogo ho un root file Android.mk e l'un l'altro all'interno della cartella opus -1.1.2.

Ecco il root file 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 di file all'interno della cartella opus-1.1.2 è qui sotto:

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

Questo è come sembra all'interno opus- 1.1.2 cartella:

Whole Opus Folder structure

L'unico tocco alle fonti originali è l'aggiunta di un file Android.mk. Niente rimosso.

In questo modo posso utilizzare e aggiornare opus proprio come una libreria separata.


Ecco gli extra per chi vuole compilare e utilizzare opus in Android; fonte Wrapper, in parte:

#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 file (facoltativo)

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

Molto utile, grazie! Anch'io ne ho uno simile al tuo e quelli sopra per costruire un libopus.so per armeabi. Tuttavia, mi stavo chiedendo se hai studiato anche la creazione di una versione di armeabi-v7a? – leenephi

+1

@leenephi Non sono sicuro ma, 'APP_ABI: = all' in' Application.mk' genererà un sacco di file .so. Se vuoi solo armeabi e armeabi-v7a allora puoi usare 'APP_ABI: = armeabi armeabi-v7a'. Non ho ancora testato altri file .so. – guness

+0

trascinami fuori! Thank u! ~ – funs