PanoramaActivity.java revision 50b3c890986aadb3780b4da8c0b8dbb0f1422eba
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 19d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraDisabledException; 20d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHardwareException; 21d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHolder; 22d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.MenuHelper; 23d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.ModePicker; 24d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.R; 25d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Storage; 26d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Util; 27d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Li 28bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.app.Activity; 295fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kongimport android.app.ProgressDialog; 30bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.content.Context; 31142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.Bitmap; 32142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.BitmapFactory; 338a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.ImageFormat; 34bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.graphics.PixelFormat; 358a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.Rect; 3641a2e9735136f372de95652d0828600282c8e967mbansalimport android.graphics.SurfaceTexture; 378a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.YuvImage; 388a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.hardware.Camera; 39bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.Sensor; 40bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.SensorEvent; 41bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.SensorEventListener; 42bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.SensorManager; 4350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansalimport android.hardware.Camera.Parameters; 4450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansalimport android.hardware.Camera.Size; 45bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.os.Bundle; 468a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.os.Handler; 47ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport android.os.Message; 48bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.util.Log; 49bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.View; 50bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.WindowManager; 51f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kongimport android.view.animation.Animation; 52f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kongimport android.view.animation.AnimationUtils; 5360fc534ec8f68d95a486984cb396a2da0e200518Angus Kongimport android.widget.Button; 54bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.widget.ImageView; 5550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansalimport android.widget.ProgressBar; 56fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kongimport android.widget.TextView; 57bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 58ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport java.io.ByteArrayOutputStream; 59bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport java.util.List; 60bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 61a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong/** 62a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong * Activity to handle panorama capturing. 63a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong */ 6498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chenpublic class PanoramaActivity extends Activity implements 6541a2e9735136f372de95652d0828600282c8e967mbansal ModePicker.OnModeChangeListener, 6636839102e03107e3fb121197036365a58ec2686eAngus Kong SurfaceTexture.OnFrameAvailableListener, 6736839102e03107e3fb121197036365a58ec2686eAngus Kong MosaicRendererSurfaceViewRenderer.MosaicSurfaceCreateListener { 68ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong public static final int DEFAULT_SWEEP_ANGLE = 160; 69bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL; 70bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720; 71bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 72ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private static final int MSG_FINAL_MOSAIC_READY = 1; 73142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private static final int MSG_RESET_TO_PREVIEW = 2; 7494f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen 75ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private static final String TAG = "PanoramaActivity"; 7698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_STOPPED = 0; 7798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_ACTIVE = 1; 7841a2e9735136f372de95652d0828600282c8e967mbansal private static final int CAPTURE_VIEWFINDER = 0; 7941a2e9735136f372de95652d0828600282c8e967mbansal private static final int CAPTURE_MOSAIC = 1; 8041a2e9735136f372de95652d0828600282c8e967mbansal 8143b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Speed is in unit of deg/sec 8243b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private static final float PANNING_SPEED_THRESHOLD = 30f; 8343b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 84a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong // Ratio of nanosecond to second 85a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private static final float NS2S = 1.0f / 1000000000.0f; 86142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 87142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mPausing; 88142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 89a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mPanoControlLayout; 90a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mCaptureLayout; 9160fc534ec8f68d95a486984cb396a2da0e200518Angus Kong private Button mStopCaptureButton; 92a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mReviewLayout; 93bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private ImageView mReview; 94bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private CaptureView mCaptureView; 952faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private MosaicRendererSurfaceView mMosaicView; 96fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong private TextView mTooFastPrompt; 97f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong private Animation mSlideIn, mSlideOut; 98142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 995fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private ProgressDialog mProgressDialog; 1005fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private String mPreparePreviewString; 1015fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private String mGeneratePanoramaString; 1025fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 103bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewWidth; 104bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewHeight; 1058a2c41754655a3733175fce81fb7506ff7022959Angus Kong private Camera mCameraDevice; 10698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private int mCameraState; 10741a2e9735136f372de95652d0828600282c8e967mbansal private int mCaptureState; 108bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private SensorManager mSensorManager; 109bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private Sensor mSensor; 110a72d73cbac59db43d413291e4db66763be08143arepo sync private ModePicker mModePicker; 1118a2c41754655a3733175fce81fb7506ff7022959Angus Kong private MosaicFrameProcessor mMosaicFrameProcessor; 1128a2c41754655a3733175fce81fb7506ff7022959Angus Kong private String mCurrentImagePath = null; 1138a2c41754655a3733175fce81fb7506ff7022959Angus Kong private long mTimeTaken; 114ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private Handler mMainHandler; 1152faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private SurfaceTexture mSurfaceTexture; 116142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mThreadRunning; 1172faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private float[] mTransformMatrix; 11843b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private float mHorizontalViewAngle; 11943b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private float mVerticalViewAngle; 120142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 121bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 122bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public void onCreate(Bundle icicle) { 123bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onCreate(icicle); 124bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 125bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, 126bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 127bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 128bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen createContentView(); 129bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 130bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 131bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 132bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (mSensor == null) { 133bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); 134bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 1358a2c41754655a3733175fce81fb7506ff7022959Angus Kong 1362faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mTransformMatrix = new float[16]; 1372faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong 1385fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mPreparePreviewString = 1395fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong getResources().getString(R.string.pano_dialog_prepare_preview); 1405fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mGeneratePanoramaString = 1415fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong getResources().getString(R.string.pano_dialog_generate_panorama); 1425fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 143f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong Context context = getApplicationContext(); 144f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong mSlideIn = AnimationUtils.loadAnimation(context, R.anim.slide_in_from_right); 145f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong mSlideOut = AnimationUtils.loadAnimation(context, R.anim.slide_out_to_right); 146f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong 147ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mMainHandler = new Handler() { 148ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong @Override 149ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong public void handleMessage(Message msg) { 150ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong switch (msg.what) { 151ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong case MSG_FINAL_MOSAIC_READY: 1525fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 153142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong showFinalMosaic((Bitmap) msg.obj); 154142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 155142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong case MSG_RESET_TO_PREVIEW: 1565fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 157142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong resetToPreview(); 158142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 159ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 160142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 161ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 162ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong }; 163bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 164bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 165bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void setupCamera() { 166bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen openCamera(); 167bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Parameters parameters = mCameraDevice.getParameters(); 168bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setupCaptureParams(parameters); 169bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen configureCamera(parameters); 170bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 171bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 172ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private void releaseCamera() { 173ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong if (mCameraDevice != null) { 174142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mCameraDevice.setPreviewCallbackWithBuffer(null); 175ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong CameraHolder.instance().release(); 176ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mCameraDevice = null; 17798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 178ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 179ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 180ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong 181bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void openCamera() { 182bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen try { 183bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCameraDevice = Util.openCamera(this, CameraHolder.instance().getBackCameraId()); 184bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } catch (CameraHardwareException e) { 185bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Util.showErrorAndFinish(this, R.string.cannot_connect_camera); 186bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return; 187bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } catch (CameraDisabledException e) { 188bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Util.showErrorAndFinish(this, R.string.camera_disabled); 189bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return; 190bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 191bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 192bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 193bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private boolean findBestPreviewSize(List<Size> supportedSizes, boolean need4To3, 194bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean needSmaller) { 195bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int pixelsDiff = DEFAULT_CAPTURE_PIXELS; 196bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean hasFound = false; 1978a2c41754655a3733175fce81fb7506ff7022959Angus Kong for (Size size : supportedSizes) { 198bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int h = size.height; 199bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int w = size.width; 200bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // we only want 4:3 format. 201bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int d = DEFAULT_CAPTURE_PIXELS - h * w; 20294f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen if (needSmaller && d < 0) { // no bigger preview than 960x720. 203bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 204bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 205bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (need4To3 && (h * 4 != w * 3)) { 206bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 207bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 208bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen d = Math.abs(d); 209bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (d < pixelsDiff) { 210bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewWidth = w; 211bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewHeight = h; 212bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen pixelsDiff = d; 213bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen hasFound = true; 214bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 215bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 216bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return hasFound; 217bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 218bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 219bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void setupCaptureParams(Parameters parameters) { 220bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<Size> supportedSizes = parameters.getSupportedPreviewSizes(); 221bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, true, true)) { 222bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "No 4:3 ratio preview size supported."); 223bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, false, true)) { 224bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "Can't find a supported preview size smaller than 960x720."); 225bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen findBestPreviewSize(supportedSizes, false, false); 226bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 227bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 228bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview h = " + mPreviewHeight + " , w = " + mPreviewWidth); 229bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); 230bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 231bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<int[]> frameRates = parameters.getSupportedPreviewFpsRange(); 232bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int last = frameRates.size() - 1; 233bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int minFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MIN_INDEX]; 234bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int maxFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MAX_INDEX]; 235bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewFpsRange(minFps, maxFps); 236bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview fps: " + minFps + ", " + maxFps); 2373ab4f0912da83f7f5f8266a57a606d521c1649e3Wu-cheng Li 23893ad273a53e7d2975a67d7d1f8a157f845e41cf2Wu-cheng Li parameters.setRecordingHint(false); 23943b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 24043b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen mHorizontalViewAngle = parameters.getHorizontalViewAngle(); 24143b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen mVerticalViewAngle = parameters.getVerticalViewAngle(); 242bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 243bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 244bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public int getPreviewBufSize() { 245bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat pixelInfo = new PixelFormat(); 246bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat.getPixelFormatInfo(mCameraDevice.getParameters().getPreviewFormat(), pixelInfo); 247bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // TODO: remove this extra 32 byte after the driver bug is fixed. 248bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return (mPreviewWidth * mPreviewHeight * pixelInfo.bitsPerPixel / 8) + 32; 249bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 250bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 251bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void configureCamera(Parameters parameters) { 252bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCameraDevice.setParameters(parameters); 253bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 2544b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li int orientation = Util.getDisplayOrientation(Util.getDisplayRotation(this), 2554b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li CameraHolder.instance().getBackCameraId()); 2564b602592e0d189499b22d107d997b83e798b5bd9Wu-cheng Li mCameraDevice.setDisplayOrientation(orientation); 257bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 258bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 259a72d73cbac59db43d413291e4db66763be08143arepo sync private boolean switchToOtherMode(int mode) { 260a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong if (isFinishing()) { 26194f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen return false; 262a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong } 263a72d73cbac59db43d413291e4db66763be08143arepo sync MenuHelper.gotoMode(mode, this); 264a72d73cbac59db43d413291e4db66763be08143arepo sync finish(); 265a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 266a72d73cbac59db43d413291e4db66763be08143arepo sync } 267a72d73cbac59db43d413291e4db66763be08143arepo sync 268a72d73cbac59db43d413291e4db66763be08143arepo sync public boolean onModeChanged(int mode) { 269a72d73cbac59db43d413291e4db66763be08143arepo sync if (mode != ModePicker.MODE_PANORAMA) { 270a72d73cbac59db43d413291e4db66763be08143arepo sync return switchToOtherMode(mode); 271a72d73cbac59db43d413291e4db66763be08143arepo sync } else { 272a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 273a72d73cbac59db43d413291e4db66763be08143arepo sync } 274a72d73cbac59db43d413291e4db66763be08143arepo sync } 275a72d73cbac59db43d413291e4db66763be08143arepo sync 2762faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 2772faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void onMosaicSurfaceCreated(final int textureID) { 27836839102e03107e3fb121197036365a58ec2686eAngus Kong runOnUiThread(new Runnable() { 27936839102e03107e3fb121197036365a58ec2686eAngus Kong @Override 28036839102e03107e3fb121197036365a58ec2686eAngus Kong public void run() { 2812faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mSurfaceTexture != null) { 2822faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.release(); 2832faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 2842faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture = new SurfaceTexture(textureID); 2852faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (!mPausing) { 2862faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(PanoramaActivity.this); 2872faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong startCameraPreview(); 2882faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 28936839102e03107e3fb121197036365a58ec2686eAngus Kong } 29036839102e03107e3fb121197036365a58ec2686eAngus Kong }); 29136839102e03107e3fb121197036365a58ec2686eAngus Kong } 29236839102e03107e3fb121197036365a58ec2686eAngus Kong 29341a2e9735136f372de95652d0828600282c8e967mbansal public void runViewFinder() { 2942faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(false); 2952faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 2962faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 2972faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 2982faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 29941a2e9735136f372de95652d0828600282c8e967mbansal } 30041a2e9735136f372de95652d0828600282c8e967mbansal 30141a2e9735136f372de95652d0828600282c8e967mbansal public void runMosaicCapture() { 3022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(true); 3032faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 3042faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 3052faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Lock the conditional variable to ensure the order of transferGPUtoCPU and 3062faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // mMosaicFrame.processFrame(). 3072faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.lockPreviewReadyFlag(); 30841a2e9735136f372de95652d0828600282c8e967mbansal // Now, transfer the textures from GPU to CPU memory for processing 3092faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.transferGPUtoCPU(); 31041a2e9735136f372de95652d0828600282c8e967mbansal // Wait on the condition variable (will be opened when GPU->CPU transfer is done). 3112faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.waitUntilPreviewReady(); 3120adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mMosaicFrameProcessor.processFrame(); 31341a2e9735136f372de95652d0828600282c8e967mbansal } 31441a2e9735136f372de95652d0828600282c8e967mbansal 315739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong public synchronized void onFrameAvailable(SurfaceTexture surface) { 3164d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong /* This function may be called by some random thread, 31741a2e9735136f372de95652d0828600282c8e967mbansal * so let's be safe and use synchronize. No OpenGL calls can be done here. 31841a2e9735136f372de95652d0828600282c8e967mbansal */ 3192faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Updating the texture should be done in the GL thread which mMosaicView is attached. 3202faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.queueEvent(new Runnable() { 3212faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 3222faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void run() { 3232faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.updateTexImage(); 3242faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.getTransformMatrix(mTransformMatrix); 3252faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 3262faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong }); 3272faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Update the transformation matrix for mosaic pre-process. 32841a2e9735136f372de95652d0828600282c8e967mbansal if (mCaptureState == CAPTURE_VIEWFINDER) { 32941a2e9735136f372de95652d0828600282c8e967mbansal runViewFinder(); 33041a2e9735136f372de95652d0828600282c8e967mbansal } else { 33141a2e9735136f372de95652d0828600282c8e967mbansal runMosaicCapture(); 33241a2e9735136f372de95652d0828600282c8e967mbansal } 33341a2e9735136f372de95652d0828600282c8e967mbansal } 33441a2e9735136f372de95652d0828600282c8e967mbansal 335a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong public void startCapture() { 3368a2c41754655a3733175fce81fb7506ff7022959Angus Kong // Reset values so we can do this again. 3378a2c41754655a3733175fce81fb7506ff7022959Angus Kong mTimeTaken = System.currentTimeMillis(); 33841a2e9735136f372de95652d0828600282c8e967mbansal mCaptureState = CAPTURE_MOSAIC; 339fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt.setVisibility(View.GONE); 3408a2c41754655a3733175fce81fb7506ff7022959Angus Kong 3418a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() { 3428a2c41754655a3733175fce81fb7506ff7022959Angus Kong @Override 34343b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen public void onProgress(boolean isFinished, float panningRateX, float panningRateY, 34443b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen int traversedAngleX, int traversedAngleY) { 3458a2c41754655a3733175fce81fb7506ff7022959Angus Kong if (isFinished) { 346a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong stopCapture(); 3478a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 34843b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen updateProgress(panningRateX, panningRateY, traversedAngleX, traversedAngleY); 3498a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 3508a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 3518a2c41754655a3733175fce81fb7506ff7022959Angus Kong }); 3528a2c41754655a3733175fce81fb7506ff7022959Angus Kong 35360fc534ec8f68d95a486984cb396a2da0e200518Angus Kong mStopCaptureButton.setVisibility(View.VISIBLE); 3545af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mCaptureView.setVisibility(View.VISIBLE); 3552faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setVisibility(View.VISIBLE); 356f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong mPanoControlLayout.startAnimation(mSlideOut); 357a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong mPanoControlLayout.setVisibility(View.GONE); 35841a2e9735136f372de95652d0828600282c8e967mbansal 3598a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 3608a2c41754655a3733175fce81fb7506ff7022959Angus Kong 361a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private void stopCapture() { 36241a2e9735136f372de95652d0828600282c8e967mbansal mCaptureState = CAPTURE_VIEWFINDER; 36341a2e9735136f372de95652d0828600282c8e967mbansal 3648a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(null); 36536839102e03107e3fb121197036365a58ec2686eAngus Kong stopCameraPreview(); 36641a2e9735136f372de95652d0828600282c8e967mbansal 3672faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(null); 36841a2e9735136f372de95652d0828600282c8e967mbansal 369ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong // TODO: show some dialog for long computation. 370142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (!mThreadRunning) { 3715fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong runBackgroundThread(mPreparePreviewString, new Thread() { 372142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 373142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 374ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong byte[] jpegData = generateFinalMosaic(false); 375ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Bitmap bitmap = null; 376ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (jpegData != null) { 377ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); 378ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 379ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mMainHandler.sendMessage(mMainHandler.obtainMessage( 380ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong MSG_FINAL_MOSAIC_READY, bitmap)); 381142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 3825fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 38350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal reportProgress(false); 384142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 3858a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 3868a2c41754655a3733175fce81fb7506ff7022959Angus Kong 38743b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private void updateProgress(float panningRateX, float panningRateY, 38843b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen int traversedAngleX, int traversedAngleY) { 389eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 3902faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 3912faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 392eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 39343b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // TODO: Now we just display warning message by the panning speed. 39443b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Since we only support horizontal panning, we should display a warning message 39543b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // in UI when there're significant vertical movements. 39643b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen if ((panningRateX * mHorizontalViewAngle > PANNING_SPEED_THRESHOLD) 39743b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen || (panningRateY * mVerticalViewAngle > PANNING_SPEED_THRESHOLD)) { 398fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong // TODO: draw speed indication according to the UI spec. 399fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt.setVisibility(View.VISIBLE); 40094f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen mCaptureView.setSweepAngle(Math.max(traversedAngleX, traversedAngleY) + 1); 4018a2c41754655a3733175fce81fb7506ff7022959Angus Kong mCaptureView.invalidate(); 4028a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 403fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt.setVisibility(View.GONE); 40494f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen mCaptureView.setSweepAngle(Math.max(traversedAngleX, traversedAngleY) + 1); 4058a2c41754655a3733175fce81fb7506ff7022959Angus Kong mCaptureView.invalidate(); 4068a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 4078a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 4088a2c41754655a3733175fce81fb7506ff7022959Angus Kong 409bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void createContentView() { 410bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setContentView(R.layout.panorama); 411bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 41241a2e9735136f372de95652d0828600282c8e967mbansal mCaptureState = CAPTURE_VIEWFINDER; 41341a2e9735136f372de95652d0828600282c8e967mbansal 414a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong mCaptureLayout = (View) findViewById(R.id.pano_capture_layout); 415bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCaptureView = (CaptureView) findViewById(R.id.pano_capture_view); 416bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCaptureView.setStartAngle(-DEFAULT_SWEEP_ANGLE / 2); 4175af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mStopCaptureButton = (Button) findViewById(R.id.pano_capture_stop_button); 418fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt = (TextView) findViewById(R.id.pano_capture_too_fast_textview); 419bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 4205af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReviewLayout = (View) findViewById(R.id.pano_review_layout); 4215af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReview = (ImageView) findViewById(R.id.pano_reviewarea); 4222faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView = (MosaicRendererSurfaceView) findViewById(R.id.pano_renderer); 4232faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.getRenderer().setMosaicSurfaceCreateListener(this); 4242faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setVisibility(View.VISIBLE); 425eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 426a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong mPanoControlLayout = (View) findViewById(R.id.pano_control_layout); 427a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker = (ModePicker) findViewById(R.id.mode_picker); 428a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setVisibility(View.VISIBLE); 429a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setOnModeChangeListener(this); 430a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setCurrentMode(ModePicker.MODE_PANORAMA); 431bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 432bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 433142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @OnClickAttr 434739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong public void onStartButtonClicked(View v) { 4352faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // If mSurfaceTexture == null then GL setup is not finished yet. 4362faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // No buttons can be pressed. 4372faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 438739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong startCapture(); 439739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong } 440739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong 441739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong @OnClickAttr 442142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void onStopButtonClicked(View v) { 4432faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 444142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong stopCapture(); 445142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 446142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 44750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void reportProgress(final boolean highRes) { 44850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal Thread t = new Thread() { 44950b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal @Override 45050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 45150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal while(true) 45250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal { 45350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal final int progress = mMosaicFrameProcessor.reportProgress(highRes); 45450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 45550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal try{ 45650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal Thread.sleep(50); 45750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }catch(Exception e) {} 45850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 45950b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal // Update the progress bar 46050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal runOnUiThread(new Runnable() { 46150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 46250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal //TODO: Set the the progress-bar progress update here... 46350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 46450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }); 46550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 46650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal if(progress>=100) 46750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal break; 46850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 46950b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 47050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }; 47150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal t.start(); 47250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 47350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 474142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @OnClickAttr 475142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void onOkButtonClicked(View v) { 4762faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 4775fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong runBackgroundThread(mGeneratePanoramaString, new Thread() { 478142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 479142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 480ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong byte[] jpegData = generateFinalMosaic(true); 481ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong savePanorama(jpegData); 482ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mMainHandler.sendMessage(mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW)); 483142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 4845fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 48550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal reportProgress(true); 4865fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong } 4875fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 4885fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private void runBackgroundThread(String str, Thread thread) { 4895fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = true; 4905fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mProgressDialog = ProgressDialog.show(this, "", str); 4915fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong thread.start(); 4925fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong } 4935fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 4945fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private void onBackgroundThreadFinished() { 4955fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = false; 4965fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mProgressDialog.dismiss(); 4975fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mProgressDialog = null; 498142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 499142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 500142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @OnClickAttr 501142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void onRetakeButtonClicked(View v) { 5022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 503142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong resetToPreview(); 504142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 505142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 506142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void resetToPreview() { 50741a2e9735136f372de95652d0828600282c8e967mbansal mCaptureState = CAPTURE_VIEWFINDER; 50841a2e9735136f372de95652d0828600282c8e967mbansal 50941a2e9735136f372de95652d0828600282c8e967mbansal mReviewLayout.setVisibility(View.GONE); 51060fc534ec8f68d95a486984cb396a2da0e200518Angus Kong mStopCaptureButton.setVisibility(View.GONE); 5115af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mCaptureView.setVisibility(View.GONE); 512142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPanoControlLayout.setVisibility(View.VISIBLE); 513f26e1ab12cb3f359fe1d6efcbe65344a3a0bf276Angus Kong mPanoControlLayout.startAnimation(mSlideIn); 51460fc534ec8f68d95a486984cb396a2da0e200518Angus Kong mCaptureLayout.setVisibility(View.VISIBLE); 515142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.reset(); 51641a2e9735136f372de95652d0828600282c8e967mbansal 5172faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(this); 51841a2e9735136f372de95652d0828600282c8e967mbansal 51936839102e03107e3fb121197036365a58ec2686eAngus Kong if (!mPausing) startCameraPreview(); 52041a2e9735136f372de95652d0828600282c8e967mbansal 5212faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setVisibility(View.VISIBLE); 522142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 523142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 524142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void showFinalMosaic(Bitmap bitmap) { 525142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (bitmap != null) { 526142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mReview.setImageBitmap(bitmap); 527142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 528ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mCaptureLayout.setVisibility(View.GONE); 529ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mReviewLayout.setVisibility(View.VISIBLE); 530ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mCaptureView.setSweepAngle(0); 531142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 532142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 533ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong private void savePanorama(byte[] jpegData) { 534ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (jpegData != null) { 535ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong String imagePath = PanoUtil.createName( 536ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong getResources().getString(R.string.pano_file_name_format), mTimeTaken); 537ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Storage.addImage(getContentResolver(), imagePath, mTimeTaken, null, 0, 538ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong jpegData); 539142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 540142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 541142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 542142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void clearMosaicFrameProcessorIfNeeded() { 543142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (!mPausing || mThreadRunning) return; 544142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.clear(); 545142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 546142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 547142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void initMosaicFrameProcessorIfNeeded() { 548142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mPausing || mThreadRunning) return; 549142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mMosaicFrameProcessor == null) { 550142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // Start the activity for the first time. 551142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor = new MosaicFrameProcessor(DEFAULT_SWEEP_ANGLE - 5, 5520adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mPreviewWidth, mPreviewHeight, getPreviewBufSize()); 553142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 554142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.initialize(); 555bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 556bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 557bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 558bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen protected void onPause() { 559bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onPause(); 5604d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong 561bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen releaseCamera(); 562142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = true; 5632faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.onPause(); 56494f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen mSensorManager.unregisterListener(mListener); 565142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 56694f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen System.gc(); 567bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 568bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 569bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 570bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen protected void onResume() { 571bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onResume(); 572bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 573142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = false; 574bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen /* 57594f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen * It is not necessary to get accelerometer events at a very high rate, 57694f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen * by using a slower rate (SENSOR_DELAY_UI), we get an automatic 57794f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen * low-pass filter, which "extracts" the gravity component of the 57894f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen * acceleration. As an added benefit, we use less power and CPU 57994f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen * resources. 580bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen */ 581bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_UI); 58241a2e9735136f372de95652d0828600282c8e967mbansal mCaptureState = CAPTURE_VIEWFINDER; 583bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setupCamera(); 5844d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong if (mSurfaceTexture != null) { 5854d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong mSurfaceTexture.setOnFrameAvailableListener(this); 5864d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong startCameraPreview(); 5874d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong } 588142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // Camera must be initialized before MosaicFrameProcessor is initialized. The preview size 589142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // has to be decided by camera device. 590142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong initMosaicFrameProcessorIfNeeded(); 5912faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.onResume(); 592bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 593bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 594bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private final SensorEventListener mListener = new SensorEventListener() { 595bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private float mCompassCurrX; // degrees 596bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private float mCompassCurrY; // degrees 597bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private float mTimestamp; 598bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 599bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public void onSensorChanged(SensorEvent event) { 600bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) { 601bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (mTimestamp != 0) { 602bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen final float dT = (event.timestamp - mTimestamp) * NS2S; 603bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCompassCurrX += event.values[1] * dT * 180.0f / Math.PI; 604bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCompassCurrY += event.values[0] * dT * 180.0f / Math.PI; 605bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 606bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mTimestamp = event.timestamp; 607bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 608bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } else if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) { 609bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCompassCurrX = event.values[0]; 610bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCompassCurrY = event.values[1]; 611bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 612bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 6138a2c41754655a3733175fce81fb7506ff7022959Angus Kong if (mMosaicFrameProcessor != null) { 6148a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.updateCompassValue(mCompassCurrX, mCompassCurrY); 615bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 616bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 617bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 618bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 619bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public void onAccuracyChanged(Sensor sensor, int accuracy) { 620bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 621bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen }; 622bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 623ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong public byte[] generateFinalMosaic(boolean highRes) { 6248a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.createMosaic(highRes); 625bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 626ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21(); 627ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (imageData == null) { 628ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "getFinalMosaicNV21() returned null."); 629ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong return null; 6308a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6318a2c41754655a3733175fce81fb7506ff7022959Angus Kong 632ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int len = imageData.length - 8; 633ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int width = (imageData[len + 0] << 24) + ((imageData[len + 1] & 0xFF) << 16) 634ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 2] & 0xFF) << 8) + (imageData[len + 3] & 0xFF); 635ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int height = (imageData[len + 4] << 24) + ((imageData[len + 5] & 0xFF) << 16) 636ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 6] & 0xFF) << 8) + (imageData[len + 7] & 0xFF); 637ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.v(TAG, "ImLength = " + (len) + ", W = " + width + ", H = " + height); 6388a2c41754655a3733175fce81fb7506ff7022959Angus Kong 639e46486104523760a4433f03e09ed615987d83b6cAngus Kong if (width <= 0 || height <= 0) { 640e46486104523760a4433f03e09ed615987d83b6cAngus Kong // TODO: pop up a error meesage indicating that the final result is not generated. 641e46486104523760a4433f03e09ed615987d83b6cAngus Kong Log.e(TAG, "width|height <= 0!!, len = " + (len) + ", W = " + width + ", H = " + 642e46486104523760a4433f03e09ed615987d83b6cAngus Kong height); 643e46486104523760a4433f03e09ed615987d83b6cAngus Kong return null; 644e46486104523760a4433f03e09ed615987d83b6cAngus Kong } 645e46486104523760a4433f03e09ed615987d83b6cAngus Kong 646ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong YuvImage yuvimage = new YuvImage(imageData, ImageFormat.NV21, width, height, null); 647ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong ByteArrayOutputStream out = new ByteArrayOutputStream(); 648ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out); 649ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong try { 650ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong out.close(); 651ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } catch (Exception e) { 652ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "Exception in storing final mosaic", e); 653ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong return null; 654ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 655ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong return out.toByteArray(); 656bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 6578a2c41754655a3733175fce81fb7506ff7022959Angus Kong 65841a2e9735136f372de95652d0828600282c8e967mbansal private void setPreviewTexture(SurfaceTexture surface) { 65998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 66041a2e9735136f372de95652d0828600282c8e967mbansal mCameraDevice.setPreviewTexture(surface); 66198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 66298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 66341a2e9735136f372de95652d0828600282c8e967mbansal throw new RuntimeException("setPreviewTexture failed", ex); 66498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 66598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 66698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 66736839102e03107e3fb121197036365a58ec2686eAngus Kong private void startCameraPreview() { 66898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // If we're previewing already, stop the preview first (this will blank 66998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // the screen). 67036839102e03107e3fb121197036365a58ec2686eAngus Kong if (mCameraState != PREVIEW_STOPPED) stopCameraPreview(); 67198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 6722faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong setPreviewTexture(mSurfaceTexture); 67398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 67498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 67598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "startPreview"); 67698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.startPreview(); 67798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 67898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 67998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen throw new RuntimeException("startPreview failed", ex); 68098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 68198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_ACTIVE; 68298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 68398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 68436839102e03107e3fb121197036365a58ec2686eAngus Kong private void stopCameraPreview() { 68598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { 68698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "stopPreview"); 68798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.stopPreview(); 68898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 68998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 69098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 691bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen} 692