import java.io.IOException;
import java.util.List;
+import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.SurfaceHolder;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
-import org.opencv.core.MatOfByte;
+import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
/**
private static final String TAG = "OpenCvJavaCameraView";
private Mat mBaseMat;
+ private byte mBuffer[];
+
+ private Thread mThread;
+ private boolean mStopThread;
public static class JavaCameraSizeAccessor implements ListItemAccessor {
Camera.Size size = (Camera.Size) obj;
return size.height;
}
-
}
private Camera mCamera;
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 connectCamera(int width, int height) {
- mCamera = Camera.open(0);
+ protected void releaseCamera() {
+ synchronized (this) {
+ mCamera.stopPreview();
+ mCamera.release();
+ mCamera = null;
+ }
+ }
- List<android.hardware.Camera.Size> sizes = mCamera.getParameters().getSupportedPreviewSizes();
- /* Select the size that fits surface considering maximum size allowed */
- FrameSize frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
+ @Override
+ protected boolean connectCamera(int width, int 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 {
- Camera.Parameters params = mCamera.getParameters();
-
- List<Integer> formats = params.getSupportedPictureFormats();
-
- params.setPreviewFormat(ImageFormat.NV21);
- params.setPreviewSize(frameSize.width, frameSize.height);
-
- mCamera.setPreviewCallback(this);
- 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) {
+ mStopThread = true;
+ Log.d(TAG, "Notify thread");
+ synchronized (this) {
+ this.notify();
+ }
+ Log.d(TAG, "Wating for thread");
+ mThread.join();
+ } catch (InterruptedException e) {
e.printStackTrace();
+ } finally {
+ mThread = null;
}
- mBaseMat = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
-
- /* Finally we are ready to start the preview */
- mCamera.startPreview();
+ /* Now release camera */
+ releaseCamera();
}
@Override
- protected void disconnectCamera() {
-
- mCamera.setPreviewCallback(null);
- mCamera.stopPreview();
- mCamera.release();
+ public void onPreviewFrame(byte[] frame, Camera arg1) {
+ Log.i(TAG, "Preview Frame received. Need to create MAT and deliver it to clients");
+ Log.i(TAG, "Frame size is " + frame.length);
+ synchronized (this)
+ {
+ 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
- public void onPreviewFrame(byte[] frame, Camera arg1) {
- Log.i(TAG, "Preview Frame received. Need to create MAT and deliver it to clients");
-
- Log.i(TAG, "Frame size is " + frame.length);
+ CameraWorker(int w, int h) {
+ mWidth = w;
+ mHeight = h;
+ }
- mBaseMat.put(0, 0, frame);
- Mat frameMat = new Mat();
- Imgproc.cvtColor(mBaseMat, frameMat, Imgproc.COLOR_YUV2RGBA_NV21, 4);
- deliverAndDrawFrame(frameMat);
- frameMat.release();
+ @Override
+ public void run() {
+ do {
+ synchronized (OpenCvJavaCameraView.this) {
+ 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");
+ }
}
-
}