diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:25 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:25 -0800 |
commit | b97ccf3f20bee44daf70f10966809e39e30ab4f7 (patch) | |
tree | fb6c421cd04ffed74e50cd62e4fdab34d5a9f448 /src/com/android/camera/VideoCamera.java | |
parent | 0eaec58e292ce4eaa6baadecf643f0f65e48d278 (diff) | |
download | LegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.zip LegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.tar.gz LegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'src/com/android/camera/VideoCamera.java')
-rw-r--r-- | src/com/android/camera/VideoCamera.java | 252 |
1 files changed, 161 insertions, 91 deletions
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java index 7fcab9a..9da1f49 100644 --- a/src/com/android/camera/VideoCamera.java +++ b/src/com/android/camera/VideoCamera.java @@ -17,11 +17,11 @@ package com.android.camera; import java.io.File; -import java.util.ArrayList; import java.io.IOException; +import java.util.ArrayList; import android.app.Activity; -import android.app.ProgressDialog; +import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -30,7 +30,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.ColorDrawable; import android.location.LocationManager; @@ -44,16 +43,14 @@ import android.os.Message; import android.os.StatFs; import android.os.SystemClock; import android.preference.PreferenceManager; -import android.provider.MediaStore.Images; +import android.provider.MediaStore; import android.provider.MediaStore.Video; import android.text.format.DateFormat; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.SurfaceHolder; -import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; @@ -62,40 +59,32 @@ import android.view.animation.Animation; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import android.widget.RelativeLayout.LayoutParams; public class VideoCamera extends Activity implements View.OnClickListener, SurfaceHolder.Callback { private static final String TAG = "videocamera"; private static final boolean DEBUG = true; - private static final boolean DEBUG_SUPPRESS_AUDIO_RECORDING = DEBUG && true; + private static final boolean DEBUG_SUPPRESS_AUDIO_RECORDING = DEBUG && false; private static final boolean DEBUG_DO_NOT_REUSE_MEDIA_RECORDER = DEBUG && true; private static final int KEEP = 2; private static final int CLEAR_SCREEN_DELAY = 4; private static final int UPDATE_RECORD_TIME = 5; - private static final int RESTART_PREVIEW = 6; private static final int SCREEN_DELAY = 2 * 60 * 1000; - private static final int POST_PICTURE_ALERT_TIMEOUT = 6 * 1000; - private static final int NO_STORAGE_ERROR = -1; - private static final int CANNOT_STAT_ERROR = -2; + private static final long NO_STORAGE_ERROR = -1L; + private static final long CANNOT_STAT_ERROR = -2L; + private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L; - public static final int MENU_SWITCH_TO_VIDEO = 0; - public static final int MENU_SWITCH_TO_CAMERA = 1; public static final int MENU_SETTINGS = 6; public static final int MENU_GALLERY_PHOTOS = 7; public static final int MENU_GALLERY_VIDEOS = 8; - public static final int MENU_SAVE_SELECT_PHOTOS = 30; - public static final int MENU_SAVE_NEW_PHOTO = 31; - public static final int MENU_SAVE_SELECTVIDEO = 32; - public static final int MENU_SAVE_TAKE_NEW_VIDEO = 33; public static final int MENU_SAVE_GALLERY_PHOTO = 34; - public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35; - public static final int MENU_SAVE_CAMERA_DONE = 36; - public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37; + public static final int MENU_SAVE_PLAY_VIDEO = 35; + public static final int MENU_SAVE_SELECT_VIDEO = 36; + public static final int MENU_SAVE_NEW_VIDEO = 37; Toast mToast; SharedPreferences mPreferences; @@ -109,9 +98,12 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa private MediaRecorder mMediaRecorder; private boolean mMediaRecorderRecording = false; + private boolean mNeedToDeletePartialRecording; + private boolean mNeedToRegisterRecording; private long mRecordingStartTime; private String mCurrentVideoFilename; private Uri mCurrentVideoUri; + private ContentValues mCurrentVideoValues; boolean mPausing = false; @@ -129,8 +121,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa View mPostPictureAlert; LocationManager mLocationManager = null; - private int mPicturesRemaining; - private Handler mHandler = new MainHandler(); private void cancelSavingNotification() { @@ -177,15 +167,17 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } String text = minutesString + ":" + secondsString; mRecordingTimeView.setText(text); + // Work around a limitation of the T-Mobile G1: The T-Mobile + // hardware blitter can't pixel-accurately scale and clip at the same time, + // and the SurfaceFlinger doesn't attempt to work around this limitation. + // In order to avoid visual corruption we must manually refresh the entire + // surface view when changing any overlapping view's contents. + mVideoPreview.invalidate(); mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000); } break; } - case RESTART_PREVIEW: - hideVideoFrameAndStartPreview(); - break; - default: Log.v(TAG, "Unhandled message: " + msg.what); break; @@ -254,16 +246,12 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa mBlackout.setBackgroundDrawable(new ColorDrawable(0xFF000000)); mPostPictureAlert = findViewById(R.id.post_picture_panel); - View b; - - b = findViewById(R.id.play); - b.setOnClickListener(this); - b = findViewById(R.id.share); - b.setOnClickListener(this); - - b = findViewById(R.id.discard); - b.setOnClickListener(this); + int[] ids = new int[]{R.id.play, R.id.share, R.id.discard, + R.id.capture, R.id.cancel, R.id.accept}; + for (int id : ids) { + findViewById(id).setOnClickListener(this); + } mModeIndicatorView = (ImageView) findViewById(R.id.mode_indicator); mRecordingIndicatorView = (ImageView) findViewById(R.id.recording_indicator); @@ -281,7 +269,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa Thread t = new Thread(new Runnable() { public void run() { - final boolean storageOK = calculatePicturesRemaining() > 0; + final boolean storageOK = getAvailableStorage() >= LOW_STORAGE_THRESHOLD; if (hintView == null) return; @@ -315,12 +303,20 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa public void onClick(View v) { switch (v.getId()) { - case R.id.discard: { - File f = new File(mCurrentVideoFilename); - f.delete(); - mContentResolver.delete(mCurrentVideoUri, null, null); + case R.id.capture: + doDiscardCurrentVideo(); + break; - hideVideoFrameAndStartPreview(); + case R.id.accept: + doReturnToPicker(true); + break; + + case R.id.cancel: + doReturnToPicker(false); + break; + + case R.id.discard: { + doDiscardCurrentVideo(); break; } @@ -339,29 +335,35 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } case R.id.play: { - Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); - try { - startActivity(intent); - } catch (android.content.ActivityNotFoundException ex) { - Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); - } + doPlayCurrentVideo(); break; } } } + private void doPlayCurrentVideo() { + Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); + try { + startActivity(intent); + } catch (android.content.ActivityNotFoundException ex) { + Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); + } + } + + private void doDiscardCurrentVideo() { + deleteCurrentVideo(); + hideVideoFrameAndStartPreview(); + } + private void showStorageToast() { - String noStorageText = null; - int remaining = calculatePicturesRemaining(); + long remaining = getAvailableStorage(); if (remaining == NO_STORAGE_ERROR) { - noStorageText = getString(R.string.no_storage); - } else if (remaining < 1) { - noStorageText = getString(R.string.not_enough_space); - } - - if (noStorageText != null) { - Toast.makeText(this, noStorageText, 5000).show(); + Toast.makeText(this, getString(R.string.no_storage), Toast.LENGTH_LONG).show(); + } else if (remaining < LOW_STORAGE_THRESHOLD) { + new AlertDialog.Builder(this).setTitle(R.string.spaceIsLow_title) + .setMessage(R.string.spaceIsLow_content) + .show(); } } @@ -456,12 +458,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa return super.onKeyDown(keyCode, event); } - @Override - public boolean onTrackballEvent(MotionEvent event) { - cancelRestartPreviewTimeout(); - return super.onTrackballEvent(event); - } - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { stopVideoRecording(); initializeVideo(); @@ -511,7 +507,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - addBaseMenuItems(menu); MenuHelper.addImageMenuItems( menu, @@ -545,26 +540,47 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } }); gallery.setIcon(android.R.drawable.ic_menu_gallery); + return true; } - private int calculatePicturesRemaining() { + private boolean isPickIntent() { + String action = getIntent().getAction(); + return (Intent.ACTION_PICK.equals(action) || MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); + } + + private void doReturnToPicker(boolean success) { + Intent resultIntent = new Intent(); + int resultCode; + if (success) { + resultCode = RESULT_OK; + resultIntent.setData(mCurrentVideoUri); + } else { + resultCode = RESULT_CANCELED; + } + setResult(resultCode, resultIntent); + finish(); + } + + /** + * Returns + * @return number of bytes available, or an ERROR code. + */ + private static long getAvailableStorage() { try { if (!ImageManager.hasStorage()) { - mPicturesRemaining = NO_STORAGE_ERROR; + return NO_STORAGE_ERROR; } else { String storageDirectory = Environment.getExternalStorageDirectory().toString(); StatFs stat = new StatFs(storageDirectory); - float remaining = ((float)stat.getAvailableBlocks() * (float)stat.getBlockSize()) / 400000F; - mPicturesRemaining = (int)remaining; + return ((long)stat.getAvailableBlocks() * (long)stat.getBlockSize()); } } catch (Exception ex) { // if we can't stat the filesystem then we don't know how many - // pictures are remaining. it might be zero but just leave it + // free bytes exist. It might be zero but just leave it // blank since we really don't know. - mPicturesRemaining = CANNOT_STAT_ERROR; + return CANNOT_STAT_ERROR; } - return mPicturesRemaining; } private void initializeVideo() { @@ -577,6 +593,8 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } mMediaRecorder = new MediaRecorder(); + mNeedToDeletePartialRecording = true; + mNeedToRegisterRecording = false; if (DEBUG_SUPPRESS_AUDIO_RECORDING) { Log.v(TAG, "DEBUG_SUPPRESS_AUDIO_RECORDING is true."); @@ -588,17 +606,26 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa Log.v(TAG, "before setOutputFile"); createVideoPath(); mMediaRecorder.setOutputFile(mCurrentVideoFilename); - Boolean videoQualityLow = getIntPreference("pref_camera_videoquality_key") == 0; + boolean videoQualityHigh = getBooleanPreference(CameraSettings.KEY_VIDEO_QUALITY, + CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE); + + { + Intent intent = getIntent(); + if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { + int extraVideoQuality = intent.getIntExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); + videoQualityHigh = (extraVideoQuality > 0); + } + } // Use the same frame rate for both, since internally // if the frame rate is too large, it can cause camera to become // unstable. We need to fix the MediaRecorder to disable the support // of setting frame rate for now. mMediaRecorder.setVideoFrameRate(20); - if (videoQualityLow) { - mMediaRecorder.setVideoSize(176,144); - } else { + if (videoQualityHigh) { mMediaRecorder.setVideoSize(352,288); + } else { + mMediaRecorder.setVideoSize(176,144); } mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); if (!DEBUG_SUPPRESS_AUDIO_RECORDING) { @@ -641,17 +668,29 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } } - private int getIntPreference(String key) { - String s = mPreferences.getString(key, "0"); - return Integer.parseInt(s); + private int getIntPreference(String key, int defaultValue) { + String s = mPreferences.getString(key, ""); + int result = defaultValue; + try { + result = Integer.parseInt(s); + } catch (NumberFormatException e) { + // Ignore, result is already the default value. + } + return result; + } + + private boolean getBooleanPreference(String key, boolean defaultValue) { + return getIntPreference(key, defaultValue ? 1 : 0) != 0; } private void createVideoPath() { long dateTaken = System.currentTimeMillis(); String title = createName(dateTaken); String displayName = title + ".3gp"; // Used when emailing. - String filename = ImageManager.CAMERA_IMAGE_BUCKET_NAME + "/" - + Long.toString(dateTaken) + ".3gp"; + String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME; + File cameraDir = new File(cameraDirPath); + cameraDir.mkdirs(); + String filename = cameraDirPath + "/" + Long.toString(dateTaken) + ".3gp"; ContentValues values = new ContentValues(7); values.put(Video.Media.TITLE, title); values.put(Video.Media.DISPLAY_NAME, displayName); @@ -659,10 +698,31 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa values.put(Video.Media.DATE_TAKEN, dateTaken); values.put(Video.Media.MIME_TYPE, "video/3gpp"); values.put(Video.Media.DATA, filename); - Uri videoTable = Uri.parse("content://media/external/video/media"); - Uri item = mContentResolver.insert(videoTable, values); mCurrentVideoFilename = filename; - mCurrentVideoUri = item; + mCurrentVideoValues = values; + mCurrentVideoUri = null; + } + + private void registerVideo() { + Uri videoTable = Uri.parse("content://media/external/video/media"); + mCurrentVideoUri = mContentResolver.insert(videoTable, + mCurrentVideoValues); + mCurrentVideoValues = null; + } + + private void deleteCurrentVideo() { + if (mCurrentVideoFilename != null) { + Log.v(TAG, "Deleting stub video " + mCurrentVideoFilename); + File f = new File(mCurrentVideoFilename); + if (! f.delete()) { + Log.v(TAG, "Could not delete " + mCurrentVideoFilename); + } + mCurrentVideoFilename = null; + } + if (mCurrentVideoUri != null) { + mContentResolver.delete(mCurrentVideoUri, null, null); + mCurrentVideoUri = null; + } } private void addBaseMenuItems(Menu menu) { @@ -734,20 +794,20 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa } private void showPostRecordingAlert() { - cancelRestartPreviewTimeout(); + boolean isPick = isPickIntent(); + int pickVisible = isPick ? View.VISIBLE : View.GONE; + int normalVisible = ! isPick ? View.VISIBLE : View.GONE; + mPostPictureAlert.findViewById(R.id.share).setVisibility(normalVisible); + mPostPictureAlert.findViewById(R.id.discard).setVisibility(normalVisible); + mPostPictureAlert.findViewById(R.id.accept).setVisibility(pickVisible); + mPostPictureAlert.findViewById(R.id.cancel).setVisibility(pickVisible); mPostPictureAlert.setVisibility(View.VISIBLE); - mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, POST_PICTURE_ALERT_TIMEOUT); } private void hidePostPictureAlert() { - cancelRestartPreviewTimeout(); mPostPictureAlert.setVisibility(View.INVISIBLE); } - private void cancelRestartPreviewTimeout() { - mHandler.removeMessages(RESTART_PREVIEW); - } - private boolean isPostRecordingAlertVisible() { return mPostPictureAlert.getVisibility() == View.VISIBLE; } @@ -757,14 +817,24 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa if (mMediaRecorderRecording || mMediaRecorder != null) { if (mMediaRecorderRecording) { mMediaRecorder.stop(); + mNeedToDeletePartialRecording = false; + mNeedToRegisterRecording = true; + mMediaRecorderRecording = false; } releaseMediaRecorder(); - mMediaRecorderRecording = false; mModeIndicatorView.setVisibility(View.VISIBLE); mRecordingIndicatorView.setVisibility(View.GONE); mRecordingTimeView.setVisibility(View.GONE); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } + if (mNeedToRegisterRecording) { + registerVideo(); + mNeedToRegisterRecording = false; + } + if (mNeedToDeletePartialRecording){ + deleteCurrentVideo(); + mNeedToDeletePartialRecording = false; + } } private void hideVideoFrameAndStartPreview() { |