Commit 68ab3d5b authored by Alexander Smorkalov's avatar Alexander Smorkalov Committed by Andrey Kamaev

Processing thread added to Java camera view.

parent 8393fd0c
...@@ -3,17 +3,20 @@ package org.opencv.framework; ...@@ -3,17 +3,20 @@ package org.opencv.framework;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.ImageFormat; import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback; import android.hardware.Camera.PreviewCallback;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.SurfaceHolder;
import org.opencv.core.CvType; import org.opencv.core.CvType;
import org.opencv.core.Mat; import org.opencv.core.Mat;
import org.opencv.core.MatOfByte; import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc; import org.opencv.imgproc.Imgproc;
/** /**
...@@ -31,6 +34,10 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements ...@@ -31,6 +34,10 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
private static final String TAG = "OpenCvJavaCameraView"; private static final String TAG = "OpenCvJavaCameraView";
private Mat mBaseMat; private Mat mBaseMat;
private byte mBuffer[];
private Thread mThread;
private boolean mStopThread;
public static class JavaCameraSizeAccessor implements ListItemAccessor { public static class JavaCameraSizeAccessor implements ListItemAccessor {
...@@ -45,7 +52,6 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements ...@@ -45,7 +52,6 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
Camera.Size size = (Camera.Size) obj; Camera.Size size = (Camera.Size) obj;
return size.height; return size.height;
} }
} }
private Camera mCamera; private Camera mCamera;
...@@ -54,67 +60,179 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements ...@@ -54,67 +60,179 @@ public class OpenCvJavaCameraView extends OpenCvCameraBridgeViewBase implements
super(context, attrs); super(context, attrs);
} }
@TargetApi(11)
protected boolean initializeCamera(int width, int height) {
synchronized (this) {
mCamera = null;
try {
mCamera = Camera.open();
}
catch (Exception e){
Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
}
if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
try {
mCamera = Camera.open(camIdx);
}
catch (RuntimeException e) {
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
}
}
}
if (mCamera == null)
return false;
mCamera.setPreviewCallbackWithBuffer(this);
List<android.hardware.Camera.Size> sizes = mCamera.getParameters().getSupportedPreviewSizes();
/* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
mFrameWidth = (int)frameSize.width;
mFrameHeight = (int)frameSize.height;
/* Now set camera parameters */
try {
Camera.Parameters params = mCamera.getParameters();
params.setPreviewFormat(ImageFormat.NV21);
params.setPreviewSize((int)frameSize.width, (int)frameSize.height);
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
params = mCamera.getParameters();
int size = params.getPreviewSize().width * params.getPreviewSize().height;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mBaseMat = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
AllocateCache();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
SurfaceTexture tex = new SurfaceTexture(MAGIC_TEXTURE_ID);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mCamera.setPreviewTexture(tex);
} else
mCamera.setPreviewDisplay(null);
} catch (IOException e) {
e.printStackTrace();
}
/* Finally we are ready to start the preview */
mCamera.startPreview();
}
return true;
}
@Override protected void releaseCamera() {
protected void connectCamera(int width, int height) { synchronized (this) {
mCamera = Camera.open(0); mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
List<android.hardware.Camera.Size> sizes = mCamera.getParameters().getSupportedPreviewSizes(); @Override
/* Select the size that fits surface considering maximum size allowed */ protected boolean connectCamera(int width, int height) {
FrameSize frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
Log.d(TAG, "Connecting to camera");
if (!initializeCamera(getWidth(), getHeight()))
return false;
/* now we can start update thread */
Log.d(TAG, "Starting processing thread");
mStopThread = false;
mThread = new Thread(new CameraWorker(getWidth(), getHeight()));
mThread.start();
return true;
}
/* Now set camera parameters */ protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try { try {
Camera.Parameters params = mCamera.getParameters(); mStopThread = true;
Log.d(TAG, "Notify thread");
List<Integer> formats = params.getSupportedPictureFormats(); synchronized (this) {
this.notify();
params.setPreviewFormat(ImageFormat.NV21); }
params.setPreviewSize(frameSize.width, frameSize.height); Log.d(TAG, "Wating for thread");
mThread.join();
mCamera.setPreviewCallback(this); } catch (InterruptedException e) {
mCamera.setParameters(params);
//mCamera.setPreviewTexture(new SurfaceTexture(MAGIC_TEXTURE_ID));
SurfaceTexture tex = new SurfaceTexture(MAGIC_TEXTURE_ID);
mCamera.setPreviewTexture(tex);
mFrameWidth = frameSize.width;
mFrameHeight = frameSize.height;
} catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
mThread = null;
} }
mBaseMat = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1); /* Now release camera */
releaseCamera();
/* Finally we are ready to start the preview */
mCamera.startPreview();
} }
@Override @Override
protected void disconnectCamera() { public void onPreviewFrame(byte[] frame, Camera arg1) {
Log.i(TAG, "Preview Frame received. Need to create MAT and deliver it to clients");
mCamera.setPreviewCallback(null); Log.i(TAG, "Frame size is " + frame.length);
mCamera.stopPreview(); synchronized (this)
mCamera.release(); {
mBaseMat.put(0, 0, frame);
this.notify();
}
if (mCamera != null)
mCamera.addCallbackBuffer(mBuffer);
} }
private class CameraWorker implements Runnable {
private Mat mRgba = new Mat();
private int mWidth;
private int mHeight;
@Override CameraWorker(int w, int h) {
public void onPreviewFrame(byte[] frame, Camera arg1) { mWidth = w;
Log.i(TAG, "Preview Frame received. Need to create MAT and deliver it to clients"); mHeight = h;
}
Log.i(TAG, "Frame size is " + frame.length);
mBaseMat.put(0, 0, frame); @Override
Mat frameMat = new Mat(); public void run() {
Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4); do {
deliverAndDrawFrame(frameMat); synchronized (OpenCvJavaCameraView.this) {
frameMat.release(); try {
OpenCvJavaCameraView.this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (!mStopThread) {
Mat frameMat = new Mat();
Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4);
deliverAndDrawFrame(frameMat);
frameMat.release();
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment