2013-11-09 56 views
1

我想用Speex語音庫進行解碼的Speex編碼的音頻文件,但我總是得到ArrayIndexOutOfBoundsExceptionGetByteArrayRegion導致ArrayIndexOutOfBoundsException異常

JNIEXPORT jint JNICALL Java_com_app_shared_Speex_decode 
    (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) { 

     jbyte buffer[dec_frame_size ]; 
     jshort output_buffer[dec_frame_size ]; 
     jsize encoded_length = size; 

     if (!codec_open) 
      return 0; 

     env->GetByteArrayRegion(encoded, rtp_header, encoded_length, buffer); 

     /* 
     jboolean isCopy; 
     jbyte* data = env->GetByteArrayElements(encoded, &isCopy); 
     if(isCopy){ 
     memcpy(buffer, data, encoded_length);    
     env->ReleaseByteArrayElements(encoded, data, JNI_ABORT); 
     } 
     */ 

     speex_bits_read_from(&dbits, (char *)buffer, encoded_length); 
     speex_decode_int(dec_state, &dbits, output_buffer); 

     std::string bufStr; 

     for(int i=0; i<20; i++){ 
      char buff[100]; 
      sprintf(buff, "Speex test %d => %d", i, output_buffer[i]); 
      bufStr = buff; 
      LOGI(bufStr.c_str()); 
     } 

     bufStr = "before SetShortArrayRegion"; 
     LOGI(bufStr.c_str()); 

     (env)->SetShortArrayRegion(lin, rtp_header, dec_frame_size, output_buffer); 

     bufStr = "after SetShortArrayRegion"; 
     LOGI(bufStr.c_str()); 

     return (jint)dec_frame_size;    
} 

我得到:

SharedSpeex before SetShortArrayRegion 
dalvikvm JNI WARNING: JNI method called with exception pending 
dalvikvm    in Lcom/company/shared/Speex;.decode:([B[SI)I (SetShortArrayRegion) 
dalvikvm Pending exception is: 
dalvikvm java.lang.ArrayIndexOutOfBoundsException: [B offset=12 length=1634 src.length=1634 

有趣的一點是,如果我完全評論包含SetShortArrayRegion的行,退出範圍時發生異常:

SharedSpeex  before SetShortArrayRegion 
SharedSpeex  after SetShortArrayRegion 
AndroidRuntime Shutting down VM 
dalvikvm   threadid=1: thread exiting with uncaught exception (group=0xa62ca288) 
AndroidRuntime FATAL EXCEPTION: main 
AndroidRuntime java.lang.ArrayIndexOutOfBoundsException: [B offset=12 length=1634 src.length=1634 

它同時在官方JNI機制的文檔很清楚喜歡GetByteArrayRegion,而不是GetByteArrayElements因爲:

  • 減少編程錯誤的風險 - 沒有忘記調用Release東西失敗後的風險。
+0

你是否得到speex解碼,請幫幫我 –

回答

5

GetByteArrayRegionGetByteArrayRegion檢查數組的邊界以確保您沒有運行結束。 GetByteArrayElements只是獲得一個指向數組開頭的指針,所以你的memcpy()可以自由運行,而不會被忽視。

的原因溢出的異常注意:

[B offset=12 length=1634 src.length=1634 

[B意味着byte[]。數組的長度與請求的長度(1634)相匹配,但是它從數組中的偏移量12個字節開始。所以你試圖讀取最後12個字節。

Java代碼引發的異常不會中斷您的C代碼;虛擬機只是在當前線程上設置一個標誌。您必須使用ExceptionCheck明確地測試它們,並清除它們或返回到VM代碼將繼續執行拋出過程的Java代碼。如果您啓用了CheckJNI,並且虛擬機看到您進行了一些調用,但發生異常,您將收到「JNI WARNING」和VM中止。