summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CameraActivity.java4
-rw-r--r--src/com/android/camera/MediaSaveService.java9
-rw-r--r--src/com/android/camera/PhotoModule.java5
-rw-r--r--src/com/android/camera/PhotoUI.java20
-rw-r--r--src/com/android/camera/VideoModule.java504
-rw-r--r--src/com/android/camera/VideoUI.java18
-rw-r--r--src/com/android/camera/ui/FilmStripView.java105
7 files changed, 157 insertions, 508 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 1baa865fd..411b29ea7 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -127,6 +127,10 @@ public class CameraActivity extends Activity
private ActionBar mActionBar;
private Menu mActionBarMenu;
+ public void gotoGallery() {
+ mFilmStripView.getController().goToNextItem();
+ }
+
private class MyOrientationEventListener
extends OrientationEventListener {
public MyOrientationEventListener(Context context) {
diff --git a/src/com/android/camera/MediaSaveService.java b/src/com/android/camera/MediaSaveService.java
index 713821d50..cec8b4329 100644
--- a/src/com/android/camera/MediaSaveService.java
+++ b/src/com/android/camera/MediaSaveService.java
@@ -37,6 +37,8 @@ import java.io.File;
* Service for saving images in the background thread.
*/
public class MediaSaveService extends Service {
+ public static final String VIDEO_BASE_URI = "content://media/external/video/media";
+
// The memory limit for unsaved image is 20MB.
private static final int SAVE_TASK_MEMORY_LIMIT = 20 * 1024 * 1024;
private static final String TAG = "CAM_" + MediaSaveService.class.getSimpleName();
@@ -207,17 +209,12 @@ public class MediaSaveService extends Service {
}
@Override
- protected void onPreExecute() {
- // do nothing.
- }
-
- @Override
protected Uri doInBackground(Void... v) {
values.put(Video.Media.SIZE, new File(path).length());
values.put(Video.Media.DURATION, duration);
Uri uri = null;
try {
- Uri videoTable = Uri.parse("content://media/external/video/media");
+ Uri videoTable = Uri.parse(VIDEO_BASE_URI);
uri = resolver.insert(videoTable, values);
// Rename the video file to the final name. This avoids other
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 6098d01f3..bb486cb62 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -681,9 +681,6 @@ public class PhotoModule
}
if (mIsImageCaptureIntent) {
stopPreview();
- } else {
- // Animate capture with real jpeg data instead of a preview frame.
- mUI.animateCapture(jpegData);
}
if (mSceneMode == CameraUtil.SCENE_MODE_HDR) {
mUI.showSwitcher();
@@ -754,6 +751,8 @@ public class PhotoModule
jpegData, title, date, mLocation, width, height,
orientation, exif, mOnMediaSavedListener, mContentResolver);
}
+ // Animate capture with real jpeg data instead of a preview frame.
+ mUI.animateCapture(jpegData, orientation);
} else {
mJpegImageData = jpegData;
if (!mQuickCapture) {
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 43862d376..7adb27f90 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -147,15 +147,24 @@ public class PhotoUI implements PieListener,
private class DecodeTask extends AsyncTask<Integer, Void, Bitmap> {
private final byte [] mData;
+ private int mOrientation;
- public DecodeTask(byte[] data) {
+ public DecodeTask(byte[] data, int orientation) {
mData = data;
+ mOrientation = orientation;
}
@Override
protected Bitmap doInBackground(Integer... params) {
// Decode image in background.
- return CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR);
+ Bitmap bitmap = CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR);
+ if (mOrientation != 0) {
+ Matrix m = new Matrix();
+ m.postRotate(mOrientation);
+ return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m,
+ false);
+ }
+ return bitmap;
}
@Override
@@ -299,9 +308,9 @@ public class PhotoUI implements PieListener,
updateOnScreenIndicators(params, prefGroup, prefs);
}
- public void animateCapture(final byte[] jpegData) {
+ public void animateCapture(final byte[] jpegData, int orientation) {
// Decode jpeg byte array and then animate the jpeg
- DecodeTask task = new DecodeTask(jpegData);
+ DecodeTask task = new DecodeTask(jpegData, orientation);
task.execute();
}
@@ -321,8 +330,7 @@ public class PhotoUI implements PieListener,
mPreviewThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- // TODO: go to filmstrip
- // mActivity.gotoGallery();
+ mActivity.gotoGallery();
}
});
mMenuButton = mRootView.findViewById(R.id.menu);
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index e1b921d4c..bd2658e1b 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -77,14 +77,10 @@ public class VideoModule implements CameraModule,
CameraPreference.OnPreferenceChangedListener,
ShutterButton.OnShutterButtonListener,
MediaRecorder.OnErrorListener,
- MediaRecorder.OnInfoListener,
- EffectsRecorder.EffectsListener {
+ MediaRecorder.OnInfoListener {
private static final String TAG = "CAM_VideoModule";
- // We number the request code from 1000 to avoid collision with Gallery.
- private static final int REQUEST_EFFECT_BACKDROPPER = 1000;
-
private static final int CHECK_DISPLAY_ROTATION = 3;
private static final int CLEAR_SCREEN_DELAY = 4;
private static final int UPDATE_RECORD_TIME = 5;
@@ -114,8 +110,6 @@ public class VideoModule implements CameraModule,
private boolean mIsInReviewMode;
private boolean mSnapshotInProgress = false;
- private static final String EFFECT_BG_FROM_GALLERY = "gallery";
-
private final CameraErrorCallback mErrorCallback = new CameraErrorCallback();
private ComboPreferences mPreferences;
@@ -128,14 +122,6 @@ public class VideoModule implements CameraModule,
private boolean mQuickCapture;
private MediaRecorder mMediaRecorder;
- private EffectsRecorder mEffectsRecorder;
- private boolean mEffectsDisplayResult;
-
- private int mEffectType = EffectsRecorder.EFFECT_NONE;
- private Object mEffectParameter = null;
- private String mEffectUriFromGallery = null;
- private String mPrefVideoEffectDefault;
- private boolean mResetEffect = true;
private boolean mSwitchingCamera;
private boolean mMediaRecorderRecording = false;
@@ -349,8 +335,6 @@ public class VideoModule implements CameraModule,
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- mPrefVideoEffectDefault = mActivity.getString(R.string.pref_video_effect_default);
- resetEffect();
mOrientationManager = new OrientationManager(mActivity);
/*
@@ -398,33 +382,19 @@ public class VideoModule implements CameraModule,
mPendingSwitchCameraId = -1;
mUI.updateOnScreenIndicators(mParameters, mPreferences);
- // Disable the shutter button if effects are ON since it might take
- // a little more time for the effects preview to be ready. We do not
- // want to allow recording before that happens. The shutter button
- // will be enabled when we get the message from effectsrecorder that
- // the preview is running. This becomes critical when the camera is
- // swapped.
- if (effectsActive()) {
- mUI.enableShutter(false);
- }
}
// SingleTapListener
// Preview area is touched. Take a picture.
@Override
public void onSingleTapUp(View view, int x, int y) {
- if (mMediaRecorderRecording && effectsActive()) {
- new RotateTextToast(mActivity, R.string.disable_video_snapshot_hint,
- mOrientation).show();
- return;
- }
takeASnapshot();
}
private void takeASnapshot() {
// Only take snapshots if video snapshot is supported by device
if (CameraUtil.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
- if (!mMediaRecorderRecording || mPaused || mSnapshotInProgress || effectsActive()) {
+ if (!mMediaRecorderRecording || mPaused || mSnapshotInProgress) {
return;
}
MediaSaveService s = mActivity.getMediaSaveService();
@@ -463,11 +433,6 @@ public class VideoModule implements CameraModule,
private void initializeVideoControl() {
loadCameraPreferences();
mUI.initializePopup(mPreferenceGroup);
- if (effectsActive()) {
- mUI.overrideSettings(
- CameraSettings.KEY_VIDEO_QUALITY,
- Integer.toString(CamcorderProfile.QUALITY_480P));
- }
}
@Override
@@ -480,14 +445,6 @@ public class VideoModule implements CameraModule,
if (mOrientation != newOrientation) {
mOrientation = newOrientation;
- // The input of effects recorder is affected by
- // android.hardware.Camera.setDisplayOrientation. Its value only
- // compensates the camera orientation (no Display.getRotation).
- // So the orientation hint here should only consider sensor
- // orientation.
- if (effectsActive()) {
- mEffectsRecorder.setOrientationHint(mOrientation);
- }
}
// Show the toast after getting the first orientation changed.
@@ -531,15 +488,12 @@ public class VideoModule implements CameraModule,
}
private void onStopVideoRecording() {
- mEffectsDisplayResult = true;
boolean recordFail = stopVideoRecording();
if (mIsVideoCaptureIntent) {
- if (!effectsActive()) {
- if (mQuickCapture) {
- doReturnToCaller(!recordFail);
- } else if (!recordFail) {
- showCaptureResult();
- }
+ if (mQuickCapture) {
+ doReturnToCaller(!recordFail);
+ } else if (!recordFail) {
+ showCaptureResult();
}
} else if (!recordFail){
// Start capture animation.
@@ -551,10 +505,7 @@ public class VideoModule implements CameraModule,
// will not be continuous for a short period of time.
mUI.animateFlash();
- Bitmap bitmap = getVideoThumbnail();
- if (bitmap != null) {
- mUI.animateCapture(bitmap);
- }
+ mUI.animateCapture();
}
}
}
@@ -631,18 +582,6 @@ public class VideoModule implements CameraModule,
mMaxVideoDurationInMs = CameraSettings.getMaxVideoDuration(mActivity);
}
- // Set effect
- mEffectType = CameraSettings.readEffectType(mPreferences);
- if (mEffectType != EffectsRecorder.EFFECT_NONE) {
- mEffectParameter = CameraSettings.readEffectParameter(mPreferences);
- // Set quality to be no higher than 480p.
- CamcorderProfile profile = CamcorderProfile.get(mCameraId, quality);
- if (profile.videoFrameHeight > 480) {
- quality = CamcorderProfile.QUALITY_480P;
- }
- } else {
- mEffectParameter = null;
- }
// Read time lapse recording interval.
if (ApiHelper.HAS_TIME_LAPSE_RECORDING) {
String frameIntervalStr = mPreferences.getString(
@@ -658,18 +597,11 @@ public class VideoModule implements CameraModule,
mPreferenceRead = true;
}
- private void writeDefaultEffectToPrefs() {
- ComboPreferences.Editor editor = mPreferences.edit();
- editor.putString(CameraSettings.KEY_VIDEO_EFFECT,
- mActivity.getString(R.string.pref_video_effect_default));
- editor.apply();
- }
-
@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
private void getDesiredPreviewSize() {
mParameters = mCameraDevice.getParameters();
if (ApiHelper.HAS_GET_SUPPORTED_VIDEO_SIZE) {
- if (mParameters.getSupportedVideoSizes() == null || effectsActive()) {
+ if (mParameters.getSupportedVideoSizes() == null) {
mDesiredPreviewWidth = mProfile.videoFrameWidth;
mDesiredPreviewHeight = mProfile.videoFrameHeight;
} else { // Driver supports separates outputs for preview and video.
@@ -729,7 +661,6 @@ public class VideoModule implements CameraModule,
showVideoSnapshotUI(false);
if (!mPreviewing) {
- resetEffect();
openCamera();
if (mOpenCameraFail) {
CameraUtil.showErrorAndFinish(mActivity,
@@ -808,10 +739,6 @@ public class VideoModule implements CameraModule,
mCameraDevice.setErrorCallback(mErrorCallback);
if (mPreviewing == true) {
stopPreview();
- if (effectsActive() && mEffectsRecorder != null) {
- mEffectsRecorder.release();
- mEffectsRecorder = null;
- }
}
setDisplayOrientation();
@@ -819,17 +746,10 @@ public class VideoModule implements CameraModule,
setCameraParameters();
try {
- if (!effectsActive()) {
- mCameraDevice.setPreviewTexture(surfaceTexture);
- mCameraDevice.startPreview();
- mPreviewing = true;
- onPreviewStarted();
- } else {
- initializeEffectsPreview();
- mEffectsRecorder.startPreview();
- mPreviewing = true;
- onPreviewStarted();
- }
+ mCameraDevice.setPreviewTexture(surfaceTexture);
+ mCameraDevice.startPreview();
+ mPreviewing = true;
+ onPreviewStarted();
} catch (Throwable ex) {
closeCamera();
throw new RuntimeException("startPreview failed", ex);
@@ -853,49 +773,12 @@ public class VideoModule implements CameraModule,
mPreviewing = false;
}
- // Closing the effects out. Will shut down the effects graph.
- private void closeEffects() {
- Log.v(TAG, "Closing effects");
- mEffectType = EffectsRecorder.EFFECT_NONE;
- if (mEffectsRecorder == null) {
- Log.d(TAG, "Effects are already closed. Nothing to do");
- return;
- }
- // This call can handle the case where the camera is already released
- // after the recording has been stopped.
- mEffectsRecorder.release();
- mEffectsRecorder = null;
- }
-
- // By default, we want to close the effects as well with the camera.
private void closeCamera() {
- closeCamera(true);
- }
-
- // In certain cases, when the effects are active, we may want to shutdown
- // only the camera related parts, and handle closing the effects in the
- // effectsUpdate callback.
- // For example, in onPause, we want to make the camera available to
- // outside world immediately, however, want to wait till the effects
- // callback to shut down the effects. In such a case, we just disconnect
- // the effects from the camera by calling disconnectCamera. That way
- // the effects can handle that when shutting down.
- //
- // @param closeEffectsAlso - indicates whether we want to close the
- // effects also along with the camera.
- private void closeCamera(boolean closeEffectsAlso) {
Log.v(TAG, "closeCamera");
if (mCameraDevice == null) {
Log.d(TAG, "already stopped.");
return;
}
-
- if (mEffectsRecorder != null) {
- // Disconnect the camera from effects so that camera is ready to
- // be released to the outside world.
- mEffectsRecorder.disconnectCamera();
- }
- if (closeEffectsAlso) closeEffects();
mCameraDevice.setZoomChangeListener(null);
mCameraDevice.setErrorCallback(null);
CameraHolder.instance().release();
@@ -919,25 +802,12 @@ public class VideoModule implements CameraModule,
onStopVideoRecording();
} else {
closeCamera();
- if (!effectsActive()) releaseMediaRecorder();
- }
- if (effectsActive()) {
- // If the effects are active, make sure we tell the graph that the
- // surfacetexture is not valid anymore. Disconnect the graph from
- // the display. This should be done before releasing the surface
- // texture.
- mEffectsRecorder.disconnectDisplay();
- } else {
- // Close the file descriptor and clear the video namer only if the
- // effects are not active. If effects are active, we need to wait
- // till we get the callback from the Effects that the graph is done
- // recording. That also needs a change in the stopVideoRecording()
- // call to not call closeCamera if the effects are active, because
- // that will close down the effects are well, thus making this if
- // condition invalid.
- closeVideoFileDescriptor();
+ releaseMediaRecorder();
}
+ closeVideoFileDescriptor();
+
+
releasePreviewResources();
if (mReceiver != null) {
@@ -1191,98 +1061,6 @@ public class VideoModule implements CameraModule,
}
}
- private void initializeEffectsPreview() {
- Log.v(TAG, "initializeEffectsPreview");
- // If the mCameraDevice is null, then this activity is going to finish
- if (mCameraDevice == null) return;
-
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
-
- mEffectsDisplayResult = false;
- mEffectsRecorder = new EffectsRecorder(mActivity);
-
- // TODO: Confirm none of the following need to go to initializeEffectsRecording()
- // and none of these change even when the preview is not refreshed.
- mEffectsRecorder.setCameraDisplayOrientation(mCameraDisplayOrientation);
- mEffectsRecorder.setCamera(mCameraDevice);
- mEffectsRecorder.setCameraFacing(info.facing);
- mEffectsRecorder.setProfile(mProfile);
- mEffectsRecorder.setEffectsListener(this);
- mEffectsRecorder.setOnInfoListener(this);
- mEffectsRecorder.setOnErrorListener(this);
-
- // The input of effects recorder is affected by
- // android.hardware.Camera.setDisplayOrientation. Its value only
- // compensates the camera orientation (no Display.getRotation). So the
- // orientation hint here should only consider sensor orientation.
- int orientation = 0;
- if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
- orientation = mOrientation;
- }
- mEffectsRecorder.setOrientationHint(orientation);
-
- mEffectsRecorder.setPreviewSurfaceTexture(mUI.getSurfaceTexture(),
- mUI.getPreviewWidth(), mUI.getPreviewHeight());
-
- if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER &&
- ((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)) {
- mEffectsRecorder.setEffect(mEffectType, mEffectUriFromGallery);
- } else {
- mEffectsRecorder.setEffect(mEffectType, mEffectParameter);
- }
- }
-
- private void initializeEffectsRecording() {
- Log.v(TAG, "initializeEffectsRecording");
-
- Intent intent = mActivity.getIntent();
- Bundle myExtras = intent.getExtras();
-
- long requestedSizeLimit = 0;
- closeVideoFileDescriptor();
- if (mIsVideoCaptureIntent && myExtras != null) {
- Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
- if (saveUri != null) {
- try {
- mVideoFileDescriptor =
- mContentResolver.openFileDescriptor(saveUri, "rw");
- mCurrentVideoUri = saveUri;
- } catch (java.io.FileNotFoundException ex) {
- // invalid uri
- Log.e(TAG, ex.toString());
- }
- }
- requestedSizeLimit = myExtras.getLong(MediaStore.EXTRA_SIZE_LIMIT);
- }
-
- mEffectsRecorder.setProfile(mProfile);
- // important to set the capture rate to zero if not timelapsed, since the
- // effectsrecorder object does not get created again for each recording
- // session
- if (mCaptureTimeLapse) {
- mEffectsRecorder.setCaptureRate((1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs));
- } else {
- mEffectsRecorder.setCaptureRate(0);
- }
-
- // Set output file
- if (mVideoFileDescriptor != null) {
- mEffectsRecorder.setOutputFile(mVideoFileDescriptor.getFileDescriptor());
- } else {
- generateVideoFilename(mProfile.fileFormat);
- mEffectsRecorder.setOutputFile(mVideoFilename);
- }
-
- // Set maximum file size.
- long maxFileSize = mActivity.getStorageSpace() - Storage.LOW_STORAGE_THRESHOLD;
- if (requestedSizeLimit > 0 && requestedSizeLimit < maxFileSize) {
- maxFileSize = requestedSizeLimit;
- }
- mEffectsRecorder.setMaxFileSize(maxFileSize);
- mEffectsRecorder.setMaxDuration(mMaxVideoDurationInMs);
- }
-
-
private void releaseMediaRecorder() {
Log.v(TAG, "Releasing media recorder.");
if (mMediaRecorder != null) {
@@ -1294,17 +1072,6 @@ public class VideoModule implements CameraModule,
mVideoFilename = null;
}
- private void releaseEffectsRecorder() {
- Log.v(TAG, "Releasing effects recorder.");
- if (mEffectsRecorder != null) {
- cleanupEmptyFile();
- mEffectsRecorder.release();
- mEffectsRecorder = null;
- }
- mEffectType = EffectsRecorder.EFFECT_NONE;
- mVideoFilename = null;
- }
-
private void generateVideoFilename(int outputFileFormat) {
long dateTaken = System.currentTimeMillis();
String title = createName(dateTaken);
@@ -1429,40 +1196,23 @@ public class VideoModule implements CameraModule,
//??
//if (!mCameraDevice.waitDone()) return;
mCurrentVideoUri = null;
- if (effectsActive()) {
- initializeEffectsRecording();
- if (mEffectsRecorder == null) {
- Log.e(TAG, "Fail to initialize effect recorder");
- return;
- }
- } else {
- initializeRecorder();
- if (mMediaRecorder == null) {
- Log.e(TAG, "Fail to initialize media recorder");
- return;
- }
+
+ initializeRecorder();
+ if (mMediaRecorder == null) {
+ Log.e(TAG, "Fail to initialize media recorder");
+ return;
}
pauseAudioPlayback();
- if (effectsActive()) {
- try {
- mEffectsRecorder.startRecording();
- } catch (RuntimeException e) {
- Log.e(TAG, "Could not start effects recorder. ", e);
- releaseEffectsRecorder();
- return;
- }
- } else {
- try {
- mMediaRecorder.start(); // Recording is now started
- } catch (RuntimeException e) {
- Log.e(TAG, "Could not start media recorder. ", e);
- releaseMediaRecorder();
- // If start fails, frameworks will not lock the camera for us.
- mCameraDevice.lock();
- return;
- }
+ try {
+ mMediaRecorder.start(); // Recording is now started
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not start media recorder. ", e);
+ releaseMediaRecorder();
+ // If start fails, frameworks will not lock the camera for us.
+ mCameraDevice.lock();
+ return;
}
// Make sure the video recording has started before announcing
@@ -1509,6 +1259,7 @@ public class VideoModule implements CameraModule,
Log.e(TAG, ex.toString());
}
}
+
if (bitmap != null) {
// MetadataRetriever already rotates the thumbnail. We should rotate
// it to match the UI orientation (and mirror if it is front-facing camera).
@@ -1542,18 +1293,10 @@ public class VideoModule implements CameraModule,
boolean shouldAddToMediaStoreNow = false;
try {
- if (effectsActive()) {
- // This is asynchronous, so we can't add to media store now because thumbnail
- // may not be ready. In such case saveVideo() is called later
- // through a callback from the MediaEncoderFilter to EffectsRecorder,
- // and then to the VideoModule.
- mEffectsRecorder.stopRecording();
- } else {
- mMediaRecorder.setOnErrorListener(null);
- mMediaRecorder.setOnInfoListener(null);
- mMediaRecorder.stop();
- shouldAddToMediaStoreNow = true;
- }
+ mMediaRecorder.setOnErrorListener(null);
+ mMediaRecorder.setOnInfoListener(null);
+ mMediaRecorder.stop();
+ shouldAddToMediaStoreNow = true;
mCurrentVideoFilename = mVideoFilename;
Log.v(TAG, "stopVideoRecording: Setting current video filename: "
+ mCurrentVideoFilename);
@@ -1570,17 +1313,8 @@ public class VideoModule implements CameraModule,
// If the activity is paused, this means activity is interrupted
// during recording. Release the camera as soon as possible because
// face unlock or other applications may need to use the camera.
- // However, if the effects are active, then we can only release the
- // camera and cannot release the effects recorder since that will
- // stop the graph. It is possible to separate out the Camera release
- // part and the effects release part. However, the effects recorder
- // does hold on to the camera, hence, it needs to be "disconnected"
- // from the camera in the closeCamera call.
if (mPaused) {
- // Closing only the camera part if effects active. Effects will
- // be closed in the callback from effects.
- boolean closeEffects = !effectsActive();
- closeCamera(closeEffects);
+ closeCamera();
}
mUI.showRecordingUI(false, mParameters.isZoomSupported());
@@ -1600,17 +1334,15 @@ public class VideoModule implements CameraModule,
}
}
}
- // always release media recorder if no effects running
- if (!effectsActive()) {
- releaseMediaRecorder();
- if (!mPaused) {
- mCameraDevice.lock();
- if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
- stopPreview();
- mUI.hideSurfaceView();
- // Switch back to use SurfaceTexture for preview.
- startPreview();
- }
+ // release media recorder
+ releaseMediaRecorder();
+ if (!mPaused) {
+ mCameraDevice.lock();
+ if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
+ stopPreview();
+ mUI.hideSurfaceView();
+ // Switch back to use SurfaceTexture for preview.
+ startPreview();
}
}
// Update the parameters here because the parameters might have been altered
@@ -1836,84 +1568,7 @@ public class VideoModule implements CameraModule,
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_EFFECT_BACKDROPPER:
- if (resultCode == Activity.RESULT_OK) {
- // onActivityResult() runs before onResume(), so this parameter will be
- // seen by startPreview from onResume()
- mEffectUriFromGallery = data.getData().toString();
- Log.v(TAG, "Received URI from gallery: " + mEffectUriFromGallery);
- mResetEffect = false;
- } else {
- mEffectUriFromGallery = null;
- Log.w(TAG, "No URI from gallery");
- mResetEffect = true;
- }
- break;
- }
- }
-
- @Override
- public void onEffectsUpdate(int effectId, int effectMsg) {
- Log.v(TAG, "onEffectsUpdate. Effect Message = " + effectMsg);
- if (effectMsg == EffectsRecorder.EFFECT_MSG_EFFECTS_STOPPED) {
- // Effects have shut down. Hide learning message if any,
- // and restart regular preview.
- checkQualityAndStartPreview();
- } else if (effectMsg == EffectsRecorder.EFFECT_MSG_RECORDING_DONE) {
- // This follows the codepath from onStopVideoRecording.
- if (mEffectsDisplayResult) {
- saveVideo();
- if (mIsVideoCaptureIntent) {
- if (mQuickCapture) {
- doReturnToCaller(true);
- } else {
- showCaptureResult();
- }
- }
- }
- mEffectsDisplayResult = false;
- // In onPause, these were not called if the effects were active. We
- // had to wait till the effects recording is complete to do this.
- if (mPaused) {
- closeVideoFileDescriptor();
- }
- } else if (effectMsg == EffectsRecorder.EFFECT_MSG_PREVIEW_RUNNING) {
- // Enable the shutter button once the preview is complete.
- mUI.enableShutter(true);
- }
- // In onPause, this was not called if the effects were active. We had to
- // wait till the effects completed to do this.
- if (mPaused) {
- Log.v(TAG, "OnEffectsUpdate: closing effects if activity paused");
- closeEffects();
- }
- }
-
- public void onCancelBgTraining(View v) {
- // Write default effect out to shared prefs
- writeDefaultEffectToPrefs();
- // Tell VideoCamer to re-init based on new shared pref values.
- onSharedPreferenceChanged();
- }
-
- @Override
- public synchronized void onEffectsError(Exception exception, String fileName) {
- // TODO: Eventually we may want to show the user an error dialog, and then restart the
- // camera and encoder gracefully. For now, we just delete the file and bail out.
- if (fileName != null && new File(fileName).exists()) {
- deleteVideoFile(fileName);
- }
- try {
- if (Class.forName("android.filterpacks.videosink.MediaRecorderStopException")
- .isInstance(exception)) {
- Log.w(TAG, "Problem recoding video file. Removing incomplete file.");
- return;
- }
- } catch (ClassNotFoundException ex) {
- Log.w(TAG, ex);
- }
- throw new RuntimeException("Error during recording!", exception);
+ // Do nothing.
}
@Override
@@ -1931,10 +1586,6 @@ public class VideoModule implements CameraModule,
public void onRestorePreferencesClicked() {
}
- private boolean effectsActive() {
- return (mEffectType != EffectsRecorder.EFFECT_NONE);
- }
-
@Override
public void onSharedPreferenceChanged() {
// ignore the events after "onPause()" or preview has not started yet
@@ -1948,21 +1599,14 @@ public class VideoModule implements CameraModule,
mPreferences, mContentResolver);
mLocationManager.recordLocation(recordLocation);
- // Check if the current effects selection has changed
- if (updateEffectSelection()) return;
-
readVideoPreferences();
mUI.showTimeLapseUI(mCaptureTimeLapse);
// We need to restart the preview if preview size is changed.
Size size = mParameters.getPreviewSize();
if (size.width != mDesiredPreviewWidth
|| size.height != mDesiredPreviewHeight) {
- if (!effectsActive()) {
- stopPreview();
- } else {
- mEffectsRecorder.release();
- mEffectsRecorder = null;
- }
+
+ stopPreview();
resizeForPreviewAspectRatio();
startPreview(); // Parameters will be set in startPreview().
} else {
@@ -2019,46 +1663,6 @@ public class VideoModule implements CameraModule,
public void onCaptureTextureCopied() {
}
- private boolean updateEffectSelection() {
- int previousEffectType = mEffectType;
- Object previousEffectParameter = mEffectParameter;
- mEffectType = CameraSettings.readEffectType(mPreferences);
- mEffectParameter = CameraSettings.readEffectParameter(mPreferences);
-
- if (mEffectType == previousEffectType) {
- if (mEffectType == EffectsRecorder.EFFECT_NONE) return false;
- if (mEffectParameter.equals(previousEffectParameter)) return false;
- }
- Log.v(TAG, "New effect selection: " + mPreferences.getString(
- CameraSettings.KEY_VIDEO_EFFECT, "none"));
-
- if (mEffectType == EffectsRecorder.EFFECT_NONE) {
- // Stop effects and return to normal preview
- mEffectsRecorder.stopPreview();
- mPreviewing = false;
- return true;
- }
- if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER &&
- ((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)) {
- // Request video from gallery to use for background
- Intent i = new Intent(Intent.ACTION_PICK);
- i.setDataAndType(Video.Media.EXTERNAL_CONTENT_URI,
- "video/*");
- i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- mActivity.startActivityForResult(i, REQUEST_EFFECT_BACKDROPPER);
- return true;
- }
- if (previousEffectType == EffectsRecorder.EFFECT_NONE) {
- // Stop regular preview and start effects.
- stopPreview();
- checkQualityAndStartPreview();
- } else {
- // Switch currently running effect
- mEffectsRecorder.setEffect(mEffectType, mEffectParameter);
- }
- return true;
- }
-
// Verifies that the current preview view size is correct before starting
// preview. If not, resets the surface texture and resizes the view.
private void checkQualityAndStartPreview() {
@@ -2090,6 +1694,7 @@ public class VideoModule implements CameraModule,
if (CameraUtil.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
if (enabled) {
mUI.animateFlash();
+ mUI.animateCapture();
} else {
mUI.showPreviewBorder(enabled);
}
@@ -2147,19 +1752,6 @@ public class VideoModule implements CameraModule,
exif, mOnPhotoSavedListener, mContentResolver);
}
- private boolean resetEffect() {
- if (mResetEffect) {
- String value = mPreferences.getString(CameraSettings.KEY_VIDEO_EFFECT,
- mPrefVideoEffectDefault);
- if (!mPrefVideoEffectDefault.equals(value)) {
- writeDefaultEffectToPrefs();
- return true;
- }
- }
- mResetEffect = true;
- return false;
- }
-
private String convertOutputFormatToMimeType(int outputFileFormat) {
if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) {
return "video/mp4";
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 684179698..74d4cea9b 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -305,9 +305,25 @@ public class VideoUI implements PieRenderer.PieListener,
/**
* Starts a capture animation
+ */
+ public void animateCapture() {
+ Bitmap bitmap = null;
+ if (mTextureView != null) {
+ bitmap = mTextureView.getBitmap((int) mSurfaceTextureUncroppedWidth / 2,
+ (int) mSurfaceTextureUncroppedHeight / 2);
+ }
+ animateCapture(bitmap);
+ }
+
+ /**
+ * Starts a capture animation
* @param bitmap the captured image that we shrink and slide in the animation
*/
public void animateCapture(Bitmap bitmap) {
+ if (bitmap == null) {
+ Log.e(TAG, "No valid bitmap for capture animation.");
+ return;
+ }
((ImageView) mPreviewThumb).setImageBitmap(bitmap);
mAnimationManager.startCaptureAnimation(mPreviewThumb);
}
@@ -418,7 +434,7 @@ public class VideoUI implements PieRenderer.PieListener,
mPreviewThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- // TODO: Go to filmstrip view
+ mActivity.gotoGallery();
}
});
}
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 4d37f04c4..85ebd6cc5 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -28,6 +28,7 @@ import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.Scroller;
@@ -43,7 +44,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
private static final String TAG = "CAM_FilmStripView";
private static final int BUFFER_SIZE = 5;
- private static final int DURATION_GEOMETRY_ADJUST = 200;
+ private static final int GEOMETRY_ADJUST_TIME_MS = 400;
private static final int SNAP_IN_CENTER_TIME_MS = 600;
private static final float FILM_STRIP_SCALE = 0.6f;
private static final float FULL_SCREEN_SCALE = 1f;
@@ -341,17 +342,19 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
public void fling(float velocity);
- public void scrollTo(int position, int duration, boolean interruptible);
+ public void scrollToPosition(int position, int duration, boolean interruptible);
+
+ public boolean goToNextItem();
public boolean stopScrolling();
public boolean isScrolling();
- public void gotoCameraFullScreen();
+ public void goToCameraFullScreen();
- public void gotoFilmStrip();
+ public void goToFilmStrip();
- public void gotoFullScreen();
+ public void goToFullScreen();
}
/**
@@ -861,13 +864,13 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (mCenterX != currentViewCenter) {
int snapInTime = (int) (SNAP_IN_CENTER_TIME_MS
* Math.abs(mCenterX - currentViewCenter) / mDrawArea.width());
- mController.scrollTo(currentViewCenter,
+ mController.scrollToPosition(currentViewCenter,
snapInTime, false);
}
if (getCurrentViewType() == ImageData.TYPE_STICKY_VIEW
&& !mController.isScalling()
&& mScale != FULL_SCREEN_SCALE) {
- mController.gotoFullScreen();
+ mController.goToFullScreen();
}
}
@@ -1031,7 +1034,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
private void slideViewBack(View v) {
v.animate().translationX(0)
.alpha(1f)
- .setDuration(DURATION_GEOMETRY_ADJUST)
+ .setDuration(GEOMETRY_ADJUST_TIME_MS)
.setInterpolator(mViewAnimInterpolator)
.start();
}
@@ -1143,7 +1146,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
.alpha(0f)
.translationYBy(transY)
.setInterpolator(mViewAnimInterpolator)
- .setDuration(DURATION_GEOMETRY_ADJUST)
+ .setDuration(GEOMETRY_ADJUST_TIME_MS)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -1236,7 +1239,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
.alpha(1f)
.translationY(0f)
.setInterpolator(mViewAnimInterpolator)
- .setDuration(DURATION_GEOMETRY_ADJUST)
+ .setDuration(GEOMETRY_ADJUST_TIME_MS)
.start();
invalidate();
}
@@ -1457,25 +1460,39 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
ValueAnimator.AnimatorUpdateListener,
Animator.AnimatorListener {
- private ValueAnimator mScaleAnimator;
+ private final ValueAnimator mScaleAnimator;
private boolean mHasNewScale;
private float mNewScale;
- private Scroller mScroller;
+ private final Scroller mScroller;
private boolean mHasNewPosition;
- private DecelerateInterpolator mDecelerateInterpolator;
+ private final DecelerateInterpolator mDecelerateInterpolator;
+ private final TimeInterpolator mDecelerateAccelerateInterpolator =
+ new TimeInterpolator() {
+ private final TimeInterpolator interpolator =
+ new AccelerateInterpolator();
+
+ @Override
+ public float getInterpolation(float v) {
+ float v2 = v * 2f;
+ return ((v2 < 1f) ?
+ mDecelerateInterpolator.getInterpolation(v2) / 2f :
+ interpolator.getInterpolation(v2 - 1f) / 2f + 0.5f);
+ }
+ };
private boolean mCanStopScroll;
MyController(Context context) {
mScroller = new Scroller(context);
mHasNewPosition = false;
+ mCanStopScroll = true;
+ mHasNewScale = false;
+
mScaleAnimator = new ValueAnimator();
mScaleAnimator.addUpdateListener(MyController.this);
mScaleAnimator.addListener(MyController.this);
- mDecelerateInterpolator = new DecelerateInterpolator();
- mCanStopScroll = true;
- mHasNewScale = false;
+ mDecelerateInterpolator = new DecelerateInterpolator(1.5f);
}
@Override
@@ -1485,7 +1502,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public boolean isScalling() {
- return mScaleAnimator.isRunning();
+ return (mScaleAnimator.isRunning());
}
boolean hasNewGeometry() {
@@ -1553,7 +1570,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (inFullScreen() && getCurrentViewType() == ImageData.TYPE_STICKY_VIEW
&& scaledVelocityX < 0) {
// Swipe left in camera preview.
- gotoFilmStrip();
+ goToFilmStrip();
}
int w = getWidth();
@@ -1585,7 +1602,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
}
@Override
- public void scrollTo(int position, int duration, boolean interruptible) {
+ public void scrollToPosition(int position, int duration, boolean interruptible) {
if (!stopScrolling()) {
return;
}
@@ -1593,9 +1610,25 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
stopScrolling();
mScroller.startScroll(mCenterX, 0, position - mCenterX,
0, duration);
+ mHasNewPosition = true;
invalidate();
}
+ @Override
+ public boolean goToNextItem() {
+ ViewItem nextItem = mViewItem[mCurrentItem + 1];
+ if (nextItem == null) {
+ return false;
+ }
+ stopScale();
+ scrollToPosition(nextItem.getCenterX(), GEOMETRY_ADJUST_TIME_MS * 2, false);
+ mScaleAnimator.setFloatValues(FULL_SCREEN_SCALE, FILM_STRIP_SCALE, FULL_SCREEN_SCALE);
+ mScaleAnimator.setInterpolator(mDecelerateAccelerateInterpolator);
+ mScaleAnimator.setDuration(GEOMETRY_ADJUST_TIME_MS * 2);
+ mScaleAnimator.start();
+ return true;
+ }
+
private void scaleTo(float scale, int duration) {
if (mViewItem[mCurrentItem] == null) {
return;
@@ -1605,13 +1638,12 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
mScaleAnimator.setFloatValues(mScale, scale);
mScaleAnimator.setInterpolator(mDecelerateInterpolator);
mScaleAnimator.start();
- mHasNewScale = true;
layoutChildren();
}
@Override
- public void gotoFilmStrip() {
- scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST);
+ public void goToFilmStrip() {
+ scaleTo(FILM_STRIP_SCALE, GEOMETRY_ADJUST_TIME_MS);
if (mListener != null) {
mListener.onSwitchMode(false);
mBottomControls.setVisibility(View.VISIBLE);
@@ -1619,10 +1651,10 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
}
@Override
- public void gotoFullScreen() {
+ public void goToFullScreen() {
if (mViewItem[mCurrentItem] != null) {
- mController.scrollTo(mViewItem[mCurrentItem].getCenterX(),
- DURATION_GEOMETRY_ADJUST, false);
+ mController.scrollToPosition(mViewItem[mCurrentItem].getCenterX(),
+ GEOMETRY_ADJUST_TIME_MS, false);
}
enterFullScreen();
}
@@ -1639,21 +1671,21 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (inFullScreen()) {
return;
}
- scaleTo(1f, DURATION_GEOMETRY_ADJUST);
+ scaleTo(1f, GEOMETRY_ADJUST_TIME_MS);
}
@Override
- public void gotoCameraFullScreen() {
+ public void goToCameraFullScreen() {
if (mDataAdapter.getImageData(0).getViewType()
!= ImageData.TYPE_STICKY_VIEW) {
return;
}
- gotoFullScreen();
- scrollTo(
+ goToFullScreen();
+ scrollToPosition(
estimateMinX(mViewItem[mCurrentItem].getID(),
mViewItem[mCurrentItem].getLeftPosition(),
getWidth()),
- DURATION_GEOMETRY_ADJUST, false);
+ GEOMETRY_ADJUST_TIME_MS, false);
}
@Override
@@ -1668,6 +1700,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public void onAnimationStart(Animator anim) {
+ mHasNewScale = true;
}
@Override
@@ -1701,7 +1734,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (inFilmStrip()) {
ViewItem centerItem = mViewItem[mCurrentItem];
if (centerItem != null && centerItem.areaContains(x, y)) {
- mController.gotoFullScreen();
+ mController.goToFullScreen();
return true;
}
} else if (inFullScreen()) {
@@ -1752,7 +1785,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
mViewItem[i].getView().animate()
.translationY(0f)
.alpha(1f)
- .setDuration(DURATION_GEOMETRY_ADJUST)
+ .setDuration(GEOMETRY_ADJUST_TIME_MS)
.start();
}
}
@@ -1772,7 +1805,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
if (deltaX > 0
&& inFullScreen()
&& getCurrentViewType() == ImageData.TYPE_STICKY_VIEW) {
- mController.gotoFilmStrip();
+ mController.goToFilmStrip();
}
mController.scroll(deltaX);
} else {
@@ -1805,7 +1838,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
}
} else if (inFullScreen()) {
if (deltaX > 0 && inCameraFullscreen()) {
- mController.gotoFilmStrip();
+ mController.goToFilmStrip();
}
// Multiplied by 1.2 to make it more easy to swipe.
mController.scroll((int) (deltaX * 1.2));
@@ -1860,9 +1893,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
@Override
public void onScaleEnd() {
if (mScaleTrend >= 1f) {
- mController.gotoFullScreen();
+ mController.goToFullScreen();
} else {
- mController.gotoFilmStrip();
+ mController.goToFilmStrip();
}
mScaleTrend = 1f;
}