2013-11-09 58 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中止。