Home | History | Annotate | Download | only in videoeditor
      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