|
|
|
@ -2,6 +2,7 @@ package org.opencv.samples.tutorial4; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
import android.content.Context; |
|
|
|
|
import android.graphics.Bitmap; |
|
|
|
|
import android.graphics.Canvas; |
|
|
|
@ -15,14 +16,14 @@ import android.view.SurfaceHolder; |
|
|
|
|
import android.view.SurfaceView; |
|
|
|
|
|
|
|
|
|
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable { |
|
|
|
|
private static final String TAG = "Sample::SurfaceView"; |
|
|
|
|
private static final String TAG = "OCVSample::BaseView"; |
|
|
|
|
|
|
|
|
|
private Camera mCamera; |
|
|
|
|
private SurfaceHolder mHolder; |
|
|
|
|
private int mFrameWidth; |
|
|
|
|
private int mFrameHeight; |
|
|
|
|
private byte[] mFrame; |
|
|
|
|
private boolean mThreadRun; |
|
|
|
|
private volatile boolean mThreadRun; |
|
|
|
|
private byte[] mBuffer; |
|
|
|
|
private SurfaceTexture mSf; |
|
|
|
|
|
|
|
|
@ -52,11 +53,29 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean openCamera() { |
|
|
|
|
Log.i(TAG, "openCamera"); |
|
|
|
|
releaseCamera(); |
|
|
|
|
mCamera = Camera.open(); |
|
|
|
|
Log.i(TAG, "Opening Camera"); |
|
|
|
|
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) { |
|
|
|
|
Log.e(TAG, "Can't open camera!"); |
|
|
|
|
Log.e(TAG, "Can't open any camera"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -69,16 +88,16 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde |
|
|
|
|
camera.addCallbackBuffer(mBuffer); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void releaseCamera() { |
|
|
|
|
Log.i(TAG, "releaseCamera"); |
|
|
|
|
Log.i(TAG, "Releasing Camera"); |
|
|
|
|
mThreadRun = false; |
|
|
|
|
synchronized (this) { |
|
|
|
|
if (mCamera != null) { |
|
|
|
|
mCamera.stopPreview(); |
|
|
|
|
mCamera.setPreviewCallback(null); |
|
|
|
|
mCamera.release(); |
|
|
|
|
mCamera = null; |
|
|
|
|
} |
|
|
|
@ -86,78 +105,81 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde |
|
|
|
|
onPreviewStopped(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setupCamera(int width, int height) { |
|
|
|
|
Log.i(TAG, "setupCamera"); |
|
|
|
|
synchronized (this) { |
|
|
|
|
if (mCamera != null) { |
|
|
|
|
Camera.Parameters params = mCamera.getParameters(); |
|
|
|
|
List<Camera.Size> sizes = params.getSupportedPreviewSizes(); |
|
|
|
|
mFrameWidth = width; |
|
|
|
|
mFrameHeight = height; |
|
|
|
|
|
|
|
|
|
// selecting optimal camera preview size
|
|
|
|
|
{ |
|
|
|
|
int minDiff = Integer.MAX_VALUE; |
|
|
|
|
for (Camera.Size size : sizes) { |
|
|
|
|
if (Math.abs(size.height - height) < minDiff) { |
|
|
|
|
mFrameWidth = size.width; |
|
|
|
|
mFrameHeight = size.height; |
|
|
|
|
minDiff = Math.abs(size.height - height); |
|
|
|
|
} |
|
|
|
|
public synchronized void setupCamera(int width, int height) { |
|
|
|
|
if (mCamera != null) { |
|
|
|
|
Log.i(TAG, "Setup Camera - " + width + "x" + height); |
|
|
|
|
Camera.Parameters params = mCamera.getParameters(); |
|
|
|
|
List<Camera.Size> sizes = params.getSupportedPreviewSizes(); |
|
|
|
|
mFrameWidth = width; |
|
|
|
|
mFrameHeight = height; |
|
|
|
|
|
|
|
|
|
// selecting optimal camera preview size
|
|
|
|
|
{ |
|
|
|
|
int minDiff = Integer.MAX_VALUE; |
|
|
|
|
for (Camera.Size size : sizes) { |
|
|
|
|
if (Math.abs(size.height - height) < minDiff) { |
|
|
|
|
mFrameWidth = size.width; |
|
|
|
|
mFrameHeight = size.height; |
|
|
|
|
minDiff = Math.abs(size.height - height); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
params.setPreviewSize(getFrameWidth(), getFrameHeight()); |
|
|
|
|
|
|
|
|
|
List<String> FocusModes = params.getSupportedFocusModes(); |
|
|
|
|
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) |
|
|
|
|
{ |
|
|
|
|
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); |
|
|
|
|
} |
|
|
|
|
params.setPreviewSize(getFrameWidth(), getFrameHeight()); |
|
|
|
|
|
|
|
|
|
mCamera.setParameters(params); |
|
|
|
|
List<String> FocusModes = params.getSupportedFocusModes(); |
|
|
|
|
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) |
|
|
|
|
{ |
|
|
|
|
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Now allocate the buffer */ |
|
|
|
|
params = mCamera.getParameters(); |
|
|
|
|
int size = params.getPreviewSize().width * params.getPreviewSize().height; |
|
|
|
|
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8; |
|
|
|
|
mBuffer = new byte[size]; |
|
|
|
|
/* The buffer where the current frame will be copied */ |
|
|
|
|
mFrame = new byte [size]; |
|
|
|
|
mCamera.addCallbackBuffer(mBuffer); |
|
|
|
|
mCamera.setParameters(params); |
|
|
|
|
|
|
|
|
|
/* Notify that the preview is about to be started and deliver preview size */ |
|
|
|
|
onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height); |
|
|
|
|
/* Now allocate the buffer */ |
|
|
|
|
params = mCamera.getParameters(); |
|
|
|
|
int size = params.getPreviewSize().width * params.getPreviewSize().height; |
|
|
|
|
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8; |
|
|
|
|
mBuffer = new byte[size]; |
|
|
|
|
/* The buffer where the current frame will be copied */ |
|
|
|
|
mFrame = new byte [size]; |
|
|
|
|
mCamera.addCallbackBuffer(mBuffer); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
setPreview(); |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e); |
|
|
|
|
} |
|
|
|
|
/* Notify that the preview is about to be started and deliver preview size */ |
|
|
|
|
onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height); |
|
|
|
|
|
|
|
|
|
/* Now we can start a preview */ |
|
|
|
|
mCamera.startPreview(); |
|
|
|
|
try { |
|
|
|
|
setPreview(); |
|
|
|
|
} catch (IOException e) { |
|
|
|
|
Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Now we can start a preview */ |
|
|
|
|
mCamera.startPreview(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) { |
|
|
|
|
Log.i(TAG, "surfaceChanged"); |
|
|
|
|
Log.i(TAG, "called surfaceChanged"); |
|
|
|
|
// stop preview before making changes
|
|
|
|
|
try { |
|
|
|
|
mCamera.stopPreview(); |
|
|
|
|
} catch (Exception e){ |
|
|
|
|
// ignore: tried to stop a non-existent preview
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// start preview with new settings
|
|
|
|
|
setupCamera(width, height); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void surfaceCreated(SurfaceHolder holder) { |
|
|
|
|
Log.i(TAG, "surfaceCreated"); |
|
|
|
|
Log.i(TAG, "called surfaceCreated"); |
|
|
|
|
(new Thread(this)).start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void surfaceDestroyed(SurfaceHolder holder) { |
|
|
|
|
Log.i(TAG, "surfaceDestroyed"); |
|
|
|
|
releaseCamera(); |
|
|
|
|
Log.i(TAG, "called surfaceDestroyed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The bitmap returned by this method shall be owned by the child and released in onPreviewStopped() */ |
|
|
|
|
protected abstract Bitmap processFrame(byte[] data); |
|
|
|
|
|
|
|
|
@ -178,13 +200,15 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde |
|
|
|
|
|
|
|
|
|
public void run() { |
|
|
|
|
mThreadRun = true; |
|
|
|
|
Log.i(TAG, "Starting processing thread"); |
|
|
|
|
Log.i(TAG, "Started processing thread"); |
|
|
|
|
while (mThreadRun) { |
|
|
|
|
Bitmap bmp = null; |
|
|
|
|
|
|
|
|
|
synchronized (this) { |
|
|
|
|
try { |
|
|
|
|
this.wait(); |
|
|
|
|
if (!mThreadRun) |
|
|
|
|
break; |
|
|
|
|
bmp = processFrame(mFrame); |
|
|
|
|
} catch (InterruptedException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
@ -199,5 +223,6 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Log.i(TAG, "Finished processing thread"); |
|
|
|
|
} |
|
|
|
|
} |