二滚秩、JNI函數(shù)動態(tài)注冊和靜態(tài)注冊

JNI函數(shù)的注冊:將Java層的native函數(shù)和JNI層對應的實現(xiàn)函數(shù)關聯(lián)起來专执。

===============================
PushNative.java
===============================
package com.fmtech.fmlive.jni;

public class PushNative {

    static{
        System.loadLibrary("FMLive");
    }

    public native void setAudioOptions(int sampleRateInHz, int channel);

}
===============================
FMLive.c
===============================
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

一、動態(tài)注冊

/*
* 音頻編碼器配置
* Class: com_fmtech_fmlive_jni_PushNative
* Method: setAudioOptions
* Signature: (II)V
*/
//JNIEXPORT void JNICALL Java_com_fmtech_fmlive_jni_PushNative_setAudioOptions
//Use dynamic register
JNIEXPORT void JNICALL native_setAudioOptions(JNIEnv *env, jobject jobj, jint sampleRateInHz, jint numChannels){
        audio_encode_handle = faacEncOpen(sampleRateInHz, numChannels,&inputSamples,&maxOutputBytes);
        if(!audio_encode_handle){
                LOGE("%s","-------open audio_encode failed");
                return;
        }

        //設置音頻編碼參數(shù)
        faacEncConfigurationPtr p_config = faacEncGetCurrentConfiguration(audio_encode_handle);
        p_config->mpegVersion = MPEG4;
        p_config->allowMidside = 1;
        p_config->aacObjectType = LOW;
        p_config->outputFormat = 0; //輸出是否包含ADTS頭
        p_config->useTns = 1; //時域噪音控制,大概就是消爆音
        p_config->useLfe = 0;
        // p_config->inputFormat = FAAC_INPUT_16BIT;
        p_config->quantqual = 100;
        p_config->bandWidth = 0; //頻寬
        p_config->shortctl = SHORTCTL_NORMAL;

        if(!faacEncSetConfiguration(audio_encode_handle, p_config)){
                LOGE("%s","set faac encode configure failed");
                return;
        }
        LOGI("%s","set faac encode configure success");

}

typedef struct {
    const char* name;
    const char* signature;
    void* fnPtr;
} JNINativeMethod;

static const JNINativeMethod gMethods[] = {
        {
                "setAudioOptions",
                "(II)V",
                (void*)native_setAudioOptions
        }
};

static int registerNatives(JNIEnv* env)
{
        LOGI("registerNatives begin");
        jclass clazz;
        clazz = (*env) -> FindClass(env, "com/fmtech/fmlive/jni/PushNative");

        if (clazz == NULL) {
                LOGI("clazz is null");
                return JNI_FALSE;
        }

        if ((*env) ->RegisterNatives(env, clazz, gMethods, NELEM(gMethods)) < 0) {
                LOGI("RegisterNatives error");
                return JNI_FALSE;
        }

        return JNI_TRUE;
}


jint JNI_OnLoad(JavaVM* vm, void* reserved){
        JNIEnv* env = NULL;

        if ((*vm)->GetEnv(vm,(void**) &env, JNI_VERSION_1_4) != JNI_OK) {
                LOGI("ERROR: GetEnv failed\n");
                return -1;
        }
        assert(env != NULL);

        registerNatives(env);

        return JNI_VERSION_1_4;//jni1.4以上支持
}

1郁油、函數(shù)動態(tài)注冊的好處:
移植方便本股?

2、使用數(shù)據(jù)結構JNINativeMethod來記錄Java native方法和JNI函數(shù)的一一對應關系桐腌。

    typedef struct {
              const char* name; //Java中native方法的名稱痊末,不用攜帶包的路徑
              const char* signature; //Java方法的簽名信息,用字符串表示哩掺,是參數(shù)類型和返回值類型的組合
              void* fnPtr; // JNI層對應函數(shù)的函數(shù)指針凿叠,注意它是void*類型
      } JNINativeMethod;

3、當Java層通過System.loadLibrary加載完JNI動態(tài)庫后嚼吞,緊接著會查找該庫中一個叫JNI_OnLoad的函數(shù)盒件。如果有,就調用它舱禽,而動態(tài)注冊的工作就是在這里完成的炒刁。
所以,如果想使用動態(tài)注冊方法誊稚,就必須實現(xiàn)JNI_OnLoad函數(shù)翔始,只有在這個函數(shù)中才有機會完成動態(tài)注冊的工作。

二里伯、靜態(tài)注冊

JNIEXPORT void JNICALL Java_com_fmtech_fmlive_jni_PushNative_setAudioOptions
(JNIEnv *env, jobject jobj, jint sampleRateInHz, jint numChannels){
        audio_encode_handle = faacEncOpen(sampleRateInHz, numChannels,&inputSamples,&maxOutputBytes);
        if(!audio_encode_handle){
                LOGE("%s","-------open audio_encode failed");
                return;
        }

        //設置音頻編碼參數(shù)
        faacEncConfigurationPtr p_config = faacEncGetCurrentConfiguration(audio_encode_handle);
        p_config->mpegVersion = MPEG4;
        p_config->allowMidside = 1;
        p_config->aacObjectType = LOW;
        p_config->outputFormat = 0; //輸出是否包含ADTS頭
        p_config->useTns = 1; //時域噪音控制,大概就是消爆音
        p_config->useLfe = 0;
        // p_config->inputFormat = FAAC_INPUT_16BIT;
        p_config->quantqual = 100;
        p_config->bandWidth = 0; //頻寬
        p_config->shortctl = SHORTCTL_NORMAL;

        if(!faacEncSetConfiguration(audio_encode_handle, p_config)){
                LOGE("%s","set faac encode configure failed");
                return;
        }
        LOGI("%s","set faac encode configure success");

}

當Java層調用setAudioOptions 函數(shù)時城瞎,它會從對應的JNI庫中尋找Java_com_fmtech_fmlive_jni_PushNative_setAudioOptions函數(shù),如果沒有疾瓮,就會報錯脖镀。如果找到,則會為這個setAudioOptions 和Java_com_fmtech_fmlive_jni_PushNative_setAudioOptions建立一個關聯(lián)關系狼电,其實就是保存JNI層函數(shù)的函數(shù)指針蜒灰。以后再調用setAudioOptions函數(shù)時,直接使用這個函數(shù)指針就可以了肩碟,當然這項工作是由虛擬機完成的强窖。
函數(shù)靜態(tài)注冊就是根據(jù)函數(shù)名來建立Java函數(shù)和JNI函數(shù)之間的關聯(lián)關系的,而且它要求JNI層函數(shù)的名字必須遵守特定的格式削祈。
函數(shù)靜態(tài)注冊的弊端:
1?需要編譯所有聲明了native方法的Java類翅溺,每個所生成的class文件 都得用javah生成一個頭文件。
2、javah生成的JNI層函數(shù)名特別長未巫,書寫起來很不方便窿撬。
3启昧、初次調用native函數(shù)時要根據(jù)函數(shù)名字搜索對應用JNI層函數(shù)來建立關聯(lián)關系叙凡,這樣會影響運行效率。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末密末,一起剝皮案震驚了整個濱河市握爷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌严里,老刑警劉巖新啼,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刹碾,居然都是意外死亡燥撞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門迷帜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來物舒,“玉大人,你說我怎么就攤上這事戏锹」诳瑁” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵锦针,是天一觀的道長荠察。 經(jīng)常有香客問我,道長奈搜,這世上最難降的妖魔是什么悉盆? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮馋吗,結果婚禮上舀瓢,老公的妹妹穿的比我還像新娘。我一直安慰自己耗美,他們只是感情好京髓,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著商架,像睡著了一般堰怨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛇摸,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天备图,我揣著相機與錄音,去河邊找鬼。 笑死揽涮,一個胖子當著我的面吹牛抠藕,可吹牛的內容都是我干的。 我是一名探鬼主播蒋困,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼盾似,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了雪标?” 一聲冷哼從身側響起零院,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎村刨,沒想到半個月后告抄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡嵌牺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年打洼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逆粹。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡募疮,死狀恐怖,靈堂內的尸體忽然破棺而出枯饿,到底是詐尸還是另有隱情酝锅,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布奢方,位于F島的核電站搔扁,受9級特大地震影響,放射性物質發(fā)生泄漏蟋字。R本人自食惡果不足惜稿蹲,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹊奖。 院中可真熱鬧苛聘,春花似錦、人聲如沸忠聚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽两蟀。三九已至网梢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赂毯,已是汗流浹背战虏。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工拣宰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烦感。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓巡社,卻偏偏與公主長得像,于是被迫代替她去往敵國和親手趣。 傳聞我的和親對象是個殘疾皇子晌该,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容