Those are Java functions in question:
targetFunctionPtr1 is public static native long nInitSpxEncoder();
targetFunctionPtr is public static native long nEncodeBuffer(long j12, short[] sArr, byte[] bArr, long j13);
Sample pseudo Java code
long nInitSpxEncoder = LibSpeex.nInitSpxEncoder();
long nEncodeBuffer = LibSpeex.nEncodeBuffer(nInitSpxEncoder, sArr, bArr, 65536);
called below via JNI
char b[16]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x00};
jinput = env->NewStringUTF(b);
jclass stringClass = env->FindClass("java/lang/String");
jmethodID getBytesMId = env->GetMethodID(stringClass, "getBytes", "()[B");
in1 = (jbyteArray)env->CallObjectMethod( jinput, getBytesMId);
jlong init;
init = targetFunctionPtr1(env, CallerObj1);
jshort outCArray[] = {100};
jshortArray retval = env->NewShortArray(10000); // allocate
env->SetShortArrayRegion(retval, 0 , 1, outCArray);
nenc = targetFunctionPtr(env, CallerObj, init, retval, in1, 10);
Don't get why above segfaults. It calls init
, that works, but in second call nEncodeBuffer
it segfaults. I see in debugger it loads byte array and shorts array, but cannot figure out why it does not return, just loops until segfault.
I mean I call it via JNI but I would expect targetFunctionPtr to return. It seems it loops somehow, until segmentation occurs.
This is sample implementation of the JNI in Java
long nInitSpxEncoder = LibSpeex.nInitSpxEncoder();
if (nInitSpxEncoder != 0) {
int nGetEncoderFrameSize = (int) LibSpeex.nGetEncoderFrameSize(nInitSpxEncoder);
System.err.println(String.format("Frame size = %d", Integer.valueOf(nGetEncoderFrameSize)));
short[] sArr = new short[nGetEncoderFrameSize];
AudioRecord audioRecord2 = null;
byte[] bArr3 = bArr2;
long j12 = 0;
while (j12 < this.f13733d) {
try {
synchronized (this) {
if (audioRecord2 != this.f13731b) {
Log.i("AudioPttRecorder", "source changed");
}
audioRecord = this.f13731b;
}
if (audioRecord == null || audioRecord.read(sArr, 0, nGetEncoderFrameSize) != nGetEncoderFrameSize) {
break;
}
if (this.f13730a != null) {
this.f13730a.a(j12, a(nGetEncoderFrameSize, sArr));
}
long j13 = j12;
int i12 = nGetEncoderFrameSize;
short[] sArr2 = sArr;
long nEncodeBuffer = LibSpeex.nEncodeBuffer(nInitSpxEncoder, sArr, bArr, 65536);
if (nEncodeBuffer >= 0) {
Log.d("AudioPttRecorder", String.format("Write packet len=%d", Long.valueOf(nEncodeBuffer)));
bArr3[0] = (byte) (255 & nEncodeBuffer);
bArr3[1] = (byte) (nEncodeBuffer >> 8);
byte[] bArr4 = bArr3;
bufferedOutputStream.write(bArr4, 0, 2);
bufferedOutputStream.write(bArr, 0, (int) nEncodeBuffer);
bArr3 = bArr4;
nGetEncoderFrameSize = i12;
sArr = sArr2;
j12 = j13 + 1;
audioRecord2 = audioRecord;
} else {
throw new RuntimeException("Something wrong with encoding Speex");
}
} finally {
LibSpeex.nDestroySpxEncoder(nInitSpxEncoder);
Log.i("AudioPttRecorder", "exited");
}
}
bufferedOutputStream.flush();
Log.d("AudioPttRecorder", "finished");
return;
}
My code using JNI directly does similar.
Any ideas what is wrong with the native code?
How should I call Libspx to encode a byte array in native code?