Camera2: Added pause button in Camcorder
- Added pause button in camcorder app.so that user pause
recording and resume later which results in a single
recorded clip.
CRs-Fixed: 587051
Change-Id: I2a7d8af7fcea74fe8af62c44119c3c1fa0c13e85
diff --git a/src/com/android/camera/PauseButton.java b/src/com/android/camera/PauseButton.java
new file mode 100644
index 0000000..a785050
--- /dev/null
+++ b/src/com/android/camera/PauseButton.java
@@ -0,0 +1,82 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.camera;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.view.MotionEvent;
+import android.view.View;
+import android.util.Log;
+
+/**
+ * A button designed to be used for the on-screen recording
+ * pausing-continue button.
+ */
+public class PauseButton extends ImageView {
+
+ public interface OnPauseButtonListener {
+ void onButtonPause();
+ void onButtonContinue();
+ }
+
+ public PauseButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setClickable(true);
+ setSelected(false);
+ }
+
+ public void setPaused(boolean paused) {
+ setSelected(paused);
+ }
+
+ @Override
+ public boolean performClick() {
+ boolean result = super.performClick();
+ if (isSelected()) {
+ setSelected(false);
+ if (mListener != null && getVisibility() == View.VISIBLE) {
+ mListener.onButtonContinue();
+ }
+ } else {
+ setSelected(true);
+ if (mListener != null && getVisibility() == View.VISIBLE) {
+ mListener.onButtonPause();
+ }
+ }
+ return result;
+ }
+
+ public void setOnPauseButtonListener(OnPauseButtonListener listener) {
+ mListener = listener;
+ }
+
+ private OnPauseButtonListener mListener;
+}
diff --git a/src/com/android/camera/VideoController.java b/src/com/android/camera/VideoController.java
index e846548..cf694a3 100644
--- a/src/com/android/camera/VideoController.java
+++ b/src/com/android/camera/VideoController.java
@@ -19,8 +19,9 @@
import android.view.View;
import com.android.camera.ShutterButton.OnShutterButtonListener;
+import com.android.camera.PauseButton.OnPauseButtonListener;
-public interface VideoController extends OnShutterButtonListener {
+public interface VideoController extends OnShutterButtonListener, OnPauseButtonListener {
public void onReviewDoneClicked(View view);
public void onReviewCancelClicked(View viwe);
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index a79bc25..f2562b1 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -129,7 +129,9 @@
private boolean mSwitchingCamera;
private boolean mMediaRecorderRecording = false;
+ private boolean mMediaRecorderPausing = false;
private long mRecordingStartTime;
+ private long mRecordingTotalTime;
private boolean mRecordingTimeCountsDown = false;
private long mOnResumeTime;
// The video file that the hardware camera is about to record into
@@ -460,6 +462,7 @@
// Preview area is touched. Take a picture.
@Override
public void onSingleTapUp(View view, int x, int y) {
+ if (mMediaRecorderPausing) return;
takeASnapshot();
}
@@ -1329,7 +1332,7 @@
private void saveVideo() {
if (mVideoFileDescriptor == null) {
- long duration = SystemClock.uptimeMillis() - mRecordingStartTime;
+ long duration = SystemClock.uptimeMillis() - mRecordingStartTime + mRecordingTotalTime;
if (duration > 0) {
if (mCaptureTimeLapse) {
duration = getTimeLapseVideoLength(duration);
@@ -1491,7 +1494,10 @@
mUI.enableCameraControls(false);
mMediaRecorderRecording = true;
+ mMediaRecorderPausing = false;
+ mUI.resetPauseButton();
mOrientationManager.lockOrientation();
+ mRecordingTotalTime = 0L;
mRecordingStartTime = SystemClock.uptimeMillis();
mUI.showRecordingUI(true);
@@ -1539,6 +1545,21 @@
mUI.showTimeLapseUI(false);
}
+ private void pauseVideoRecording() {
+ Log.v(TAG, "pauseVideoRecording");
+ mMediaRecorderPausing = true;
+ mRecordingTotalTime += SystemClock.uptimeMillis() - mRecordingStartTime;
+ mMediaRecorder.pause();
+ }
+
+ private void resumeVideoRecording() {
+ Log.v(TAG, "resumeVideoRecording");
+ mMediaRecorderPausing = false;
+ mRecordingStartTime = SystemClock.uptimeMillis();
+ updateRecordingTime();
+ mMediaRecorder.start();
+ }
+
private boolean stopVideoRecording() {
Log.v(TAG, "stopVideoRecording");
mStopRecPending = true;
@@ -1616,7 +1637,7 @@
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
fail ? UsageStatistics.ACTION_CAPTURE_FAIL :
UsageStatistics.ACTION_CAPTURE_DONE, "Video",
- SystemClock.uptimeMillis() - mRecordingStartTime);
+ SystemClock.uptimeMillis() - mRecordingStartTime + mRecordingTotalTime);
mStopRecPending = false;
return fail;
}
@@ -1693,8 +1714,12 @@
if (!mMediaRecorderRecording) {
return;
}
+ if (mMediaRecorderPausing) {
+ return;
+ }
+
long now = SystemClock.uptimeMillis();
- long delta = now - mRecordingStartTime;
+ long delta = now - mRecordingStartTime + mRecordingTotalTime;
// Starting a minute before reaching the max duration
// limit, we'll countdown the remaining time instead.
@@ -2227,4 +2252,15 @@
public void onPreviewUIDestroyed() {
stopPreview();
}
+
+ @Override
+ public void onButtonPause() {
+ pauseVideoRecording();
+ }
+
+ @Override
+ public void onButtonContinue() {
+ resumeVideoRecording();
+ }
+
}
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index bb270b7..8ea7091 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -49,6 +49,7 @@
import com.android.camera.ui.PieRenderer;
import com.android.camera.ui.RenderOverlay;
import com.android.camera.ui.RotateLayout;
+import com.android.camera.PauseButton.OnPauseButtonListener;
import com.android.camera.ui.ZoomRenderer;
import com.android.camera.util.CameraUtil;
import com.android.camera2.R;
@@ -58,7 +59,8 @@
public class VideoUI implements PieRenderer.PieListener,
PreviewGestures.SingleTapListener,
CameraRootView.MyDisplayListener,
- SurfaceTextureListener, SurfaceHolder.Callback {
+ SurfaceTextureListener, SurfaceHolder.Callback,
+ PauseButton.OnPauseButtonListener {
private static final String TAG = "CAM_VideoUI";
private static final int UPDATE_TRANSFORM_MATRIX = 1;
// module fields
@@ -72,6 +74,7 @@
private View mReviewDoneButton;
private View mReviewPlayButton;
private ShutterButton mShutterButton;
+ private PauseButton mPauseButton;
private ModuleSwitcher mSwitcher;
private TextView mRecordingTimeView;
private LinearLayout mLabelsLinearLayout;
@@ -192,6 +195,7 @@
initializeMiscControls();
initializeControlByIntent();
initializeOverlay();
+ initializePauseButton();
mAnimationManager = new AnimationManager();
mOrientationResize = false;
mPrevOrientationResize = false;
@@ -514,6 +518,11 @@
mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels);
}
+ private void initializePauseButton() {
+ mPauseButton = (PauseButton) mRootView.findViewById(R.id.video_pause);
+ mPauseButton.setOnPauseButtonListener(this);
+ }
+
public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) {
mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode());
boolean location = RecordLocationPreference.get(
@@ -631,12 +640,14 @@
hideSwitcher();
mRecordingTimeView.setText("");
mRecordingTimeView.setVisibility(View.VISIBLE);
+ mPauseButton.setVisibility(View.VISIBLE);
} else {
mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
if (!mController.isVideoCaptureIntent()) {
showSwitcher();
}
mRecordingTimeView.setVisibility(View.GONE);
+ mPauseButton.setVisibility(View.GONE);
}
}
@@ -811,4 +822,24 @@
Log.v(TAG, "Surface destroyed");
mController.stopPreview();
}
+
+ @Override
+ public void onButtonPause() {
+ mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+ R.drawable.ic_pausing_indicator, 0, 0, 0);
+ mController.onButtonPause();
+ }
+
+ @Override
+ public void onButtonContinue() {
+ mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+ R.drawable.ic_recording_indicator, 0, 0, 0);
+ mController.onButtonContinue();
+ }
+
+ public void resetPauseButton() {
+ mRecordingTimeView.setCompoundDrawablesWithIntrinsicBounds(
+ R.drawable.ic_recording_indicator, 0, 0, 0);
+ mPauseButton.setPaused(false);
+ }
}