From 0095c4455f5bba6352abe0476948ef99b42a0c96 Mon Sep 17 00:00:00 2001 From: Byunghun Jeon Date: Wed, 9 Mar 2016 15:14:18 -0800 Subject: SnapdragonCamera: Camera2 add zoom support Add zoom support to Camera2 CRs-Fixed: 989750 Change-Id: Id6b558ff5215f04ca7c201b1d1807521d615c353 --- src/com/android/camera/CaptureModule.java | 74 +++++++++++++++++++++++++---- src/com/android/camera/CaptureUI.java | 44 ++++++++++------- src/com/android/camera/PhotoController.java | 2 + src/com/android/camera/PhotoModule.java | 5 ++ src/com/android/camera/PhotoUI.java | 5 ++ src/com/android/camera/VideoUI.java | 5 ++ src/com/android/camera/ui/ZoomRenderer.java | 31 +++++++++++- src/com/android/camera/util/CameraUtil.java | 12 +++++ 8 files changed, 150 insertions(+), 28 deletions(-) diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index 699f66121..7362a6582 100644 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -63,6 +63,7 @@ import com.android.camera.util.CameraUtil; import org.codeaurora.snapcam.R; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -133,6 +134,9 @@ public class CaptureModule implements CameraModule, PhotoController, private CameraActivity mActivity; private PreferenceGroup mPreferenceGroup; private ComboPreferences mPreferences; + private CameraCharacteristics[] mCharacteristics = new CameraCharacteristics[MAX_NUM_CAM]; + private List mCharacteristicsIndex; + private float mZoomValue = 1f; private LocationManager mLocationManager; /** @@ -346,7 +350,8 @@ public class CaptureModule implements CameraModule, PhotoController, mActivity.runOnUiThread(new Runnable() { @Override public void run() { - mUI.onCameraOpened(mPreferenceGroup, prefListener); + mUI.onCameraOpened(mCharacteristics, mCharacteristicsIndex, + mPreferenceGroup, prefListener); } }); } @@ -596,6 +601,7 @@ public class CaptureModule implements CameraModule, PhotoController, builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); applyWhiteBalance(builder); + applyZoom(builder, id); mState[id] = STATE_WAITING_LOCK; mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler); } catch (CameraAccessException e) { @@ -622,7 +628,7 @@ public class CaptureModule implements CameraModule, PhotoController, captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest .CONTROL_AF_TRIGGER_IDLE); - applyCaptureSettings(captureBuilder); + applyCaptureSettings(captureBuilder, id); // Orientation int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); @@ -670,6 +676,7 @@ public class CaptureModule implements CameraModule, PhotoController, // Applying flash only to capture does not work. Need to apply flash here. applyFlash(builder); applyWhiteBalance(builder); + applyZoom(builder, id); mState[id] = STATE_WAITING_PRECAPTURE; mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler); } catch (CameraAccessException e) { @@ -684,8 +691,7 @@ public class CaptureModule implements CameraModule, PhotoController, * @param height The height of available size for camera preview */ private void setUpCameraOutputs() { - Activity activity = mActivity; - CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE); + CameraManager manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE); try { String[] cameraIdList = manager.getCameraIdList(); @@ -693,7 +699,8 @@ public class CaptureModule implements CameraModule, PhotoController, String cameraId = cameraIdList[i]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); - + mCharacteristics[i] = characteristics; + mCharacteristicsIndex.add(i); StreamConfigurationMap map = characteristics.get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); if (map == null) { @@ -737,6 +744,7 @@ public class CaptureModule implements CameraModule, PhotoController, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL); //Todo: Create applyCommonSettings function for settings applied everytime applyWhiteBalance(builder); + applyZoom(builder, id); mCaptureSession[id].capture(builder.build(), mCaptureCallback, mCameraHandler); mState[id] = STATE_PREVIEW; mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(), @@ -848,7 +856,7 @@ public class CaptureModule implements CameraModule, PhotoController, @Override public void onPreviewFocusChanged(boolean previewFocused) { - + mUI.onPreviewFocusChanged(previewFocused); } @Override @@ -874,6 +882,7 @@ public class CaptureModule implements CameraModule, PhotoController, @Override public void onResumeAfterSuper() { Log.d(TAG, "onResume " + MODE); + mCharacteristicsIndex = new ArrayList<>(); setUpCameraOutputs(); readInitialValues(); startBackgroundThread(); @@ -922,7 +931,7 @@ public class CaptureModule implements CameraModule, PhotoController, @Override public boolean onBackPressed() { - return false; + return mUI.onBackPressed(); } @Override @@ -940,6 +949,24 @@ public class CaptureModule implements CameraModule, PhotoController, return 0; } + @Override + public void onZoomChanged(float requestedZoom) { + mZoomValue = requestedZoom; + + switch (MODE) { + case DUAL_MODE: + applyZoomAndUpdate(BAYER_ID); + applyZoomAndUpdate(MONO_ID); + break; + case BAYER_MODE: + applyZoomAndUpdate(BAYER_ID); + break; + case MONO_MODE: + applyZoomAndUpdate(MONO_ID); + break; + } + } + @Override public boolean isImageCaptureIntent() { return false; @@ -947,7 +974,7 @@ public class CaptureModule implements CameraModule, PhotoController, @Override public boolean isCameraIdle() { - return false; + return true; } @Override @@ -1144,6 +1171,7 @@ public class CaptureModule implements CameraModule, PhotoController, mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest .FLASH_MODE_OFF); applyWhiteBalance(mPreviewRequestBuilder[id]); + applyZoom(mPreviewRequestBuilder[id], id); } private void readInitialValues() { @@ -1156,10 +1184,28 @@ public class CaptureModule implements CameraModule, PhotoController, } } - private void applyCaptureSettings(CaptureRequest.Builder request) { + public Rect cropRegionForZoom(int id) { + Rect activeRegion = mCharacteristics[id].get(CameraCharacteristics + .SENSOR_INFO_ACTIVE_ARRAY_SIZE); + Rect cropRegion = new Rect(); + + int xCenter = activeRegion.width() / 2; + int yCenter = activeRegion.height() / 2; + int xDelta = (int) (activeRegion.width() / (2 * mZoomValue)); + int yDelta = (int) (activeRegion.height() / (2 * mZoomValue)); + cropRegion.set(xCenter - xDelta, yCenter - yDelta, xCenter + xDelta, yCenter + yDelta); + return cropRegion; + } + + private void applyZoom(CaptureRequest.Builder request, int id) { + request.set(CaptureRequest.SCALER_CROP_REGION, cropRegionForZoom(id)); + } + + private void applyCaptureSettings(CaptureRequest.Builder request, int id) { applyFlash(request); applyWhiteBalance(request); applyJpegQuality(request); + applyZoom(request, id); } private void applyPreference(int cameraId, ListPreference pref) { @@ -1187,6 +1233,16 @@ public class CaptureModule implements CameraModule, PhotoController, } } + private void applyZoomAndUpdate(int id) { + applyZoom(mPreviewRequestBuilder[id], id); + try { + mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] + .build(), mCaptureCallback, mCameraHandler); + } catch (CameraAccessException e) { + e.printStackTrace(); + } + } + private void storeSetting(String key, String value) { mSettings.put(key, value); } diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java index ed1020732..01b66fb70 100644 --- a/src/com/android/camera/CaptureUI.java +++ b/src/com/android/camera/CaptureUI.java @@ -24,8 +24,8 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; -import android.hardware.Camera; import android.hardware.Camera.Face; +import android.hardware.camera2.CameraCharacteristics; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; @@ -111,8 +111,6 @@ public class CaptureUI implements PieListener, private OnScreenIndicators mOnScreenIndicators; private PieRenderer mPieRenderer; private ZoomRenderer mZoomRenderer; - private int mZoomMax; - private List mZoomRatios; private int mPreviewWidth = 0; private int mPreviewHeight = 0; private int mOriginalPreviewWidth = 0; @@ -280,7 +278,9 @@ public class CaptureUI implements PieListener, mRootView.findViewById(R.id.on_screen_indicators)); } - public void onCameraOpened(PreferenceGroup prefGroup, OnPreferenceChangedListener listener) { + public void onCameraOpened(CameraCharacteristics[] characteristics, + List characteristicsIndex, PreferenceGroup prefGroup, + OnPreferenceChangedListener listener) { if (mMenu == null) { mMenu = new CaptureMenu(mActivity, this); mMenu.setListener(listener); @@ -300,8 +300,11 @@ public class CaptureUI implements PieListener, } mGestures.setCaptureMenu(mMenu); + mGestures.setZoomEnabled(CameraUtil.isZoomSupported(characteristics, characteristicsIndex)); mGestures.setRenderOverlay(mRenderOverlay); mRenderOverlay.requestLayout(); + + initializeZoom(characteristics, characteristicsIndex); mActivity.setPreviewGestures(mGestures); } @@ -364,17 +367,19 @@ public class CaptureUI implements PieListener, frameAnimation.start(); } - public void initializeZoom(Camera.Parameters params) { - if ((params == null) || !params.isZoomSupported() - || (mZoomRenderer == null)) return; - mZoomMax = params.getMaxZoom(); - mZoomRatios = params.getZoomRatios(); - // Currently we use immediate zoom for fast zooming to get better UX and - // there is no plan to take advantage of the smooth zoom. + public void initializeZoom(CameraCharacteristics[] characteristics, + List characteristicsIndex) { + if ((characteristics == null) || !CameraUtil.isZoomSupported(characteristics, + characteristicsIndex) || (mZoomRenderer == null)) + return; if (mZoomRenderer != null) { - mZoomRenderer.setZoomMax(mZoomMax); - mZoomRenderer.setZoom(params.getZoom()); - mZoomRenderer.setZoomValue(mZoomRatios.get(params.getZoom())); + float zoomMax = Float.MAX_VALUE; + for (int i = 0; i < characteristicsIndex.size(); i++) { + zoomMax = Math.min(characteristics[characteristicsIndex.get(i)].get + (CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM), zoomMax); + } + mZoomRenderer.setZoomMax(zoomMax); + mZoomRenderer.setZoom(1f); mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener()); } } @@ -781,10 +786,10 @@ public class CaptureUI implements PieListener, private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener { @Override - public void onZoomValueChanged(int index) { - int newZoom = mController.onZoomChanged(index); + public void onZoomValueChanged(float mZoomValue) { + mController.onZoomChanged(mZoomValue); if (mZoomRenderer != null) { - mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom)); + mZoomRenderer.setZoom(mZoomValue); } } @@ -802,6 +807,11 @@ public class CaptureUI implements PieListener, mPieRenderer.setBlockFocus(false); } } + + @Override + public void onZoomValueChanged(int index) { + + } } } diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java index b08f8c088..887f0d375 100644 --- a/src/com/android/camera/PhotoController.java +++ b/src/com/android/camera/PhotoController.java @@ -37,6 +37,8 @@ public interface PhotoController extends OnShutterButtonListener { // returns the actual set zoom value public int onZoomChanged(int requestedZoom); + public void onZoomChanged(float requestedZoom); + public boolean isImageCaptureIntent(); public boolean isCameraIdle(); diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 589f55152..d7f38a156 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -4656,6 +4656,11 @@ public class PhotoModule return index; } + @Override + public void onZoomChanged(float requestedZoom) { + + } + @Override public int getCameraState() { return mCameraState; diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 7e3659f0f..02d8f7183 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -1148,6 +1148,11 @@ public class PhotoUI implements PieListener, mPieRenderer.setBlockFocus(false); } } + + @Override + public void onZoomValueChanged(float value) { + + } } @Override diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 9a882e946..f67480e55 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -1108,6 +1108,11 @@ public class VideoUI implements PieRenderer.PieListener, mPieRenderer.setBlockFocus(false); } } + + @Override + public void onZoomValueChanged(float value) { + + } } // SurfaceHolder callbacks diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java index 7a2e2e805..0358bda7a 100644 --- a/src/com/android/camera/ui/ZoomRenderer.java +++ b/src/com/android/camera/ui/ZoomRenderer.java @@ -49,11 +49,16 @@ public class ZoomRenderer extends OverlayRenderer private int mZoomFraction; private Rect mTextBounds; private int mOrientation; + private boolean mCamera2 = false; + private float mZoomValue; + private float mZoomMinValue; + private float mZoomMaxValue; public interface OnZoomChangedListener { void onZoomStart(); void onZoomEnd(); void onZoomValueChanged(int index); // only for immediate zoom + void onZoomValueChanged(float value); } public ZoomRenderer(Context ctx) { @@ -81,10 +86,23 @@ public class ZoomRenderer extends OverlayRenderer mMinZoom = 0; } + public void setZoomMax(float zoomMax) { + mCamera2 = true; + mZoomMaxValue = zoomMax; + mZoomMinValue = 1f; + } + public void setZoom(int index) { mCircleSize = mMinCircle + index * (mMaxCircle - mMinCircle) / (mMaxZoom - mMinZoom); } + public void setZoom(float zoomValue) { + mCamera2 = true; + mZoomValue = zoomValue; + mCircleSize = (int) (mMinCircle + (mMaxCircle - mMinCircle) * (mZoomValue - mZoomMinValue) / + (mZoomMaxValue - mZoomMinValue)); + } + public void setZoomValue(int value) { value = value / 10; mZoomSig = value / 10; @@ -120,6 +138,7 @@ public class ZoomRenderer extends OverlayRenderer canvas.drawCircle((float) mCenterX, (float) mCenterY, mCircleSize, mPaint); String txt = mZoomSig+"."+mZoomFraction+"x"; + if (mCamera2) txt = "" + mZoomValue; mTextPaint.getTextBounds(txt, 0, txt.length(), mTextBounds); canvas.drawText(txt, mCenterX - mTextBounds.centerX(), mCenterY - mTextBounds.centerY(), mTextPaint); @@ -133,8 +152,16 @@ public class ZoomRenderer extends OverlayRenderer circle = Math.min(mMaxCircle, circle); if (mListener != null && circle != mCircleSize) { mCircleSize = circle; - int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle)); - mListener.onZoomValueChanged(zoom); + if (mCamera2) { + float zoom = mZoomMinValue + (mZoomMaxValue - mZoomMinValue) / (mMaxCircle - + mMinCircle) * (mCircleSize - mMinCircle); + zoom = ((int) (zoom * 10)) / 10.0f; + mListener.onZoomValueChanged(zoom); + } else { + int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / + (mMaxCircle - mMinCircle)); + mListener.onZoomValueChanged(zoom); + } update(); } return true; diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java index 812220c1a..be66091e2 100644 --- a/src/com/android/camera/util/CameraUtil.java +++ b/src/com/android/camera/util/CameraUtil.java @@ -35,6 +35,7 @@ import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; +import android.hardware.camera2.CameraCharacteristics; import android.location.Location; import android.net.Uri; import android.os.Handler; @@ -1168,4 +1169,15 @@ public class CameraUtil { return retRatio; } + public static boolean isZoomSupported(CameraCharacteristics[] characteristics, List + characteristicsIndex) { + boolean supported = true; + + for (int i = 0; i < characteristicsIndex.size(); i++) { + if (characteristics[characteristicsIndex.get(i)].get(CameraCharacteristics + .SCALER_AVAILABLE_MAX_DIGITAL_ZOOM) <= 1f) + return false; + } + return supported; + } } -- cgit v1.2.3