VideoEditor.java revision fdacc8be92cd36f712cfdb0fcf9b0e847f8eeb58
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
17package android.media.videoeditor;
18
19import java.io.IOException;
20import java.util.List;
21import java.util.concurrent.CancellationException;
22
23import android.view.SurfaceHolder;
24
25/**
26 * This is the interface implemented by classes which provide video editing
27 * functionality. The VideoEditor implementation class manages all input and
28 * output files. Unless specifically mentioned, methods are blocking. A
29 * typical editing session may consist of the following sequence of operations:
30 *
31 * <ul>
32 *  <li>Add a set of MediaItems</li>
33 *  <li>Apply a set of Transitions between MediaItems</li>
34 *  <li>Add Effects and Overlays to media items</li>
35 *  <li>Preview the movie at any time</li>
36 *  <li>Save the VideoEditor implementation class internal state</li>
37 *  <li>Release the VideoEditor implementation class instance by invoking
38 * {@link #release()}
39 * </ul>
40 * The internal VideoEditor state consists of the following elements:
41 * <ul>
42 *  <li>Ordered & trimmed MediaItems</li>
43 *  <li>Transition video clips</li>
44 *  <li>Overlays</li>
45 *  <li>Effects</li>
46 *  <li>Audio waveform for the background audio and MediaItems</li>
47 *  <li>Project thumbnail</li>
48 *  <li>Last exported movie.</li>
49 *  <li>Other project specific data such as the current aspect ratio.</li>
50 * </ul>
51 * {@hide}
52 */
53public interface VideoEditor {
54    // The file name of the project thumbnail
55    public static final String THUMBNAIL_FILENAME = "thumbnail.jpg";
56
57    // Use this value instead of the specific end of the storyboard timeline
58    // value.
59    public final static int DURATION_OF_STORYBOARD = -1;
60
61    /**
62     * This listener interface is used by the VideoEditor to emit preview
63     * progress notifications. This callback should be invoked after the
64     * number of frames specified by
65     * {@link #startPreview(SurfaceHolder surfaceHolder, long fromMs,
66     *           int callbackAfterFrameCount, PreviewProgressListener listener)}
67     */
68    public interface PreviewProgressListener {
69        /**
70         * This method notifies the listener of the current time position while
71         * previewing a project.
72         *
73         * @param videoEditor The VideoEditor instance
74         * @param timeMs The current preview position (expressed in milliseconds
75         *            since the beginning of the storyboard timeline).
76         * @param end true if the end of the timeline was reached
77         */
78        public void onProgress(VideoEditor videoEditor, long timeMs, boolean end);
79    }
80
81    /**
82     * This listener interface is used by the VideoEditor to emit export status
83     * notifications.
84     * {@link #export(String filename, ExportProgressListener listener, int height, int bitrate)}
85     */
86    public interface ExportProgressListener {
87        /**
88         * This method notifies the listener of the progress status of a export
89         * operation.
90         *
91         * @param videoEditor The VideoEditor instance
92         * @param filename The name of the file which is in the process of being
93         *            exported.
94         * @param progress The progress in %. At the beginning of the export, this
95         *            value is set to 0; at the end, the value is set to 100.
96         */
97        public void onProgress(VideoEditor videoEditor, String filename, int progress);
98    }
99
100    /**
101     * @return The path where the VideoEditor stores all files related to the
102     * project
103     */
104    public String getPath();
105
106    /**
107     * This method releases all in-memory resources used by the VideoEditor
108     * instance. All pending operations such as preview, export and extract
109     * audio waveform must be canceled.
110     */
111    public void release();
112
113    /**
114     * Persist the current internal state of VideoEditor to the project path.
115     * The VideoEditor state may be restored by invoking the
116     * {@link VideoEditorFactory#load(String)} method. This method does not
117     * release the internal in-memory state of the VideoEditor. To release
118     * the in-memory state of the VideoEditor the {@link #release()} method
119     * must be invoked.
120     *
121     * Pending transition generations must be allowed to complete before the
122     * state is saved.
123     * Pending audio waveform generations must be allowed to complete.
124     * Pending export operations must be allowed to continue.
125     */
126    public void save() throws IOException;
127
128    /**
129     * Create the output movie based on all media items added and the applied
130     * storyboard items. This method can take a long time to execute and is
131     * blocking. The application will receive progress notifications via the
132     * ExportProgressListener. Specific implementations may not support multiple
133     * simultaneous export operations.
134     *
135     * Note that invoking methods which would change the contents of the output
136     * movie throw an IllegalStateException while an export operation is
137     * pending.
138     *
139     * @param filename The output file name (including the full path)
140     * @param height The height of the output video file. The supported values
141     *            for height are described in the MediaProperties class, for
142     *            example: HEIGHT_480. The width will be automatically
143     *            computed according to the aspect ratio provided by
144     *            {@link #setAspectRatio(int)}
145     * @param bitrate The bitrate of the output video file. This is approximate
146     *            value for the output movie. Supported bitrate values are
147     *            described in the MediaProperties class for example:
148     *            BITRATE_384K
149     * @param listener The listener for progress notifications. Use null if
150     *            export progress notifications are not needed.
151     *
152     * @throws IllegalArgumentException if height or bitrate are not supported.
153     * @throws IOException if output file cannot be created
154     * @throws IllegalStateException if a preview or an export is in progress or
155     *             if no MediaItem has been added
156     * @throws CancellationException if export is canceled by calling
157     *             {@link #cancelExport()}
158     * @throws UnsupportOperationException if multiple simultaneous export()
159     *  are not allowed
160     */
161    public void export(String filename, int height, int bitrate, ExportProgressListener listener)
162            throws IOException;
163
164    /**
165     * Cancel the running export operation. This method blocks until the
166     * export is canceled and the exported file (if any) is deleted. If the
167     * export completed by the time this method is invoked, the export file
168     * will be deleted.
169     *
170     * @param filename The filename which identifies the export operation to be
171     *            canceled.
172     **/
173    public void cancelExport(String filename);
174
175    /**
176     * Add a media item at the end of the storyboard.
177     *
178     * @param mediaItem The media item object to add
179     * @throws IllegalStateException if a preview or an export is in progress or
180     *             if the media item id is not unique across all the media items
181     *             added.
182     */
183    public void addMediaItem(MediaItem mediaItem);
184
185    /**
186     * Insert a media item after the media item with the specified id.
187     *
188     * @param mediaItem The media item object to insert
189     * @param afterMediaItemId Insert the mediaItem after the media item
190     *            identified by this id. If this parameter is null, the media
191     *            item is inserted at the beginning of the timeline.
192     *
193     * @throws IllegalStateException if a preview or an export is in progress
194     * @throws IllegalArgumentException if media item with the specified id does
195     *             not exist (null is a valid value) or if the media item id is
196     *             not unique across all the media items added.
197     */
198    public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId);
199
200    /**
201     * Move a media item after the media item with the specified id.
202     *
203     * Note: The project thumbnail is regenerated if the media item is or
204     * becomes the first media item in the storyboard timeline.
205     *
206     * @param mediaItemId The id of the media item to move
207     * @param afterMediaItemId Move the media item identified by mediaItemId after
208     *          the media item identified by this parameter. If this parameter
209     *          is null, the media item is moved at the beginning of the
210     *          timeline.
211     *
212     * @throws IllegalStateException if a preview or an export is in progress
213     * @throws IllegalArgumentException if one of media item ids is invalid
214     *          (null is a valid value)
215     */
216    public void moveMediaItem(String mediaItemId, String afterMediaItemId);
217
218    /**
219     * Remove the media item with the specified id. If there are transitions
220     * before or after this media item, then this/these transition(s) are
221     * removed from the storyboard. If the extraction of the audio waveform is
222     * in progress, the extraction is canceled and the file is deleted.
223     *
224     * Effects and overlays associated with the media item will also be
225     * removed.
226     *
227     * Note: The project thumbnail is regenerated if the media item which
228     * is removed is the first media item in the storyboard or if the
229     * media item is the only one in the storyboard. If the
230     * media item is the only one in the storyboard, the project thumbnail
231     * will be set to a black frame and the aspect ratio will revert to the
232     * default aspect ratio, and this method is equivalent to
233     * removeAllMediaItems() in this case.
234     *
235     * @param mediaItemId The unique id of the media item to be removed
236     *
237     * @return The media item that was removed
238     *
239     * @throws IllegalStateException if a preview or an export is in progress
240     * @throws IllegalArgumentException if media item with the specified id
241     *          does not exist
242     */
243    public MediaItem removeMediaItem(String mediaItemId);
244
245    /**
246     * Remove all media items in the storyboard. All effects, overlays and all
247     * transitions are also removed.
248     *
249     * Note: The project thumbnail will be set to a black frame and the aspect
250     * ratio will revert to the default aspect ratio.
251     *
252     * @throws IllegalStateException if a preview or an export is in progress
253     */
254    public void removeAllMediaItems();
255
256    /**
257     * Get the list of media items in the order in which it they appear in the
258     * storyboard timeline.
259     *
260     * Note that if any media item source files are no longer
261     * accessible, this method will still provide the full list of media items.
262     *
263     * @return The list of media items. If no media item exist an empty list
264     *          will be returned.
265     */
266    public List<MediaItem> getAllMediaItems();
267
268    /**
269     * Find the media item with the specified id
270     *
271     * @param mediaItemId The media item id
272     *
273     * @return The media item with the specified id (null if it does not exist)
274     */
275    public MediaItem getMediaItem(String mediaItemId);
276
277    /**
278     * Add a transition between the media items specified by the transition.
279     * If a transition existed at the same position it is invalidated and then
280     * the transition is replaced. Note that the new transition video clip is
281     * not automatically generated by this method. The
282     * {@link Transition#generate()} method must be invoked to generate
283     * the transition video clip.
284     *
285     * Note that the TransitionAtEnd and TransitionAtStart are special kinds
286     * that can not be applied between two media items.
287     *
288     * A crossfade audio transition will be automatically applied regardless of
289     * the video transition.
290     *
291     * @param transition The transition to apply
292     *
293     * @throws IllegalStateException if a preview or an export is in progress
294     * @throws IllegalArgumentException if the transition duration is larger
295     *              than the smallest duration of the two media item files or
296     *              if the two media items specified in the transition are not
297     *              adjacent
298     */
299    public void addTransition(Transition transition);
300
301    /**
302     * Remove the transition with the specified id.
303     *
304     * @param transitionId The id of the transition to be removed
305     *
306     * @return The transition that was removed
307     * @throws IllegalStateException if a preview or an export is in progress
308     * @throws IllegalArgumentException if transition with the specified id does
309     *             not exist
310     */
311    public Transition removeTransition(String transitionId);
312
313    /**
314     * Get the list of transitions
315     *
316     * @return The list of transitions. If no transitions exist an empty list
317     *  will be returned.
318     */
319    public List<Transition> getAllTransitions();
320
321    /**
322     * Find the transition with the specified transition id.
323     *
324     * @param transitionId The transition id
325     *
326     * @return The transition
327     */
328    public Transition getTransition(String transitionId);
329
330    /**
331     * Add the specified AudioTrack to the storyboard. Note: Specific
332     * implementations may support a limited number of audio tracks (e.g. only
333     * one audio track)
334     *
335     * @param audioTrack The AudioTrack to add
336     * @throws UnsupportedOperationException if the implementation supports a
337     *             limited number of audio tracks.
338     * @throws IllegalArgumentException if media item is not unique across all
339     *             the audio tracks already added.
340     */
341    public void addAudioTrack(AudioTrack audioTrack);
342
343    /**
344     * Insert an audio track after the audio track with the specified id. Use
345     * addAudioTrack to add an audio track at the end of the storyboard
346     * timeline.
347     *
348     * @param audioTrack The audio track object to insert
349     * @param afterAudioTrackId Insert the audio track after the audio track
350     *            identified by this parameter. If this parameter is null the
351     *            audio track is added at the beginning of the timeline.
352     * @throws IllegalStateException if a preview or an export is in progress
353     * @throws IllegalArgumentException if media item with the specified id does
354     *             not exist (null is a valid value). if media item is not
355     *             unique across all the audio tracks already added.
356     * @throws UnsupportedOperationException if the implementation supports a
357     *             limited number of audio tracks
358     */
359    public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId);
360
361    /**
362     * Move an AudioTrack after the AudioTrack with the specified id.
363     *
364     * @param audioTrackId The id of the AudioTrack to move
365     * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId
366     *            after the AudioTrack identified by this parameter. If this
367     *            parameter is null the audio track is added at the beginning of
368     *            the timeline.
369     * @throws IllegalStateException if a preview or an export is in progress
370     * @throws IllegalArgumentException if one of media item ids is invalid
371     *             (null is a valid value)
372     */
373    public void moveAudioTrack(String audioTrackId, String afterAudioTrackId);
374
375    /**
376     * Remove the audio track with the specified id. If the extraction of the
377     * audio waveform is in progress, the extraction is canceled and the file is
378     * deleted.
379     *
380     * @param audioTrackId The id of the audio track to be removed
381     *
382     * @return The audio track that was removed
383     * @throws IllegalStateException if a preview or an export is in progress
384     */
385    public AudioTrack removeAudioTrack(String audioTrackId);
386
387    /**
388     * Get the list of AudioTracks in order in which they appear in the storyboard.
389     *
390     * Note that if any AudioTrack source files are not accessible anymore,
391     * this method will still provide the full list of audio tracks.
392     *
393     * @return The list of AudioTracks. If no audio tracks exist an empty list
394     *  will be returned.
395     */
396    public List<AudioTrack> getAllAudioTracks();
397
398    /**
399     * Find the AudioTrack with the specified id
400     *
401     * @param audioTrackId The AudioTrack id
402     *
403     * @return The AudioTrack with the specified id (null if it does not exist)
404     */
405    public AudioTrack getAudioTrack(String audioTrackId);
406
407    /**
408     * Set the aspect ratio used in the preview and the export movie.
409     *
410     * The default aspect ratio is ASPECTRATIO_16_9 (16:9).
411     *
412     * @param aspectRatio to apply. If aspectRatio is the same as the current
413     *            aspect ratio, then this function just returns. The supported
414     *            aspect ratio are defined in the MediaProperties class for
415     *            example: ASPECTRATIO_16_9
416     *
417     * @throws IllegalStateException if a preview or an export is in progress
418     * @throws IllegalArgumentException if aspect ratio is not supported
419     */
420    public void setAspectRatio(int aspectRatio);
421
422    /**
423     * Get current aspect ratio.
424     *
425     * @return The aspect ratio as described in MediaProperties
426     */
427    public int getAspectRatio();
428
429    /**
430     * Get the preview (and output movie) duration.
431     *
432     * @return The duration of the preview (and output movie)
433     */
434    public long getDuration();
435
436    /**
437     * Render a frame according to the preview aspect ratio and activating all
438     * storyboard items relative to the specified time.
439     *
440     * @param surfaceHolder SurfaceHolder used by the application
441     * @param timeMs time corresponding to the frame to display
442     *
443     * @return The accurate time stamp of the frame that is rendered
444     * .
445     * @throws IllegalStateException if a preview or an export is already
446     *             in progress
447     * @throws IllegalArgumentException if time is negative or beyond the
448     *             preview duration
449     */
450    public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs);
451
452    /**
453     * This method must be called after the aspect ratio of the project changes
454     * and before startPreview is called. Note that this method may block for
455     * an extensive period of time.
456     */
457    public void generatePreview();
458
459    /**
460     * Start the preview of all the storyboard items applied on all MediaItems
461     * This method does not block (does not wait for the preview to complete).
462     * The PreviewProgressListener allows to track the progress at the time
463     * interval determined by the callbackAfterFrameCount parameter. The
464     * SurfaceHolder has to be created and ready for use before calling this
465     * method. The method is a no-op if there are no MediaItems in the
466     * storyboard.
467     *
468     * @param surfaceHolder SurfaceHolder where the preview is rendered.
469     * @param fromMs The time (relative to the timeline) at which the preview
470     *            will start
471     * @param toMs The time (relative to the timeline) at which the preview will
472     *            stop. Use -1 to play to the end of the timeline
473     * @param loop true if the preview should be looped once it reaches the end
474     * @param callbackAfterFrameCount The listener interface should be invoked
475     *            after the number of frames specified by this parameter.
476     * @param listener The listener which will be notified of the preview
477     *            progress
478     * @throws IllegalArgumentException if fromMs is beyond the preview duration
479     * @throws IllegalStateException if a preview or an export is already in
480     *             progress
481     */
482    public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs, boolean loop,
483            int callbackAfterFrameCount, PreviewProgressListener listener);
484
485    /**
486     * Stop the current preview. This method blocks until ongoing preview is
487     * stopped. Ignored if there is no preview running.
488     *
489     * @return The accurate current time when stop is effective expressed in
490     *          milliseconds
491     */
492    public long stopPreview();
493}
494