Try harder to find suitable camera parameters. #346

This commit is contained in:
akwizgran
2016-09-21 13:22:19 +01:00
parent eb6189150f
commit a4d08f4cf1

View File

@@ -8,24 +8,24 @@ import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import org.briarproject.android.util.PreviewConsumer;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import static android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT;
import static android.hardware.Camera.Parameters.FLASH_MODE_OFF;
import static android.hardware.Camera.Parameters.FOCUS_MODE_AUTO;
import static android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
import static android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
import static android.hardware.Camera.Parameters.FOCUS_MODE_EDOF;
import static android.hardware.Camera.Parameters.FOCUS_MODE_FIXED;
import static android.hardware.Camera.Parameters.FOCUS_MODE_MACRO;
import static android.hardware.Camera.Parameters.SCENE_MODE_AUTO;
import static android.hardware.Camera.Parameters.SCENE_MODE_BARCODE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
@@ -75,10 +75,23 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
this.camera = camera;
this.previewConsumer = previewConsumer;
setDisplayOrientation(rotationDegrees);
// Use barcode scene mode if it's available
Parameters params = camera.getParameters();
setFocusMode(params);
setPreviewSize(params);
applyParameters(params);
params = setSceneMode(camera, params);
if (SCENE_MODE_BARCODE.equals(params.getSceneMode())) {
// If the scene mode enabled the flash, try to disable it
if (!FLASH_MODE_OFF.equals(params.getFlashMode()))
params = disableFlash(camera, params);
// If the flash is still enabled, disable the scene mode
if (!FLASH_MODE_OFF.equals(params.getFlashMode()))
params = disableSceneMode(camera, params);
}
// Use the best available focus mode, preview size and other options
params = setBestParameters(camera, params);
// Enable auto focus if the selected focus mode uses it
enableAutoFocus(params.getFocusMode());
// Log the parameters that are being used (maybe not what we asked for)
logCameraParameters();
if (surfaceExists) startPreview(getHolder());
}
@@ -145,55 +158,67 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
displayOrientation = orientation;
}
private void setFocusMode(Parameters params) {
private Parameters setSceneMode(Camera camera, Parameters params) {
List<String> sceneModes = params.getSupportedSceneModes();
if (sceneModes == null) return params;
if (LOG.isLoggable(INFO)) LOG.info("Scene modes: " + sceneModes);
if (sceneModes.contains(SCENE_MODE_BARCODE)) {
params.setSceneMode(SCENE_MODE_BARCODE);
camera.setParameters(params);
return camera.getParameters();
}
return params;
}
private Parameters disableFlash(Camera camera, Parameters params) {
params.setFlashMode(FLASH_MODE_OFF);
camera.setParameters(params);
return camera.getParameters();
}
private Parameters disableSceneMode(Camera camera, Parameters params) {
params.setSceneMode(SCENE_MODE_AUTO);
camera.setParameters(params);
return camera.getParameters();
}
private Parameters setBestParameters(Camera camera, Parameters params) {
setVideoStabilisation(params);
setFocusMode(params);
params.setFlashMode(FLASH_MODE_OFF);
setPreviewSize(params);
camera.setParameters(params);
return camera.getParameters();
}
private void setVideoStabilisation(Parameters params) {
if (Build.VERSION.SDK_INT >= 15 &&
params.isVideoStabilizationSupported()) {
LOG.info("Enabling video stabilisation");
params.setVideoStabilization(true);
}
// This returns null on the HTC Wildfire S
List<String> sceneModes = params.getSupportedSceneModes();
if (sceneModes == null) sceneModes = Collections.emptyList();
}
private void setFocusMode(Parameters params) {
List<String> focusModes = params.getSupportedFocusModes();
if (LOG.isLoggable(INFO)) {
LOG.info("Scene modes: " + sceneModes);
LOG.info("Focus modes: " + focusModes);
}
if (sceneModes.contains(SCENE_MODE_BARCODE)) {
LOG.info("Setting scene mode to barcode");
params.setSceneMode(SCENE_MODE_BARCODE);
}
if (LOG.isLoggable(INFO)) LOG.info("Focus modes: " + focusModes);
if (focusModes.contains(FOCUS_MODE_CONTINUOUS_PICTURE)) {
LOG.info("Setting focus mode to continuous picture");
params.setFocusMode(FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (focusModes.contains(FOCUS_MODE_CONTINUOUS_VIDEO)) {
LOG.info("Setting focus mode to continuous video");
params.setFocusMode(FOCUS_MODE_CONTINUOUS_VIDEO);
} else if (focusModes.contains(FOCUS_MODE_EDOF)) {
LOG.info("Setting focus mode to EDOF");
params.setFocusMode(FOCUS_MODE_EDOF);
} else if (focusModes.contains(FOCUS_MODE_MACRO)) {
LOG.info("Setting focus mode to macro");
params.setFocusMode(FOCUS_MODE_MACRO);
autoFocus = true;
} else if (focusModes.contains(FOCUS_MODE_AUTO)) {
LOG.info("Setting focus mode to auto");
params.setFocusMode(FOCUS_MODE_AUTO);
autoFocus = true;
} else if (focusModes.contains(FOCUS_MODE_FIXED)) {
LOG.info("Setting focus mode to fixed");
params.setFocusMode(FOCUS_MODE_FIXED);
} else {
LOG.info("No suitable focus mode");
}
params.setZoom(0);
}
private void setPreviewSize(Parameters params) {
if (surfaceWidth == 0 || surfaceHeight == 0) return;
float idealRatio = (float) surfaceWidth / surfaceHeight;
DisplayMetrics screen = getContext().getResources().getDisplayMetrics();
int screenMax = Math.max(screen.widthPixels, screen.heightPixels);
boolean rotatePreview = displayOrientation % 180 == 90;
List<Size> sizes = params.getSupportedPreviewSizes();
Size bestSize = null;
@@ -204,7 +229,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
float ratio = (float) width / height;
float stretch = Math.max(ratio / idealRatio, idealRatio / ratio);
int pixels = width * height;
float score = width * height / stretch;
float score = pixels / stretch;
if (LOG.isLoggable(INFO)) {
LOG.info("Size " + size.width + "x" + size.height
+ ", stretch " + stretch + ", pixels " + pixels
@@ -222,20 +247,34 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
}
}
private void applyParameters(Parameters params) {
try {
camera.setParameters(params);
} catch (RuntimeException e) {
LOG.log(WARNING, "Error setting camera parameters", e);
private void enableAutoFocus(String focusMode) {
autoFocus = FOCUS_MODE_AUTO.equals(focusMode) ||
FOCUS_MODE_MACRO.equals(focusMode);
}
private void logCameraParameters() {
if (LOG.isLoggable(INFO)) {
Parameters params = camera.getParameters();
if (Build.VERSION.SDK_INT >= 15) {
LOG.info("Video stabilisation enabled: "
+ params.getVideoStabilization());
}
LOG.info("Scene mode: " + params.getSceneMode());
LOG.info("Focus mode: " + params.getFocusMode());
LOG.info("Flash mode: " + params.getFlashMode());
Size size = params.getPreviewSize();
LOG.info("Preview size: " + size.width + "x" + size.height);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
LOG.info("Surface created");
surfaceExists = true;
if (camera != null) startPreview(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (LOG.isLoggable(INFO)) LOG.info("Surface changed: " + w + "x" + h);
surfaceWidth = w;
@@ -245,21 +284,25 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
try {
Parameters params = camera.getParameters();
setPreviewSize(params);
applyParameters(params);
camera.setParameters(params);
logCameraParameters();
} catch (RuntimeException e) {
LOG.log(WARNING, "Error getting camera parameters", e);
LOG.log(WARNING, "Error setting preview size", e);
}
startPreview(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
LOG.info("Surface destroyed");
surfaceExists = false;
}
@Override
public void onAutoFocus(boolean success, final Camera camera) {
LOG.info("Auto focus succeeded: " + success);
postDelayed(new Runnable() {
@Override
public void run() {
retryAutoFocus();
}