re-enable direct capture

Closes #3664
// FREEBIE
This commit is contained in:
Jake McGinty
2015-07-13 17:35:34 -07:00
committed by Moxie Marlinspike
parent 47b21707be
commit 1a7ab6346f
10 changed files with 236 additions and 124 deletions

View File

@@ -19,7 +19,6 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Build;
@@ -30,7 +29,6 @@ import android.util.Log;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.io.IOException;
@@ -91,7 +89,7 @@ public class CameraView extends FrameLayout {
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void onResume() {
Log.w(TAG, "onResume()");
Log.w(TAG, "onResume() queued");
final CameraHost host = getHost();
submitTask(new SerializedAsyncTask<FailureReason>() {
@Override protected FailureReason onRunBackground() {
@@ -110,11 +108,11 @@ public class CameraView extends FrameLayout {
}
@Override protected void onPostMain(FailureReason result) {
cameraReady = true;
if (result != null) {
host.onCameraFail(result);
return;
}
cameraReady = true;
if (getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
onOrientationChange.enable();
}
@@ -126,12 +124,13 @@ public class CameraView extends FrameLayout {
initPreview();
requestLayout();
invalidate();
Log.w(TAG, "onResume() completed");
}
});
}
public void onPause() {
Log.w(TAG, "onPause()");
Log.w(TAG, "onPause() queued");
submitTask(new SerializedAsyncTask<Void>() {
@Override protected void onPreMain() {
cameraReady = false;
@@ -151,6 +150,7 @@ public class CameraView extends FrameLayout {
outputOrientation = -1;
cameraId = -1;
lastPictureOrientation = -1;
Log.w(TAG, "onPause() completed");
}
});
}
@@ -255,6 +255,7 @@ public class CameraView extends FrameLayout {
}
void previewCreated() {
Log.w(TAG, "previewCreated() queued");
final CameraHost host = getHost();
submitTask(new PostInitializationTask<Void>() {
@Override protected void onPostMain(Void avoid) {
@@ -265,6 +266,7 @@ public class CameraView extends FrameLayout {
} catch (IOException e) {
host.handleException(e);
}
Log.w(TAG, "previewCreated() completed");
}
});
}
@@ -277,11 +279,6 @@ public class CameraView extends FrameLayout {
}
}
void previewReset() {
previewStopped();
initPreview();
}
private void previewStopped() {
if (inPreview) {
stopPreview();
@@ -290,6 +287,7 @@ public class CameraView extends FrameLayout {
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void initPreview() {
Log.w(TAG, "initPreview() queued");
submitTask(new PostInitializationTask<Void>() {
@Override protected void onPostMain(Void avoid) {
if (camera != null && cameraReady) {
@@ -305,20 +303,19 @@ public class CameraView extends FrameLayout {
startPreview();
requestLayout();
invalidate();
Log.w(TAG, "initPreview() completed");
}
}
});
}
private void startPreview() {
Log.w(TAG, "startPreview()");
camera.startPreview();
inPreview = true;
getHost().autoFocusAvailable();
}
private void stopPreview() {
Log.w(TAG, "stopPreview()");
camera.startPreview();
inPreview = false;
getHost().autoFocusUnavailable();
@@ -453,20 +450,24 @@ public class CameraView extends FrameLayout {
@Override public void onAdded() {}
@Override public final void onRun() {
onWait();
runOnMainSync(new Runnable() {
@Override public void run() {
onPreMain();
}
});
try {
onWait();
runOnMainSync(new Runnable() {
@Override public void run() {
onPreMain();
}
});
final Result result = onRunBackground();
final Result result = onRunBackground();
runOnMainSync(new Runnable() {
@Override public void run() {
onPostMain(result);
}
});
runOnMainSync(new Runnable() {
@Override public void run() {
onPostMain(result);
}
});
} catch (PreconditionsNotMetException e) {
Log.w(TAG, "skipping task, preconditions not met in onWait()");
}
}
@Override public boolean onShouldRetry(Exception e) {
@@ -493,19 +494,26 @@ public class CameraView extends FrameLayout {
}
}
protected void onWait() {}
protected void onWait() throws PreconditionsNotMetException {}
protected void onPreMain() {}
protected Result onRunBackground() { return null; }
protected void onPostMain(Result result) {}
}
private abstract class PostInitializationTask<Result> extends SerializedAsyncTask<Result> {
@Override protected void onWait() {
@Override protected void onWait() throws PreconditionsNotMetException {
synchronized (CameraView.this) {
if (!cameraReady) {
throw new PreconditionsNotMetException();
}
while (camera == null || previewSize == null || !previewStrategy.isReady()) {
Log.w(TAG, String.format("waiting. camera? %s previewSize? %s prevewStrategy? %s",
camera != null, previewSize != null, previewStrategy.isReady()));
Util.wait(CameraView.this, 0);
}
}
}
}
private static class PreconditionsNotMetException extends Exception {}
}

View File

@@ -52,6 +52,7 @@ public class QuickAttachmentDrawer extends ViewGroup {
private float halfExpandedAnchorPoint = COLLAPSED_ANCHOR_POINT;
private boolean halfModeUnsupported = VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH;
private Rect drawChildrenRect = new Rect();
private boolean paused = false;
public QuickAttachmentDrawer(Context context) {
this(context, null);
@@ -128,7 +129,7 @@ public class QuickAttachmentDrawer extends ViewGroup {
}
shutterButton.setOnClickListener(new ShutterClickListener());
fullScreenButton.setOnClickListener(new FullscreenClickListener());
controls.setVisibility(GONE);
controls.setVisibility(INVISIBLE);
addView(controls, controlsIndex > -1 ? controlsIndex : indexOfChild(quickCamera) + 1);
}
@@ -274,10 +275,10 @@ public class QuickAttachmentDrawer extends ViewGroup {
}
if (slideOffset == COLLAPSED_ANCHOR_POINT && quickCamera.isStarted()) {
controls.setVisibility(GONE);
quickCamera.setVisibility(GONE);
quickCamera.onPause();
} else if (slideOffset != COLLAPSED_ANCHOR_POINT && !quickCamera.isStarted()) {
controls.setVisibility(INVISIBLE);
quickCamera.setVisibility(INVISIBLE);
} else if (slideOffset != COLLAPSED_ANCHOR_POINT && !quickCamera.isStarted() & !paused) {
controls.setVisibility(VISIBLE);
quickCamera.setVisibility(VISIBLE);
quickCamera.onResume();
@@ -507,10 +508,12 @@ public class QuickAttachmentDrawer extends ViewGroup {
}
public void onPause() {
paused = true;
quickCamera.onPause();
}
public void onResume() {
paused = false;
if (drawerState.isVisible()) quickCamera.onResume();
}

View File

@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.components.camera;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
@@ -13,11 +12,10 @@ import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
import com.commonsware.cwac.camera.CameraHost.FailureReason;
import com.commonsware.cwac.camera.SimpleCameraHost;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.BitmapUtil;
import java.io.IOException;
@@ -78,29 +76,33 @@ import java.util.List;
setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, final Camera camera) {
final int rotation = getCameraPictureOrientation();
final int rotation = getCameraPictureOrientation();
final Size previewSize = cameraParameters.getPreviewSize();
final Rect croppingRect = getCroppedRect(previewSize, previewRect, rotation);
new AsyncTask<byte[], Void, Bitmap>() {
Log.w(TAG, "previewSize: " + previewSize.width + "x" + previewSize.height);
Log.w(TAG, "croppingRect: " + croppingRect.toString());
Log.w(TAG, "rotation: " + rotation);
new AsyncTask<byte[], Void, byte[]>() {
@Override
protected Bitmap doInBackground(byte[]... params) {
protected byte[] doInBackground(byte[]... params) {
byte[] data = params[0];
try {
Size previewSize = cameraParameters.getPreviewSize();
return BitmapUtil.createFromNV21(data,
previewSize.width,
previewSize.height,
rotation,
getCroppedRect(previewSize, previewRect, rotation));
croppingRect);
} catch (IOException e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
protected void onPostExecute(byte[] imageBytes) {
capturing = false;
if (bitmap != null && listener != null) listener.onImageCapture(bitmap);
if (imageBytes != null && listener != null) listener.onImageCapture(imageBytes);
}
}.execute(data);
}
@@ -111,10 +113,7 @@ import java.util.List;
final int previewWidth = cameraPreviewSize.width;
final int previewHeight = cameraPreviewSize.height;
if (rotation % 180 > 0) {
//noinspection SuspiciousNameCombination
visibleRect.set(visibleRect.top, visibleRect.left, visibleRect.bottom, visibleRect.right);
}
if (rotation % 180 > 0) rotateRect(visibleRect);
float scale = (float) previewWidth / visibleRect.width();
if (visibleRect.height() * scale > previewHeight) {
@@ -128,9 +127,16 @@ import java.util.List;
(int) (centerY - newHeight / 2),
(int) (centerX + newWidth / 2),
(int) (centerY + newHeight / 2));
if (rotation % 180 > 0) rotateRect(visibleRect);
return visibleRect;
}
@SuppressWarnings("SuspiciousNameCombination")
private void rotateRect(Rect rect) {
rect.set(rect.top, rect.left, rect.bottom, rect.right);
}
public void setQuickCameraListener(QuickCameraListener listener) {
this.listener = listener;
}
@@ -150,7 +156,8 @@ import java.util.List;
}
public interface QuickCameraListener {
void onImageCapture(@NonNull final Bitmap bitmap);
void onImageCapture(@NonNull final byte[] imageBytes);
void onCameraFail(FailureReason reason);
}
private class QuickCameraHost extends SimpleCameraHost {
@@ -186,7 +193,7 @@ import java.util.List;
@Override
public void onCameraFail(FailureReason reason) {
super.onCameraFail(reason);
Toast.makeText(getContext(), R.string.quick_camera_unavailable, Toast.LENGTH_SHORT).show();
if (listener != null) listener.onCameraFail(reason);
}
}
}