diff options
Diffstat (limited to 'src/com/android/gallery3d/app/TrimVideo.java')
-rw-r--r-- | src/com/android/gallery3d/app/TrimVideo.java | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java new file mode 100644 index 000000000..1e7728162 --- /dev/null +++ b/src/com/android/gallery3d/app/TrimVideo.java @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.app; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.provider.MediaStore; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.VideoView; + +import com.android.gallery3d.R; +import com.android.gallery3d.util.SaveVideoFileInfo; +import com.android.gallery3d.util.SaveVideoFileUtils; + +import java.io.File; +import java.io.IOException; + +public class TrimVideo extends Activity implements + MediaPlayer.OnErrorListener, + MediaPlayer.OnCompletionListener, + ControllerOverlay.Listener { + + private VideoView mVideoView; + private TextView mSaveVideoTextView; + private TrimControllerOverlay mController; + private Context mContext; + private Uri mUri; + private final Handler mHandler = new Handler(); + public static final String TRIM_ACTION = "com.android.camera.action.TRIM"; + + public ProgressDialog mProgress; + + private int mTrimStartTime = 0; + private int mTrimEndTime = 0; + private int mVideoPosition = 0; + public static final String KEY_TRIM_START = "trim_start"; + public static final String KEY_TRIM_END = "trim_end"; + public static final String KEY_VIDEO_POSITION = "video_pos"; + private boolean mHasPaused = false; + + private String mSrcVideoPath = null; + private static final String TIME_STAMP_NAME = "'TRIM'_yyyyMMdd_HHmmss"; + private SaveVideoFileInfo mDstFileInfo = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + mContext = getApplicationContext(); + super.onCreate(savedInstanceState); + + requestWindowFeature(Window.FEATURE_ACTION_BAR); + requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); + + ActionBar actionBar = getActionBar(); + int displayOptions = ActionBar.DISPLAY_SHOW_HOME; + actionBar.setDisplayOptions(0, displayOptions); + displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM; + actionBar.setDisplayOptions(displayOptions, displayOptions); + actionBar.setCustomView(R.layout.trim_menu); + + mSaveVideoTextView = (TextView) findViewById(R.id.start_trim); + mSaveVideoTextView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View arg0) { + trimVideo(); + } + }); + mSaveVideoTextView.setEnabled(false); + + Intent intent = getIntent(); + mUri = intent.getData(); + mSrcVideoPath = intent.getStringExtra(PhotoPage.KEY_MEDIA_ITEM_PATH); + setContentView(R.layout.trim_view); + View rootView = findViewById(R.id.trim_view_root); + + mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); + + mController = new TrimControllerOverlay(mContext); + ((ViewGroup) rootView).addView(mController.getView()); + mController.setListener(this); + mController.setCanReplay(true); + + mVideoView.setOnErrorListener(this); + mVideoView.setOnCompletionListener(this); + mVideoView.setVideoURI(mUri); + + playVideo(); + } + + @Override + public void onResume() { + super.onResume(); + if (mHasPaused) { + mVideoView.seekTo(mVideoPosition); + mVideoView.resume(); + mHasPaused = false; + } + mHandler.post(mProgressChecker); + } + + @Override + public void onPause() { + mHasPaused = true; + mHandler.removeCallbacksAndMessages(null); + mVideoPosition = mVideoView.getCurrentPosition(); + mVideoView.suspend(); + super.onPause(); + } + + @Override + public void onStop() { + if (mProgress != null) { + mProgress.dismiss(); + mProgress = null; + } + super.onStop(); + } + + @Override + public void onDestroy() { + mVideoView.stopPlayback(); + super.onDestroy(); + } + + private final Runnable mProgressChecker = new Runnable() { + @Override + public void run() { + int pos = setProgress(); + mHandler.postDelayed(mProgressChecker, 200 - (pos % 200)); + } + }; + + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + savedInstanceState.putInt(KEY_TRIM_START, mTrimStartTime); + savedInstanceState.putInt(KEY_TRIM_END, mTrimEndTime); + savedInstanceState.putInt(KEY_VIDEO_POSITION, mVideoPosition); + super.onSaveInstanceState(savedInstanceState); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + mTrimStartTime = savedInstanceState.getInt(KEY_TRIM_START, 0); + mTrimEndTime = savedInstanceState.getInt(KEY_TRIM_END, 0); + mVideoPosition = savedInstanceState.getInt(KEY_VIDEO_POSITION, 0); + } + + // This updates the time bar display (if necessary). It is called by + // mProgressChecker and also from places where the time bar needs + // to be updated immediately. + private int setProgress() { + mVideoPosition = mVideoView.getCurrentPosition(); + // If the video position is smaller than the starting point of trimming, + // correct it. + if (mVideoPosition < mTrimStartTime) { + mVideoView.seekTo(mTrimStartTime); + mVideoPosition = mTrimStartTime; + } + // If the position is bigger than the end point of trimming, show the + // replay button and pause. + if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) { + if (mVideoPosition > mTrimEndTime) { + mVideoView.seekTo(mTrimEndTime); + mVideoPosition = mTrimEndTime; + } + mController.showEnded(); + mVideoView.pause(); + } + + int duration = mVideoView.getDuration(); + if (duration > 0 && mTrimEndTime == 0) { + mTrimEndTime = duration; + } + mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime); + return mVideoPosition; + } + + private void playVideo() { + mVideoView.start(); + mController.showPlaying(); + setProgress(); + } + + private void pauseVideo() { + mVideoView.pause(); + mController.showPaused(); + } + + + private boolean isModified() { + int delta = mTrimEndTime - mTrimStartTime; + + // Considering that we only trim at sync frame, we don't want to trim + // when the time interval is too short or too close to the origin. + if (delta < 100 || Math.abs(mVideoView.getDuration() - delta) < 100) { + return false; + } else { + return true; + } + } + + private void trimVideo() { + + mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME, + getContentResolver(), mUri, getString(R.string.folder_download)); + final File mSrcFile = new File(mSrcVideoPath); + + showProgressDialog(); + + new Thread(new Runnable() { + @Override + public void run() { + try { + VideoUtils.startTrim(mSrcFile, mDstFileInfo.mFile, + mTrimStartTime, mTrimEndTime); + // Update the database for adding a new video file. + SaveVideoFileUtils.insertContent(mDstFileInfo, + getContentResolver(), mUri); + } catch (IOException e) { + e.printStackTrace(); + } + // After trimming is done, trigger the UI changed. + mHandler.post(new Runnable() { + @Override + public void run() { + Toast.makeText(getApplicationContext(), + getString(R.string.save_into, mDstFileInfo.mFolderName), + Toast.LENGTH_SHORT) + .show(); + // TODO: change trimming into a service to avoid + // this progressDialog and add notification properly. + if (mProgress != null) { + mProgress.dismiss(); + mProgress = null; + // Show the result only when the activity not stopped. + Intent intent = new Intent(android.content.Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*"); + intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false); + startActivity(intent); + finish(); + } + } + }); + } + }).start(); + } + + private void showProgressDialog() { + // create a background thread to trim the video. + // and show the progress. + mProgress = new ProgressDialog(this); + mProgress.setTitle(getString(R.string.trimming)); + mProgress.setMessage(getString(R.string.please_wait)); + // TODO: make this cancelable. + mProgress.setCancelable(false); + mProgress.setCanceledOnTouchOutside(false); + mProgress.show(); + } + + @Override + public void onPlayPause() { + if (mVideoView.isPlaying()) { + pauseVideo(); + } else { + playVideo(); + } + } + + @Override + public void onSeekStart() { + pauseVideo(); + } + + @Override + public void onSeekMove(int time) { + mVideoView.seekTo(time); + } + + @Override + public void onSeekEnd(int time, int start, int end) { + mVideoView.seekTo(time); + mTrimStartTime = start; + mTrimEndTime = end; + setProgress(); + // Enable save if there's modifications + mSaveVideoTextView.setEnabled(isModified()); + } + + @Override + public void onShown() { + } + + @Override + public void onHidden() { + } + + @Override + public void onReplay() { + mVideoView.seekTo(mTrimStartTime); + playVideo(); + } + + @Override + public void onCompletion(MediaPlayer mp) { + mController.showEnded(); + } + + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + return false; + } +} |