VideoEditor.java revision 600acf14ff12eaf139f0ac644fb7e17849af65fa
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.Paint;
27import android.graphics.Rect;
28import 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 */
58public 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_H264BP). 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