Android: fix JavaCameraView implementation

1) Fixed deadlock if camera is started and stopped immediately
2) Invalid pattern usage of Object.wait(). Refer to "spurious wakeup": http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait
3) Fixed buffer usage:
  a) fix eliminates processing of zero NV12 (green in RGB) first frame
  b) latest ready frame is delivered for processing (not previous)
This commit is contained in:
Alexander Alekhin 2015-02-17 01:28:43 +03:00
parent 8714219dab
commit dc21a0a6b5

View File

@ -43,11 +43,13 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
public static class JavaCameraSizeAccessor implements ListItemAccessor {
@Override
public int getWidth(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.width;
}
@Override
public int getHeight(Object obj) {
Camera.Size size = (Camera.Size) obj;
return size.height;
@ -228,6 +230,8 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
}
}
private boolean mCameraFrameReady = false;
@Override
protected boolean connectCamera(int width, int height) {
@ -239,6 +243,8 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
if (!initializeCamera(width, height))
return false;
mCameraFrameReady = false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
@ -248,6 +254,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
return true;
}
@Override
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
@ -270,12 +277,16 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
/* Now release camera */
releaseCamera();
mCameraFrameReady = false;
}
@Override
public void onPreviewFrame(byte[] frame, Camera arg1) {
Log.d(TAG, "Preview Frame received. Frame size: " + frame.length);
synchronized (this) {
mFrameChain[1 - mChainIdx].put(0, 0, frame);
mFrameChain[mChainIdx].put(0, 0, frame);
mCameraFrameReady = true;
this.notify();
}
if (mCamera != null)
@ -283,10 +294,12 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
}
private class JavaCameraFrame implements CvCameraViewFrame {
@Override
public Mat gray() {
return mYuvFrameData.submat(0, mHeight, 0, mWidth);
}
@Override
public Mat rgba() {
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
return mRgba;
@ -312,21 +325,25 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
private class CameraWorker implements Runnable {
@Override
public void run() {
do {
synchronized (JavaCameraView.this) {
try {
JavaCameraView.this.wait();
while (!mCameraFrameReady && !mStopThread) {
JavaCameraView.this.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (mCameraFrameReady)
mChainIdx = 1 - mChainIdx;
}
if (!mStopThread) {
if (!mFrameChain[mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[mChainIdx]);
mChainIdx = 1 - mChainIdx;
if (!mStopThread && mCameraFrameReady) {
mCameraFrameReady = false;
if (!mFrameChain[1 - mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]);
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");