OpenCV-Android icon indicating copy to clipboard operation
OpenCV-Android copied to clipboard

Segmentation fault in VideoEmulation

Open pflammertsma opened this issue 14 years ago • 6 comments

Firstly, I'd like to commend Bill and Noritsuna on the amazing job they've done in porting OpenCV to Android. Compiling the library was surprisingly simple and all-in-all it's a great achievement.

I have been running the VideoEmulation example (using the Java implementation of SocketCamera) on the emulator, and am encountering a segmentation fault at VideoEmulation.java:226:

data = mOpenCV.getSourceImage();

LogCat first warns me of a mismatch between JNI and Java:

WARN/dalvikvm(29093): JNI WARNING: method declared to return '[B' returned '[Z'
              failed in Lorg/siprop/opencv/OpenCV;.getSourceImage ('[B' not found)

I took a look at the C declaration and JNI declaration, and the former, [Z, is a boolean array while the latter, [B is a byte array.

A stack trace of org.siprop.opencv.OpenCV.getSourceImage(Native Method) is outputted and the VM instantly aborts.

What have I done wrong here? Is my library somehow not compiled correctly?

pflammertsma avatar May 24 '10 22:05 pflammertsma

After some debugging, I've confirmed that the native method getSourceImage() in cvjni.cpp:134 is actually called; the JNI WARNING above is raised immediately after the function returns, and has the following trace:

"Thread-8" prio=5 tid=15 RUNNABLE
  | group="main" sCount=0 dsCount=0 s=N obj=0x43d16548 self=0x119ff8
  | sysTid=16284 nice=0 sched=0/0 cgrp=default handle=1196176
  at org.siprop.opencv.OpenCV.getSourceImage(Native Method)
  at org.siprop.opencv.VideoEmulation$1.run(VideoEmulation.java:226)

pflammertsma avatar May 25 '10 09:05 pflammertsma

If I change the type declaration in OpenCV.java:38 from:

public native byte[] getSourceImage();

To:

public native boolean[] getSourceImage();

The application no longer crashes, but then of course I cannot decode the byte array in VideoEmulation.java:240.

pflammertsma avatar May 25 '10 11:05 pflammertsma

I resolved the problem, but needed to make changes to cvjni.h and cvjni.cpp:

  1. The datatype of Java_org_siprop_opencv_OpenCV_getSourceImage() should be jbyteArray, not jbooleanArray.
  2. With all subsequent modifications within that function (line 152, 154 and 157), the Android application works as expected.

I would also suggest changing the datatype of Java_org_siprop_opencv_OpenCV_findContours() to jbyteArray.

pflammertsma avatar May 25 '10 11:05 pflammertsma

The solution mentioned above was so useful, and therefore I've completed the porting of face detector from PC to android.

Thanks to pflammertsma and the author of this awesome project!

ntbb avatar Nov 06 '10 00:11 ntbb

Hello,

Thanks for all the good pointers (pardon the joke).

I took your advice and made changes to cvjni.h file. Here are the changes:

JNIEXPORT jbyteArray JNICALL Java_org_siprop_opencv_OpenCV_findContours(JNIEnv* env, jobject thiz, jint width, jint height);

and also this:

JNIEXPORT jbyteArray JNICALL Java_org_siprop_opencv_OpenCV_getSourceImage(JNIEnv* env, jobject thiz);

I then made chanes to the implementation file cvjni.cpp as such:

/ Generate and return a boolean array from the source image. // Return 0 if a failure occurs or if the source image is undefined. JNIEXPORT jbyteArray JNICALL Java_org_siprop_opencv_OpenCV_getSourceImage(JNIEnv* env, jobject thiz) {

...

jbyteArray res_array = env->NewByteArray(imageSize);
if (res_array == 0) {
    LOGE("Unable to allocate a new boolean array for the source image.");
    return 0;
}
env->SetByteArrayRegion(res_array, 0, imageSize, (jbyte*)strm->GetByte());

strm->Close();
SAFE_DELETE(strm);

return res_array;

}

and finally the 2nd file:

JNIEXPORT jbyteArray JNICALL Java_org_siprop_opencv_OpenCV_findContours(JNIEnv* env, jobject thiz, jint width, jint height) { ...

jbyteArray res_array = env->NewByteArray(imageSize);
LOGV("Load NewBooleanArray.");
if (res_array == 0) {
    return 0;
}
env->SetByteArrayRegion(res_array, 0, imageSize, (jbyte*)strm->GetByte());
LOGV("Load SetBooleanArrayRegion.");

LOGV("Release sourceImage");
if (m_sourceImage) {
    cvReleaseImage(&m_sourceImage);
    m_sourceImage = 0;
}
LOGV("Release binaryImage");
cvReleaseImage( &binaryImage );
LOGV("Release grayImage");
cvReleaseImage( &grayImage );
LOGV("Release contourImage");
cvReleaseImage( &contourImage );
LOGV("Release storage");
cvReleaseMemStorage( &storage );
LOGV("Delete strm");
strm->Close();
SAFE_DELETE(strm);

return res_array;

}

I still get the same seg fault alluded to by the previous writers on this thread.

I have not run the emulator program. I have an ADP2

Thanks!

-Bruce

bruciebruce avatar Nov 26 '10 22:11 bruciebruce

Yes, much thanks to pflammertsma. I have been rather disconnected from this project of late because of other priorities, but I am going to try to integrate this work back into the project.

billmccord avatar Dec 27 '10 08:12 billmccord