summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/panorama
diff options
context:
space:
mode:
authormbansal <mayank.bansal@sri.com>2011-08-08 20:23:02 -0400
committerWei-Ta Chen <weita@google.com>2011-08-12 15:05:43 -0700
commit41a2e9735136f372de95652d0828600282c8e967 (patch)
tree25e946121b6940cd3dfa19746a393e5c05179ef4 /src/com/android/camera/panorama
parent7058a9318dd5d6d5a1e79a84080cdc02975f68c1 (diff)
downloadpackages_apps_LegacyCamera-41a2e9735136f372de95652d0828600282c8e967.zip
packages_apps_LegacyCamera-41a2e9735136f372de95652d0828600282c8e967.tar.gz
packages_apps_LegacyCamera-41a2e9735136f372de95652d0828600282c8e967.tar.bz2
Updates to allow using SurfaceTexture for reading the preview frames directly from GPU memory.
1) SurfaceTexture is now used to obtain the data processed by the mosaicing library. 2) SurfaceTexture in GPU memory is directly rendered using the transformation from the mosaicing library to generate the preview mosaic. 3) GPU is also used to generate the Low-Res frames from the High-res frames (was being done in CPU before). 4) SurfaceTexture is also used to render the viewfinder as soon as the mosaicing application starts (eliminating the need for a separate SurfaceHolder to render the camera). 5) Modified the XML layout during the preview state to be the same size as during the capture stage to accommodate the SurfaceTexture based viewfinder [this needs to be reviewed and adjusted]. 6) Fixed the viewfinder and back button issues identified by Wei-Ta. 7) Round-1 of removing trailing spaces and tabs. 8) Added documentation to new Java side interfaces and cleaned up code in general. 9) Cleaned up redundant and commented out code from the native side. 10) Merged with latest updates from the main trunk. 11) Fixed issues identified in code review and also cleaned up and refactored some code. 12) Added layout-w1024dp/pano_capture.xml for tablet layout. Change-Id: If8fb0116de6c7fc6652cc67ac453553726961c32
Diffstat (limited to 'src/com/android/camera/panorama')
-rw-r--r--src/com/android/camera/panorama/Mosaic.java14
-rw-r--r--src/com/android/camera/panorama/MosaicFrameProcessor.java21
-rw-r--r--src/com/android/camera/panorama/MosaicRenderer.java34
-rw-r--r--src/com/android/camera/panorama/MosaicRendererSurfaceView.java78
-rw-r--r--src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java67
-rw-r--r--src/com/android/camera/panorama/PanoramaActivity.java193
6 files changed, 309 insertions, 98 deletions
diff --git a/src/com/android/camera/panorama/Mosaic.java b/src/com/android/camera/panorama/Mosaic.java
index 5012ff4..80e8263 100644
--- a/src/com/android/camera/panorama/Mosaic.java
+++ b/src/com/android/camera/panorama/Mosaic.java
@@ -99,6 +99,20 @@ public class Mosaic {
public native float[] setSourceImage(byte[] pixels);
/**
+ * This is an alternative to the setSourceImage function above. This should
+ * be called when the image data is already on the native side in a fixed
+ * byte array. In implementation, this array is filled by the GL thread
+ * using glReadPixels directly from GPU memory (where it is accessed by
+ * an associated SurfaceTexture).
+ *
+ * @return Float array of length 10; first 9 entries correspond to the 3x3
+ * transformation matrix between the first frame and the passed frame,
+ * and the last entry is the number of the passed frame,
+ * where the counting starts from 1.
+ */
+ public native float[] setSourceImageFromGPU();
+
+ /**
* Set the type of blending.
*
* @param type the blending type defined in the class. {BLENDTYPE_FULL,
diff --git a/src/com/android/camera/panorama/MosaicFrameProcessor.java b/src/com/android/camera/panorama/MosaicFrameProcessor.java
index 6496f11..502d41f 100644
--- a/src/com/android/camera/panorama/MosaicFrameProcessor.java
+++ b/src/com/android/camera/panorama/MosaicFrameProcessor.java
@@ -56,18 +56,20 @@ public class MosaicFrameProcessor {
private int mPreviewWidth;
private int mPreviewHeight;
private int mPreviewBufferSize;
+ private boolean mUseSurfaceTexture;
public interface ProgressListener {
public void onProgress(boolean isFinished, float translationRate,
int traversedAngleX, int traversedAngleY);
}
- public MosaicFrameProcessor(int sweepAngle, int previewWidth, int previewHeight, int bufSize) {
+ public MosaicFrameProcessor(int sweepAngle, int previewWidth, int previewHeight, int bufSize, boolean useSurfaceTexture) {
mMosaicer = new Mosaic();
mCompassThreshold = sweepAngle;
mPreviewWidth = previewWidth;
mPreviewHeight = previewHeight;
mPreviewBufferSize = bufSize;
+ mUseSurfaceTexture = useSurfaceTexture;
}
public void setProgressListener(ProgressListener listener) {
@@ -75,7 +77,7 @@ public class MosaicFrameProcessor {
}
public void initialize() {
- setupMosaicer(mPreviewWidth, mPreviewHeight, mPreviewBufferSize);
+ setupMosaicer(mPreviewWidth, mPreviewHeight, mPreviewBufferSize, mUseSurfaceTexture);
reset();
}
@@ -87,8 +89,7 @@ public class MosaicFrameProcessor {
}
}
-
- private void setupMosaicer(int previewWidth, int previewHeight, int bufSize) {
+ private void setupMosaicer(int previewWidth, int previewHeight, int bufSize, boolean useSurfaceTexture) {
Log.v(TAG, "setupMosaicer w, h=" + previewWidth + ',' + previewHeight + ',' + bufSize);
mMosaicer.allocateMosaicMemory(previewWidth, previewHeight);
@@ -133,11 +134,14 @@ public class MosaicFrameProcessor {
}
long t1 = System.currentTimeMillis();
mFrameTimestamp[mFillIn] = t1;
- System.arraycopy(data, 0, mFrames[mFillIn], 0, data.length);
+
+ // TODO: Remove the case of byte data copy when SurfaceTexture is ready
+ if(!mUseSurfaceTexture)
+ System.arraycopy(data, 0, mFrames[mFillIn], 0, data.length);
+
mCurrProcessFrameIdx = mFillIn;
mFillIn = ((mFillIn + 1) % NUM_FRAMES_IN_BUFFER);
-
// Check that we are trying to process a frame different from the
// last one processed (useful if this class was running asynchronously)
if (mCurrProcessFrameIdx != mLastProcessFrameIdx) {
@@ -184,11 +188,12 @@ public class MosaicFrameProcessor {
float deltaTime = (now - mLastProcessedFrameTimestamp) / 1000.0f;
mLastProcessedFrameTimestamp = now;
- float[] frameData = mMosaicer.setSourceImage(data);
+ float[] frameData = mUseSurfaceTexture ?
+ mMosaicer.setSourceImageFromGPU() :
+ mMosaicer.setSourceImage(data);
mTotalFrameCount = (int) frameData[FRAME_COUNT_INDEX];
float translationCurrX = frameData[X_COORD_INDEX];
float translationCurrY = frameData[Y_COORD_INDEX];
-
mTranslationRate = Math.max(Math.abs(translationCurrX - mTranslationLastX),
Math.abs(translationCurrY - mTranslationLastY)) / deltaTime;
mTranslationLastX = translationCurrX;
diff --git a/src/com/android/camera/panorama/MosaicRenderer.java b/src/com/android/camera/panorama/MosaicRenderer.java
index 8db95c0..2bf471c 100644
--- a/src/com/android/camera/panorama/MosaicRenderer.java
+++ b/src/com/android/camera/panorama/MosaicRenderer.java
@@ -30,9 +30,12 @@ public class MosaicRenderer
/**
* Function to be called in onSurfaceCreated() to initialize
* the GL context, load and link the shaders and create the
- * program.
+ * program. Returns a texture ID to be used for SurfaceTexture.
+ *
+ * @return textureID the texture ID of the newly generated texture to
+ * be assigned to the SurfaceTexture object.
*/
- public static native void init();
+ public static native int init();
/**
* Pass the drawing surface's width and height to initialize the
@@ -44,6 +47,23 @@ public class MosaicRenderer
public static native void reset(int width, int height);
/**
+ * Calling this function will render the SurfaceTexture to a new 2D texture
+ * using the provided STMatrix and then call glReadPixels to fill the data
+ * array that will be processed by the mosaicing thread.
+ *
+ * @param stMatrix texture coordinate transform matrix obtained from the
+ * Surface texture
+ */
+ public static native void preprocess(float[] stMatrix);
+
+ /**
+ * This function calls glReadPixels to transfer both the low-res and high-res
+ * data from the GPU memory to the CPU memory for further processing by the
+ * mosaicing library.
+ */
+ public static native void transferGPUtoCPU();
+
+ /**
* Function to be called in onDrawFrame() to update the screen with
* the new frame data.
*/
@@ -59,9 +79,11 @@ public class MosaicRenderer
/**
* This function allows toggling between showing the input image data
- * (without applying any warp) and the warped image data. This is more
- * for debugging purposes to see if the image data is being updated
- * correctly or not.
+ * (without applying any warp) and the warped image data. For running
+ * the renderer as a viewfinder, we set the flag to false. To see the
+ * preview mosaic, we set the flag to true.
+ *
+ * @param flag boolean flag to set the warping to true or false.
*/
- public static native void togglewarping();
+ public static native void setWarping(boolean flag);
}
diff --git a/src/com/android/camera/panorama/MosaicRendererSurfaceView.java b/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
index 3220b22..6767c87 100644
--- a/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
+++ b/src/com/android/camera/panorama/MosaicRendererSurfaceView.java
@@ -21,9 +21,12 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
+import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
+import android.graphics.SurfaceTexture;
import android.opengl.GLSurfaceView;
+import android.os.ConditionVariable;
import android.util.AttributeSet;
import android.util.Log;
@@ -31,6 +34,7 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
private static String TAG = "MosaicRendererSurfaceView";
private static final boolean DEBUG = false;
private MosaicRendererSurfaceViewRenderer mRenderer;
+ private ConditionVariable mPreviewFrameReadyForProcessing;
public MosaicRendererSurfaceView(Context context) {
super(context);
@@ -50,7 +54,6 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
setZOrderMediaOverlay(true);
}
-
private void init(boolean translucent, int depth, int stencil) {
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
@@ -80,6 +83,7 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
mRenderer = new MosaicRendererSurfaceViewRenderer();
setRenderer(mRenderer);
setRenderMode(RENDERMODE_WHEN_DIRTY);
+ mPreviewFrameReadyForProcessing = new ConditionVariable();
}
private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
@@ -298,6 +302,21 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
private int[] mValue = new int[1];
}
+ public void lockPreviewReadyFlag()
+ {
+ mPreviewFrameReadyForProcessing.close();
+ }
+
+ private void unlockPreviewReadyFlag()
+ {
+ mPreviewFrameReadyForProcessing.open();
+ }
+
+ public void waitUntilPreviewReady()
+ {
+ mPreviewFrameReadyForProcessing.block();
+ }
+
public void setReady()
{
queueEvent(new Runnable() {
@@ -309,14 +328,67 @@ public class MosaicRendererSurfaceView extends GLSurfaceView {
});
}
- public void toggleWarping()
+ public void preprocess()
+ {
+ queueEvent(new Runnable() {
+
+ @Override
+ public void run() {
+ mRenderer.preprocess();
+ }
+ });
+ }
+
+ public void transferGPUtoCPU()
+ {
+ queueEvent(new Runnable() {
+
+ @Override
+ public void run() {
+ mRenderer.transferGPUtoCPU();
+ unlockPreviewReadyFlag();
+ }
+ });
+ }
+
+ public void setUIObject(final Activity activity)
{
queueEvent(new Runnable() {
@Override
public void run() {
- mRenderer.toggleWarping();
+ mRenderer.setUIObject(activity);
}
});
}
+
+ public void setWarping(final boolean flag)
+ {
+ queueEvent(new Runnable() {
+
+ @Override
+ public void run() {
+ mRenderer.setWarping(flag);
+ }
+ });
+ }
+
+ public int getTextureID() {
+ return mRenderer.getTextureID();
+ }
+
+ public void setSurfaceTexture(SurfaceTexture surface) {
+ mRenderer.setSurfaceTexture(surface);
+ }
+
+ public void updateSurfaceTexture() {
+ queueEvent(new Runnable() {
+
+ @Override
+ public void run() {
+ mRenderer.updateSurfaceTexture();
+ }
+ });
+ }
+
}
diff --git a/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java b/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
index a27d4be..d29765a 100644
--- a/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
+++ b/src/com/android/camera/panorama/MosaicRendererSurfaceViewRenderer.java
@@ -19,37 +19,78 @@ package com.android.camera.panorama;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
+import android.app.Activity;
+import android.graphics.SurfaceTexture;
import android.opengl.GLSurfaceView;
-
+import android.util.Log;
public class MosaicRendererSurfaceViewRenderer implements GLSurfaceView.Renderer
{
@Override
- public void onDrawFrame(GL10 gl)
- {
+ public void onDrawFrame(GL10 gl) {
MosaicRenderer.step();
}
@Override
- public void onSurfaceChanged(GL10 gl, int width, int height)
- {
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ Log.i(TAG, "Renderer: onSurfaceChanged");
MosaicRenderer.reset(width, height);
+ Log.i(TAG, "Renderer: onSurfaceChanged");
}
@Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config)
- {
- MosaicRenderer.init();
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mTextureID = MosaicRenderer.init();
+
+ mActivity.runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ mActivity.createSurfaceTextureAndStartPreview(mTextureID);
+ setSurfaceTexture(mActivity.getSurfaceTexture());
+ }
+ });
}
- public void setReady()
- {
+ public void setReady() {
MosaicRenderer.ready();
}
- public void toggleWarping()
- {
- MosaicRenderer.togglewarping();
+ public void preprocess() {
+ MosaicRenderer.preprocess(mSTMatrix);
+ }
+
+ public void transferGPUtoCPU() {
+ MosaicRenderer.transferGPUtoCPU();
+ }
+
+ public void setWarping(boolean flag) {
+ MosaicRenderer.setWarping(flag);
+ }
+
+ public void updateSurfaceTexture() {
+ mSurface.updateTexImage();
+ mSurface.getTransformMatrix(mSTMatrix);
}
+ public void setUIObject(Activity activity) {
+ mActivity = (PanoramaActivity)activity;
+ }
+
+ public int getTextureID() {
+ return mTextureID;
+ }
+
+ public void setSurfaceTexture(SurfaceTexture surface) {
+ mSurface = surface;
+ }
+
+ private float[] mSTMatrix = new float[16];
+ private int mTextureID;
+
+ private PanoramaActivity mActivity;
+
+ private static String TAG = "MosaicRendererSurfaceViewRenderer";
+
+ private SurfaceTexture mSurface;
}
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index 0b1ec60..d9645ff 100644
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -33,19 +33,19 @@ import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
-import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
@@ -58,7 +58,8 @@ import java.util.List;
* Activity to handle panorama capturing.
*/
public class PanoramaActivity extends Activity implements
- ModePicker.OnModeChangeListener, SurfaceHolder.Callback {
+ ModePicker.OnModeChangeListener,
+ SurfaceTexture.OnFrameAvailableListener {
public static final int DEFAULT_SWEEP_ANGLE = 60;
public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL;
public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720;
@@ -69,6 +70,9 @@ public class PanoramaActivity extends Activity implements
private static final String TAG = "PanoramaActivity";
private static final int PREVIEW_STOPPED = 0;
private static final int PREVIEW_ACTIVE = 1;
+ private static final int CAPTURE_VIEWFINDER = 0;
+ private static final int CAPTURE_MOSAIC = 1;
+
// Ratio of nanosecond to second
private static final float NS2S = 1.0f / 1000000000.0f;
@@ -89,6 +93,7 @@ public class PanoramaActivity extends Activity implements
private int mPreviewHeight;
private Camera mCameraDevice;
private int mCameraState;
+ private int mCaptureState;
private SensorManager mSensorManager;
private Sensor mSensor;
private ModePicker mModePicker;
@@ -96,7 +101,8 @@ public class PanoramaActivity extends Activity implements
private String mCurrentImagePath = null;
private long mTimeTaken;
private Handler mMainHandler;
- private SurfaceHolder mSurfaceHolder;
+ private SurfaceTexture mSurface;
+ private boolean mUseSurfaceTexture = true;
private boolean mThreadRunning;
@@ -133,6 +139,22 @@ public class PanoramaActivity extends Activity implements
};
}
+ public void createSurfaceTextureAndStartPreview(int textureID)
+ {
+ /*
+ * Create the SurfaceTexture that will feed this textureID, and pass it to the camera
+ */
+ mSurface = new SurfaceTexture(textureID);
+ mSurface.setOnFrameAvailableListener(this);
+ startPreview();
+ Log.i(TAG, "Created Surface Texture");
+ }
+
+ public SurfaceTexture getSurfaceTexture()
+ {
+ return mSurface;
+ }
+
private void setupCamera() {
openCamera();
Parameters parameters = mCameraDevice.getParameters();
@@ -223,14 +245,16 @@ public class PanoramaActivity extends Activity implements
CameraHolder.instance().getBackCameraId());
mCameraDevice.setDisplayOrientation(orientation);
- int bufSize = getPreviewBufSize();
- Log.v(TAG, "BufSize = " + bufSize);
- for (int i = 0; i < 10; i++) {
- try {
- mCameraDevice.addCallbackBuffer(new byte[bufSize]);
- } catch (OutOfMemoryError e) {
- Log.v(TAG, "Buffer allocation failed: buffer " + i);
- break;
+ if(!mUseSurfaceTexture) {
+ int bufSize = getPreviewBufSize();
+ Log.v(TAG, "BufSize = " + bufSize);
+ for (int i = 0; i < 10; i++) {
+ try {
+ mCameraDevice.addCallbackBuffer(new byte[bufSize]);
+ } catch (OutOfMemoryError e) {
+ Log.v(TAG, "Buffer allocation failed: buffer " + i);
+ break;
+ }
}
}
}
@@ -252,9 +276,51 @@ public class PanoramaActivity extends Activity implements
}
}
+ public void runViewFinder() {
+ mRealTimeMosaicView.setWarping(false);
+
+ // First update the surface texture...
+ mRealTimeMosaicView.updateSurfaceTexture();
+ // ...then call preprocess to render it to low-res and high-res RGB textures
+ mRealTimeMosaicView.preprocess();
+
+ mRealTimeMosaicView.setReady();
+ mRealTimeMosaicView.requestRender();
+ }
+
+ public void runMosaicCapture() {
+ mRealTimeMosaicView.setWarping(true);
+
+ // Lock the condition variable
+ mRealTimeMosaicView.lockPreviewReadyFlag();
+ // First update the surface texture...
+ mRealTimeMosaicView.updateSurfaceTexture();
+ // ...then call preprocess to render it to low-res and high-res RGB textures
+ mRealTimeMosaicView.preprocess();
+ // Now, transfer the textures from GPU to CPU memory for processing
+ mRealTimeMosaicView.transferGPUtoCPU();
+ // Wait on the condition variable (will be opened when GPU->CPU transfer is done).
+ mRealTimeMosaicView.waitUntilPreviewReady();
+
+ mMosaicFrameProcessor.processFrame(null);
+ }
+
+ synchronized public void onFrameAvailable(SurfaceTexture surface) {
+ /* For simplicity, SurfaceTexture calls here when it has new
+ * data available. Call may come in from some random thread,
+ * so let's be safe and use synchronize. No OpenGL calls can be done here.
+ */
+ if (mCaptureState == CAPTURE_VIEWFINDER) {
+ runViewFinder();
+ } else {
+ runMosaicCapture();
+ }
+ }
+
public void startCapture() {
// Reset values so we can do this again.
mTimeTaken = System.currentTimeMillis();
+ mCaptureState = CAPTURE_MOSAIC;
mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() {
@Override
@@ -268,26 +334,38 @@ public class PanoramaActivity extends Activity implements
}
});
- // Preview callback used whenever new viewfinder frame is available
- mCameraDevice.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
- @Override
- public void onPreviewFrame(final byte[] data, Camera camera) {
- mMosaicFrameProcessor.processFrame(data);
- // The returned buffer needs be added back to callback buffer
- // again.
- camera.addCallbackBuffer(data);
- }
- });
+ if (!mUseSurfaceTexture) {
+ // Preview callback used whenever new viewfinder frame is available
+ mCameraDevice.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
+ @Override
+ public void onPreviewFrame(final byte[] data, Camera camera) {
+ mMosaicFrameProcessor.processFrame(data);
+ // The returned buffer needs be added back to callback buffer
+ // again.
+ camera.addCallbackBuffer(data);
+ }
+ });
+ }
mCaptureLayout.setVisibility(View.VISIBLE);
mPreview.setVisibility(View.INVISIBLE); // will be re-used, invisible is better than gone.
mRealTimeMosaicView.setVisibility(View.VISIBLE);
mPanoControlLayout.setVisibility(View.GONE);
+
}
private void stopCapture() {
+ mCaptureState = CAPTURE_VIEWFINDER;
+
mMosaicFrameProcessor.setProgressListener(null);
stopPreview();
+
+ if (!mUseSurfaceTexture) {
+ mCameraDevice.setPreviewCallbackWithBuffer(null);
+ }
+
+ mSurface.setOnFrameAvailableListener(null);
+
// TODO: show some dialog for long computation.
if (!mThreadRunning) {
mThreadRunning = true;
@@ -322,17 +400,19 @@ public class PanoramaActivity extends Activity implements
private void createContentView() {
setContentView(R.layout.panorama);
+ mCaptureState = CAPTURE_VIEWFINDER;
+
mCaptureLayout = (View) findViewById(R.id.pano_capture_layout);
mReviewLayout = (View) findViewById(R.id.pano_review_layout);
mPreview = (SurfaceView) findViewById(R.id.pano_preview_view);
- mPreview.getHolder().addCallback(this);
+
mCaptureView = (CaptureView) findViewById(R.id.pano_capture_view);
mCaptureView.setStartAngle(-DEFAULT_SWEEP_ANGLE / 2);
mReview = (ImageView) findViewById(R.id.pano_reviewarea);
mRealTimeMosaicView = (MosaicRendererSurfaceView) findViewById(R.id.pano_renderer);
- mRealTimeMosaicView.setVisibility(View.GONE);
+ mRealTimeMosaicView.setUIObject(this);
mShutterButton = (ShutterButton) findViewById(R.id.pano_shutter_button);
mShutterButton.setOnClickListener(new View.OnClickListener() {
@@ -349,6 +429,8 @@ public class PanoramaActivity extends Activity implements
mModePicker.setVisibility(View.VISIBLE);
mModePicker.setOnModeChangeListener(this);
mModePicker.setCurrentMode(ModePicker.MODE_PANORAMA);
+
+ mRealTimeMosaicView.setVisibility(View.VISIBLE);
}
@OnClickAttr
@@ -377,13 +459,19 @@ public class PanoramaActivity extends Activity implements
}
private void resetToPreview() {
+ mCaptureState = CAPTURE_VIEWFINDER;
+
+ mReviewLayout.setVisibility(View.GONE);
mPreview.setVisibility(View.VISIBLE);
mPanoControlLayout.setVisibility(View.VISIBLE);
- mRealTimeMosaicView.setVisibility(View.GONE);
mCaptureLayout.setVisibility(View.GONE);
- mReviewLayout.setVisibility(View.GONE);
mMosaicFrameProcessor.reset();
+
+ mSurface.setOnFrameAvailableListener(this);
+
if (!mPausing) startPreview();
+
+ mRealTimeMosaicView.setVisibility(View.VISIBLE);
}
private void showFinalMosaic(Bitmap bitmap) {
@@ -394,6 +482,7 @@ public class PanoramaActivity extends Activity implements
mReviewLayout.setVisibility(View.VISIBLE);
mCaptureView.setStatusText("");
mCaptureView.setSweepAngle(0);
+ mCaptureView.invalidate();
}
}
@@ -416,7 +505,7 @@ public class PanoramaActivity extends Activity implements
if (mMosaicFrameProcessor == null) {
// Start the activity for the first time.
mMosaicFrameProcessor = new MosaicFrameProcessor(DEFAULT_SWEEP_ANGLE - 5,
- mPreviewWidth, mPreviewHeight, getPreviewBufSize());
+ mPreviewWidth, mPreviewHeight, getPreviewBufSize(), mUseSurfaceTexture);
}
mMosaicFrameProcessor.initialize();
}
@@ -424,10 +513,12 @@ public class PanoramaActivity extends Activity implements
@Override
protected void onPause() {
super.onPause();
+ mSurface.setOnFrameAvailableListener(null);
releaseCamera();
mPausing = true;
- mCaptureView.onPause();
+
mRealTimeMosaicView.onPause();
+ mCaptureView.onPause();
mSensorManager.unregisterListener(mListener);
clearMosaicFrameProcessorIfNeeded();
System.gc();
@@ -446,12 +537,11 @@ public class PanoramaActivity extends Activity implements
* resources.
*/
mSensorManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_UI);
-
+ mCaptureState = CAPTURE_VIEWFINDER;
setupCamera();
// Camera must be initialized before MosaicFrameProcessor is initialized. The preview size
// has to be decided by camera device.
initMosaicFrameProcessorIfNeeded();
- startPreview();
mCaptureView.onResume();
mRealTimeMosaicView.onResume();
}
@@ -526,45 +616,12 @@ public class PanoramaActivity extends Activity implements
System.gc();
}
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
- mSurfaceHolder = holder;
-
- if (mCameraDevice == null) return;
-
- // Set preview display if the surface is being created. Preview was
- // already started. Also restart the preview if display rotation has
- // changed. Sometimes this happens when the device is held in portrait
- // and camera app is opened. Rotation animation takes some time and
- // display rotation in onCreate may not be what we want.
- if (holder.isCreating()) {
- // Set preview display if the surface is being created and preview
- // was already started. That means preview display was set to null
- // and we need to set it now.
- setPreviewDisplay(holder);
- } else {
- // 1. Restart the preview if the size of surface was changed. The
- // framework may not support changing preview display on the fly.
- // 2. Start the preview now if surface was destroyed and preview
- // stopped.
- startPreview();
- }
- }
-
- private void setPreviewDisplay(SurfaceHolder holder) {
+ private void setPreviewTexture(SurfaceTexture surface) {
try {
- mCameraDevice.setPreviewDisplay(holder);
+ mCameraDevice.setPreviewTexture(surface);
} catch (Throwable ex) {
releaseCamera();
- throw new RuntimeException("setPreviewDisplay failed", ex);
+ throw new RuntimeException("setPreviewTexture failed", ex);
}
}
@@ -573,7 +630,7 @@ public class PanoramaActivity extends Activity implements
// the screen).
if (mCameraState != PREVIEW_STOPPED) stopPreview();
- setPreviewDisplay(mSurfaceHolder);
+ setPreviewTexture(mSurface);
try {
Log.v(TAG, "startPreview");