Fix various bugs

pull/580/head
Mattia Iavarone 6 years ago
parent 6db954420d
commit a9f6e50ac4
  1. 29
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  2. 17
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/Actions.java
  3. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/action/BaseAction.java
  4. 7
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/BaseMeter.java
  5. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/ExposureMeter.java
  6. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/FocusMeter.java
  7. 15
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/MeterAction.java
  8. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceMeter.java
  9. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/meter/WhiteBalanceReset.java
  10. 2
      demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java
  11. 3
      demo/src/main/res/layout/activity_camera.xml

@ -69,6 +69,7 @@ import com.otaliastudios.cameraview.video.Full2VideoRecorder;
import com.otaliastudios.cameraview.video.SnapshotVideoRecorder; import com.otaliastudios.cameraview.video.SnapshotVideoRecorder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -270,7 +271,7 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
@NonNull TotalCaptureResult result) { @NonNull TotalCaptureResult result) {
mLastRepeatingResult = result; mLastRepeatingResult = result;
for (Action action : mActions) { for (Action action : mActions) {
action.onCaptureProgressed(Camera2Engine.this, request, result); action.onCaptureCompleted(Camera2Engine.this, request, result);
} }
} }
}; };
@ -1287,15 +1288,29 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
//region Actions //region Actions
@Override @Override
public void addAction(@NonNull Action action) { public void addAction(final @NonNull Action action) {
if (!mActions.contains(action)) { // This is likely to be called during a Capture callback while we iterate
mActions.add(action); // on the actions list, or worse, from other threads. We must use mHandler.post.
} mHandler.post(new Runnable() {
@Override
public void run() {
if (!mActions.contains(action)) {
mActions.add(action);
}
}
});
} }
@Override @Override
public void removeAction(@NonNull Action action) { public void removeAction(final @NonNull Action action) {
mActions.remove(action); // This is likely to be called during a Capture callback while we iterate
// on the actions list, or worse, from other threads. We must use mHandler.post.
mHandler.post(new Runnable() {
@Override
public void run() {
mActions.remove(action);
}
});
} }
@NonNull @NonNull

@ -8,6 +8,7 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -44,18 +45,20 @@ public class Actions {
private static class TogetherAction extends BaseAction { private static class TogetherAction extends BaseAction {
// Need to be BaseAction so we can call onStart() instead of start() // Need to be BaseAction so we can call onStart() instead of start()
private final List<BaseAction> actions; private final List<BaseAction> actions;
private final List<BaseAction> runningActions;
private TogetherAction(@NonNull final List<BaseAction> actions) { private TogetherAction(@NonNull final List<BaseAction> actions) {
this.actions = actions; this.actions = new ArrayList<>(actions);
this.runningActions = new ArrayList<>(actions);
for (BaseAction action : actions) { for (BaseAction action : actions) {
action.addCallback(new ActionCallback() { action.addCallback(new ActionCallback() {
@Override @Override
public void onActionStateChanged(@NonNull Action action, int state) { public void onActionStateChanged(@NonNull Action action, int state) {
if (state == STATE_COMPLETED) { if (state == STATE_COMPLETED) {
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
actions.remove(action); runningActions.remove(action);
} }
if (actions.isEmpty()) { if (runningActions.isEmpty()) {
setState(STATE_COMPLETED); setState(STATE_COMPLETED);
} }
} }
@ -67,7 +70,7 @@ public class Actions {
protected void onStart(@NonNull ActionHolder holder) { protected void onStart(@NonNull ActionHolder holder) {
super.onStart(holder); super.onStart(holder);
for (BaseAction action : actions) { for (BaseAction action : actions) {
action.onStart(holder); if (!action.isCompleted()) action.onStart(holder);
} }
} }
@ -75,7 +78,7 @@ public class Actions {
public void onCaptureStarted(@NonNull ActionHolder holder, @NonNull CaptureRequest request) { public void onCaptureStarted(@NonNull ActionHolder holder, @NonNull CaptureRequest request) {
super.onCaptureStarted(holder, request); super.onCaptureStarted(holder, request);
for (BaseAction action : actions) { for (BaseAction action : actions) {
action.onCaptureStarted(holder, request); if (!action.isCompleted()) action.onCaptureStarted(holder, request);
} }
} }
@ -84,7 +87,7 @@ public class Actions {
@NonNull CaptureResult result) { @NonNull CaptureResult result) {
super.onCaptureProgressed(holder, request, result); super.onCaptureProgressed(holder, request, result);
for (BaseAction action : actions) { for (BaseAction action : actions) {
action.onCaptureProgressed(holder, request, result); if (!action.isCompleted()) action.onCaptureProgressed(holder, request, result);
} }
} }
@ -93,7 +96,7 @@ public class Actions {
@NonNull TotalCaptureResult result) { @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(holder, request, result); super.onCaptureCompleted(holder, request, result);
for (BaseAction action : actions) { for (BaseAction action : actions) {
action.onCaptureCompleted(holder, request, result); if (!action.isCompleted()) action.onCaptureCompleted(holder, request, result);
} }
} }
} }

@ -6,6 +6,7 @@ import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.TotalCaptureResult;
import android.os.Build; import android.os.Build;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
@ -37,7 +38,6 @@ public abstract class BaseAction implements Action {
@Override @Override
public final void start(@NonNull ActionHolder holder) { public final void start(@NonNull ActionHolder holder) {
this.holder = holder;
holder.addAction(this); holder.addAction(this);
onStart(holder); onStart(holder);
} }
@ -47,7 +47,9 @@ public abstract class BaseAction implements Action {
* holder stream. * holder stream.
* @param holder holder * @param holder holder
*/ */
@CallSuper
protected void onStart(@NonNull ActionHolder holder) { protected void onStart(@NonNull ActionHolder holder) {
this.holder = holder; // must be here
// Overrideable // Overrideable
} }

@ -6,6 +6,7 @@ import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
import com.otaliastudios.cameraview.engine.action.BaseAction; import com.otaliastudios.cameraview.engine.action.BaseAction;
@ -14,6 +15,9 @@ import java.util.List;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public abstract class BaseMeter extends BaseAction { public abstract class BaseMeter extends BaseAction {
private final static String TAG = BaseMeter.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG);
private final List<MeteringRectangle> areas; private final List<MeteringRectangle> areas;
private boolean isSuccessful; private boolean isSuccessful;
private boolean skipIfPossible; private boolean skipIfPossible;
@ -30,8 +34,10 @@ public abstract class BaseMeter extends BaseAction {
boolean isSkipped = skipIfPossible && checkShouldSkip(holder); boolean isSkipped = skipIfPossible && checkShouldSkip(holder);
boolean isSupported = checkIsSupported(holder); boolean isSupported = checkIsSupported(holder);
if (isSupported && !isSkipped) { if (isSupported && !isSkipped) {
LOG.i("onStart:", "supported and not skipped. Dispatching onStarted.");
onStarted(holder, areas); onStarted(holder, areas);
} else { } else {
LOG.i("onStart:", "not supported or skipped. Dispatching COMPLETED state.");
setSuccessful(true); setSuccessful(true);
setState(STATE_COMPLETED); setState(STATE_COMPLETED);
} }
@ -49,6 +55,7 @@ public abstract class BaseMeter extends BaseAction {
isSuccessful = successful; isSuccessful = successful;
} }
@SuppressWarnings("WeakerAccess")
public boolean isSuccessful() { public boolean isSuccessful() {
return isSuccessful; return isSuccessful;
} }

@ -57,6 +57,8 @@ public class ExposureMeter extends BaseMeter {
@Override @Override
protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) { protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) {
LOG.i("onStarted:", "with areas:", areas);
// Launch the precapture trigger. // Launch the precapture trigger.
holder.getBuilder(this).set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, holder.getBuilder(this).set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);

@ -50,6 +50,7 @@ public class FocusMeter extends BaseMeter {
@Override @Override
protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) { protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) {
LOG.i("onStarted:", "with areas:", areas);
holder.getBuilder(this).set(CaptureRequest.CONTROL_AF_TRIGGER, holder.getBuilder(this).set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START); CaptureRequest.CONTROL_AF_TRIGGER_START);
int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AF, 0); int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AF, 0);

@ -4,6 +4,7 @@ import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.MeteringRectangle; import android.hardware.camera2.params.MeteringRectangle;
import android.os.Build; import android.os.Build;
@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.engine.CameraEngine; import com.otaliastudios.cameraview.engine.CameraEngine;
import com.otaliastudios.cameraview.engine.action.ActionHolder; import com.otaliastudios.cameraview.engine.action.ActionHolder;
import com.otaliastudios.cameraview.engine.action.ActionWrapper; import com.otaliastudios.cameraview.engine.action.ActionWrapper;
@ -28,6 +30,9 @@ import java.util.List;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class MeterAction extends ActionWrapper { public class MeterAction extends ActionWrapper {
private final static String TAG = MeterAction.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG);
private List<BaseMeter> meters; private List<BaseMeter> meters;
private BaseAction action; private BaseAction action;
private ActionHolder holder; private ActionHolder holder;
@ -56,15 +61,19 @@ public class MeterAction extends ActionWrapper {
public boolean isSuccessful() { public boolean isSuccessful() {
for (BaseMeter meter : meters) { for (BaseMeter meter : meters) {
if (!meter.isSuccessful()) { if (!meter.isSuccessful()) {
LOG.i("isSuccessful:", "returning false.");
return false; return false;
} }
} }
LOG.i("isSuccessful:", "returning true.");
return true; return true;
} }
@Override @Override
protected void onStart(@NonNull ActionHolder holder) { protected void onStart(@NonNull ActionHolder holder) {
LOG.w("onStart:", "initializing.");
initialize(holder); initialize(holder);
LOG.w("onStart:", "initialized.");
super.onStart(holder); super.onStart(holder);
} }
@ -208,8 +217,10 @@ public class MeterAction extends ActionWrapper {
referencePoint.x += cropRect == null ? 0 : cropRect.left; referencePoint.x += cropRect == null ? 0 : cropRect.left;
referencePoint.y += cropRect == null ? 0 : cropRect.top; referencePoint.y += cropRect == null ? 0 : cropRect.top;
// Finally, get the active rect width and height from characteristics. // Finally, get the active rect width and height from characteristics.
Rect activeRect = readCharacteristic(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE, Rect activeRect = holder.getCharacteristics(this).get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
new Rect(0, 0, referenceSize.getWidth(), referenceSize.getHeight())); if (activeRect == null) { // Should never happen
activeRect = new Rect(0, 0, referenceSize.getWidth(), referenceSize.getHeight());
}
return new Size(activeRect.width(), activeRect.height()); return new Size(activeRect.width(), activeRect.height());
} }

@ -45,6 +45,7 @@ public class WhiteBalanceMeter extends BaseMeter {
@Override @Override
protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) { protected void onStarted(@NonNull ActionHolder holder, @NonNull List<MeteringRectangle> areas) {
LOG.i("onStarted:", "with areas:", areas);
int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0); int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
if (!areas.isEmpty() && maxRegions > 0) { if (!areas.isEmpty() && maxRegions > 0) {
int max = Math.min(maxRegions, areas.size()); int max = Math.min(maxRegions, areas.size());

@ -28,6 +28,7 @@ public class WhiteBalanceReset extends BaseReset {
@Override @Override
protected void onStarted(@NonNull ActionHolder holder, @Nullable MeteringRectangle area) { protected void onStarted(@NonNull ActionHolder holder, @Nullable MeteringRectangle area) {
LOG.w("onStarted:", "with area:", area);
int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0); int maxRegions = readCharacteristic(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
if (area != null && maxRegions > 0) { if (area != null && maxRegions > 0) {
holder.getBuilder(this).set(CaptureRequest.CONTROL_AWB_REGIONS, new MeteringRectangle[]{area}); holder.getBuilder(this).set(CaptureRequest.CONTROL_AWB_REGIONS, new MeteringRectangle[]{area});

@ -213,7 +213,7 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis
PicturePreviewActivity.setPictureResult(result); PicturePreviewActivity.setPictureResult(result);
Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class); Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class);
intent.putExtra("delay", callbackTime - mCaptureTime); intent.putExtra("delay", callbackTime - mCaptureTime);
// startActivity(intent); startActivity(intent);
mCaptureTime = 0; mCaptureTime = 0;
LOG.w("onPictureTaken called! Launched activity."); LOG.w("onPictureTaken called! Launched activity.");
} }

@ -20,8 +20,7 @@
app:cameraPreview="glSurface" app:cameraPreview="glSurface"
app:cameraPlaySounds="true" app:cameraPlaySounds="true"
app:cameraGrid="off" app:cameraGrid="off"
app:cameraFlash="on" app:cameraFlash="auto"
app:cameraPictureSnapshotMetering="true"
app:cameraAudio="on" app:cameraAudio="on"
app:cameraFacing="back" app:cameraFacing="back"
app:cameraGestureTap="autoFocus" app:cameraGestureTap="autoFocus"

Loading…
Cancel
Save