|
|
|
@ -58,10 +58,11 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
private @NonNull volatile Optional<Camera> camera = Optional.absent();
|
|
|
|
|
private volatile int cameraId = CameraInfo.CAMERA_FACING_BACK;
|
|
|
|
|
|
|
|
|
|
private boolean started;
|
|
|
|
|
private @NonNull State state = State.PAUSED;
|
|
|
|
|
private @Nullable Size previewSize;
|
|
|
|
|
private @Nullable CameraViewListener listener;
|
|
|
|
|
private int displayOrientation = -1;
|
|
|
|
|
private int outputOrientation = -1;
|
|
|
|
|
private int displayOrientation = -1;
|
|
|
|
|
private int outputOrientation = -1;
|
|
|
|
|
|
|
|
|
|
public CameraView(Context context) {
|
|
|
|
|
this(context, null);
|
|
|
|
@ -92,8 +93,8 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
|
|
|
|
|
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
|
|
|
|
public void onResume() {
|
|
|
|
|
if (started) return;
|
|
|
|
|
started = true;
|
|
|
|
|
if (state != State.PAUSED) return;
|
|
|
|
|
state = State.RESUMED;
|
|
|
|
|
Log.w(TAG, "onResume() queued");
|
|
|
|
|
enqueueTask(new SerialAsyncTask<Camera>() {
|
|
|
|
|
@Override
|
|
|
|
@ -125,8 +126,6 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
synchronized (CameraView.this) {
|
|
|
|
|
CameraView.this.notifyAll();
|
|
|
|
|
}
|
|
|
|
|
requestLayout();
|
|
|
|
|
invalidate();
|
|
|
|
|
Log.w(TAG, "onResume() completed");
|
|
|
|
|
} catch (RuntimeException e) {
|
|
|
|
|
Log.w(TAG, "exception when starting camera preview", e);
|
|
|
|
@ -137,8 +136,8 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onPause() {
|
|
|
|
|
if (!started) return;
|
|
|
|
|
started = false;
|
|
|
|
|
if (state == State.PAUSED) return;
|
|
|
|
|
state = State.PAUSED;
|
|
|
|
|
Log.w(TAG, "onPause() queued");
|
|
|
|
|
|
|
|
|
|
enqueueTask(new SerialAsyncTask<Void>() {
|
|
|
|
@ -175,28 +174,7 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isStarted() {
|
|
|
|
|
return started;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
|
|
|
|
|
|
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && camera.isPresent()) {
|
|
|
|
|
final Size preferredPreviewSize = CameraUtils.getPreferredPreviewSize(displayOrientation,
|
|
|
|
|
getMeasuredWidth(),
|
|
|
|
|
getMeasuredHeight(),
|
|
|
|
|
camera.get());
|
|
|
|
|
final Parameters parameters = camera.get().getParameters();
|
|
|
|
|
if (preferredPreviewSize != null && !parameters.getPreviewSize().equals(preferredPreviewSize)) {
|
|
|
|
|
Log.w(TAG, "setting preview size to " + preferredPreviewSize.width + "x" + preferredPreviewSize.height);
|
|
|
|
|
stopPreview();
|
|
|
|
|
parameters.setPreviewSize(preferredPreviewSize.width, preferredPreviewSize.height);
|
|
|
|
|
camera.get().setParameters(parameters);
|
|
|
|
|
requestLayout();
|
|
|
|
|
startPreview();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return state != State.PAUSED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("SuspiciousNameCombination")
|
|
|
|
@ -207,8 +185,7 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
final int previewWidth;
|
|
|
|
|
final int previewHeight;
|
|
|
|
|
|
|
|
|
|
if (camera.isPresent()) {
|
|
|
|
|
final Size previewSize = camera.get().getParameters().getPreviewSize();
|
|
|
|
|
if (camera.isPresent() && previewSize != null) {
|
|
|
|
|
if (displayOrientation == 90 || displayOrientation == 270) {
|
|
|
|
|
previewWidth = previewSize.height;
|
|
|
|
|
previewHeight = previewSize.width;
|
|
|
|
@ -225,7 +202,6 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
Log.w(TAG, "skipping layout due to zero-width/height preview size");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Log.w(TAG, "layout " + width + "x" + height + ", target " + previewWidth + "x" + previewHeight);
|
|
|
|
|
|
|
|
|
|
if (width * previewHeight > height * previewWidth) {
|
|
|
|
|
final int scaledChildHeight = previewHeight * width / previewWidth;
|
|
|
|
@ -236,11 +212,18 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
|
|
|
|
Log.w(TAG, "onSizeChanged(" + oldw + "x" + oldh + " -> " + w + "x" + h + ")");
|
|
|
|
|
super.onSizeChanged(w, h, oldw, oldh);
|
|
|
|
|
if (camera.isPresent()) startPreview(camera.get().getParameters());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setListener(@Nullable CameraViewListener listener) {
|
|
|
|
|
this.listener = listener;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setPreviewCallback(final PreviewCallback previewCallback) {
|
|
|
|
|
public void setPreviewCallback(final @NonNull PreviewCallback previewCallback) {
|
|
|
|
|
enqueueTask(new PostInitializationTask<Void>() {
|
|
|
|
|
@Override
|
|
|
|
|
protected void onPostMain(Void avoid) {
|
|
|
|
@ -252,8 +235,8 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final int rotation = getCameraPictureOrientation();
|
|
|
|
|
final Size previewSize = camera.getParameters().getPreviewSize();
|
|
|
|
|
final int rotation = getCameraPictureOrientation();
|
|
|
|
|
final Size previewSize = camera.getParameters().getPreviewSize();
|
|
|
|
|
if (data != null) {
|
|
|
|
|
previewCallback.onPreviewFrame(new PreviewFrame(data, previewSize.width, previewSize.height, rotation));
|
|
|
|
|
}
|
|
|
|
@ -308,6 +291,7 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
if (camera.isPresent()) {
|
|
|
|
|
try {
|
|
|
|
|
camera.get().setPreviewDisplay(surface.getHolder());
|
|
|
|
|
startPreview(parameters);
|
|
|
|
|
requestLayout();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.w(TAG, e);
|
|
|
|
@ -317,10 +301,24 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void startPreview() {
|
|
|
|
|
if (camera.isPresent()) {
|
|
|
|
|
private void startPreview(final @NonNull Parameters parameters) {
|
|
|
|
|
if (this.camera.isPresent()) {
|
|
|
|
|
try {
|
|
|
|
|
camera.get().startPreview();
|
|
|
|
|
final Camera camera = this.camera.get();
|
|
|
|
|
final Size preferredPreviewSize = getPreferredPreviewSize(parameters);
|
|
|
|
|
|
|
|
|
|
if (preferredPreviewSize != null && !parameters.getPreviewSize().equals(preferredPreviewSize)) {
|
|
|
|
|
Log.w(TAG, "starting preview with size " + preferredPreviewSize.width + "x" + preferredPreviewSize.height);
|
|
|
|
|
if (state == State.ACTIVE) stopPreview();
|
|
|
|
|
previewSize = preferredPreviewSize;
|
|
|
|
|
parameters.setPreviewSize(preferredPreviewSize.width, preferredPreviewSize.height);
|
|
|
|
|
camera.setParameters(parameters);
|
|
|
|
|
} else {
|
|
|
|
|
previewSize = parameters.getPreviewSize();
|
|
|
|
|
}
|
|
|
|
|
camera.startPreview();
|
|
|
|
|
requestLayout();
|
|
|
|
|
state = State.ACTIVE;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.w(TAG, e);
|
|
|
|
|
}
|
|
|
|
@ -331,13 +329,21 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
if (camera.isPresent()) {
|
|
|
|
|
try {
|
|
|
|
|
camera.get().stopPreview();
|
|
|
|
|
state = State.RESUMED;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.w(TAG, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getCameraPictureOrientation() {
|
|
|
|
|
private Size getPreferredPreviewSize(@NonNull Parameters parameters) {
|
|
|
|
|
return CameraUtils.getPreferredPreviewSize(displayOrientation,
|
|
|
|
|
getMeasuredWidth(),
|
|
|
|
|
getMeasuredHeight(),
|
|
|
|
|
parameters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int getCameraPictureOrientation() {
|
|
|
|
|
if (getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
|
|
|
|
|
outputOrientation = getCameraPictureRotation(getActivity().getWindowManager()
|
|
|
|
|
.getDefaultDisplay()
|
|
|
|
@ -589,4 +595,8 @@ public class CameraView extends FrameLayout {
|
|
|
|
|
return orientation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private enum State {
|
|
|
|
|
PAUSED, RESUMED, ACTIVE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|