Libspeexjni JNI integration

47 views Asked by At

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?

0

There are 0 answers