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