/modules/java/generator/src/java/android+JavaCameraView.java
https://github.com/nielsgm/opencv · Java · 304 lines · 234 code · 48 blank · 22 comment · 33 complexity · 9711a105c2a7bf017b921719d1d6804e MD5 · raw file
- package org.opencv.android;
- 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.Size;
- import org.opencv.imgproc.Imgproc;
- /**
- * This class is an implementation of the Bridge View between OpenCV and Java Camera.
- * This class relays on the functionality available in base class and only implements
- * required functions:
- * connectCamera - opens Java camera and sets the PreviewCallback to be delivered.
- * disconnectCamera - closes the camera and stops preview.
- * When frame is delivered via callback from Camera - it processed via OpenCV to be
- * converted to RGBA32 and then passed to the external callback for modifications if required.
- */
- public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallback {
- private static final int MAGIC_TEXTURE_ID = 10;
- private static final String TAG = "JavaCameraView";
- private byte mBuffer[];
- private Mat[] mFrameChain;
- private int mChainIdx = 0;
- private Thread mThread;
- private boolean mStopThread;
- protected Camera mCamera;
- protected JavaCameraFrame mCameraFrame;
- private SurfaceTexture mSurfaceTexture;
- public static class JavaCameraSizeAccessor implements ListItemAccessor {
- public int getWidth(Object obj) {
- Camera.Size size = (Camera.Size) obj;
- return size.width;
- }
- public int getHeight(Object obj) {
- Camera.Size size = (Camera.Size) obj;
- return size.height;
- }
- }
- public JavaCameraView(Context context, int cameraId) {
- super(context, cameraId);
- }
- public JavaCameraView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Log.d(TAG, "Java camera view ctor");
- }
- @TargetApi(11)
- protected boolean initializeCamera(int width, int height) {
- Log.d(TAG, "Initialize java camera");
- boolean result = true;
- synchronized (this) {
- mCamera = null;
- if (mCameraIndex == -1) {
- Log.d(TAG, "Trying to open camera with old open()");
- 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) {
- boolean connected = false;
- for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
- Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
- try {
- mCamera = Camera.open(camIdx);
- connected = true;
- } catch (RuntimeException e) {
- Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
- }
- if (connected) break;
- }
- }
- } else {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
- Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(mCameraIndex) + ")");
- try {
- mCamera = Camera.open(mCameraIndex);
- } catch (RuntimeException e) {
- Log.e(TAG, "Camera #" + mCameraIndex + "failed to open: " + e.getLocalizedMessage());
- }
- }
- }
- if (mCamera == null)
- return false;
- /* Now set camera parameters */
- try {
- Camera.Parameters params = mCamera.getParameters();
- Log.d(TAG, "getSupportedPreviewSizes()");
- List<android.hardware.Camera.Size> sizes = params.getSupportedPreviewSizes();
- if (sizes != null) {
- /* Select the size that fits surface considering maximum size allowed */
- Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
- params.setPreviewFormat(ImageFormat.NV21);
- Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height));
- params.setPreviewSize((int)frameSize.width, (int)frameSize.height);
- List<String> FocusModes = params.getSupportedFocusModes();
- if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
- {
- params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
- }
- mCamera.setParameters(params);
- params = mCamera.getParameters();
- mFrameWidth = params.getPreviewSize().width;
- mFrameHeight = params.getPreviewSize().height;
- if (mFpsMeter != null) {
- mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
- }
- int size = mFrameWidth * mFrameHeight;
- size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
- mBuffer = new byte[size];
- mCamera.addCallbackBuffer(mBuffer);
- mCamera.setPreviewCallbackWithBuffer(this);
- mFrameChain = new Mat[2];
- mFrameChain[0] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
- mFrameChain[1] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
- AllocateCache();
- mCameraFrame = new JavaCameraFrame(mFrameChain[mChainIdx], mFrameWidth, mFrameHeight);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
- getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mCamera.setPreviewTexture(mSurfaceTexture);
- } else
- mCamera.setPreviewDisplay(null);
- /* Finally we are ready to start the preview */
- Log.d(TAG, "startPreview");
- mCamera.startPreview();
- }
- else
- result = false;
- } catch (Exception e) {
- result = false;
- e.printStackTrace();
- }
- }
- return result;
- }
- protected void releaseCamera() {
- synchronized (this) {
- if (mCamera != null) {
- mCamera.stopPreview();
- mCamera.release();
- }
- mCamera = null;
- if (mFrameChain != null) {
- mFrameChain[0].release();
- mFrameChain[1].release();
- }
- if (mCameraFrame != null)
- mCameraFrame.release();
- }
- }
- @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(width, height))
- return false;
- /* now we can start update thread */
- Log.d(TAG, "Starting processing thread");
- mStopThread = false;
- mThread = new Thread(new CameraWorker());
- mThread.start();
- return true;
- }
- 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 {
- mStopThread = true;
- Log.d(TAG, "Notify thread");
- synchronized (this) {
- this.notify();
- }
- Log.d(TAG, "Wating for thread");
- if (mThread != null)
- mThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- mThread = null;
- }
- /* Now release camera */
- releaseCamera();
- }
- @TargetApi(Build.VERSION_CODES.FROYO)
- 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)
- {
- mFrameChain[1 - mChainIdx].put(0, 0, frame);
- this.notify();
- }
- if (mCamera != null)
- mCamera.addCallbackBuffer(mBuffer);
- }
- private class JavaCameraFrame implements CvCameraViewFrame
- {
- public Mat gray() {
- return mYuvFrameData.submat(0, mHeight, 0, mWidth);
- }
- public Mat rgba() {
- Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2BGR_NV12, 4);
- return mRgba;
- }
- public JavaCameraFrame(Mat Yuv420sp, int width, int height) {
- super();
- mWidth = width;
- mHeight = height;
- mYuvFrameData = Yuv420sp;
- mRgba = new Mat();
- }
- public void release() {
- mRgba.release();
- }
- private JavaCameraFrame(CvCameraViewFrame obj) {
- }
- private Mat mYuvFrameData;
- private Mat mRgba;
- private int mWidth;
- private int mHeight;
- };
- private class CameraWorker implements Runnable {
- public void run() {
- do {
- synchronized (JavaCameraView.this) {
- try {
- JavaCameraView.this.wait();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if (!mStopThread) {
- if (!mFrameChain[mChainIdx].empty())
- deliverAndDrawFrame(mCameraFrame);
- mChainIdx = 1 - mChainIdx;
- }
- } while (!mStopThread);
- Log.d(TAG, "Finish processing thread");
- }
- }
- }