MediaVideoItem.java revision 6ea92ecabbb53a2997eb5835c11945fecc177b91
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;
20
21import android.graphics.Bitmap;
22import android.view.SurfaceHolder;
23
24/**
25 * This class represents a video clip item on the storyboard
26 * {@hide}
27 */
28public class MediaVideoItem extends MediaItem {
29    // Instance variables
30    private final int mWidth;
31    private final int mHeight;
32    private final int mAspectRatio;
33    private final int mFileType;
34    private final int mVideoType;
35    private final int mVideoProfile;
36    private final int mVideoBitrate;
37    private final long mDurationMs;
38    private final int mAudioBitrate;
39    private final int mFps;
40    private final int mAudioType;
41    private final int mAudioChannels;
42    private final int mAudioSamplingFrequency;
43
44    private long mBeginBoundaryTimeMs;
45    private long mEndBoundaryTimeMs;
46    private int mVolumePercentage;
47    private boolean mMuted;
48    private String mAudioWaveformFilename;
49    // The audio waveform data
50    private WaveformData mWaveformData;
51
52    /**
53     * An object of this type cannot be instantiated with a default constructor
54     */
55    @SuppressWarnings("unused")
56    private MediaVideoItem() throws IOException {
57        this(null, null, null, RENDERING_MODE_BLACK_BORDER);
58    }
59
60    /**
61     * Constructor
62     *
63     * @param editor The video editor reference
64     * @param mediaItemId The MediaItem id
65     * @param filename The image file name
66     * @param renderingMode The rendering mode
67     *
68     * @throws IOException if the file cannot be opened for reading
69     */
70    public MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
71            int renderingMode)
72        throws IOException {
73        this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null);
74    }
75
76    /**
77     * Constructor
78     *
79     * @param editor The video editor reference
80     * @param mediaItemId The MediaItem id
81     * @param filename The image file name
82     * @param renderingMode The rendering mode
83     * @param beginMs Start time in milliseconds. Set to 0 to extract from the
84     *           beginning
85     * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
86     *           extract until the end
87     * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
88     *            means double, 0% means silent.
89     * @param muted true if the audio is muted
90     * @param audioWaveformFilename The name of the audio waveform file
91     *
92     * @throws IOException if the file cannot be opened for reading
93     */
94    MediaVideoItem(VideoEditor editor, String mediaItemId, String filename, int renderingMode,
95            long beginMs, long endMs, int volumePercent, boolean muted,
96            String audioWaveformFilename)  throws IOException {
97        super(editor, mediaItemId, filename, renderingMode);
98        // TODO: Set these variables correctly
99        mWidth = 1080;
100        mHeight = 720;
101        mAspectRatio = MediaProperties.ASPECT_RATIO_3_2;
102        mFileType = MediaProperties.FILE_MP4;
103        mVideoType = MediaProperties.VCODEC_H264BP;
104        // Do we have predefined values for this variable?
105        mVideoProfile = 0;
106        // Can video and audio duration be different?
107        mDurationMs = 10000;
108        mVideoBitrate = 800000;
109        mAudioBitrate = 30000;
110        mFps = 30;
111        mAudioType = MediaProperties.ACODEC_AAC_LC;
112        mAudioChannels = 2;
113        mAudioSamplingFrequency = 16000;
114
115        mBeginBoundaryTimeMs = beginMs;
116        mEndBoundaryTimeMs = endMs == END_OF_FILE ? mDurationMs : endMs;
117        mVolumePercentage = volumePercent;
118        mMuted = muted;
119        mAudioWaveformFilename = audioWaveformFilename;
120        if (audioWaveformFilename != null) {
121            mWaveformData = new WaveformData(audioWaveformFilename);
122        } else {
123            mWaveformData = null;
124        }
125    }
126
127    /**
128     * Sets the start and end marks for trimming a video media item.
129     * This method will adjust the duration of bounding transitions, effects
130     * and overlays if the current duration of the transactions become greater
131     * than the maximum allowable duration.
132     *
133     * @param beginMs Start time in milliseconds. Set to 0 to extract from the
134     *           beginning
135     * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
136     *           extract until the end
137     *
138     * @throws IllegalArgumentException if the start time is greater or equal than
139     *           end time, the end time is beyond the file duration, the start time
140     *           is negative
141     */
142    public void setExtractBoundaries(long beginMs, long endMs) {
143        if (beginMs > mDurationMs) {
144            throw new IllegalArgumentException("Invalid start time");
145        }
146        if (endMs > mDurationMs) {
147            throw new IllegalArgumentException("Invalid end time");
148        }
149
150        if (beginMs != mBeginBoundaryTimeMs) {
151            if (mBeginTransition != null) {
152                mBeginTransition.invalidate();
153            }
154        }
155
156        if (endMs != mEndBoundaryTimeMs) {
157            if (mEndTransition != null) {
158                mEndTransition.invalidate();
159            }
160        }
161
162        mBeginBoundaryTimeMs = beginMs;
163        mEndBoundaryTimeMs = endMs;
164
165        adjustTransitions();
166
167        // Note that the start and duration of any effects and overlays are
168        // not adjusted nor are they automatically removed if they fall
169        // outside the new boundaries.
170    }
171
172    /**
173     * @return The boundary begin time
174     */
175    public long getBoundaryBeginTime() {
176        return mBeginBoundaryTimeMs;
177    }
178
179    /**
180     * @return The boundary end time
181     */
182    public long getBoundaryEndTime() {
183        return mEndBoundaryTimeMs;
184    }
185
186    /*
187     * {@inheritDoc}
188     */
189    @Override
190    public void addEffect(Effect effect) {
191        if (effect instanceof EffectKenBurns) {
192            throw new IllegalArgumentException("Ken Burns effects cannot be applied to MediaVideoItem");
193        }
194        super.addEffect(effect);
195    }
196
197    /*
198     * {@inheritDoc}
199     */
200    @Override
201    public Bitmap getThumbnail(int width, int height, long timeMs) {
202        return null;
203    }
204
205    /*
206     * {@inheritDoc}
207     */
208    @Override
209    public Bitmap[] getThumbnailList(int width, int height, long startMs, long endMs,
210            int thumbnailCount) throws IOException {
211        return null;
212    }
213
214    /*
215     * {@inheritDoc}
216     */
217    @Override
218    public int getAspectRatio() {
219        return mAspectRatio;
220    }
221
222    /*
223     * {@inheritDoc}
224     */
225    @Override
226    public int getFileType() {
227        return mFileType;
228    }
229
230    /*
231     * {@inheritDoc}
232     */
233    @Override
234    public int getWidth() {
235        return mWidth;
236    }
237
238    /*
239     * {@inheritDoc}
240     */
241    @Override
242    public int getHeight() {
243        return mHeight;
244    }
245
246    /*
247     * {@inheritDoc}
248     */
249    @Override
250    public long getDuration() {
251        return mDurationMs;
252    }
253
254    /*
255     * {@inheritDoc}
256     */
257    @Override
258    public long getTimelineDuration() {
259        return mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
260    }
261
262    /**
263     * Render a frame according to the playback (in the native aspect ratio) for
264     * the specified media item. All effects and overlays applied to the media
265     * item are ignored. The extract boundaries are also ignored. This method
266     * can be used to playback frames when implementing trimming functionality.
267     *
268     * @param surfaceHolder SurfaceHolder used by the application
269     * @param timeMs time corresponding to the frame to display (relative to the
270     *            the beginning of the media item).
271     * @return The accurate time stamp of the frame that is rendered .
272     * @throws IllegalStateException if a playback, preview or an export is
273     *             already in progress
274     * @throws IllegalArgumentException if time is negative or greater than the
275     *             media item duration
276     */
277    public long renderFrame(SurfaceHolder surfaceHolder, long timeMs) {
278        return timeMs;
279    }
280
281    /**
282     * This API allows to generate a file containing the sample volume levels of
283     * the Audio track of this media item. This function may take significant
284     * time and is blocking. The file can be retrieved using
285     * getAudioWaveformFilename().
286     *
287     * @param listener The progress listener
288     *
289     * @throws IOException if the output file cannot be created
290     * @throws IllegalArgumentException if the mediaItem does not have a valid
291     *             Audio track
292     */
293    public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
294            throws IOException {
295        // TODO: Set mAudioWaveformFilename at the end once the export is complete
296        mWaveformData = new WaveformData(mAudioWaveformFilename);
297    }
298
299    /**
300     * Get the audio waveform file name if {@link #extractAudioWaveform()} was
301     * successful. The file format is as following:
302     * <ul>
303     *  <li>first 4 bytes provide the number of samples for each value, as big-endian signed</li>
304     *  <li>4 following bytes is the total number of values in the file, as big-endian signed</li>
305     *  <li>all values follow as bytes Name is unique.</li>
306     *</ul>
307     * @return the name of the file, null if the file has not been computed or
308     *         if there is no Audio track in the mediaItem
309     */
310    String getAudioWaveformFilename() {
311        return mAudioWaveformFilename;
312    }
313
314    /**
315     * @return The waveform data
316     */
317    public WaveformData getWaveformData() {
318        return mWaveformData;
319    }
320
321    /**
322     * Set volume of the Audio track of this mediaItem
323     *
324     * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
325     *            means double, 0% means silent.
326     * @throws UsupportedOperationException if volume value is not supported
327     */
328    public void setVolume(int volumePercent) {
329        mVolumePercentage = volumePercent;
330    }
331
332    /**
333     * Get the volume value of the audio track as percentage. Call of this
334     * method before calling setVolume will always return 100%
335     *
336     * @return the volume in percentage
337     */
338    public int getVolume() {
339        return mVolumePercentage;
340    }
341
342    /**
343     * @param muted true to mute the media item
344     */
345    public void setMute(boolean muted) {
346        mMuted = muted;
347    }
348
349    /**
350     * @return true if the media item is muted
351     */
352    public boolean isMuted() {
353        return mMuted;
354    }
355
356    /**
357     * @return The video type
358     */
359    public int getVideoType() {
360        return mVideoType;
361    }
362
363    /**
364     * @return The video profile
365     */
366    public int getVideoProfile() {
367        return mVideoProfile;
368    }
369
370    /**
371     * @return The video bitrate
372     */
373    public int getVideoBitrate() {
374        return mVideoBitrate;
375    }
376
377    /**
378     * @return The audio bitrate
379     */
380    public int getAudioBitrate() {
381        return mAudioBitrate;
382    }
383
384    /**
385     * @return The number of frames per second
386     */
387    public int getFps() {
388        return mFps;
389    }
390
391    /**
392     * @return The audio codec
393     */
394    public int getAudioType() {
395        return mAudioType;
396    }
397
398    /**
399     * @return The number of audio channels
400     */
401    public int getAudioChannels() {
402        return mAudioChannels;
403    }
404
405    /**
406     * @return The audio sample frequency
407     */
408    public int getAudioSamplingFrequency() {
409        return mAudioSamplingFrequency;
410    }
411}
412