VideoEditor.java revision c006e8ef64bbfd47a9ecd4cfd708362e40b0d337
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. Note that invoking methods which would
134     * change the contents of the output movie throw an IllegalStateException
135     * while an export operation is pending.
136     *
137     * The audio and video codecs are automatically selected by the underlying
138     * implementation.
139     *
140     * @param filename The output file name (including the full path)
141     * @param height The height of the output video file. The supported values
142     *            for height are described in the MediaProperties class, for
143     *            example: HEIGHT_480. The width will be automatically computed
144     *            according to the aspect ratio provided by
145     *            {@link #setAspectRatio(int)}
146     * @param bitrate The bitrate of the output video file. This is approximate
147     *            value for the output movie. Supported bitrate values are
148     *            described in the MediaProperties class for example:
149     *            BITRATE_384K
150     * @param listener The listener for progress notifications. Use null if
151     *            export progress notifications are not needed.
152     * @throws IllegalArgumentException if height or bitrate are not supported
153     *             or if the audio or video codecs are not supported
154     * @throws IOException if output file cannot be created
155     * @throws IllegalStateException if a preview or an export is in progress or
156     *             if no MediaItem has been added
157     * @throws CancellationException if export is canceled by calling
158     *             {@link #cancelExport()}
159     * @throws UnsupportOperationException if multiple simultaneous export() are
160     *             not allowed
161     */
162    public void export(String filename, int height, int bitrate, ExportProgressListener listener)
163            throws IOException;
164
165    /**
166     * Create the output movie based on all media items added and the applied
167     * storyboard items. This method can take a long time to execute and is
168     * blocking. The application will receive progress notifications via the
169     * ExportProgressListener. Specific implementations may not support multiple
170     * simultaneous export operations. Note that invoking methods which would
171     * change the contents of the output movie throw an IllegalStateException
172     * while an export operation is pending.
173     *
174     * @param filename The output file name (including the full path)
175     * @param height The height of the output video file. The supported values
176     *            for height are described in the MediaProperties class, for
177     *            example: HEIGHT_480. The width will be automatically computed
178     *            according to the aspect ratio provided by
179     *            {@link #setAspectRatio(int)}
180     * @param bitrate The bitrate of the output video file. This is approximate
181     *            value for the output movie. Supported bitrate values are
182     *            described in the MediaProperties class for example:
183     *            BITRATE_384K
184     * @param audioCodec The audio codec to be used for the export. The audio
185     *            codec values are defined in the MediaProperties class (e.g.
186     *            ACODEC_AAC_LC). Note that not all audio codec types are
187     *            supported for export purposes.
188     * @param videoCodec The video codec to be used for the export. The video
189     *            codec values are defined in the MediaProperties class (e.g.
190     *            VCODEC_H264BP). Note that not all video codec types are
191     *            supported for export purposes.
192     * @param listener The listener for progress notifications. Use null if
193     *            export progress notifications are not needed.
194     * @throws IllegalArgumentException if height or bitrate are not supported
195     *             or if the audio or video codecs are not supported
196     * @throws IOException if output file cannot be created
197     * @throws IllegalStateException if a preview or an export is in progress or
198     *             if no MediaItem has been added
199     * @throws CancellationException if export is canceled by calling
200     *             {@link #cancelExport()}
201     * @throws UnsupportOperationException if multiple simultaneous export() are
202     *             not allowed
203     */
204    public void export(String filename, int height, int bitrate, int audioCodec, int videoCodec,
205            ExportProgressListener listener) throws IOException;
206
207    /**
208     * Cancel the running export operation. This method blocks until the
209     * export is canceled and the exported file (if any) is deleted. If the
210     * export completed by the time this method is invoked, the export file
211     * will be deleted.
212     *
213     * @param filename The filename which identifies the export operation to be
214     *            canceled.
215     **/
216    public void cancelExport(String filename);
217
218    /**
219     * Add a media item at the end of the storyboard.
220     *
221     * @param mediaItem The media item object to add
222     * @throws IllegalStateException if a preview or an export is in progress or
223     *             if the media item id is not unique across all the media items
224     *             added.
225     */
226    public void addMediaItem(MediaItem mediaItem);
227
228    /**
229     * Insert a media item after the media item with the specified id.
230     *
231     * @param mediaItem The media item object to insert
232     * @param afterMediaItemId Insert the mediaItem after the media item
233     *            identified by this id. If this parameter is null, the media
234     *            item is inserted at the beginning of the timeline.
235     *
236     * @throws IllegalStateException if a preview or an export is in progress
237     * @throws IllegalArgumentException if media item with the specified id does
238     *             not exist (null is a valid value) or if the media item id is
239     *             not unique across all the media items added.
240     */
241    public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId);
242
243    /**
244     * Move a media item after the media item with the specified id.
245     *
246     * Note: The project thumbnail is regenerated if the media item is or
247     * becomes the first media item in the storyboard timeline.
248     *
249     * @param mediaItemId The id of the media item to move
250     * @param afterMediaItemId Move the media item identified by mediaItemId after
251     *          the media item identified by this parameter. If this parameter
252     *          is null, the media item is moved at the beginning of the
253     *          timeline.
254     *
255     * @throws IllegalStateException if a preview or an export is in progress
256     * @throws IllegalArgumentException if one of media item ids is invalid
257     *          (null is a valid value)
258     */
259    public void moveMediaItem(String mediaItemId, String afterMediaItemId);
260
261    /**
262     * Remove the media item with the specified id. If there are transitions
263     * before or after this media item, then this/these transition(s) are
264     * removed from the storyboard. If the extraction of the audio waveform is
265     * in progress, the extraction is canceled and the file is deleted.
266     *
267     * Effects and overlays associated with the media item will also be
268     * removed.
269     *
270     * Note: The project thumbnail is regenerated if the media item which
271     * is removed is the first media item in the storyboard or if the
272     * media item is the only one in the storyboard. If the
273     * media item is the only one in the storyboard, the project thumbnail
274     * will be set to a black frame and the aspect ratio will revert to the
275     * default aspect ratio, and this method is equivalent to
276     * removeAllMediaItems() in this case.
277     *
278     * @param mediaItemId The unique id of the media item to be removed
279     *
280     * @return The media item that was removed
281     *
282     * @throws IllegalStateException if a preview or an export is in progress
283     * @throws IllegalArgumentException if media item with the specified id
284     *          does not exist
285     */
286    public MediaItem removeMediaItem(String mediaItemId);
287
288    /**
289     * Remove all media items in the storyboard. All effects, overlays and all
290     * transitions are also removed.
291     *
292     * Note: The project thumbnail will be set to a black frame and the aspect
293     * ratio will revert to the default aspect ratio.
294     *
295     * @throws IllegalStateException if a preview or an export is in progress
296     */
297    public void removeAllMediaItems();
298
299    /**
300     * Get the list of media items in the order in which it they appear in the
301     * storyboard timeline.
302     *
303     * Note that if any media item source files are no longer
304     * accessible, this method will still provide the full list of media items.
305     *
306     * @return The list of media items. If no media item exist an empty list
307     *          will be returned.
308     */
309    public List<MediaItem> getAllMediaItems();
310
311    /**
312     * Find the media item with the specified id
313     *
314     * @param mediaItemId The media item id
315     *
316     * @return The media item with the specified id (null if it does not exist)
317     */
318    public MediaItem getMediaItem(String mediaItemId);
319
320    /**
321     * Add a transition between the media items specified by the transition.
322     * If a transition existed at the same position it is invalidated and then
323     * the transition is replaced. Note that the new transition video clip is
324     * not automatically generated by this method. The
325     * {@link Transition#generate()} method must be invoked to generate
326     * the transition video clip.
327     *
328     * Note that the TransitionAtEnd and TransitionAtStart are special kinds
329     * that can not be applied between two media items.
330     *
331     * A crossfade audio transition will be automatically applied regardless of
332     * the video transition.
333     *
334     * @param transition The transition to apply
335     *
336     * @throws IllegalStateException if a preview or an export is in progress
337     * @throws IllegalArgumentException if the transition duration is larger
338     *              than the smallest duration of the two media item files or
339     *              if the two media items specified in the transition are not
340     *              adjacent
341     */
342    public void addTransition(Transition transition);
343
344    /**
345     * Remove the transition with the specified id.
346     *
347     * @param transitionId The id of the transition to be removed
348     *
349     * @return The transition that was removed
350     * @throws IllegalStateException if a preview or an export is in progress
351     * @throws IllegalArgumentException if transition with the specified id does
352     *             not exist
353     */
354    public Transition removeTransition(String transitionId);
355
356    /**
357     * Get the list of transitions
358     *
359     * @return The list of transitions. If no transitions exist an empty list
360     *  will be returned.
361     */
362    public List<Transition> getAllTransitions();
363
364    /**
365     * Find the transition with the specified transition id.
366     *
367     * @param transitionId The transition id
368     *
369     * @return The transition
370     */
371    public Transition getTransition(String transitionId);
372
373    /**
374     * Add the specified AudioTrack to the storyboard. Note: Specific
375     * implementations may support a limited number of audio tracks (e.g. only
376     * one audio track)
377     *
378     * @param audioTrack The AudioTrack to add
379     * @throws UnsupportedOperationException if the implementation supports a
380     *             limited number of audio tracks.
381     * @throws IllegalArgumentException if media item is not unique across all
382     *             the audio tracks already added.
383     */
384    public void addAudioTrack(AudioTrack audioTrack);
385
386    /**
387     * Insert an audio track after the audio track with the specified id. Use
388     * addAudioTrack to add an audio track at the end of the storyboard
389     * timeline.
390     *
391     * @param audioTrack The audio track object to insert
392     * @param afterAudioTrackId Insert the audio track after the audio track
393     *            identified by this parameter. If this parameter is null the
394     *            audio track is added at the beginning of the timeline.
395     * @throws IllegalStateException if a preview or an export is in progress
396     * @throws IllegalArgumentException if media item with the specified id does
397     *             not exist (null is a valid value). if media item is not
398     *             unique across all the audio tracks already added.
399     * @throws UnsupportedOperationException if the implementation supports a
400     *             limited number of audio tracks
401     */
402    public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId);
403
404    /**
405     * Move an AudioTrack after the AudioTrack with the specified id.
406     *
407     * @param audioTrackId The id of the AudioTrack to move
408     * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId
409     *            after the AudioTrack identified by this parameter. If this
410     *            parameter is null the audio track is added at the beginning of
411     *            the timeline.
412     * @throws IllegalStateException if a preview or an export is in progress
413     * @throws IllegalArgumentException if one of media item ids is invalid
414     *             (null is a valid value)
415     */
416    public void moveAudioTrack(String audioTrackId, String afterAudioTrackId);
417
418    /**
419     * Remove the audio track with the specified id. If the extraction of the
420     * audio waveform is in progress, the extraction is canceled and the file is
421     * deleted.
422     *
423     * @param audioTrackId The id of the audio track to be removed
424     *
425     * @return The audio track that was removed
426     * @throws IllegalStateException if a preview or an export is in progress
427     */
428    public AudioTrack removeAudioTrack(String audioTrackId);
429
430    /**
431     * Get the list of AudioTracks in order in which they appear in the storyboard.
432     *
433     * Note that if any AudioTrack source files are not accessible anymore,
434     * this method will still provide the full list of audio tracks.
435     *
436     * @return The list of AudioTracks. If no audio tracks exist an empty list
437     *  will be returned.
438     */
439    public List<AudioTrack> getAllAudioTracks();
440
441    /**
442     * Find the AudioTrack with the specified id
443     *
444     * @param audioTrackId The AudioTrack id
445     *
446     * @return The AudioTrack with the specified id (null if it does not exist)
447     */
448    public AudioTrack getAudioTrack(String audioTrackId);
449
450    /**
451     * Set the aspect ratio used in the preview and the export movie.
452     *
453     * The default aspect ratio is ASPECTRATIO_16_9 (16:9).
454     *
455     * @param aspectRatio to apply. If aspectRatio is the same as the current
456     *            aspect ratio, then this function just returns. The supported
457     *            aspect ratio are defined in the MediaProperties class for
458     *            example: ASPECTRATIO_16_9
459     *
460     * @throws IllegalStateException if a preview or an export is in progress
461     * @throws IllegalArgumentException if aspect ratio is not supported
462     */
463    public void setAspectRatio(int aspectRatio);
464
465    /**
466     * Get current aspect ratio.
467     *
468     * @return The aspect ratio as described in MediaProperties
469     */
470    public int getAspectRatio();
471
472    /**
473     * Get the preview (and output movie) duration.
474     *
475     * @return The duration of the preview (and output movie)
476     */
477    public long getDuration();
478
479    /**
480     * Render a frame according to the preview aspect ratio and activating all
481     * storyboard items relative to the specified time.
482     *
483     * @param surfaceHolder SurfaceHolder used by the application
484     * @param timeMs time corresponding to the frame to display
485     *
486     * @return The accurate time stamp of the frame that is rendered
487     * .
488     * @throws IllegalStateException if a preview or an export is already
489     *             in progress
490     * @throws IllegalArgumentException if time is negative or beyond the
491     *             preview duration
492     */
493    public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs);
494
495    /**
496     * This method must be called after the aspect ratio of the project changes
497     * and before startPreview is called. Note that this method may block for
498     * an extensive period of time.
499     */
500    public void generatePreview();
501
502    /**
503     * Start the preview of all the storyboard items applied on all MediaItems
504     * This method does not block (does not wait for the preview to complete).
505     * The PreviewProgressListener allows to track the progress at the time
506     * interval determined by the callbackAfterFrameCount parameter. The
507     * SurfaceHolder has to be created and ready for use before calling this
508     * method. The method is a no-op if there are no MediaItems in the
509     * storyboard.
510     *
511     * @param surfaceHolder SurfaceHolder where the preview is rendered.
512     * @param fromMs The time (relative to the timeline) at which the preview
513     *            will start
514     * @param toMs The time (relative to the timeline) at which the preview will
515     *            stop. Use -1 to play to the end of the timeline
516     * @param loop true if the preview should be looped once it reaches the end
517     * @param callbackAfterFrameCount The listener interface should be invoked
518     *            after the number of frames specified by this parameter.
519     * @param listener The listener which will be notified of the preview
520     *            progress
521     * @throws IllegalArgumentException if fromMs is beyond the preview duration
522     * @throws IllegalStateException if a preview or an export is already in
523     *             progress
524     */
525    public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs, boolean loop,
526            int callbackAfterFrameCount, PreviewProgressListener listener);
527
528    /**
529     * Stop the current preview. This method blocks until ongoing preview is
530     * stopped. Ignored if there is no preview running.
531     *
532     * @return The accurate current time when stop is effective expressed in
533     *          milliseconds
534     */
535    public long stopPreview();
536}
537