TrimVideo.java revision 3f1f1baf3a674927e25cd5cd885fb372796bd3a0
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.app; 18 19import android.app.ActionBar; 20import android.app.Activity; 21import android.app.ProgressDialog; 22import android.content.Context; 23import android.content.Intent; 24import android.media.MediaPlayer; 25import android.net.Uri; 26import android.os.Bundle; 27import android.os.Handler; 28import android.view.Menu; 29import android.view.MenuInflater; 30import android.view.MenuItem; 31import android.view.View; 32import android.view.ViewGroup; 33import android.widget.Toast; 34import android.widget.VideoView; 35 36import com.android.gallery3d.R; 37 38 39public class TrimVideo extends Activity implements 40 MediaPlayer.OnErrorListener, 41 MediaPlayer.OnCompletionListener, 42 ControllerOverlay.Listener { 43 44 private VideoView mVideoView; 45 private TrimControllerOverlay mController; 46 private Context mContext; 47 private Uri mUri; 48 private final Handler mHandler = new Handler(); 49 public static final String TRIM_ACTION = "com.android.camera.action.TRIM"; 50 51 public ProgressDialog mProgress; 52 53 private int mTrimStartTime = 0; 54 private int mTrimEndTime = 0; 55 private int mVideoPosition = 0; 56 public static final String KEY_TRIM_START = "trim_start"; 57 public static final String KEY_TRIM_END = "trim_end"; 58 public static final String KEY_VIDEO_POSITION = "video_pos"; 59 private boolean mHasPaused = false; 60 61 @Override 62 public void onCreate(Bundle savedInstanceState) { 63 mContext = getApplicationContext(); 64 super.onCreate(savedInstanceState); 65 66 ActionBar actionBar = getActionBar(); 67 actionBar.setDisplayHomeAsUpEnabled(true); 68 69 Intent intent = getIntent(); 70 mUri = intent.getData(); 71 72 setContentView(R.layout.trim_view); 73 View rootView = findViewById(R.id.trim_view_root); 74 75 mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); 76 77 mController = new TrimControllerOverlay(mContext); 78 ((ViewGroup)rootView).addView(mController.getView()); 79 mController.setListener(this); 80 mController.setCanReplay(true); 81 82 mVideoView.setOnErrorListener(this); 83 mVideoView.setOnCompletionListener(this); 84 mVideoView.setVideoURI(mUri); 85 86 playVideo(); 87 } 88 89 @Override 90 public void onResume() { 91 super.onResume(); 92 if (mHasPaused) { 93 mVideoView.seekTo(mVideoPosition); 94 mVideoView.resume(); 95 mHasPaused = false; 96 } 97 mHandler.post(mProgressChecker); 98 } 99 100 @Override 101 public void onPause() { 102 mHasPaused = true; 103 mHandler.removeCallbacksAndMessages(null); 104 mVideoPosition = mVideoView.getCurrentPosition(); 105 mVideoView.suspend(); 106 super.onPause(); 107 } 108 109 @Override 110 public void onDestroy() { 111 mVideoView.stopPlayback(); 112 super.onDestroy(); 113 } 114 115 private final Runnable mProgressChecker = new Runnable() { 116 @Override 117 public void run() { 118 int pos = setProgress(); 119 mHandler.postDelayed(mProgressChecker, 200 - (pos % 200)); 120 } 121 }; 122 123 @Override 124 public void onSaveInstanceState(Bundle savedInstanceState) { 125 savedInstanceState.putInt(KEY_TRIM_START, mTrimStartTime); 126 savedInstanceState.putInt(KEY_TRIM_END, mTrimEndTime); 127 savedInstanceState.putInt(KEY_VIDEO_POSITION, mVideoPosition); 128 super.onSaveInstanceState(savedInstanceState); 129 } 130 131 @Override 132 public void onRestoreInstanceState(Bundle savedInstanceState) { 133 super.onRestoreInstanceState(savedInstanceState); 134 mTrimStartTime = savedInstanceState.getInt(KEY_TRIM_START, 0); 135 mTrimEndTime = savedInstanceState.getInt(KEY_TRIM_END, 0); 136 mVideoPosition = savedInstanceState.getInt(KEY_VIDEO_POSITION, 0); 137 } 138 139 // This updates the time bar display (if necessary). It is called by 140 // mProgressChecker and also from places where the time bar needs 141 // to be updated immediately. 142 private int setProgress() { 143 mVideoPosition = mVideoView.getCurrentPosition(); 144 // If the video position is smaller than the starting point of trimming, 145 // correct it. 146 if (mVideoPosition < mTrimStartTime) { 147 mVideoView.seekTo(mTrimStartTime); 148 mVideoPosition = mTrimStartTime; 149 } 150 // If the position is bigger than the end point of trimming, show the 151 // replay button and pause. 152 if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) { 153 if (mVideoPosition > mTrimEndTime) { 154 mVideoView.seekTo(mTrimEndTime); 155 mVideoPosition = mTrimEndTime; 156 } 157 mController.showEnded(); 158 mVideoView.pause(); 159 } 160 161 int duration = mVideoView.getDuration(); 162 if (duration > 0 && mTrimEndTime == 0) { 163 mTrimEndTime = duration; 164 } 165 mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime); 166 return mVideoPosition; 167 } 168 169 private void playVideo() { 170 mVideoView.start(); 171 mController.showPlaying(); 172 setProgress(); 173 } 174 175 private void pauseVideo() { 176 mVideoView.pause(); 177 mController.showPaused(); 178 } 179 180 @Override 181 public boolean onCreateOptionsMenu(Menu menu) { 182 super.onCreateOptionsMenu(menu); 183 MenuInflater inflater = getMenuInflater(); 184 inflater.inflate(R.menu.trim, menu); 185 return true; 186 }; 187 188 @Override 189 public boolean onOptionsItemSelected(MenuItem item) { 190 int id = item.getItemId(); 191 if (id == android.R.id.home) { 192 finish(); 193 return true; 194 } else if (id == R.id.action_trim_video) { 195 // TODO: Add the new MediaMuxer API to support the trimming. 196 Toast.makeText(getApplicationContext(), 197 "Trimming will be implemented soon!", Toast.LENGTH_SHORT).show(); 198 return true; 199 } 200 return false; 201 } 202 203 @Override 204 public void onPlayPause() { 205 if (mVideoView.isPlaying()) { 206 pauseVideo(); 207 } else { 208 playVideo(); 209 } 210 } 211 212 @Override 213 public void onSeekStart() { 214 pauseVideo(); 215 } 216 217 @Override 218 public void onSeekMove(int time) { 219 mVideoView.seekTo(time); 220 } 221 222 @Override 223 public void onSeekEnd(int time, int start, int end) { 224 mVideoView.seekTo(time); 225 mTrimStartTime = start; 226 mTrimEndTime = end; 227 setProgress(); 228 } 229 230 @Override 231 public void onShown() { 232 } 233 234 235 @Override 236 public void onHidden() { 237 } 238 239 @Override 240 public void onReplay() { 241 mVideoView.seekTo(mTrimStartTime); 242 playVideo(); 243 } 244 245 @Override 246 public void onCompletion(MediaPlayer mp) { 247 mController.showEnded(); 248 } 249 250 @Override 251 public boolean onError(MediaPlayer mp, int what, int extra) { 252 return false; 253 } 254} 255