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