国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

【JNI】OPUS壓縮與解壓的JNI調(diào)用(.DLL版本)

2019-11-14 20:50:41
字體:
供稿:網(wǎng)友
【JNI】OPUS壓縮與解壓的JNI調(diào)用(.DLL版本)


OPUS壓縮與解壓的JNI調(diào)用(.DLL版本)
一、寫在開頭:

理論上講,這是我在博客園的第一篇原創(chuàng)的博客,之前也一直想找個(gè)地方寫點(diǎn)東西,把最近做的一些東西歸納總結(jié)下,但是一般工程做完了一高興就把東西丟一邊就很久不碰了,久而久之就淡忘了。這不是一個(gè)很好的習(xí)慣,古人也說更好記性不如爛筆頭,無論是做學(xué)術(shù)還是做工程,定期總結(jié)與歸納都是一個(gè)不錯(cuò)的鞏固與提高的方法。另外,也希望給后來者一點(diǎn)可行性的參考(有誤導(dǎo)的地方請(qǐng)輕噴)。


二、引言:

言歸正傳,最近在做Android的一個(gè)工程,大體是實(shí)現(xiàn)在Android平臺(tái)的錄音、壓縮、傳輸、解壓、識(shí)別的功能。其中,識(shí)別包括語音識(shí)別與音樂片段的識(shí)別,這是兩個(gè)很大的模塊,有其他的工程師負(fù)責(zé)。我負(fù)責(zé)錄音、壓縮、傳輸、解壓等幾個(gè)小模塊。

其中錄音功能是比較簡單的,網(wǎng)上參考的范例比較多,以后找時(shí)間再整理下。壓縮部分包括語音壓縮(VAD+壓縮)與旋律的壓縮,因?yàn)橛眠^Speex壓縮,所以語音壓縮模塊就直接沿用了之前的范例,但是Speex只能對(duì)語音進(jìn)行壓縮,不能對(duì)旋律進(jìn)行壓縮(失真較大,影響片段的檢索),所以考慮采用一種較新的壓縮方式:Opus壓縮。


三、OPUS簡介:

Opus編碼器 是一個(gè)有損聲音編碼的格式,由互聯(lián)網(wǎng)工程任務(wù)組(IETF)進(jìn)來開發(fā),適用于網(wǎng)絡(luò)上的實(shí)時(shí)聲音傳輸,標(biāo)準(zhǔn)格式為RFC6716。Opus 格式是一個(gè)開放格式,使用上沒有任何專利或限制。

Opus壓縮幾乎包含了Speex壓縮的所有功能,并且支持對(duì)旋律的壓縮,可以說功能是相當(dāng)強(qiáng)大的,同Speex一樣,Opus也是開源的,可以在官網(wǎng)上下載到Opus的源碼。我下載的是最新的1.1版本的,解壓后如下圖所示:

但是除了官網(wǎng)外,Opus壓縮的參考比較少,跨平臺(tái)應(yīng)用的就更少了點(diǎn),做慣了伸手黨的我對(duì)此相當(dāng)郁悶,所以就花了點(diǎn)時(shí)間研究了下,實(shí)現(xiàn)了Android客戶端(.so庫)與windows服務(wù)器端(.dll庫)的調(diào)用。

服務(wù)器端相對(duì)簡單一點(diǎn),基本思路是:利用VS2010創(chuàng)建生成相應(yīng)的dll庫,然后在服務(wù)器端利用NDK實(shí)現(xiàn)JNI接口,繼而在主函數(shù)中實(shí)現(xiàn)調(diào)用。


四、Opus的DLL生成過程

Opus使用C語言實(shí)現(xiàn)的,并且官網(wǎng)上給了幾個(gè)不錯(cuò)的DEMO,要實(shí)現(xiàn)java對(duì)C/C++跨平臺(tái)的調(diào)用,首先我們要保證我們的C語言接口是正確的,也就是說,首先要在VS2010等平臺(tái)上將調(diào)用的函數(shù)跑通,只有測試函數(shù)通過了,才能保證我們移植到JVM上的程序是正確的。之后要根據(jù)正確的測試函數(shù)書寫C語言接口,然后將C語言寫的接口編譯生成相應(yīng)的dll庫。

4.1、書寫完整的測試函數(shù)

打開Opus官網(wǎng)上給的工程,其中,測試了一下,test_opus_encode工程和test_opus_decode工程里面都有完整的壓縮與解壓實(shí)體。所以,我們只需要改寫其中的一個(gè)工程的主函數(shù)OK了,主函數(shù)書寫的基本思路為:壓縮與解壓對(duì)象的創(chuàng)建、參數(shù)的設(shè)置、壓縮/解壓、資源的釋放,代碼如下:

  1 #ifdef HAVE_CONFIG_H  2 #include "config.h"  3 #endif  4 #include <stdio.h>  5 #include <stdlib.h>  6 #include <limits.h>  7 #include <stdint.h>  8 #include <math.h>  9 #include <string.h> 10 #include <time.h> 11 #if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__) 12 #include <unistd.h> 13 #else 14 #include <PRocess.h> 15 #define getpid _getpid 16 #endif 17 #include "opus_multistream.h" 18 #include "opus.h" 19 #include "../src/opus_private.h" 20 //#include "test_opus_common.h" 21  22 /*#define MAX_PACKET (1500) 23 #define SAMPLES (48000*30) 24 #define SSAMPLES (SAMPLES/3) 25 #define MAX_FRAME_SAMP (5760)*/ 26  27 int error; 28 int Fs=16000; 29 int channels=1; 30 int application=OPUS_APPLICATION_AUDIO; 31 OpusEncoder *enc=NULL; 32  33 opus_int32 bitrate_bps=16000; 34 int bandwidth = OPUS_AUTO; 35 int use_vbr = 0; 36 int cvbr=1; 37 int complexity = 8; 38  39 int frame_size_1=320; 40 int frame_size_2=320; 41 opus_int32 max_data_bytes=2500; 42  43 unsigned char *data; 44 const opus_int16 *pcm; 45 opus_int16 *pcm_re; 46  OpusDecoder *dec=NULL; 47  unsigned char data_1[60][40]; 48  opus_int16 pcm_re_1[60][320]; 49  opus_int16 pcm_bf[60][320]; 50  51 #define PI (3.141592653589793238462643f) 52     int i; 53     int j; 54     int n; 55     int m; 56     int packet_loss_perc=0; 57  58     int max_frame_size = 2*16000; 59     int output_samples; 60     opus_uint32 dec_final_range; 61     int dur; 62  63     FILE *fp; 64     FILE *fp_1; 65     int num_pcm; 66     int num_pcm_re; 67     short temp_end[19200]; 68  69 int main(int _argc, char **_argv) 70 { 71     short temp[19200]; 72     FILE *foo; 73     printf("I am lzhen/n"); 74     //memset(temp,1,600); 75      76   77     if((fp=fopen("e://dkdt.pcm","rb"))==NULL) 78     { 79        printf("cant open the file"); 80     } 81      82 num_pcm=fread(&temp[0],sizeof(short),19200,fp);   83  84 printf("%d ",num_pcm); 85 //for(i=0;i<19200;i++) 86 //{ 87     //printf("%d ",temp[i]); 88 //} 89    fclose(fp);//將打開的文件關(guān)閉 90  91    for (i=0;i<60;i++) 92        for(j=0;j<320;j++) 93        { 94        pcm_bf[i][j]=temp[320*i+j]; 95        } 96  97  98     enc = opus_encoder_create(Fs, channels, application, &error); 99 100     if (error != OPUS_OK)101     {printf("創(chuàng)建失敗");102     }else103     {printf("創(chuàng)建成功");104     }105 106     //for(pcm=number,i=0;i<2000;i++,pcm++)107     //{printf("%d  ",*pcm);}108 109        opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));110        opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));111        opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr));112        opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));113        opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));114        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));115        /*opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(use_inbandfec));116        opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(forcechannels));117        opus_encoder_ctl(enc, OPUS_SET_DTX(use_dtx));118        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));119 120        opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));121        opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));122        opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));*/123 124        for(i=0;i<60;i++)125        {126        pcm=pcm_bf[i]; 127        data=data_1[i];128 129     n=opus_encode(130          enc,131          pcm,132          frame_size_1,133          data,134          max_data_bytes);135        }//OPUS壓縮136     opus_encoder_destroy(enc);//釋放資源137     dec = opus_decoder_create(Fs, channels, &error);138     139     output_samples = max_frame_size;140     /*opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));141     opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));142     opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&dur));*/143 144     for(i=0;i<60;i++)145     {146     data=data_1[i];147     pcm_re=pcm_re_1[i];148     m=opus_decode(149          dec,150          data,151          n,152          pcm_re,153          frame_size_2,154          0);155     }156     opus_decoder_destroy(dec);157     printf("/n/n/n解壓后的長度為:%d/n  ",m);158 159    for (i=0;i<60;i++)160        for(j=0;j<320;j++)161        {162        temp_end[320*i+j]=pcm_re_1[i][j];163        }164 165     if((fp_1=fopen("e://dkdt_re.pcm","wb"))==NULL)166     {167        printf("cant open the file");168     }169     num_pcm_re=fwrite(&temp_end[0],sizeof(short),19200,fp_1);  170 getchar();171 }

這里面我用一個(gè)dkdt.pcm的語音文件做范例,分幀進(jìn)行壓縮與解壓,每一幀為320short,壓縮后為40byte,壓縮比為16,之后進(jìn)行解壓還原,生成相應(yīng)的dkdt_out.pcm文件。這里給出我的測試結(jié)果,如下圖所示:第一個(gè)是壓縮前的音頻信號(hào),第二個(gè)是壓縮解壓后恢復(fù)的音頻文件。

可以看到壓縮前后還原后的波形幾乎是一致的(聽起來無差別),所以我們寫的測試函數(shù)中壓縮與解壓是沒有問題的。這一步很關(guān)鍵,是我們接下來的基礎(chǔ)。

4.2、JNI接口的C語言部分

上一步OK了之后,就可以根據(jù)書寫的測試函數(shù)書寫JNI接口的C語言部分,這部分是比較簡單的,稍微改下就OK了,JNI的書寫規(guī)則,網(wǎng)上參考的東西比較詳細(xì),這里就不在贅述,直接給出代碼如下:

  1 #ifdef HAVE_CONFIG_H  2 #include "config.h"  3 #endif  4 #include "StdAfx.h"  5 #include <stdio.h>  6 #include <stdlib.h>  7 #include <limits.h>  8 #include <stdint.h>  9 #include <math.h> 10 #include <string.h> 11 #include "jni.h" 12 #include <time.h> 13 #if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__) 14 #include <unistd.h> 15 #else 16 #include <process.h> 17 #define getpid _getpid 18 #endif 19 #include "opus_multistream.h" 20 #include "opus.h" 21 #include "../src/opus_private.h" 22  23 int opus_num; 24 int pcm_num; 25 short pcm_data_encoder[320]; 26 unsigned char opus_data_encoder[40]; 27 short pcm_data_decoder[320]; 28 unsigned char opus_data_decoder[40]; 29 OpusEncoder *enc=NULL; 30 OpusDecoder *dec=NULL; 31  32  33  34 JNIEXPORT int JNICALL Java_audioTest_OpusJni_test(JNIEnv *env, jobject thiz) 35 { 36   return 103;//測試函數(shù) 37 } 38  39 JNIEXPORT void JNICALL Java_audioTest_OpusJni_Init(JNIEnv *env, jobject thiz) 40 { 41   int error; 42   int Fs=16000; 43   int channels=1; 44   int application=OPUS_APPLICATION_AUDIO; 45    46   opus_int32 bitrate_bps=16000; 47   int bandwidth = OPUS_AUTO; 48   int use_vbr = 0; 49   int cvbr=1; 50   int complexity = 8; 51   int packet_loss_perc=0; 52    53   enc = opus_encoder_create(Fs, channels, application, &error); 54   dec = opus_decoder_create(Fs, channels, &error); 55  56    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps)); 57    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth)); 58    opus_encoder_ctl(enc, OPUS_SET_VBR(use_vbr)); 59    opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr)); 60    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); 61    opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); 62 } 63  64 JNIEXPORT jint JNICALL Java_audioTest_OpusJni_opusEncoder(JNIEnv *env, jobject thiz,jshortArray encoder_insrc,jbyteArray encoder_out) 65 { 66   int frame_size=320; 67   opus_int32 max_data_bytes=2500; 68   jshort* pcm_data_encoder=(*env)->GetShortArrayElements(env, encoder_insrc, 0); 69   jbyte* opus_data_encoder=(*env)->GetByteArrayElements(env, encoder_out, 0); 70  71   opus_num=opus_encode( 72          enc, 73          pcm_data_encoder, 74          frame_size, 75          opus_data_encoder, 76          max_data_bytes); 77  78   (*env)->ReleaseShortArrayElements(env, encoder_insrc, pcm_data_encoder, 0); 79   (*env)->ReleaseByteArrayElements(env, encoder_out, opus_data_encoder, 0); 80   if((*env)->ExceptionCheck(env)) 81      { 82         return - 1; 83      } 84   return opus_num; 85 } 86  87 JNIEXPORT jint JNICALL Java_audioTest_OpusJni_opusDecoder(JNIEnv *env, jobject thiz,jbyteArray decoder_insrc,jshortArray decoder_out) 88 { 89   int frame_size=320; 90   jshort* pcm_data_decoder=(*env)->GetShortArrayElements(env, decoder_out, 0); 91   jbyte* opus_data_decoder=(*env)->GetByteArrayElements(env, decoder_insrc, 0); 92   pcm_num=opus_decode( 93          dec, 94          opus_data_decoder, 95          40, 96          pcm_data_decoder, 97          frame_size, 98          0); 99          100   (*env)->ReleaseShortArrayElements(env, decoder_out, pcm_data_decoder, 0);101   (*env)->ReleaseByteArrayElements(env, decoder_insrc, opus_data_decoder, 0);102   if((*env)->ExceptionCheck(env))103      {104         return - 1;105      }106   return pcm_num;107 }108 109 JNIEXPORT void JNICALL Java_audioTest_OpusJni_Destroy(JNIEnv *env, jobject thiz)110 {111   opus_encoder_destroy(enc);112   opus_decoder_destroy(dec);113 }

這里面稍微說一下,一個(gè)師兄跟我說,寫這種跨平臺(tái)的東西總會(huì)遇到各種莫名奇妙的問題,但是一切的BUG都是有原因的,這里寫一個(gè)JNIEXPORT int JNICALL Java_audioTest_OpusJni_test(JNIEnv *env, jobject thiz)這樣的測試函數(shù),就可以簡單地判斷我們的JNI時(shí)候調(diào)用成功,成功的話,其他的就是調(diào)用函數(shù)內(nèi)部的問題了。這樣可以很快的縮小BUG的范圍。

4.3、編譯生成相應(yīng)的dll庫

寫完JNI接口之后,就要將我們用到的所有依賴的文件(包括.c 、.h)一起打包編譯為.dll文件。在VS2010中新建dll工程,dll工程里面有一個(gè)DEMO,我們這里用不到,可以講里面的東西刪了,將上一步寫的接口文件拷貝其中,如下圖所示:

和一般的C/C++工程一樣,我們需要添加依賴的.C文件與.h文件,首先我們需要添加頭文件,Opus依賴頭文件分布的比較零散,不像speex全部在include文件里面,不過這里我們也只需要指定好路徑,編譯器會(huì)自動(dòng)鏈接到相應(yīng)的頭文件,如下圖所示:

此外,我們還要設(shè)置好依賴(調(diào)用)的.C文件,最直觀的辦法是將所有需要的.C文件都添加進(jìn)工程,要不重不漏,重了會(huì)報(bào)重復(fù)定義的錯(cuò)誤,漏了會(huì)報(bào)缺少定義的錯(cuò)誤,編譯Android的依賴庫.so文件的時(shí)候,我的確是這么做的,這個(gè)過程需要一定時(shí)間的調(diào)試,要理清開源庫中函數(shù)之間的關(guān)系,知道需要調(diào)用哪些函數(shù)。這里其實(shí)有個(gè)更加簡單粗暴地辦法,之前我們第一步編譯測試工程的時(shí)候,會(huì)生成四個(gè)相應(yīng)的.lib庫,如下圖所示:

只需要指定依賴的庫文件的路徑,如下圖所示:

并將這四個(gè)庫添加到依賴庫中,如下圖,編譯器在編譯的時(shí)候就可以直接連接到相應(yīng)的函數(shù)實(shí)體。

這步成功之后,就可以在Release或者Debug文件夾中找到我們編譯成功的opus.dll文件,157KB,沉甸甸的。接下來就就是Java部分對(duì)dll文件的調(diào)用了。


五、Opus的DLL調(diào)用過程

首先,我們需要書寫Java端的JNI接口部分,這部分代碼比較簡單,直接給出。如下所示:

 1 package audioTest; 2 /** 3  * 壓縮庫 4  *  5  * @author lzhen 6  * 7  */ 8 public class OpusJni 9 {10     static11     {12         System.loadLibrary("opus");13     }14     public native int test();15     public native void Init(); // 壓縮初始化16     public native int opusEncoder(short[] src, byte[] out); // 壓縮數(shù)據(jù),長度為320short->40byte17     public native int opusDecoder(byte[] src, short[] out);// 解壓縮數(shù)據(jù),長度為40byte->320short18     public native void Destroy(); // 釋放內(nèi)存19 }

剩下的就是簡單的Java對(duì)象的調(diào)用了。這里,我們可以首先測試下test()函數(shù)是否成功,如果成功的話,說明dll庫至少是沒問題的。

在之后.so庫的調(diào)用的時(shí)候再具體總結(jié)一下Opus壓縮與解壓調(diào)用的詳細(xì)過程,這里就不再贅述了。


六、BUG與調(diào)試BUG1:

Exception in thread "main" java.lang.UnsatisfiedLinkError: E:/jni/testopus/libs/opus.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

at java.lang.ClassLoader$NativeLibrary.load(Native Method)

at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1965)

at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1890)

at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1880)

at java.lang.Runtime.loadLibrary0(Runtime.java:849)

at java.lang.System.loadLibrary(System.java:1088)

at audioTest.OpusJni.<clinit>(OpusJni.java:12)

at audioTest.Server.main(Server.java:22)

DEBUG1:

這里是因?yàn)镺pus官網(wǎng)上給的程序是根據(jù)32bit系統(tǒng)給出的,如果采用64bit系統(tǒng),在VS2010中設(shè)置為X64會(huì)報(bào)錯(cuò),所以只能按照X86編譯,但是如果JDK是64bit的話,在eclipse中就會(huì)報(bào)上面的錯(cuò)誤。

解決的辦法是:將64bit的JDK卸載掉,安裝一個(gè)32bit的JDK就可以編譯通過,但是有一個(gè)問題,JDK如果卸載重裝的話,有可能會(huì)失敗,原因是重裝的時(shí)候,之前注冊(cè)表沒有完全刪除的問題,可以用Windows Installer Clean Up將之前的注冊(cè)表徹底刪除。不過,我覺得最簡單的辦法是重新安裝一個(gè)其他版本的JDK就OK了,方法是死的,人是活的,我喜歡簡單粗暴又能解決問題的方法。

BUG2:

java.lang.UnsatisfiedLinkError: E:/jni/testopus/libs/opus.dll: Can't find dependent libraries。

DEBUG2:

意思是找不到依賴庫,我們編譯生成的opus.dll文件可以放在系統(tǒng)的DLL庫中(C:/Windows/System32),當(dāng)然,也可以直接放在工程中,這樣都是可以load到的,所以Can't find dependent libraries不是說找不到我們編譯生成的DLL文件,而是我們編譯生成的DLL文件也需要一些依賴庫,這里面有兩種情況:

一種是,我們?cè)谝慌_(tái)主機(jī)上編譯生成的,拿到另外一臺(tái)主機(jī)上面跑,可能兩臺(tái)主機(jī)配置或者是其他種種不同,系統(tǒng)DLL庫會(huì)有所差異,可以用DLL依賴查看工具這個(gè)軟件查找缺失的依賴庫,如下圖所示:

黃色標(biāo)記表示缺失的DLL,我這里是因?yàn)?,換了一臺(tái)沒有安裝VS2010的主機(jī)上測試導(dǎo)致的,解決辦法很簡單,可以在網(wǎng)上下載缺失的DLL放到C:/Windows/System32中,或者,直接在編譯的那臺(tái)PC上拷貝,都是可以的。

第二種情況比較復(fù)雜一點(diǎn),就是,我們?cè)诰幾g的時(shí)候,沒有添加最原始的.lib庫,這在不同的工程中會(huì)有所不同,一般用DLL依賴查看工具檢察缺失的為.exe文件就是這種情況,那就要回頭檢察,我們?cè)诰幾g之前添加的.lib文件是不是有問題了。

BUG3:

## A fatal error has been detected by the Java Runtime Environment:## EXCEPTION_access_VIOLATION (0xc0000005) at pc=0x15c21781, pid=5264, tid=14016## JRE version: Java(TM) SE Runtime Environment (8.0_11-b12) (build 1.8.0_11-b12)# Java VM: Java HotSpot(TM) Client VM (25.11-b03 mixed mode, sharing windows-x86 )# Problematic frame:# C [test_opus_decode.exe+0x51781]## Failed to write core dump. Minidumps are not enabled by default on client versions of Windows## An error report file with more information is saved as:# C:/Users/test/Desktop/Music0808_sever/hs_err_pid5264.log## If you would like to submit a bug report, please visit:# http://bugreport.sun.com/bugreport/crash.jsp# The crash happened outside the Java Virtual Machine in native code.# See problematic frame for where to report the bug.#

DEBUG3:

這個(gè)bug在很多游戲里面會(huì)出現(xiàn),在JNI的跨平臺(tái)調(diào)用中,出現(xiàn)類似情況,其實(shí)也是容易判斷的,首先,我們要看一下,我們?cè)贘ava端查看test()函數(shù)是否運(yùn)行成功,如果成功過了,那么說明DLL庫的編譯是沒有問題的,那么接下來,就可以通過單步調(diào)試,查找具體在哪一個(gè)調(diào)用函數(shù)出現(xiàn)問題了,同時(shí),在C語言端要通過注釋等方式聯(lián)合調(diào)試,最終確定具體是哪一個(gè)函數(shù)的哪一句出現(xiàn)了問題,目前,我還沒有發(fā)現(xiàn)在DLL內(nèi)部單步調(diào)試的方法,所以只能用這種方法嘗試,不過效果還是很明顯的,我的問題是初始化函數(shù)出現(xiàn)了一點(diǎn)問題。

另外,現(xiàn)在eclipse已經(jīng)支持直接的NDK編譯了,所以在Android平臺(tái)上,好像是可以對(duì).so庫進(jìn)行單步調(diào)試的,這個(gè)以后再說。


七、后記

寫到這里,本章差不多結(jié)束了,有機(jī)會(huì)希望能夠跟大家一起溝通交流,相互促進(jìn),相互提高,我的微博地址:http://weibo.com/3109428257/profile?rightmod=1&wvr=5&mod=personinfo。最后,跟大家分享一句OPUS官網(wǎng)上對(duì)開源的解釋,我覺得很贊!

——Imagine a road system where each type of car could only drive on its own manufacturer's pavement. We all benefit from living in a world where all the roads are connected. This is why Opus, unlike many codecs, is free.

Reference:

https://wiki.xiph.org/Main_Page

http://int.zhubajie.com/case-studies/3307420?utm_source=TiaoZhuan_RenWuYe&utm_medium=RenWuYe_3307420&utm_campaign=TiaoZhuan


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 抚顺市| 江川县| 许昌县| 虞城县| 镇宁| 砚山县| 商水县| 浦江县| 西安市| 溆浦县| 柯坪县| 凤城市| 义乌市| 陇西县| 营山县| 罗田县| 六安市| 哈巴河县| 寿阳县| 镇沅| 达州市| 萨迦县| 常熟市| 丰顺县| 霍城县| 巴东县| 泽普县| 新兴县| 鹰潭市| 石狮市| 麻城市| 偏关县| 石河子市| 仪陇县| 双鸭山市| 辽宁省| 祥云县| 西吉县| 秀山| 嘉黎县| 安福县|