title: Android OpenCV VideoCapture::retrieve(&mat) causes fatal signal 11
body: <p>So I'm trying to make an android application, that would open a video file frame by frame with OpenCV througn JNI and NDK, detect faces in each frame and display them (the end goal is to acclerate the algorithm, to better suit crappy mobile processing).</p>
  
  <p>First method I attempted was <a href="http://developer.android.com/reference/android/media/MediaMetadataRetriever.html" rel="nofollow">MediaMetadataRetriever</a> with no results, it just returned null.</p>
  
  <p>The second method was <a href="https://github.com/wseemann/FFmpegMediaMetadataRetriever" rel="nofollow">FFMpegMediaMetadataRetriever</a>, which does work as expected, but is very slow (up to 2fps; too slow), partially because you have to convert from FFMpegMMR's bitmap to Mat then detect and draw and then convert back to bitmap, which is very caveman of me to even attempt.</p>
  
  <p>The third method I'm currently working on is the VideoCapture grab() and retrieve(). I made a wrapper for the native code, mostly by copying the facedtector from OpenCV samples. I've also tried read() that supposedly combines the two, but it also causes fatal signal 11 (segmentation fault at some god forsaken level of OpenCV or Android platform).</p>
  
  <p>Here's how the application get the absolute file path (note that it did work for FFMpegMMR):</p>
  
  <pre><code>    //The file name, file path and filerawresource are used in getting the path of the video file on device's disk
  String videoFileName="samplemp4";
  String videoFileType=".mp4";
  int videoFileRawResourceId=R.raw.samplemp4;
  
  public String getVideoFilePath()
  {
      InputStream is = getResources().openRawResource(videoFileRawResourceId);
      File sampleDir = getDir(videoFileName, Context.MODE_PRIVATE);
      File sampleFile= new File(sampleDir, videoFileName+videoFileType);
      try {
      FileOutputStream os = new FileOutputStream(sampleFile);
  
      byte[] buffer = new byte[4096];
      int bytesRead;
      while ((bytesRead = is.read(buffer)) != -1) {
          os.write(buffer, 0, bytesRead);
      }
  
          is.close();
          os.close();
      } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
      File videoDir = getDir(videoFileName, Context.MODE_PRIVATE);
      File videoFile = new File(videoDir, videoFileName+videoFileType);
      return videoFile.getAbsolutePath();
  }
  </code></pre>
  
  <p>This is where the java wrappers of the native methods are called and results used:</p>
  
  <pre><code>class AsyncPlay extends AsyncTask&lt;String, Mat, Bitmap&gt;
          {
  
          @Override
          protected Bitmap doInBackground(String... params) {
              //for(;play;)
              {
                  if(play)
                  {
                      if(currentTime==0)
                      {
                          test=new Test();
                          test.startTime.setToNow();
                          test.type="Video";
                          frameGrabber.open(videoFilePath);
                      }
              //publishProgress(retriever.getFrameAtTime(currentTime*1000+111,
                      //      FFmpegMediaMetadataRetriever.OPTION_CLOSEST));
  
  
                      Mat tmp=new Mat();
                      //frameGrabber.read(tmp);
                      frameGrabber.grab();
                      frameGrabber.retrieve(tmp);
                      publishProgress(tmp);
  
                      currentTime+=111;
                      if(currentTime*1000&gt;=duration*1000)
                      {
                          currentTime=0;
                          test.endTime.setToNow();
                          tester.publishResult(test);
                          frameGrabber.release();
                      }
                  }
                  try 
                  {
                      Thread.sleep(111);
                  } catch (InterruptedException e) 
                  {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
              }
              return null;
          }
          @Override
          protected void onProgressUpdate(Mat... values) {
  
              //face detection logic goes here
              //Bitmap bmp=values[0];
  
              //Mat rgbMat = new Mat();
              //Utils.bitmapToMat(bmp, rgbMat);
  
              DetectionResult detectionResult = openCVFaceDetector.detectFromImage(values[0], Imgproc.COLOR_RGB2GRAY);//Detecting with a native detector from OpenCV
  
              test.addDetection(detectionResult.detection);
  
              imageViewOriginal.setImageBitmap(detectionResult.detectedImage);
  
              super.onProgressUpdate(values);
          }
  
      };`
  </code></pre>
  
  <p>Where FrameGrabber frameGrabber is the java wrapper of the natives and the signal gets sent when retrieve() or read() are called, note that the constructor, open() and grab() all work (or at least don't crash the application).</p>
  
  <p>This is the wrapper (I have passed the VideoCapture object properly, which I learned was one of the causes of the fatal signal):</p>
  
  <pre><code>import org.opencv.core.Mat;
  
  public class FrameGrabber
  { 
      private long mNativeObj = 0;
      private static native long nativeCreateObject(String fileName);
      private static native void nativeDestroyObject(long thiz);
      private static native boolean nativeOpen(long thiz, String fileName);
      private static native boolean nativeGrab(long thiz);
      private static native boolean nativeRetrieve(long thiz, Mat imageMat);
      private static native boolean nativeRead(long thiz, Mat imageMat);
      private static native void nativeRelease(long thiz);    
      public FrameGrabber(String fileName) {
          mNativeObj = nativeCreateObject(fileName);
      }
      public void destroy() {
          nativeDestroyObject(mNativeObj);
          mNativeObj = 0;
      }
      public boolean open(String fileName)
      {
          return nativeOpen(mNativeObj, fileName);
      }  
      public boolean grab()
      {
          return nativeGrab(mNativeObj);
      }   
      public boolean retrieve(Mat imageMat)
      {
          return nativeRetrieve(mNativeObj, imageMat);
      }    
      public boolean read(Mat imageMat)
      {
          return nativeRead(mNativeObj, imageMat);
      }    
      public void release()
      {
          nativeRelease(mNativeObj);
      }
  }
  </code></pre>
  
  <p>And this is it's native part (the exact line causing the error is <code>result = ((VideoCapture*)thiz)-&gt;retrieve((*((Mat*)imageMat)));</code>, which is in the method nativeRetrieve()</p>
  
  <pre><code>#include &lt;string&gt;
  #include &lt;vector&gt;
  #include &lt;opencv2/core/core.hpp&gt;
  #include &lt;opencv2/highgui/highgui.hpp&gt;
  #include &lt;FrameGrabber_jni.h&gt;
  
  #include &lt;android/log.h&gt;
  
  #define LOG_TAG "FrameGrabber"
  #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
  
  using namespace std;
  using namespace cv;
  
  inline void jStringToString(JNIEnv * jenv, jstring jString, string stdName)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_jStringToString enter");
      LOGD("grabber is Making jnamestr");//this is buggy as hell, the line serves as a debug tool
      const char* jnamestr = jenv-&gt;GetStringUTFChars(jString, NULL);
      string stdNameTmp(jnamestr);
      stdName=stdNameTmp;
      LOGD("grabber is releasing jnamestr");
      jenv-&gt;ReleaseStringUTFChars(jString, jnamestr);
  }
  
  /*
   * CONSTRUCTOR AND DESTRUCTOR
   */
  JNIEXPORT jlong JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeCreateObject
  (JNIEnv * jenv, jclass, jstring jFileName)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_nativeCreateObject enter");
      string stdFileName;
      jStringToString(jenv, jFileName,stdFileName);
      jlong result = 0;
  
      try
      {
          result = (jlong)new VideoCapture(stdFileName);
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("nativeCreateObject caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("nativeCreateObject caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.nativeCreateObject()");
          return 0;
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_nativeCreateObject exit");
      return result;
  }
  
  //should work
  JNIEXPORT void JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeDestroyObject
  (JNIEnv * jenv, jclass, jlong thiz)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_nativeDestroyObject enter");
      try
      {
          if(thiz != 0)
          {
              delete (VideoCapture*)thiz;
          }
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("nativeestroyObject caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("nativeDestroyObject caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.nativeDestroyObject()");
      }
      LOGD("Java_boris_springar_diplomska_FrameGrabber_nativeDestroyObject exit");
  }
  
  
  /*
   * CORE METHODS
   */
  
  //Open function opens the filename for playing
  JNIEXPORT jboolean JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeOpen
  (JNIEnv * jenv, jclass,jlong thiz,jstring jFileName)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_open enter");
      string stdFileName;
      jStringToString(jenv, jFileName,stdFileName);
  
      jboolean result = false;
  
      try
      {
          result = ((VideoCapture*)thiz)-&gt;open(stdFileName);
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("frame grabber open exception caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("frame grabber open caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.open()");
          return 0;
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_open exit");
  
      return result;
  }
  
  //grab grabs the next frame from file or camera
  JNIEXPORT jboolean JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeGrab
  (JNIEnv * jenv, jclass,jlong thiz)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_grab enter");
      jboolean result = false;
  
      try
      {
          result = ((VideoCapture*)thiz)-&gt;grab();
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("frame grabber grab exception caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("frame grabber grab caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.grab()");
          return 0;
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_grab exit");
  
      return result;
  }
  
  //retrieve retrieves the next frame and writes it to the image matrix
  JNIEXPORT jboolean JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeRetrieve
  (JNIEnv * jenv, jclass,jlong thiz, jlong imageMat)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_retrieve enter");
      jboolean result = false;
  
      try
      {
          LOGD("grabber trying to retrieve");
          result = ((VideoCapture*)thiz)-&gt;retrieve((*((Mat*)imageMat)));//should write the current frame to the image matrix
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("frame grabber retrieve exception caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("frame grabber retrieve caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.retrieve(fileName)");
          return 0;
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_retrieve exit");
  
      return result;
  }
  
  //read combines grab and retrieve and writes the stuff to the image matrix
  JNIEXPORT jboolean JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeRead
  (JNIEnv * jenv, jclass,jlong thiz, jlong imageMat)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_read enter");
      LOGD("grabber setting result to false");
      jboolean result = false;
  
      try
      {
          LOGD("grabber trying to read capture");
          result = ((VideoCapture*)thiz)-&gt;read((*((Mat*)imageMat)));//should write the current frame to the image matrix
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("frame grabber read exception caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("frame grabber read caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.open(fileName)");
          return 0;
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_read exit");
  
      return result;
  }
  
  //Release releases the resource it's using, I hope
  JNIEXPORT void JNICALL Java_boris_springar_diplomska_FrameGrabber_nativeRelease
  (JNIEnv * jenv, jclass,jlong thiz)
  {
      LOGD("Java_boris_springar_diplomska_FrameGrabber_release enter");
      jboolean result = false;
  
      try
      {
          ((VideoCapture*)thiz)-&gt;release();//should release
      }
      catch(cv::Exception&amp; e)
      {
          LOGD("frame grabber read exception caught cv::Exception: %s", e.what());
          jclass je = jenv-&gt;FindClass("org/opencv/core/CvException");
          if(!je)
              je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, e.what());
      }
      catch (...)
      {
          LOGD("frame grabber release caught unknown exception");
          jclass je = jenv-&gt;FindClass("java/lang/Exception");
          jenv-&gt;ThrowNew(je, "Unknown exception in JNI code of FrameGrabber.open(fileName)");
      }
  
      LOGD("Java_boris_springar_diplomska_FrameGrabber_release exit");
  }
  </code></pre>
  
  <p>And also the LogCat output:</p>
  
  <pre><code>07-22 17:36:24.886: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_nativeCreateObject enter
  07-22 17:36:24.886: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_jStringToString enter
  07-22 17:36:24.886: D/FrameGrabber(15359): grabber is Making jnamestr
  07-22 17:36:24.886: D/FrameGrabber(15359): grabber is releasing jnamestr
  07-22 17:36:24.886: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_nativeCreateObject exit
  07-22 17:36:24.936: I/dalvikvm(15359): threadid=3: reacting to signal 3
  07-22 17:36:24.936: I/dalvikvm(15359): Wrote stack traces to '/data/anr/traces.txt'
  07-22 17:36:24.946: D/libEGL(15359): loaded /system/lib/egl/libEGL_mali.so
  07-22 17:36:24.956: D/libEGL(15359): loaded /system/lib/egl/libGLESv1_CM_mali.so
  07-22 17:36:24.976: D/libEGL(15359): loaded /system/lib/egl/libGLESv2_mali.so
  07-22 17:36:25.006: D/OpenGLRenderer(15359): Enabling debug mode 0
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_open enter
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_jStringToString enter
  07-22 17:36:27.336: D/FrameGrabber(15359): grabber is Making jnamestr
  07-22 17:36:27.336: D/FrameGrabber(15359): grabber is releasing jnamestr
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_open exit
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_grab enter
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_grab exit
  07-22 17:36:27.336: D/FrameGrabber(15359): Java_boris_springar_diplomska_FrameGrabber_retrieve enter
  07-22 17:36:27.336: D/FrameGrabber(15359): grabber trying to retrieve
  07-22 17:36:27.336: A/libc(15359): Fatal signal 11 (SIGSEGV) at 0x1d400019 (code=1)
  </code></pre>
  
  <p>The problem with debugging this code is that it's JNI in Eclipse and I don't know how to even make debugging c++ in Eclipse work, that's why I used the log messages to find the bugs in the code. Those helped immensely, as open() and grab() didn't work and I found and squashed a bug, where I forgot to pass thiz to the methods. The problem with retrieve() is that I can not for the life of me find it's source. There's partial definitions in highgui.hpp, but no implementation, where I could put the log messages to help me debug.</p>
  
  <p>Possible solutions would be:</p>
  
  <ul>
  <li>a different file format that's supported by retrieve(), except that I don't know which file format that might be</li>
  <li>use a non absolute file path? Although neither open() and grab() did not cause a fatal signal</li>
  <li>scrap the whole thing and use a PNG (I really want to figure this out though)</li>
  </ul>
  
  <p>So if anyone could tell me where I can find the implementations of retrieve() and read(), I'd be most grateful. Or if it's something obvious and stupid that I missed (I wish).</p>
  
  <p>In the meantime, I'll try to find a way to debug c++ in Eclipse and maybe try another format?</p>