PanoramaActivity.java revision 0cefcea01849364be6955a1b3f7e7d1639010abc
1bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen/* 2bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Copyright (C) 2011 The Android Open Source Project 3bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 4bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 5bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * you may not use this file except in compliance with the License. 6bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * You may obtain a copy of the License at 7bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 8bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 9bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 10bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Unless required by applicable law or agreed to in writing, software 11bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 12bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * See the License for the specific language governing permissions and 14bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * limitations under the License. 15bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen */ 16bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 17bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenpackage com.android.camera.panorama; 18bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 195f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wangimport com.android.camera.ActivityBase; 20d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraDisabledException; 21d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHardwareException; 22d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHolder; 23a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.Exif; 24d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.MenuHelper; 25d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.ModePicker; 26a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.OnClickAttr; 27d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.R; 28ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kongimport com.android.camera.RotateDialogController; 29fcdf619d92701052621a96572d956d047e07cf24Angus Kongimport com.android.camera.ShutterButton; 30d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Storage; 31a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.Thumbnail; 32d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Util; 33d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport com.android.camera.ui.Rotatable; 34a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.ui.RotateImageView; 35d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport com.android.camera.ui.RotateLayout; 36a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.ui.SharePopup; 37d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Li 389a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagnerimport android.content.ContentResolver; 39bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.content.Context; 40174b8b7fc4d55e8c63eb3ed0b71f1519a13e345dAngus Kongimport android.content.res.AssetFileDescriptor; 41d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport android.content.pm.ActivityInfo; 42057040c0e19834d98719143c2627a9f0df3e4c35Angus Kongimport android.content.res.Resources; 43142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.Bitmap; 44142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.BitmapFactory; 458a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.ImageFormat; 46bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.graphics.PixelFormat; 478a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.Rect; 4841a2e9735136f372de95652d0828600282c8e967mbansalimport android.graphics.SurfaceTexture; 498a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.YuvImage; 506f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kongimport android.hardware.Camera.Parameters; 516f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kongimport android.hardware.Camera.Size; 52d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvalaimport android.hardware.Camera.Sound; 53bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.Sensor; 54bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.SensorManager; 55e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chenimport android.media.ExifInterface; 56a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport android.net.Uri; 57bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.os.Bundle; 588a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.os.Handler; 59ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport android.os.Message; 60174b8b7fc4d55e8c63eb3ed0b71f1519a13e345dAngus Kongimport android.os.ParcelFileDescriptor; 61bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.util.Log; 62a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport android.view.Gravity; 63c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kongimport android.view.Menu; 64c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kongimport android.view.OrientationEventListener; 65bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.View; 66d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport android.view.ViewGroup; 67a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chenimport android.view.Window; 68bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.WindowManager; 69bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.widget.ImageView; 70fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kongimport android.widget.TextView; 71bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 72ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport java.io.ByteArrayOutputStream; 739a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagnerimport java.io.File; 74e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chenimport java.io.IOException; 75bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport java.util.List; 76bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 77a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong/** 78a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong * Activity to handle panorama capturing. 79a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong */ 805f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wangpublic class PanoramaActivity extends ActivityBase implements 81fcdf619d92701052621a96572d956d047e07cf24Angus Kong ModePicker.OnModeChangeListener, SurfaceTexture.OnFrameAvailableListener, 82fcdf619d92701052621a96572d956d047e07cf24Angus Kong ShutterButton.OnShutterButtonListener, 8336839102e03107e3fb121197036365a58ec2686eAngus Kong MosaicRendererSurfaceViewRenderer.MosaicSurfaceCreateListener { 84ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong public static final int DEFAULT_SWEEP_ANGLE = 160; 85bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL; 86bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720; 87bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 882f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1; 89a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private static final int MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL = 2; 9022d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 3; 9159a140990af1ba6d2c9aa627047a02e50c8dd0e1Angus Kong private static final int MSG_RESET_TO_PREVIEW = 4; 92bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private static final int MSG_CLEAR_SCREEN_DELAY = 5; 93bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 94bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private static final int SCREEN_DELAY = 2 * 60 * 1000; 9594f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen 96ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private static final String TAG = "PanoramaActivity"; 9798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_STOPPED = 0; 9898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_ACTIVE = 1; 99a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong private static final int CAPTURE_STATE_VIEWFINDER = 0; 100a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong private static final int CAPTURE_STATE_MOSAIC = 1; 10141a2e9735136f372de95652d0828600282c8e967mbansal 10243b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Speed is in unit of deg/sec 103e47b5624a1aa3cc7bd9763852bed4ac3215a77b2Wei-Ta Chen private static final float PANNING_SPEED_THRESHOLD = 20f; 10443b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 105a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong // Ratio of nanosecond to second 106a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private static final float NS2S = 1.0f / 1000000000.0f; 107142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 108142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mPausing; 109142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 1107648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li private View mPanoLayout; 111a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mCaptureLayout; 112a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mReviewLayout; 113bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private ImageView mReview; 114d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private RotateLayout mCaptureIndicator; 115057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong private PanoProgressBar mPanoProgressBar; 116215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private PanoProgressBar mSavingProgressBar; 1178b0e23544474480345937c0c0985429f61569761Angus Kong private View mFastIndicationBorder; 1186108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private View mLeftIndicator; 1196108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private View mRightIndicator; 1202faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private MosaicRendererSurfaceView mMosaicView; 121fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong private TextView mTooFastPrompt; 122fcdf619d92701052621a96572d956d047e07cf24Angus Kong private ShutterButton mShutterButton; 123215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private Object mWaitObject = new Object(); 124142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 1255fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private String mPreparePreviewString; 12622d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong private String mDialogTitle; 127d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private String mDialogOkString; 128d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private String mDialogPanoramaFailedString; 1292f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong 130fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong private int mIndicatorColor; 131fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong private int mIndicatorColorFast; 132fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong 133c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueX; 134c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueY; 135c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueXStart; 136c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueYStart; 137c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueXStartBuffer; 138c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueYStartBuffer; 139c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mCompassThreshold; 140c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mTraversedAngleX; 141c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mTraversedAngleY; 142c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private long mTimestamp; 143c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 144a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private RotateImageView mThumbnailView; 145a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private Thumbnail mThumbnail; 146a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private SharePopup mSharePopup; 147a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 148bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewWidth; 149bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewHeight; 15098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private int mCameraState; 15141a2e9735136f372de95652d0828600282c8e967mbansal private int mCaptureState; 152bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private SensorManager mSensorManager; 153bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private Sensor mSensor; 154a72d73cbac59db43d413291e4db66763be08143arepo sync private ModePicker mModePicker; 1558a2c41754655a3733175fce81fb7506ff7022959Angus Kong private MosaicFrameProcessor mMosaicFrameProcessor; 1568a2c41754655a3733175fce81fb7506ff7022959Angus Kong private long mTimeTaken; 157ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private Handler mMainHandler; 1582faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private SurfaceTexture mSurfaceTexture; 159142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mThreadRunning; 160e1178a73fd5756771d25d0b8375452450f509e99mbansal private boolean mCancelComputation; 1612faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private float[] mTransformMatrix; 16243b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private float mHorizontalViewAngle; 1632d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen private float mVerticalViewAngle; 164c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 165d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of 166d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // getting a better image quality by the former. 167d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY; 168d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen 169c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private PanoOrientationEventListener mOrientationEventListener; 17022400adc90877480c3229d0ee86df9a6736c66cdAngus Kong // The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise 171c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong // respectively. 172c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mDeviceOrientation; 173e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private int mDeviceOrientationAtCapture; 174e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private int mCameraOrientation; 1755201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner private int mOrientationCompensation; 176142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 177ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong private RotateDialogController mRotateDialog; 178ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong 1797648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li private class MosaicJpeg { 1807648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public MosaicJpeg(byte[] data, int width, int height) { 1817648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.data = data; 1827648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.width = width; 1837648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.height = height; 18413e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.isValid = true; 18513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } 18613e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong 18713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong public MosaicJpeg() { 18813e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.data = null; 18913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.width = 0; 19013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.height = 0; 19113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.isValid = false; 1927648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li } 1937648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 1947648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final byte[] data; 1957648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final int width; 1967648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final int height; 19713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong public final boolean isValid; 1987648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li } 1997648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 200c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private class PanoOrientationEventListener extends OrientationEventListener { 201c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong public PanoOrientationEventListener(Context context) { 202c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong super(context); 203c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 204c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 205c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong @Override 206c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong public void onOrientationChanged(int orientation) { 2075201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // We keep the last known orientation. So if the user first orient 2085201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // the camera then point the camera to floor or sky, we still have 2095201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // the correct orientation. 210c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong if (orientation == ORIENTATION_UNKNOWN) return; 211131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala mDeviceOrientation = Util.roundOrientation(orientation, mDeviceOrientation); 2125201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // When the screen is unlocked, display rotation may change. Always 2135201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // calculate the up-to-date orientationCompensation. 2145201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner int orientationCompensation = mDeviceOrientation 2155201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner + Util.getDisplayRotation(PanoramaActivity.this); 2165201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner if (mOrientationCompensation != orientationCompensation) { 2175201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mOrientationCompensation = orientationCompensation; 2185201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner setOrientationIndicator(mOrientationCompensation); 2195201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner } 220c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 221c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 222c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 2235201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner private void setOrientationIndicator(int degree) { 2245201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner if (mSharePopup != null) mSharePopup.setOrientation(degree); 2255201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner } 2265201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 227bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 228c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public boolean onCreateOptionsMenu(Menu menu) { 229c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong super.onCreateOptionsMenu(menu); 230c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 231c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong addBaseMenuItems(menu); 232c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong return true; 233c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 234c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 235c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong private void addBaseMenuItems(Menu menu) { 236c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong MenuHelper.addSwitchModeMenuItem(menu, ModePicker.MODE_CAMERA, new Runnable() { 237c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public void run() { 238c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong switchToOtherMode(ModePicker.MODE_CAMERA); 239c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 240c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong }); 241c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong MenuHelper.addSwitchModeMenuItem(menu, ModePicker.MODE_VIDEO, new Runnable() { 242c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public void run() { 243c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong switchToOtherMode(ModePicker.MODE_VIDEO); 244c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 245c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong }); 246c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 247c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 248c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong @Override 249bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public void onCreate(Bundle icicle) { 250bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onCreate(icicle); 251bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 252a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Window window = getWindow(); 253a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Util.enterLightsOutMode(window); 254a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Util.initializeScreenBrightness(window, getContentResolver()); 255bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 256bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen createContentView(); 257bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 258bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 259bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 260bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (mSensor == null) { 261bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); 262bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 2638a2c41754655a3733175fce81fb7506ff7022959Angus Kong 264c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener = new PanoOrientationEventListener(this); 265c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 2662faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mTransformMatrix = new float[16]; 2672faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong 2685fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mPreparePreviewString = 2695fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong getResources().getString(R.string.pano_dialog_prepare_preview); 27022d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong mDialogTitle = getResources().getString(R.string.pano_dialog_title); 271d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mDialogOkString = getResources().getString(R.string.dialog_ok); 272d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mDialogPanoramaFailedString = 273d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang getResources().getString(R.string.pano_dialog_panorama_failed); 2745fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 275ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mMainHandler = new Handler() { 276ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong @Override 277ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong public void handleMessage(Message msg) { 278ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong switch (msg.what) { 2792f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong case MSG_LOW_RES_FINAL_MOSAIC_READY: 2805fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 281142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong showFinalMosaic((Bitmap) msg.obj); 282215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong saveHighResMosaic(); 283142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 284a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong case MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL: 2855fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 286a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // Set the thumbnail bitmap here because mThumbnailView must be accessed 287a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // from the UI thread. 2889a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner updateThumbnailButton(); 2899a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner 290db288b8686e5bcecef620176b934b00eb0742597Wu-cheng Li // Share popup may still have the reference to the old thumbnail. Clear it. 291db288b8686e5bcecef620176b934b00eb0742597Wu-cheng Li mSharePopup = null; 292142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong resetToPreview(); 293142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 29422d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong case MSG_GENERATE_FINAL_MOSAIC_ERROR: 29522d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong onBackgroundThreadFinished(); 2963eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong if (mPausing) { 2973eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong resetToPreview(); 2983eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong } else { 299ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.showAlertDialog( 300ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mDialogTitle, mDialogPanoramaFailedString, 301ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mDialogOkString, new Runnable() { 302ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong @Override 303ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong public void run() { 304ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong resetToPreview(); 305ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong }}, 306ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong null, null); 3073eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong } 30822d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong break; 30913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong case MSG_RESET_TO_PREVIEW: 310e1178a73fd5756771d25d0b8375452450f509e99mbansal onBackgroundThreadFinished(); 311e1178a73fd5756771d25d0b8375452450f509e99mbansal resetToPreview(); 312bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang break; 313bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang case MSG_CLEAR_SCREEN_DELAY: 314bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().clearFlags(WindowManager.LayoutParams. 315bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang FLAG_KEEP_SCREEN_ON); 316bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang break; 317ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 318142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 319ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 320ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong }; 321d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 32259a140990af1ba6d2c9aa627047a02e50c8dd0e1Angus Kong 323bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void setupCamera() { 324bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen openCamera(); 325bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Parameters parameters = mCameraDevice.getParameters(); 326bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setupCaptureParams(parameters); 327bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen configureCamera(parameters); 328bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 329bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 330ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private void releaseCamera() { 331ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong if (mCameraDevice != null) { 332142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mCameraDevice.setPreviewCallbackWithBuffer(null); 333ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong CameraHolder.instance().release(); 334ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mCameraDevice = null; 33598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 336ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 337ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 338ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong 339bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void openCamera() { 340bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen try { 341e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen int backCameraId = CameraHolder.instance().getBackCameraId(); 342e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen mCameraDevice = Util.openCamera(this, backCameraId); 343e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen mCameraOrientation = Util.getCameraOrientation(backCameraId); 344bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } catch (CameraHardwareException e) { 345bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Util.showErrorAndFinish(this, R.string.cannot_connect_camera); 346bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return; 347bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } catch (CameraDisabledException e) { 348bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Util.showErrorAndFinish(this, R.string.camera_disabled); 349bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return; 350bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 351bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 352bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 353bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private boolean findBestPreviewSize(List<Size> supportedSizes, boolean need4To3, 354bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean needSmaller) { 355bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int pixelsDiff = DEFAULT_CAPTURE_PIXELS; 356bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean hasFound = false; 3578a2c41754655a3733175fce81fb7506ff7022959Angus Kong for (Size size : supportedSizes) { 358bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int h = size.height; 359bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int w = size.width; 360bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // we only want 4:3 format. 361bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int d = DEFAULT_CAPTURE_PIXELS - h * w; 36294f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen if (needSmaller && d < 0) { // no bigger preview than 960x720. 363bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 364bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 365bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (need4To3 && (h * 4 != w * 3)) { 366bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 367bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 368bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen d = Math.abs(d); 369bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (d < pixelsDiff) { 370bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewWidth = w; 371bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewHeight = h; 372bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen pixelsDiff = d; 373bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen hasFound = true; 374bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 375bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 376bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return hasFound; 377bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 378bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 379bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void setupCaptureParams(Parameters parameters) { 380bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<Size> supportedSizes = parameters.getSupportedPreviewSizes(); 381bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, true, true)) { 382bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "No 4:3 ratio preview size supported."); 383bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, false, true)) { 384bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "Can't find a supported preview size smaller than 960x720."); 385bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen findBestPreviewSize(supportedSizes, false, false); 386bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 387bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 388bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview h = " + mPreviewHeight + " , w = " + mPreviewWidth); 389bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); 390bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 391bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<int[]> frameRates = parameters.getSupportedPreviewFpsRange(); 392bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int last = frameRates.size() - 1; 393bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int minFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MIN_INDEX]; 394bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int maxFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MAX_INDEX]; 395bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewFpsRange(minFps, maxFps); 396bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview fps: " + minFps + ", " + maxFps); 3973ab4f0912da83f7f5f8266a57a606d521c1649e3Wu-cheng Li 398d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen List<String> supportedFocusModes = parameters.getSupportedFocusModes(); 399d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) { 400d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen parameters.setFocusMode(mTargetFocusMode); 401d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen } else { 402d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // Use the default focus mode and log a message 403d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode + 404d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen " becuase the mode is not supported."); 405d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen } 406d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen 40793ad273a53e7d2975a67d7d1f8a157f845e41cf2Wu-cheng Li parameters.setRecordingHint(false); 40843b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 4092d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mHorizontalViewAngle = parameters.getHorizontalViewAngle(); 4102d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mVerticalViewAngle = parameters.getVerticalViewAngle(); 411bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 412bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 413bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public int getPreviewBufSize() { 414bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat pixelInfo = new PixelFormat(); 415bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat.getPixelFormatInfo(mCameraDevice.getParameters().getPreviewFormat(), pixelInfo); 416bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // TODO: remove this extra 32 byte after the driver bug is fixed. 417bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return (mPreviewWidth * mPreviewHeight * pixelInfo.bitsPerPixel / 8) + 32; 418bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 419bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 420bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void configureCamera(Parameters parameters) { 421bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCameraDevice.setParameters(parameters); 422bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 423bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 424a72d73cbac59db43d413291e4db66763be08143arepo sync private boolean switchToOtherMode(int mode) { 425a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong if (isFinishing()) { 42694f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen return false; 427a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong } 428a72d73cbac59db43d413291e4db66763be08143arepo sync MenuHelper.gotoMode(mode, this); 429a72d73cbac59db43d413291e4db66763be08143arepo sync finish(); 430a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 431a72d73cbac59db43d413291e4db66763be08143arepo sync } 432a72d73cbac59db43d413291e4db66763be08143arepo sync 433a72d73cbac59db43d413291e4db66763be08143arepo sync public boolean onModeChanged(int mode) { 434a72d73cbac59db43d413291e4db66763be08143arepo sync if (mode != ModePicker.MODE_PANORAMA) { 435a72d73cbac59db43d413291e4db66763be08143arepo sync return switchToOtherMode(mode); 436a72d73cbac59db43d413291e4db66763be08143arepo sync } else { 437a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 438a72d73cbac59db43d413291e4db66763be08143arepo sync } 439a72d73cbac59db43d413291e4db66763be08143arepo sync } 440a72d73cbac59db43d413291e4db66763be08143arepo sync 4412faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 442575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi public void onMosaicSurfaceChanged() { 443575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi runOnUiThread(new Runnable() { 444575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi @Override 445575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi public void run() { 446575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi if (!mPausing) { 447575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi startCameraPreview(); 448575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 449575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 450575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi }); 451575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 452575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 453575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi @Override 4542faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void onMosaicSurfaceCreated(final int textureID) { 45536839102e03107e3fb121197036365a58ec2686eAngus Kong runOnUiThread(new Runnable() { 45636839102e03107e3fb121197036365a58ec2686eAngus Kong @Override 45736839102e03107e3fb121197036365a58ec2686eAngus Kong public void run() { 4582faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mSurfaceTexture != null) { 4592faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.release(); 4602faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 4612faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture = new SurfaceTexture(textureID); 4622faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (!mPausing) { 4632faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(PanoramaActivity.this); 4642faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 46536839102e03107e3fb121197036365a58ec2686eAngus Kong } 46636839102e03107e3fb121197036365a58ec2686eAngus Kong }); 46736839102e03107e3fb121197036365a58ec2686eAngus Kong } 46836839102e03107e3fb121197036365a58ec2686eAngus Kong 46941a2e9735136f372de95652d0828600282c8e967mbansal public void runViewFinder() { 4702faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(false); 4712faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 4722faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 4732faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 4742faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 47541a2e9735136f372de95652d0828600282c8e967mbansal } 47641a2e9735136f372de95652d0828600282c8e967mbansal 47741a2e9735136f372de95652d0828600282c8e967mbansal public void runMosaicCapture() { 4782faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(true); 4792faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 4802faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 4812faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Lock the conditional variable to ensure the order of transferGPUtoCPU and 4822faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // mMosaicFrame.processFrame(). 4832faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.lockPreviewReadyFlag(); 48441a2e9735136f372de95652d0828600282c8e967mbansal // Now, transfer the textures from GPU to CPU memory for processing 4852faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.transferGPUtoCPU(); 48641a2e9735136f372de95652d0828600282c8e967mbansal // Wait on the condition variable (will be opened when GPU->CPU transfer is done). 4872faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.waitUntilPreviewReady(); 4880adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mMosaicFrameProcessor.processFrame(); 48941a2e9735136f372de95652d0828600282c8e967mbansal } 49041a2e9735136f372de95652d0828600282c8e967mbansal 491739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong public synchronized void onFrameAvailable(SurfaceTexture surface) { 4924d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong /* This function may be called by some random thread, 49341a2e9735136f372de95652d0828600282c8e967mbansal * so let's be safe and use synchronize. No OpenGL calls can be done here. 49441a2e9735136f372de95652d0828600282c8e967mbansal */ 4950cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // Frames might still be available after the activity is paused. If we call onFrameAvailable 4960cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // after pausing, the GL thread will crash. 4970cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong if (mPausing) return; 4980cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong 4992faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Updating the texture should be done in the GL thread which mMosaicView is attached. 5002faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.queueEvent(new Runnable() { 5012faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 5022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void run() { 5030cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // Check if the activity is paused here can speed up the onPause() process. 5040cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong if (mPausing) return; 5052faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.updateTexImage(); 5062faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.getTransformMatrix(mTransformMatrix); 5072faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 5082faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong }); 5092faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Update the transformation matrix for mosaic pre-process. 510a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong if (mCaptureState == CAPTURE_STATE_VIEWFINDER) { 51141a2e9735136f372de95652d0828600282c8e967mbansal runViewFinder(); 51241a2e9735136f372de95652d0828600282c8e967mbansal } else { 51341a2e9735136f372de95652d0828600282c8e967mbansal runMosaicCapture(); 51441a2e9735136f372de95652d0828600282c8e967mbansal } 51541a2e9735136f372de95652d0828600282c8e967mbansal } 51641a2e9735136f372de95652d0828600282c8e967mbansal 5176108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private void hideDirectionIndicators() { 5186108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.GONE); 5196108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.GONE); 5206108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5216108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 5226108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private void showDirectionIndicators(int direction) { 5236108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong switch (direction) { 5246108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_NONE: 5256108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.VISIBLE); 5266108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.VISIBLE); 5276108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5286108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_LEFT: 5296108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.VISIBLE); 5306108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.GONE); 5316108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5326108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_RIGHT: 5336108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.GONE); 5346108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.VISIBLE); 5356108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5366108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5376108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5386108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 539a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong public void startCapture() { 5408a2c41754655a3733175fce81fb7506ff7022959Angus Kong // Reset values so we can do this again. 54113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mCancelComputation = false; 5428a2c41754655a3733175fce81fb7506ff7022959Angus Kong mTimeTaken = System.currentTimeMillis(); 543a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_MOSAIC; 544fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan_recording); 5458df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong mCaptureIndicator.setVisibility(View.VISIBLE); 5466108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong showDirectionIndicators(PanoProgressBar.DIRECTION_NONE); 5474a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.setEnabled(false); 5488a2c41754655a3733175fce81fb7506ff7022959Angus Kong 549c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mCompassValueXStart = mCompassValueXStartBuffer; 550c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mCompassValueYStart = mCompassValueYStartBuffer; 551c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mTimestamp = 0; 552c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 5538a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() { 5548a2c41754655a3733175fce81fb7506ff7022959Angus Kong @Override 555d991766dc3bcc03a02c6648e2cfd54ee4f8cbd9eAngus Kong public void onProgress(boolean isFinished, float panningRateX, float panningRateY, 556d991766dc3bcc03a02c6648e2cfd54ee4f8cbd9eAngus Kong float progressX, float progressY) { 5572d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float accumulatedHorizontalAngle = progressX * mHorizontalViewAngle; 5582d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float accumulatedVerticalAngle = progressY * mVerticalViewAngle; 559c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong if (isFinished 5602d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE) 5612d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE)) { 56227c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(false); 5638a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 5642d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float panningRateXInDegree = panningRateX * mHorizontalViewAngle; 5652d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float panningRateYInDegree = panningRateY * mVerticalViewAngle; 5662d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen updateProgress(panningRateXInDegree, panningRateYInDegree, 5672d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen accumulatedHorizontalAngle, accumulatedVerticalAngle); 5688a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 5698a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 5708a2c41754655a3733175fce81fb7506ff7022959Angus Kong }); 5718a2c41754655a3733175fce81fb7506ff7022959Angus Kong 5722512c685868eadb274f5be8cd71068078b1f5dddMark Wagner if (mModePicker != null) mModePicker.setEnabled(false); 5732512c685868eadb274f5be8cd71068078b1f5dddMark Wagner 574057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.reset(); 575057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong // TODO: calculate the indicator width according to different devices to reflect the actual 576057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong // angle of view of the camera device. 577057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setIndicatorWidth(20); 578057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setMaxProgress(DEFAULT_SWEEP_ANGLE); 579057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setVisibility(View.VISIBLE); 580e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen mDeviceOrientationAtCapture = mDeviceOrientation; 581bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang keepScreenOn(); 5828a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 5838a2c41754655a3733175fce81fb7506ff7022959Angus Kong 58427c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void stopCapture(boolean aborted) { 585a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 5868df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong mCaptureIndicator.setVisibility(View.GONE); 5878b0e23544474480345937c0c0985429f61569761Angus Kong hideTooFastIndication(); 5886108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong hideDirectionIndicators(); 5894a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.setEnabled(true); 59041a2e9735136f372de95652d0828600282c8e967mbansal 5918a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(null); 59236839102e03107e3fb121197036365a58ec2686eAngus Kong stopCameraPreview(); 59341a2e9735136f372de95652d0828600282c8e967mbansal 5942faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(null); 59541a2e9735136f372de95652d0828600282c8e967mbansal 59627c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong if (!aborted && !mThreadRunning) { 597ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.showWaitingDialog(mPreparePreviewString); 598215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong runBackgroundThread(new Thread() { 599142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 600142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 6017648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li MosaicJpeg jpeg = generateFinalMosaic(false); 602e1178a73fd5756771d25d0b8375452450f509e99mbansal 60313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (jpeg != null && jpeg.isValid) { 604e1178a73fd5756771d25d0b8375452450f509e99mbansal Bitmap bitmap = null; 60513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length); 606e1178a73fd5756771d25d0b8375452450f509e99mbansal mMainHandler.sendMessage(mMainHandler.obtainMessage( 607e1178a73fd5756771d25d0b8375452450f509e99mbansal MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap)); 60813e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } else { 60913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendMessage(mMainHandler.obtainMessage( 61013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong MSG_RESET_TO_PREVIEW)); 611ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 612142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 6135fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 614142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 6152512c685868eadb274f5be8cd71068078b1f5dddMark Wagner // do we have to wait for the thread to complete before enabling this? 6162512c685868eadb274f5be8cd71068078b1f5dddMark Wagner if (mModePicker != null) mModePicker.setEnabled(true); 617bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang keepScreenOnAwhile(); 6188a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6198a2c41754655a3733175fce81fb7506ff7022959Angus Kong 6208b0e23544474480345937c0c0985429f61569761Angus Kong private void showTooFastIndication() { 6218b0e23544474480345937c0c0985429f61569761Angus Kong mTooFastPrompt.setVisibility(View.VISIBLE); 6228b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder.setVisibility(View.VISIBLE); 623fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColorFast); 6248b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(true); 6258b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(true); 6268b0e23544474480345937c0c0985429f61569761Angus Kong } 6278b0e23544474480345937c0c0985429f61569761Angus Kong 6288b0e23544474480345937c0c0985429f61569761Angus Kong private void hideTooFastIndication() { 6298b0e23544474480345937c0c0985429f61569761Angus Kong mTooFastPrompt.setVisibility(View.GONE); 6308b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder.setVisibility(View.GONE); 631fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColor); 6328b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(false); 6338b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(false); 6348b0e23544474480345937c0c0985429f61569761Angus Kong } 6358b0e23544474480345937c0c0985429f61569761Angus Kong 6362d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen private void updateProgress(float panningRateXInDegree, float panningRateYInDegree, 6372d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float progressHorizontalAngle, float progressVerticalAngle) { 6382faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 6392faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 640eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 64143b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // TODO: Now we just display warning message by the panning speed. 64243b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Since we only support horizontal panning, we should display a warning message 64343b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // in UI when there're significant vertical movements. 6442d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen if ((Math.abs(panningRateXInDegree) > PANNING_SPEED_THRESHOLD) 6452d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(panningRateYInDegree) > PANNING_SPEED_THRESHOLD)) { 6468b0e23544474480345937c0c0985429f61569761Angus Kong showTooFastIndication(); 6478a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 6488b0e23544474480345937c0c0985429f61569761Angus Kong hideTooFastIndication(); 6498a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6502d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen int angleInMajorDirection = 6512d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen (Math.abs(progressHorizontalAngle) > Math.abs(progressVerticalAngle)) 6522d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen ? (int) progressHorizontalAngle 6532d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen : (int) progressVerticalAngle; 6542d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mPanoProgressBar.setProgress((angleInMajorDirection)); 6558a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6568a2c41754655a3733175fce81fb7506ff7022959Angus Kong 657bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void createContentView() { 658bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setContentView(R.layout.panorama); 659bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 660a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 66141a2e9735136f372de95652d0828600282c8e967mbansal 662057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong Resources appRes = getResources(); 663057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong 664a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong mCaptureLayout = (View) findViewById(R.id.pano_capture_layout); 665215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mPanoProgressBar = (PanoProgressBar) findViewById(R.id.pano_pan_progress_bar); 666057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty)); 667057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_done)); 668fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mIndicatorColor = appRes.getColor(R.color.pano_progress_indication); 669fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast); 670fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColor); 6716108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mPanoProgressBar.setOnDirectionChangeListener( 6726108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong new PanoProgressBar.OnDirectionChangeListener () { 6736108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong @Override 6746108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong public void onDirectionChange(int direction) { 6756108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong if (mCaptureState == CAPTURE_STATE_MOSAIC) { 6766108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong showDirectionIndicators(direction); 6776108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 6786108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 6796108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong }); 6806108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 6816108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator = (ImageView) findViewById(R.id.pano_pan_left_indicator); 6826108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator = (ImageView) findViewById(R.id.pano_pan_right_indicator); 6838b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(false); 6848b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(false); 685fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt = (TextView) findViewById(R.id.pano_capture_too_fast_textview); 6868b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder = (View) findViewById(R.id.pano_speed_indication_border); 687bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 688215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar = (PanoProgressBar) findViewById(R.id.pano_saving_progress_bar); 689215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setIndicatorWidth(0); 690215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setMaxProgress(100); 691215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty)); 692215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication)); 693215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 694d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mCaptureIndicator = (RotateLayout) findViewById(R.id.pano_capture_indicator); 6958df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong 696a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong mThumbnailView = (RotateImageView) findViewById(R.id.thumbnail); 6974a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.enableFilter(false); 698a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 6995af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReviewLayout = (View) findViewById(R.id.pano_review_layout); 7005af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReview = (ImageView) findViewById(R.id.pano_reviewarea); 7012faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView = (MosaicRendererSurfaceView) findViewById(R.id.pano_renderer); 7022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.getRenderer().setMosaicSurfaceCreateListener(this); 703eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 704a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker = (ModePicker) findViewById(R.id.mode_picker); 705a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setVisibility(View.VISIBLE); 706a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setOnModeChangeListener(this); 707a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setCurrentMode(ModePicker.MODE_PANORAMA); 7087648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 709fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton = (ShutterButton) findViewById(R.id.shutter_button); 710fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan); 711fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setOnShutterButtonListener(this); 712fcdf619d92701052621a96572d956d047e07cf24Angus Kong 7137648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li mPanoLayout = findViewById(R.id.pano_layout); 714d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang 715ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog); 716d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang 717d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { 718d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang Rotatable[] rotateLayout = { 719d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_pan_progress_bar_layout), 720d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_capture_too_fast_textview_layout), 721d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_review_saving_indication_layout), 722d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_saving_progress_bar_layout), 723d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_review_cancel_button_layout), 724562db5a0ec57f65cf4014ce3f7dad0f9324bb2f1Angus Kong (Rotatable) findViewById(R.id.pano_rotate_reviewarea), 725d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) mRotateDialog, 7263a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mCaptureIndicator, 7273a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mModePicker, 7283a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mThumbnailView}; 729d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang for (Rotatable r : rotateLayout) { 730d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang r.setOrientation(270); 731d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 732d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 733bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 734bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 735fcdf619d92701052621a96572d956d047e07cf24Angus Kong @Override 7361bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li public void onShutterButtonClick() { 7372faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // If mSurfaceTexture == null then GL setup is not finished yet. 7382faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // No buttons can be pressed. 7392faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 740a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong // Since this button will stay on the screen when capturing, we need to check the state 741a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong // right now. 742fcdf619d92701052621a96572d956d047e07cf24Angus Kong switch (mCaptureState) { 743fcdf619d92701052621a96572d956d047e07cf24Angus Kong case CAPTURE_STATE_VIEWFINDER: 744d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvala mCameraDevice.playSound(Sound.START_VIDEO_RECORDING); 745fcdf619d92701052621a96572d956d047e07cf24Angus Kong startCapture(); 746fcdf619d92701052621a96572d956d047e07cf24Angus Kong break; 747fcdf619d92701052621a96572d956d047e07cf24Angus Kong case CAPTURE_STATE_MOSAIC: 748d628e27f561c4bedf0d457f64270fc12740b5280Eino-Ville Talvala mCameraDevice.playSound(Sound.STOP_VIDEO_RECORDING); 74927c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(false); 750a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong } 751739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong } 752739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong 753fcdf619d92701052621a96572d956d047e07cf24Angus Kong @Override 7541bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li public void onShutterButtonFocus(boolean pressed) { 755142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 756142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 757215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong public void reportProgress() { 758215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.reset(); 759215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setRightIncreasing(true); 76050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal Thread t = new Thread() { 76150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal @Override 76250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 7636f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong while (mThreadRunning) { 764e1178a73fd5756771d25d0b8375452450f509e99mbansal final int progress = mMosaicFrameProcessor.reportProgress( 765215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong true, mCancelComputation); 76650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 7676f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong try { 768215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong synchronized (mWaitObject) { 769215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mWaitObject.wait(50); 770215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 771215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } catch (InterruptedException e) { 7726f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong throw new RuntimeException("Panorama reportProgress failed", e); 7736f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong } 7746f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong // Update the progress bar 77550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal runOnUiThread(new Runnable() { 77650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 777215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setProgress(progress); 77850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 77950b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }); 78050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 78150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 78250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }; 78350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal t.start(); 78450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 78550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 78682dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner private void initThumbnailButton() { 78782dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner // Load the thumbnail from the disk. 78882dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner if (mThumbnail == null) { 78982dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner mThumbnail = Thumbnail.loadFrom(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); 79082dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner } 79182dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner updateThumbnailButton(); 79282dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner } 79382dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner 7949a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner private void updateThumbnailButton() { 7959a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner // Update last image if URI is invalid and the storage is ready. 7969a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner ContentResolver contentResolver = getContentResolver(); 7979a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner if ((mThumbnail == null || !Util.isUriValid(mThumbnail.getUri(), contentResolver))) { 7989a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnail = Thumbnail.getLastThumbnail(contentResolver); 7999a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8009a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner if (mThumbnail != null) { 8019a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnailView.setBitmap(mThumbnail.getBitmap()); 8029a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } else { 8039a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnailView.setBitmap(null); 8049a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8059a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8069a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner 807215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong public void saveHighResMosaic() { 808215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong runBackgroundThread(new Thread() { 809142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 810142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 8117648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li MosaicJpeg jpeg = generateFinalMosaic(true); 812e1178a73fd5756771d25d0b8375452450f509e99mbansal 81313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (jpeg == null) { // Cancelled by user. 81413e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendEmptyMessage(MSG_RESET_TO_PREVIEW); 81513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } else if (!jpeg.isValid) { // Error when generating mosaic. 81613e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR); 81722d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong } else { 818e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // The panorama image returned from the library is orientated based on the 819e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // natural orientation of a camera. We need to set an orientation for the image 820e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // in its EXIF header, so the image can be displayed correctly. 821e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // The orientation is calculated from compensating the 822e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // device orientation at capture and the camera orientation respective to 823e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // the natural orientation of the device. 824e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen int orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360; 825ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong Uri uri = savePanorama(jpeg.data, jpeg.width, jpeg.height, orientation); 82613e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (uri != null) { 82766188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen // Create a thumbnail whose width or height is equal or bigger 82866188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen // than the screen's width or height. 82966188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int widthRatio = (int) Math.ceil((double) jpeg.width 83066188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen / mPanoLayout.getWidth()); 83166188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int heightRatio = (int) Math.ceil((double) jpeg.height 83266188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen / mPanoLayout.getHeight()); 83366188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int inSampleSize = Integer.highestOneBit( 83466188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen Math.max(widthRatio, heightRatio)); 83513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mThumbnail = Thumbnail.createThumbnail( 83613e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong jpeg.data, orientation, inSampleSize, uri); 837d22fff61ae44ea5213aeb91f400bfe1456411d25Angus Kong Util.broadcastNewPicture(PanoramaActivity.this, uri); 83822d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong } 83913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendMessage( 84013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL)); 841a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 842142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 8435fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 844215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong reportProgress(); 845215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 846215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 847215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private void runBackgroundThread(Thread thread) { 8485fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = true; 8495fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong thread.start(); 8505fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong } 8515fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 8525fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private void onBackgroundThreadFinished() { 8535fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = false; 854ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.dismissDialog(); 855142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 856142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 857ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong private void cancelHighResComputation() { 858215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mCancelComputation = true; 859215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong synchronized (mWaitObject) { 860215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mWaitObject.notify(); 861215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 862142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 863142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 864a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong @OnClickAttr 865ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong public void onCancelButtonClicked(View v) { 866ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong if (mPausing || mSurfaceTexture == null) return; 867ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong cancelHighResComputation(); 868ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong } 869ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong 870ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong @OnClickAttr 871a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong public void onThumbnailClicked(View v) { 872a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 873a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong showSharePopup(); 874a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 875a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 876a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private void showSharePopup() { 877a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mThumbnail == null) return; 878a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong Uri uri = mThumbnail.getUri(); 879a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mSharePopup == null || !uri.equals(mSharePopup.getUri())) { 880a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // The orientation compensation is set to 0 here because we only support landscape. 8815201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mSharePopup = new SharePopup(this, uri, mThumbnail.getBitmap(), 8825201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mOrientationCompensation, 883977d06c6278cb7b131ed3c0960853d9168aacbddWu-cheng Li findViewById(R.id.frame_layout)); 884a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 885a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong mSharePopup.showAtLocation(mThumbnailView, Gravity.NO_GRAVITY, 0, 0); 886a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 887a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 88827c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void reset() { 889a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 89041a2e9735136f372de95652d0828600282c8e967mbansal 89141a2e9735136f372de95652d0828600282c8e967mbansal mReviewLayout.setVisibility(View.GONE); 892fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan); 893057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setVisibility(View.GONE); 89460fc534ec8f68d95a486984cb396a2da0e200518Angus Kong mCaptureLayout.setVisibility(View.VISIBLE); 895142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.reset(); 89641a2e9735136f372de95652d0828600282c8e967mbansal 8972faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(this); 89827c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong } 89941a2e9735136f372de95652d0828600282c8e967mbansal 90027c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void resetToPreview() { 90127c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong reset(); 90236839102e03107e3fb121197036365a58ec2686eAngus Kong if (!mPausing) startCameraPreview(); 903142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 904142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 905142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void showFinalMosaic(Bitmap bitmap) { 906142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (bitmap != null) { 907142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mReview.setImageBitmap(bitmap); 908142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 909ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mCaptureLayout.setVisibility(View.GONE); 910ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mReviewLayout.setVisibility(View.VISIBLE); 911142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 912142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 913ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong private Uri savePanorama(byte[] jpegData, int width, int height, int orientation) { 914ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (jpegData != null) { 915e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen String filename = PanoUtil.createName( 916ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong getResources().getString(R.string.pano_file_name_format), mTimeTaken); 917e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Uri uri = Storage.addImage(getContentResolver(), filename, mTimeTaken, null, 918ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong orientation, jpegData, width, height); 919e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen if (uri != null && orientation != 0) { 920e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen String filepath = Storage.generateFilepath(filename); 921e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen try { 922e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // Save the orientation in EXIF. 923e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen ExifInterface exif = new ExifInterface(filepath); 924e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen exif.setAttribute(ExifInterface.TAG_ORIENTATION, 925e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen getExifOrientation(orientation)); 926e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen exif.saveAttributes(); 927e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } catch (IOException e) { 928e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Log.e(TAG, "cannot set exif data: " + filepath); 929e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 930e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 931e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return uri; 932142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 933a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong return null; 934142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 935142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 936e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private static String getExifOrientation(int orientation) { 937e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen switch (orientation) { 938e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 0: 939e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_NORMAL); 940e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 90: 941e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_90); 942e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 180: 943e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_180); 944e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 270: 945e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_270); 946e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen default: 947e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen throw new AssertionError("invalid: " + orientation); 948e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 949e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 950e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen 951142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void clearMosaicFrameProcessorIfNeeded() { 952142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (!mPausing || mThreadRunning) return; 953142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.clear(); 954142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 955142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 956142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void initMosaicFrameProcessorIfNeeded() { 957142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mPausing || mThreadRunning) return; 958142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mMosaicFrameProcessor == null) { 959142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // Start the activity for the first time. 960c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mMosaicFrameProcessor = new MosaicFrameProcessor( 9610adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mPreviewWidth, mPreviewHeight, getPreviewBufSize()); 962142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 963142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.initialize(); 964bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 965bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 966bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 967bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen protected void onPause() { 968bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onPause(); 9694d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong 970142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = true; 971ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong cancelHighResComputation(); 97227c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong // Stop the capturing first. 97327c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong if (mCaptureState == CAPTURE_STATE_MOSAIC) { 97427c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(true); 97527c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong reset(); 97627c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong } 9778b084a607d0b207272d5c87fecbb5d33cbef1b4fMark Wagner if (mSharePopup != null) mSharePopup.dismiss(); 9785201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 9795201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner if (mThumbnail != null && !mThumbnail.fromFile()) { 9805201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mThumbnail.saveTo(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); 9815201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner } 9825201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 98327c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong releaseCamera(); 9842faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.onPause(); 985142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 986c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener.disable(); 987bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang resetScreenOn(); 98894f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen System.gc(); 989bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 990bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 991bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 9927d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller protected void doOnResume() { 993142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = false; 994c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener.enable(); 995215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 996a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 997bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setupCamera(); 998575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 999142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // Camera must be initialized before MosaicFrameProcessor is initialized. The preview size 1000142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // has to be decided by camera device. 1001142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong initMosaicFrameProcessorIfNeeded(); 10022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.onResume(); 100382dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner 100482dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner initThumbnailButton(); 1005bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang keepScreenOnAwhile(); 1006bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 1007bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 10080a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen /** 10090a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * Generate the final mosaic image. 10100a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * 10110a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * @param highRes flag to indicate whether we want to get a high-res version. 10120a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * @return a MosaicJpeg with its isValid flag set to true if successful; null if the generation 10130a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * process is cancelled; and a MosaicJpeg with its isValid flag set to false if there 10140a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * is an error in generating the final mosaic. 10150a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen */ 10167648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public MosaicJpeg generateFinalMosaic(boolean highRes) { 10170a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen int mosaicReturnCode = mMosaicFrameProcessor.createMosaic(highRes); 10180a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (mosaicReturnCode == Mosaic.MOSAIC_RET_CANCELLED) { 1019e1178a73fd5756771d25d0b8375452450f509e99mbansal return null; 10200a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } else if (mosaicReturnCode == Mosaic.MOSAIC_RET_ERROR) { 10210a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return new MosaicJpeg(); 102213e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } 1023bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 1024ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21(); 1025ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (imageData == null) { 1026ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "getFinalMosaicNV21() returned null."); 102713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 10288a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 10298a2c41754655a3733175fce81fb7506ff7022959Angus Kong 1030ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int len = imageData.length - 8; 1031ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int width = (imageData[len + 0] << 24) + ((imageData[len + 1] & 0xFF) << 16) 1032ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 2] & 0xFF) << 8) + (imageData[len + 3] & 0xFF); 1033ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int height = (imageData[len + 4] << 24) + ((imageData[len + 5] & 0xFF) << 16) 1034ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 6] & 0xFF) << 8) + (imageData[len + 7] & 0xFF); 1035ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.v(TAG, "ImLength = " + (len) + ", W = " + width + ", H = " + height); 10368a2c41754655a3733175fce81fb7506ff7022959Angus Kong 1037e46486104523760a4433f03e09ed615987d83b6cAngus Kong if (width <= 0 || height <= 0) { 1038e46486104523760a4433f03e09ed615987d83b6cAngus Kong // TODO: pop up a error meesage indicating that the final result is not generated. 1039e46486104523760a4433f03e09ed615987d83b6cAngus Kong Log.e(TAG, "width|height <= 0!!, len = " + (len) + ", W = " + width + ", H = " + 1040e46486104523760a4433f03e09ed615987d83b6cAngus Kong height); 104113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 1042e46486104523760a4433f03e09ed615987d83b6cAngus Kong } 1043e46486104523760a4433f03e09ed615987d83b6cAngus Kong 1044ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong YuvImage yuvimage = new YuvImage(imageData, ImageFormat.NV21, width, height, null); 1045ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong ByteArrayOutputStream out = new ByteArrayOutputStream(); 1046ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out); 1047ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong try { 1048ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong out.close(); 1049ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } catch (Exception e) { 1050ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "Exception in storing final mosaic", e); 105113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 1052ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 10537648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li return new MosaicJpeg(out.toByteArray(), width, height); 1054bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 10558a2c41754655a3733175fce81fb7506ff7022959Angus Kong 105641a2e9735136f372de95652d0828600282c8e967mbansal private void setPreviewTexture(SurfaceTexture surface) { 105798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 105841a2e9735136f372de95652d0828600282c8e967mbansal mCameraDevice.setPreviewTexture(surface); 105998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 106098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 106141a2e9735136f372de95652d0828600282c8e967mbansal throw new RuntimeException("setPreviewTexture failed", ex); 106298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 106398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 106498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 106536839102e03107e3fb121197036365a58ec2686eAngus Kong private void startCameraPreview() { 106698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // If we're previewing already, stop the preview first (this will blank 106798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // the screen). 106836839102e03107e3fb121197036365a58ec2686eAngus Kong if (mCameraState != PREVIEW_STOPPED) stopCameraPreview(); 106998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 1070d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Set the display orientation to 0, so that the underlying mosaic library 1071d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // can always get undistorted mPreviewWidth x mPreviewHeight image data 1072d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // from SurfaceTexture. 1073d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen mCameraDevice.setDisplayOrientation(0); 1074575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 10752faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong setPreviewTexture(mSurfaceTexture); 107698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 107798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 107898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "startPreview"); 107998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.startPreview(); 108098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 108198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 108298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen throw new RuntimeException("startPreview failed", ex); 108398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 108498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_ACTIVE; 108598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 108698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 108736839102e03107e3fb121197036365a58ec2686eAngus Kong private void stopCameraPreview() { 108898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { 108998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "stopPreview"); 109098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.stopPreview(); 109198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 109298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 109398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 1094bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1095bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang @Override 1096bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang public void onUserInteraction() { 1097bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang super.onUserInteraction(); 1098bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang if (mCaptureState != CAPTURE_STATE_MOSAIC) keepScreenOnAwhile(); 1099bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1100bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1101bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void resetScreenOn() { 1102bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1103bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1104bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1105bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1106bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void keepScreenOnAwhile() { 1107bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1108bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1109bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_DELAY, SCREEN_DELAY); 1110bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1111bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1112bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void keepScreenOn() { 1113bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1114bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1115bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1116bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen} 1117