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