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