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