VideoEditor.java revision 05d9f81bd638a749669192b50e680b166529d5f3
1/* 2 * Copyright (C) 2010 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 17 18package android.media.videoeditor; 19 20import java.io.IOException; 21import java.util.List; 22import java.util.concurrent.CancellationException; 23 24import android.view.SurfaceHolder; 25 26/** 27 * This is the interface implemented by classes which provide video editing 28 * functionality. The VideoEditor implementation class manages all input and 29 * output files. Unless specifically mentioned, methods are blocking. A typical 30 * editing session may consist of the following sequence of operations: 31 * 32 * <ul> 33 * <li>Add a set of MediaItems</li> 34 * <li>Apply a set of Transitions between MediaItems</li> 35 * <li>Add Effects and Overlays to media items</li> 36 * <li>Preview the movie at any time</li> 37 * <li>Save the VideoEditor implementation class internal state</li> 38 * <li>Release the VideoEditor implementation class instance by invoking 39 * {@link #release()} 40 * </ul> 41 * The internal VideoEditor state consists of the following elements: 42 * <ul> 43 * <li>Ordered & trimmed MediaItems</li> 44 * <li>Transition video clips</li> 45 * <li>Overlays</li> 46 * <li>Effects</li> 47 * <li>Audio waveform for the background audio and MediaItems</li> 48 * <li>Project thumbnail</li> 49 * <li>Last exported movie.</li> 50 * <li>Other project specific data such as the current aspect ratio.</li> 51 * </ul> 52 * {@hide} 53 */ 54public interface VideoEditor { 55 /** 56 * The file name of the project thumbnail 57 */ 58 public static final String THUMBNAIL_FILENAME = "thumbnail.jpg"; 59 60 /** 61 * Use this value instead of the specific end of the storyboard timeline 62 * value. 63 */ 64 public final static int DURATION_OF_STORYBOARD = -1; 65 66 /** 67 * This listener interface is used by the VideoEditor to emit preview 68 * progress notifications. This callback should be invoked after the number 69 * of frames specified by 70 * {@link #startPreview(SurfaceHolder surfaceHolder, long fromMs, 71 * int callbackAfterFrameCount, PreviewProgressListener listener)} 72 */ 73 public interface PreviewProgressListener { 74 /** 75 * This method notifies the listener of the current time position while 76 * previewing a project. 77 * 78 * @param videoEditor The VideoEditor instance 79 * @param timeMs The current preview position (expressed in milliseconds 80 * since the beginning of the storyboard timeline). 81 * @param end true if the end of the timeline was reached 82 */ 83 public void onProgress(VideoEditor videoEditor, long timeMs, boolean end); 84 } 85 86 /** 87 * This listener interface is used by the VideoEditor to emit export status 88 * notifications. 89 * {@link #export(String filename, ExportProgressListener listener, 90 * int height, int bitrate)} 91 */ 92 public interface ExportProgressListener { 93 /** 94 * This method notifies the listener of the progress status of a export 95 * operation. 96 * 97 * @param videoEditor The VideoEditor instance 98 * @param filename The name of the file which is in the process of being 99 * exported. 100 * @param progress The progress in %. At the beginning of the export, 101 * this value is set to 0; at the end, the value is set to 100. 102 */ 103 public void onProgress(VideoEditor videoEditor, String filename, 104 int progress); 105 } 106 107 public interface MediaProcessingProgressListener { 108 /** 109 * Values used for the action parameter 110 */ 111 public static final int ACTION_ENCODE = 1; 112 public static final int ACTION_DECODE = 2; 113 114 /** 115 * This method notifies the listener of the progress status of 116 * processing a media object such as a Transition, AudioTrack & Kenburns 117 * This method may be called maximum 100 times for one operation. 118 * 119 * @param object The object that is being processed such as a Transition 120 * or AudioTrack 121 * @param action The type of processing being performed 122 * @param progress The progress in %. At the beginning of the operation, 123 * this value is set to 0; at the end, the value is set to 100. 124 */ 125 public void onProgress(Object item, int action, int progress); 126 } 127 128 /** 129 * @return The path where the VideoEditor stores all files related to the 130 * project 131 */ 132 public String getPath(); 133 134 /** 135 * This method releases all in-memory resources used by the VideoEditor 136 * instance. All pending operations such as preview, export and extract 137 * audio waveform must be canceled. 138 */ 139 public void release(); 140 141 /** 142 * Persist the current internal state of VideoEditor to the project path. 143 * The VideoEditor state may be restored by invoking the 144 * {@link VideoEditorFactory#load(String)} method. This method does not 145 * release the internal in-memory state of the VideoEditor. To release 146 * the in-memory state of the VideoEditor the {@link #release()} method 147 * must be invoked. 148 * 149 * Pending transition generations must be allowed to complete before the 150 * state is saved. 151 * Pending audio waveform generations must be allowed to complete. 152 * Pending export operations must be allowed to continue. 153 * 154 * @throws IOException if the internal state cannot be saved to project file 155 */ 156 public void save() throws IOException; 157 158 /** 159 * Create the output movie based on all media items added and the applied 160 * storyboard items. This method can take a long time to execute and is 161 * blocking. The application will receive progress notifications via the 162 * ExportProgressListener. Specific implementations may not support multiple 163 * simultaneous export operations. Note that invoking methods which would 164 * change the contents of the output movie throw an IllegalStateException 165 * while an export operation is pending. 166 * 167 * The audio and video codecs are automatically selected by the underlying 168 * implementation. 169 * 170 * @param filename The output file name (including the full path) 171 * @param height The height of the output video file. The supported values 172 * for height are described in the MediaProperties class, for 173 * example: HEIGHT_480. The width will be automatically computed 174 * according to the aspect ratio provided by 175 * {@link #setAspectRatio(int)} 176 * @param bitrate The bitrate of the output video file. This is approximate 177 * value for the output movie. Supported bitrate values are 178 * described in the MediaProperties class for example: BITRATE_384K 179 * @param listener The listener for progress notifications. Use null if 180 * export progress notifications are not needed. 181 * 182 * @throws IllegalArgumentException if height or bitrate are not supported 183 * or if the audio or video codecs are not supported 184 * @throws IOException if output file cannot be created 185 * @throws IllegalStateException if a preview or an export is in progress or 186 * if no MediaItem has been added 187 * @throws CancellationException if export is canceled by calling 188 * {@link #cancelExport()} 189 * @throws UnsupportOperationException if multiple simultaneous export() are 190 * not allowed 191 */ 192 public void export(String filename, int height, int bitrate, 193 ExportProgressListener listener) 194 throws IOException; 195 196 /** 197 * Create the output movie based on all media items added and the applied 198 * storyboard items. This method can take a long time to execute and is 199 * blocking. The application will receive progress notifications via the 200 * ExportProgressListener. Specific implementations may not support multiple 201 * simultaneous export operations. Note that invoking methods which would 202 * change the contents of the output movie throw an IllegalStateException 203 * while an export operation is pending. 204 * 205 * @param filename The output file name (including the full path) 206 * @param height The height of the output video file. The supported values 207 * for height are described in the MediaProperties class, for 208 * example: HEIGHT_480. The width will be automatically computed 209 * according to the aspect ratio provided by 210 * {@link #setAspectRatio(int)} 211 * @param bitrate The bitrate of the output video file. This is approximate 212 * value for the output movie. Supported bitrate values are 213 * described in the MediaProperties class for example: BITRATE_384K 214 * @param audioCodec The audio codec to be used for the export. The audio 215 * codec values are defined in the MediaProperties class (e.g. 216 * ACODEC_AAC_LC). Note that not all audio codec types are 217 * supported for export purposes. 218 * @param videoCodec The video codec to be used for the export. The video 219 * codec values are defined in the MediaProperties class (e.g. 220 * VCODEC_H264BP). Note that not all video codec types are 221 * supported for export purposes. 222 * @param listener The listener for progress notifications. Use null if 223 * export progress notifications are not needed. 224 * 225 * @throws IllegalArgumentException if height or bitrate are not supported 226 * or if the audio or video codecs are not supported 227 * @throws IOException if output file cannot be created 228 * @throws IllegalStateException if a preview or an export is in progress or 229 * if no MediaItem has been added 230 * @throws CancellationException if export is cancelled by calling 231 * {@link #cancelExport()} 232 * @throws UnsupportOperationException if multiple simultaneous export() are 233 * not allowed 234 */ 235 public void export(String filename, int height, int bitrate, int audioCodec, 236 int videoCodec, ExportProgressListener listener) 237 throws IOException; 238 239 /** 240 * Cancel the running export operation. This method blocks until the export 241 * is cancelled and the exported file (if any) is deleted. If the export 242 * completed by the time this method is invoked, the export file will be 243 * deleted. 244 * 245 * @param filename The filename which identifies the export operation to be 246 * canceled. 247 **/ 248 public void cancelExport(String filename); 249 250 /** 251 * Add a media item at the end of the storyboard. 252 * 253 * @param mediaItem The media item object to add 254 * 255 * @throws IllegalStateException if a preview or an export is in progress or 256 * if the media item id is not unique across all the media items 257 * added. 258 */ 259 public void addMediaItem(MediaItem mediaItem); 260 261 /** 262 * Insert a media item after the media item with the specified id. 263 * 264 * @param mediaItem The media item object to insert 265 * @param afterMediaItemId Insert the mediaItem after the media item 266 * identified by this id. If this parameter is null, the media 267 * item is inserted at the beginning of the timeline. 268 * 269 * @throws IllegalStateException if a preview or an export is in progress 270 * @throws IllegalArgumentException if media item with the specified id does 271 * not exist (null is a valid value) or if the media item id is 272 * not unique across all the media items added. 273 */ 274 public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId); 275 276 /** 277 * Move a media item after the media item with the specified id. 278 * 279 * Note: The project thumbnail is regenerated if the media item is or 280 * becomes the first media item in the storyboard timeline. 281 * 282 * @param mediaItemId The id of the media item to move 283 * @param afterMediaItemId Move the media item identified by mediaItemId 284 * after the media item identified by this parameter. If this 285 * parameter is null, the media item is moved at the beginning of 286 * the timeline. 287 * 288 * @throws IllegalStateException if a preview or an export is in progress 289 * @throws IllegalArgumentException if one of media item ids is invalid 290 * (null is a valid value) 291 */ 292 public void moveMediaItem(String mediaItemId, String afterMediaItemId); 293 294 /** 295 * Remove the media item with the specified id. If there are transitions 296 * before or after this media item, then this/these transition(s) are 297 * removed from the storyboard. If the extraction of the audio waveform is 298 * in progress, the extraction is canceled and the file is deleted. 299 * 300 * Effects and overlays associated with the media item will also be removed. 301 * 302 * Note: The project thumbnail is regenerated if the media item which is 303 * removed is the first media item in the storyboard or if the media item is 304 * the only one in the storyboard. If the media item is the only one in the 305 * storyboard, the project thumbnail will be set to a black frame and the 306 * aspect ratio will revert to the default aspect ratio and this method is 307 * equivalent to removeAllMediaItems() in this case. 308 * 309 * @param mediaItemId The unique id of the media item to be removed 310 * 311 * @return The media item that was removed 312 * 313 * @throws IllegalStateException if a preview or an export is in progress 314 * @throws IllegalArgumentException if media item with the specified id does 315 * not exist 316 */ 317 public MediaItem removeMediaItem(String mediaItemId); 318 319 /** 320 * Remove all media items in the storyboard. All effects, overlays and all 321 * transitions are also removed. 322 * 323 * Note: The project thumbnail will be set to a black frame and the aspect 324 * ratio will revert to the default aspect ratio. 325 * 326 * @throws IllegalStateException if a preview or an export is in progress 327 */ 328 public void removeAllMediaItems(); 329 330 /** 331 * Get the list of media items in the order in which it they appear in the 332 * storyboard timeline. 333 * 334 * Note that if any media item source files are no longer 335 * accessible, this method will still provide the full list of media items. 336 * 337 * @return The list of media items. If no media item exist an empty list 338 * will be returned. 339 */ 340 public List<MediaItem> getAllMediaItems(); 341 342 /** 343 * Find the media item with the specified id 344 * 345 * @param mediaItemId The media item id 346 * 347 * @return The media item with the specified id (null if it does not exist) 348 */ 349 public MediaItem getMediaItem(String mediaItemId); 350 351 /** 352 * Add a transition between the media items specified by the transition. 353 * If a transition existed at the same position it is invalidated and then 354 * the transition is replaced. Note that the new transition video clip is 355 * not automatically generated by this method. The 356 * {@link Transition#generate()} method must be invoked to generate 357 * the transition video clip. 358 * 359 * Note that the TransitionAtEnd and TransitionAtStart are special kinds 360 * that can not be applied between two media items. 361 * 362 * A crossfade audio transition will be automatically applied regardless of 363 * the video transition. 364 * 365 * @param transition The transition to apply 366 * 367 * @throws IllegalStateException if a preview or an export is in progress 368 * @throws IllegalArgumentException if the transition duration is larger 369 * than the smallest duration of the two media item files or if 370 * the two media items specified in the transition are not 371 * adjacent 372 */ 373 public void addTransition(Transition transition); 374 375 /** 376 * Remove the transition with the specified id. 377 * 378 * @param transitionId The id of the transition to be removed 379 * 380 * @return The transition that was removed 381 * 382 * @throws IllegalStateException if a preview or an export is in progress 383 * @throws IllegalArgumentException if transition with the specified id does 384 * not exist 385 */ 386 public Transition removeTransition(String transitionId); 387 388 /** 389 * Get the list of transitions 390 * 391 * @return The list of transitions. If no transitions exist an empty list 392 * will be returned. 393 */ 394 public List<Transition> getAllTransitions(); 395 396 /** 397 * Find the transition with the specified transition id. 398 * 399 * @param transitionId The transition id 400 * 401 * @return The transition 402 */ 403 public Transition getTransition(String transitionId); 404 405 /** 406 * Add the specified AudioTrack to the storyboard. Note: Specific 407 * implementations may support a limited number of audio tracks (e.g. only 408 * one audio track) 409 * 410 * @param audioTrack The AudioTrack to add 411 * 412 * @throws UnsupportedOperationException if the implementation supports a 413 * limited number of audio tracks. 414 * @throws IllegalArgumentException if media item is not unique across all 415 * the audio tracks already added. 416 */ 417 public void addAudioTrack(AudioTrack audioTrack); 418 419 /** 420 * Insert an audio track after the audio track with the specified id. Use 421 * addAudioTrack to add an audio track at the end of the storyboard 422 * timeline. 423 * 424 * @param audioTrack The audio track object to insert 425 * @param afterAudioTrackId Insert the audio track after the audio track 426 * identified by this parameter. If this parameter is null the 427 * audio track is added at the beginning of the timeline. 428 * 429 * @throws IllegalStateException if a preview or an export is in progress 430 * @throws IllegalArgumentException if media item with the specified id does 431 * not exist (null is a valid value). if media item is not unique 432 * across all the audio tracks already added. 433 * @throws UnsupportedOperationException if the implementation supports a 434 * limited number of audio tracks 435 */ 436 public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId); 437 438 /** 439 * Move an AudioTrack after the AudioTrack with the specified id. 440 * 441 * @param audioTrackId The id of the AudioTrack to move 442 * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId 443 * after the AudioTrack identified by this parameter. If this 444 * parameter is null the audio track is added at the beginning of 445 * the timeline. 446 * 447 * @throws IllegalStateException if a preview or an export is in progress 448 * @throws IllegalArgumentException if one of media item ids is invalid 449 * (null is a valid value) 450 */ 451 public void moveAudioTrack(String audioTrackId, String afterAudioTrackId); 452 453 /** 454 * Remove the audio track with the specified id. If the extraction of the 455 * audio waveform is in progress, the extraction is canceled and the file is 456 * deleted. 457 * 458 * @param audioTrackId The id of the audio track to be removed 459 * 460 * @return The audio track that was removed 461 * @throws IllegalStateException if a preview or an export is in progress 462 */ 463 public AudioTrack removeAudioTrack(String audioTrackId); 464 465 /** 466 * Get the list of AudioTracks in order in which they appear in the 467 * storyboard. 468 * 469 * Note that if any AudioTrack source files are not accessible anymore, 470 * this method will still provide the full list of audio tracks. 471 * 472 * @return The list of AudioTracks. If no audio tracks exist an empty list 473 * will be returned. 474 */ 475 public List<AudioTrack> getAllAudioTracks(); 476 477 /** 478 * Find the AudioTrack with the specified id 479 * 480 * @param audioTrackId The AudioTrack id 481 * 482 * @return The AudioTrack with the specified id (null if it does not exist) 483 */ 484 public AudioTrack getAudioTrack(String audioTrackId); 485 486 /** 487 * Set the aspect ratio used in the preview and the export movie. 488 * 489 * The default aspect ratio is ASPECTRATIO_16_9 (16:9). 490 * 491 * @param aspectRatio to apply. If aspectRatio is the same as the current 492 * aspect ratio, then this function just returns. The supported 493 * aspect ratio are defined in the MediaProperties class for 494 * example: ASPECTRATIO_16_9 495 * 496 * @throws IllegalStateException if a preview or an export is in progress 497 * @throws IllegalArgumentException if aspect ratio is not supported 498 */ 499 public void setAspectRatio(int aspectRatio); 500 501 /** 502 * Get current aspect ratio. 503 * 504 * @return The aspect ratio as described in MediaProperties 505 */ 506 public int getAspectRatio(); 507 508 /** 509 * Get the preview (and output movie) duration. 510 * 511 * @return The duration of the preview (and output movie) 512 */ 513 public long getDuration(); 514 515 /** 516 * Render a frame according to the preview aspect ratio and activating all 517 * storyboard items relative to the specified time. 518 * 519 * @param surfaceHolder SurfaceHolder used by the application 520 * @param timeMs time corresponding to the frame to display 521 * 522 * @return The accurate time stamp of the frame that is rendered. 523 * 524 * @throws IllegalStateException if a preview or an export is already in 525 * progress 526 * @throws IllegalArgumentException if time is negative or beyond the 527 * preview duration 528 */ 529 public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs); 530 531 /** 532 * This method must be called after any changes made to the storyboard 533 * and before startPreview is called. Note that this method may block for an 534 * extensive period of time. 535 */ 536 public void generatePreview(MediaProcessingProgressListener listener); 537 538 539 /** 540 * Start the preview of all the storyboard items applied on all MediaItems 541 * This method does not block (does not wait for the preview to complete). 542 * The PreviewProgressListener allows to track the progress at the time 543 * interval determined by the callbackAfterFrameCount parameter. The 544 * SurfaceHolder has to be created and ready for use before calling this 545 * method. The method is a no-op if there are no MediaItems in the 546 * storyboard. 547 * 548 * @param surfaceHolder SurfaceHolder where the preview is rendered. 549 * @param fromMs The time (relative to the timeline) at which the preview 550 * will start 551 * @param toMs The time (relative to the timeline) at which the preview will 552 * stop. Use -1 to play to the end of the timeline 553 * @param loop true if the preview should be looped once it reaches the end 554 * @param callbackAfterFrameCount The listener interface should be invoked 555 * after the number of frames specified by this parameter. 556 * @param listener The listener which will be notified of the preview 557 * progress 558 * 559 * @throws IllegalArgumentException if fromMs is beyond the preview duration 560 * @throws IllegalStateException if a preview or an export is already in 561 * progress 562 */ 563 public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs, 564 boolean loop,int callbackAfterFrameCount, 565 PreviewProgressListener listener); 566 567 /** 568 * Stop the current preview. This method blocks until ongoing preview is 569 * stopped. Ignored if there is no preview running. 570 * 571 * @return The accurate current time when stop is effective expressed in 572 * milliseconds 573 */ 574 public long stopPreview(); 575 576 /** 577 * Clears the preview surface 578 * 579 * @param surfaceHolder SurfaceHolder where the preview is rendered 580 * and needs to be cleared. 581 */ 582 public void clearSurface(SurfaceHolder surfaceHolder); 583 584} 585