diff options
Diffstat (limited to 'src/com/android/camera/WideAnglePanoramaModule.java')
-rw-r--r-- | src/com/android/camera/WideAnglePanoramaModule.java | 148 |
1 files changed, 113 insertions, 35 deletions
diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java index 0aab8f804..364e815ff 100644 --- a/src/com/android/camera/WideAnglePanoramaModule.java +++ b/src/com/android/camera/WideAnglePanoramaModule.java @@ -16,7 +16,6 @@ package com.android.camera; -import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -68,9 +67,10 @@ public class WideAnglePanoramaModule implements CameraModule, WideAnglePanoramaController, SurfaceTexture.OnFrameAvailableListener { - public static final int DEFAULT_SWEEP_ANGLE = 160; + public static final int DEFAULT_SWEEP_ANGLE_PORTRAIT = 160; + public static final int DEFAULT_SWEEP_ANGLE_LANDSCAPE = 270; public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL; - public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720; + public static final int DEFAULT_CAPTURE_PIXELS = 1440 * 1000; private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1; private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 2; @@ -124,15 +124,12 @@ public class WideAnglePanoramaModule private float mHorizontalViewAngle; private float mVerticalViewAngle; - // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of - // getting a better image quality by the former. - private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY; - private PanoOrientationEventListener mOrientationEventListener; // The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise // respectively. private int mDeviceOrientation; private int mDeviceOrientationAtCapture; + private int mOrientationOffset; private int mCameraOrientation; private int mOrientationCompensation; private boolean mOrientationLocked; @@ -197,6 +194,7 @@ public class WideAnglePanoramaModule // the camera then point the camera to floor or sky, we still have // the correct orientation. if (orientation == ORIENTATION_UNKNOWN) return; + orientation = (orientation - mOrientationOffset + 360) % 360; int oldOrientation = mDeviceOrientation; mDeviceOrientation = CameraUtil.roundOrientation(orientation, mDeviceOrientation); // When the screen is unlocked, display rotation may change. Always @@ -230,6 +228,7 @@ public class WideAnglePanoramaModule public void init(CameraActivity activity, View parent) { mActivity = activity; mRootView = parent; + mOrientationOffset = CameraUtil.isDefaultToPortrait(mActivity) ? 0 : 90; mOrientationManager = new OrientationManager(activity); mCaptureState = CAPTURE_STATE_VIEWFINDER; @@ -310,6 +309,9 @@ public class WideAnglePanoramaModule CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal(), activity); mLocationManager = new LocationManager(mActivity, null); + // Power shutter + mActivity.initPowerShutter(mPreferences); + mMainHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -427,7 +429,7 @@ public class WideAnglePanoramaModule int w = size.width; // we only want 4:3 format. int d = DEFAULT_CAPTURE_PIXELS - h * w; - if (needSmaller && d < 0) { // no bigger preview than 960x720. + if (needSmaller && d < 0) { continue; } if (need4To3 && (h * 4 != w * 3)) { @@ -456,6 +458,7 @@ public class WideAnglePanoramaModule Log.d(TAG, "camera preview h = " + mCameraPreviewHeight + " , w = " + mCameraPreviewWidth); parameters.setPreviewSize(mCameraPreviewWidth, mCameraPreviewHeight); + mUI.setPreviewSize(mCameraPreviewWidth, mCameraPreviewHeight); List<int[]> frameRates = parameters.getSupportedPreviewFpsRange(); int last = frameRates.size() - 1; @@ -464,12 +467,13 @@ public class WideAnglePanoramaModule parameters.setPreviewFpsRange(minFps, maxFps); Log.d(TAG, "preview fps: " + minFps + ", " + maxFps); + // use CAF for viewfinder until starting the real mosaic, then lock List<String> supportedFocusModes = parameters.getSupportedFocusModes(); - if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) { - parameters.setFocusMode(mTargetFocusMode); + if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) >= 0) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else { // Use the default focus mode and log a message - Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode + + Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_CONTINUOUS_PICTURE + " becuase the mode is not supported."); } @@ -567,15 +571,28 @@ public class WideAnglePanoramaModule public void startCapture() { // Reset values so we can do this again. + + Parameters parameters = mCameraDevice.getParameters(); + List<String> supportedFocusModes = parameters.getSupportedFocusModes(); + if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_FIXED) >= 0) { + parameters.setFocusMode(Parameters.FOCUS_MODE_FIXED); + } else { + // Use the default focus mode and log a message + Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_FIXED + + " becuase the mode is not supported."); + } + parameters.setAutoExposureLock(true); + parameters.setAutoWhiteBalanceLock(true); + configureCamera(parameters); + mCancelComputation = false; mTimeTaken = System.currentTimeMillis(); mActivity.setSwipingEnabled(false); mCaptureState = CAPTURE_STATE_MOSAIC; mUI.onStartCapture(); - Parameters parameters = mCameraDevice.getParameters(); - parameters.setAutoExposureLock(true); - parameters.setAutoWhiteBalanceLock(true); - configureCamera(parameters); + + final int sweepAngle = (mDeviceOrientation == 90 || mDeviceOrientation == 270) ? + DEFAULT_SWEEP_ANGLE_LANDSCAPE : DEFAULT_SWEEP_ANGLE_PORTRAIT; mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() { @Override @@ -585,8 +602,8 @@ public class WideAnglePanoramaModule float accumulatedVerticalAngle = progressY * mVerticalViewAngle; boolean isRotated = !(mDeviceOrientationAtCapture == mDeviceOrientation); if (isFinished - || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE) - || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE) + || (Math.abs(accumulatedHorizontalAngle) >= sweepAngle) + || (Math.abs(accumulatedVerticalAngle) >= sweepAngle) || isRotated) { stopCapture(false); } else { @@ -606,7 +623,7 @@ public class WideAnglePanoramaModule mUI.resetCaptureProgress(); // TODO: calculate the indicator width according to different devices to reflect the actual // angle of view of the camera device. - mUI.setMaxCaptureProgress(DEFAULT_SWEEP_ANGLE); + mUI.setMaxCaptureProgress(sweepAngle); mUI.showCaptureProgress(); mDeviceOrientationAtCapture = mDeviceOrientation; keepScreenOn(); @@ -624,6 +641,14 @@ public class WideAnglePanoramaModule Parameters parameters = mCameraDevice.getParameters(); parameters.setAutoExposureLock(false); parameters.setAutoWhiteBalanceLock(false); + List<String> supportedFocusModes = parameters.getSupportedFocusModes(); + if (supportedFocusModes.indexOf(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) >= 0) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } else { + // Use the default focus mode and log a message + Log.w(TAG, "Cannot set the focus mode to " + Parameters.FOCUS_MODE_CONTINUOUS_PICTURE + + " becuase the mode is not supported."); + } configureCamera(parameters); mMosaicFrameProcessor.setProgressListener(null); @@ -701,13 +726,21 @@ public class WideAnglePanoramaModule } catch (InterruptedException e) { throw new RuntimeException("Panorama reportProgress failed", e); } - // Update the progress bar - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - mUI.updateSavingProgress(progress); - } - }); + // Update the progress bar if we haven't paused. In the case where + // we pause the UI, then launch the camera from the lockscreen with + // this thread still running, a new WideAnglePanoramaModule is + // created, but this thread is left running to finish the task (and + // mPaused continues to be true for that instance. + if (!mPaused) { + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + if (!mPaused) { + mUI.updateSavingProgress(progress); + } + } + }); + } } } }; @@ -725,9 +758,11 @@ public class WideAnglePanoramaModule if (mUsingFrontCamera) { // mCameraOrientation is negative with respect to the front facing camera. // See document of android.hardware.Camera.Parameters.setRotation. - orientation = (mDeviceOrientationAtCapture - mCameraOrientation - 360) % 360; + orientation = (mDeviceOrientationAtCapture - mCameraOrientation - + mOrientationOffset + 360) % 360; } else { - orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360; + orientation = (mDeviceOrientationAtCapture + mCameraOrientation + + mOrientationOffset) % 360; } return orientation; } @@ -882,12 +917,7 @@ public class WideAnglePanoramaModule return; } - int perct = 100; - final ActivityManager am = (ActivityManager) - mActivity.getSystemService(Context.ACTIVITY_SERVICE); - if (am.isLowRamDevice()) { - perct = mActivity.getResources().getInteger(R.integer.panorama_frame_size_reduction); - } + int perct = mActivity.getResources().getInteger(R.integer.panorama_frame_size_reduction); int width = (mCameraPreviewWidth * perct) / 100; int height = (mCameraPreviewHeight * perct) / 100; @@ -943,6 +973,10 @@ public class WideAnglePanoramaModule } mUI.showPreviewCover(); releaseCamera(); + + // Load the power shutter + mActivity.initPowerShutter(mPreferences); + synchronized (mRendererLock) { mCameraTexture = null; @@ -1139,6 +1173,13 @@ public class WideAnglePanoramaModule mCameraTexture.setOnFrameAvailableListener(this); mCameraDevice.setPreviewTexture(mCameraTexture); } + mCameraDevice.setOneShotPreviewCallback(mMainHandler, + new CameraManager.CameraPreviewDataCallback() { + @Override + public void onPreviewFrame(byte[] data, CameraProxy camera) { + mUI.hidePreviewCover(); + } + }); mCameraDevice.startPreview(); mCameraState = PREVIEW_ACTIVE; } @@ -1216,7 +1257,7 @@ public class WideAnglePanoramaModule @Override public void cancelHighResStitching() { - if (mPaused || mCameraTexture == null) return; + if (mPaused) return; cancelHighResComputation(); } @@ -1235,14 +1276,51 @@ public class WideAnglePanoramaModule public void onActivityResult(int requestCode, int resultCode, Intent data) { } - @Override public boolean onKeyDown(int keyCode, KeyEvent event) { + // Do not handle any key if the activity is paused + // or not in active camera/video mode + if (mPaused) { + return true; + } else if (!mActivity.isInCameraApp()) { + return false; + } + + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + return true; + case KeyEvent.KEYCODE_CAMERA: + case KeyEvent.KEYCODE_HEADSETHOOK: + if (event.getRepeatCount() == 0) { + onShutterButtonClick(); + } + return true; + case KeyEvent.KEYCODE_POWER: + return true; + } return false; } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + if (!CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) { + onShutterButtonClick(); + } + return true; + case KeyEvent.KEYCODE_POWER: + if (CameraActivity.mPowerShutter && !CameraUtil.hasCameraKey()) { + onShutterButtonClick(); + } + return true; + } return false; } |