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