diff --git a/briar-android/src/org/briarproject/android/view/CameraView.java b/briar-android/src/org/briarproject/android/view/CameraView.java index 0ce1ad13627837ac2a3bda936a99ff8bc3eb16b0..f0b3d6a7a8769de3c6e5af231c18391629c7ceef 100644 --- a/briar-android/src/org/briarproject/android/view/CameraView.java +++ b/briar-android/src/org/briarproject/android/view/CameraView.java @@ -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(); }