MediaMetadataRetriever.java revision c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716b
1/*
2 * Copyright (C) 2008 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;
18
19import android.content.ContentResolver;
20import android.content.Context;
21import android.content.res.AssetFileDescriptor;
22import android.graphics.Bitmap;
23import android.net.Uri;
24
25import java.io.FileDescriptor;
26import java.io.FileNotFoundException;
27import java.io.IOException;
28
29/**
30 * MediaMetadataRetriever class provides a unified interface for retrieving
31 * frame and meta data from an input media file.
32 */
33public class MediaMetadataRetriever
34{
35    static {
36        System.loadLibrary("media_jni");
37        native_init();
38    }
39
40    // The field below is accessed by native methods
41    @SuppressWarnings("unused")
42    private int mNativeContext;
43
44    private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF;
45
46    public MediaMetadataRetriever() {
47        native_setup();
48    }
49
50    /**
51     * Sets the data source (file pathname) to use. Call this
52     * method before the rest of the methods in this class. This method may be
53     * time-consuming.
54     *
55     * @param path The path of the input media file.
56     * @throws IllegalArgumentException If the path is invalid.
57     */
58    public native void setDataSource(String path) throws IllegalArgumentException;
59
60    /**
61     * Sets the data source (FileDescriptor) to use.  It is the caller's
62     * responsibility to close the file descriptor. It is safe to do so as soon
63     * as this call returns. Call this method before the rest of the methods in
64     * this class. This method may be time-consuming.
65     *
66     * @param fd the FileDescriptor for the file you want to play
67     * @param offset the offset into the file where the data to be played starts,
68     * in bytes. It must be non-negative
69     * @param length the length in bytes of the data to be played. It must be
70     * non-negative.
71     * @throws IllegalArgumentException if the arguments are invalid
72     */
73    public native void setDataSource(FileDescriptor fd, long offset, long length)
74            throws IllegalArgumentException;
75
76    /**
77     * Sets the data source (FileDescriptor) to use. It is the caller's
78     * responsibility to close the file descriptor. It is safe to do so as soon
79     * as this call returns. Call this method before the rest of the methods in
80     * this class. This method may be time-consuming.
81     *
82     * @param fd the FileDescriptor for the file you want to play
83     * @throws IllegalArgumentException if the FileDescriptor is invalid
84     */
85    public void setDataSource(FileDescriptor fd)
86            throws IllegalArgumentException {
87        // intentionally less than LONG_MAX
88        setDataSource(fd, 0, 0x7ffffffffffffffL);
89    }
90
91    /**
92     * Sets the data source as a content Uri. Call this method before
93     * the rest of the methods in this class. This method may be time-consuming.
94     *
95     * @param context the Context to use when resolving the Uri
96     * @param uri the Content URI of the data you want to play
97     * @throws IllegalArgumentException if the Uri is invalid
98     * @throws SecurityException if the Uri cannot be used due to lack of
99     * permission.
100     */
101    public void setDataSource(Context context, Uri uri)
102        throws IllegalArgumentException, SecurityException {
103        if (uri == null) {
104            throw new IllegalArgumentException();
105        }
106
107        String scheme = uri.getScheme();
108        if(scheme == null || scheme.equals("file")) {
109            setDataSource(uri.getPath());
110            return;
111        }
112
113        AssetFileDescriptor fd = null;
114        try {
115            ContentResolver resolver = context.getContentResolver();
116            try {
117                fd = resolver.openAssetFileDescriptor(uri, "r");
118            } catch(FileNotFoundException e) {
119                throw new IllegalArgumentException();
120            }
121            if (fd == null) {
122                throw new IllegalArgumentException();
123            }
124            FileDescriptor descriptor = fd.getFileDescriptor();
125            if (!descriptor.valid()) {
126                throw new IllegalArgumentException();
127            }
128            // Note: using getDeclaredLength so that our behavior is the same
129            // as previous versions when the content provider is returning
130            // a full file.
131            if (fd.getDeclaredLength() < 0) {
132                setDataSource(descriptor);
133            } else {
134                setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength());
135            }
136            return;
137        } catch (SecurityException ex) {
138        } finally {
139            try {
140                if (fd != null) {
141                    fd.close();
142                }
143            } catch(IOException ioEx) {
144            }
145        }
146        setDataSource(uri.toString());
147    }
148
149    /**
150     * Call this method after setDataSource(). This method retrieves the
151     * meta data value associated with the keyCode.
152     *
153     * The keyCode currently supported is listed below as METADATA_XXX
154     * constants. With any other value, it returns a null pointer.
155     *
156     * @param keyCode One of the constants listed below at the end of the class.
157     * @return The meta data value associate with the given keyCode on success;
158     * null on failure.
159     */
160    public native String extractMetadata(int keyCode);
161
162    /**
163     * Call this method after setDataSource(). This method finds a
164     * representative frame close to the given time position by considering
165     * the given option if possible, and returns it as a bitmap. This is
166     * useful for generating a thumbnail for an input data source or just
167     * obtain and display a frame at the given time position.
168     *
169     * @param timeUs The time position where the frame will be retrieved.
170     * When retrieving the frame at the given time position, there is no
171     * guarantee that the data source has a frame located at the position.
172     * When this happens, a frame nearby will be returned. If timeUs is
173     * negative, time position and option will ignored, and any frame
174     * that the implementation considers as representative may be returned.
175     *
176     * @param option a hint on how the frame is found. Use
177     * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
178     * that has a timestamp earlier than or the same as timeUs. Use
179     * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
180     * that has a timestamp later than or the same as timeUs. Use
181     * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
182     * that has a timestamp closest to or the same as timeUs. Use
183     * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
184     * or may not be a sync frame but is closest to or the same as timeUs.
185     * {@link #OPTION_CLOSEST} often has larger performance overhead compared
186     * to the other options if there is no sync frame located at timeUs.
187     *
188     * @return A Bitmap containing a representative video frame, which
189     *         can be null, if such a frame cannot be retrieved.
190     */
191    public Bitmap getFrameAtTime(long timeUs, int option) {
192        if (option < OPTION_PREVIOUS_SYNC ||
193            option > OPTION_CLOSEST) {
194            throw new IllegalArgumentException("Unsupported option: " + option);
195        }
196
197        return _getFrameAtTime(timeUs, option);
198    }
199
200    /**
201     * Call this method after setDataSource(). This method finds a
202     * representative frame close to the given time position if possible,
203     * and returns it as a bitmap. This is useful for generating a thumbnail
204     * for an input data source. Call this method if one does not care
205     * how the frame is found as long as it is close to the given time;
206     * otherwise, please call {@link #getFrameAtTime(long, int)}.
207     *
208     * @param timeUs The time position where the frame will be retrieved.
209     * When retrieving the frame at the given time position, there is no
210     * guarentee that the data source has a frame located at the position.
211     * When this happens, a frame nearby will be returned. If timeUs is
212     * negative, time position and option will ignored, and any frame
213     * that the implementation considers as representative may be returned.
214     *
215     * @return A Bitmap containing a representative video frame, which
216     *         can be null, if such a frame cannot be retrieved.
217     *
218     * @see #getFrameAtTime(long, int)
219     */
220    public Bitmap getFrameAtTime(long timeUs) {
221        return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC);
222    }
223
224    /**
225     * Call this method after setDataSource(). This method finds a
226     * representative frame at any time position if possible,
227     * and returns it as a bitmap. This is useful for generating a thumbnail
228     * for an input data source. Call this method if one does not
229     * care about where the frame is located; otherwise, please call
230     * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)}
231     *
232     * @return A Bitmap containing a representative video frame, which
233     *         can be null, if such a frame cannot be retrieved.
234     *
235     * @see #getFrameAtTime(long)
236     * @see #getFrameAtTime(long, int)
237     */
238    public Bitmap getFrameAtTime() {
239        return getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
240    }
241
242    private native Bitmap _getFrameAtTime(long timeUs, int option);
243
244
245    /**
246     * Call this method after setDataSource(). This method finds the optional
247     * graphic or album art associated associated with the data source. If
248     * there are more than one pictures, (any) one of them is returned.
249     *
250     * @return null if no such graphic is found.
251     */
252    public byte[] getEmbeddedPicture() {
253        return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY);
254    }
255
256    private native byte[] getEmbeddedPicture(int pictureType);
257
258    /**
259     * Call it when one is done with the object. This method releases the memory
260     * allocated internally.
261     */
262    public native void release();
263    private native void native_setup();
264    private static native void native_init();
265
266    private native final void native_finalize();
267
268    @Override
269    protected void finalize() throws Throwable {
270        try {
271            native_finalize();
272        } finally {
273            super.finalize();
274        }
275    }
276
277    /**
278     * Option used in method {@link #getFrameAtTime(long, int)} to get a
279     * frame at a specified location.
280     *
281     * @see #getFrameAtTime(long, int)
282     */
283    /* Do not change these option values without updating their counterparts
284     * in include/media/stagefright/MediaSource.h!
285     */
286    /**
287     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
288     * a sync (or key) frame associated with a data source that is located
289     * right before or at the given time.
290     *
291     * @see #getFrameAtTime(long, int)
292     */
293    public static final int OPTION_PREVIOUS_SYNC    = 0x00;
294    /**
295     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
296     * a sync (or key) frame associated with a data source that is located
297     * right after or at the given time.
298     *
299     * @see #getFrameAtTime(long, int)
300     */
301    public static final int OPTION_NEXT_SYNC        = 0x01;
302    /**
303     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
304     * a sync (or key) frame associated with a data source that is located
305     * closest to (in time) or at the given time.
306     *
307     * @see #getFrameAtTime(long, int)
308     */
309    public static final int OPTION_CLOSEST_SYNC     = 0x02;
310    /**
311     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
312     * a frame (not necessarily a key frame) associated with a data source that
313     * is located closest to or at the given time.
314     *
315     * @see #getFrameAtTime(long, int)
316     */
317    public static final int OPTION_CLOSEST          = 0x03;
318
319    /*
320     * Do not change these metadata key values without updating their
321     * counterparts in include/media/mediametadataretriever.h!
322     */
323    /**
324     * The metadata key to retrieve the numberic string describing the
325     * order of the audio data source on its original recording.
326     */
327    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
328    /**
329     * The metadata key to retrieve the information about the album title
330     * of the data source.
331     */
332    public static final int METADATA_KEY_ALBUM           = 1;
333    /**
334     * The metadata key to retrieve the information about the artist of
335     * the data source.
336     */
337    public static final int METADATA_KEY_ARTIST          = 2;
338    /**
339     * The metadata key to retrieve the information about the author of
340     * the data source.
341     */
342    public static final int METADATA_KEY_AUTHOR          = 3;
343    /**
344     * The metadata key to retrieve the information about the composer of
345     * the data source.
346     */
347    public static final int METADATA_KEY_COMPOSER        = 4;
348    /**
349     * The metadata key to retrieve the date when the data source was created
350     * or modified.
351     */
352    public static final int METADATA_KEY_DATE            = 5;
353    /**
354     * The metadata key to retrieve the content type or genre of the data
355     * source.
356     */
357    public static final int METADATA_KEY_GENRE           = 6;
358    /**
359     * The metadata key to retrieve the data source title.
360     */
361    public static final int METADATA_KEY_TITLE           = 7;
362    /**
363     * The metadata key to retrieve the year when the data source was created
364     * or modified.
365     */
366    public static final int METADATA_KEY_YEAR            = 8;
367    /**
368     * The metadata key to retrieve the playback duration of the data source.
369     */
370    public static final int METADATA_KEY_DURATION        = 9;
371    /**
372     * The metadata key to retrieve the number of tracks, such as audio, video,
373     * text, in the data source, such as a mp4 or 3gpp file.
374     */
375    public static final int METADATA_KEY_NUM_TRACKS      = 10;
376    /**
377     * The metadata key to retrieve the information of the writer (such as
378     * lyricist) of the data source.
379     */
380    public static final int METADATA_KEY_WRITER          = 11;
381    /**
382     * The metadata key to retrieve the mime type of the data source. Some
383     * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb",
384     * etc.
385     */
386    public static final int METADATA_KEY_MIMETYPE        = 12;
387    /**
388     * The metadata key to retrieve the information about the performers or
389     * artist associated with the data source.
390     */
391    public static final int METADATA_KEY_ALBUMARTIST     = 13;
392    /**
393     * The metadata key to retrieve the numberic string that describes which
394     * part of a set the audio data source comes from.
395     */
396    public static final int METADATA_KEY_DISC_NUMBER     = 14;
397    /**
398     * The metadata key to retrieve the music album compilation status.
399     */
400    public static final int METADATA_KEY_COMPILATION     = 15;
401    /**
402     * If this key exists the media contains audio content.
403     */
404    public static final int METADATA_KEY_HAS_AUDIO       = 16;
405    /**
406     * If this key exists the media contains video content.
407     */
408    public static final int METADATA_KEY_HAS_VIDEO       = 17;
409    /**
410     * If the media contains video, this key retrieves its width.
411     */
412    public static final int METADATA_KEY_VIDEO_WIDTH     = 18;
413    /**
414     * If the media contains video, this key retrieves its height.
415     */
416    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
417    /**
418     * This key retrieves the average bitrate (in bits/sec), if available.
419     */
420    public static final int METADATA_KEY_BITRATE         = 20;
421    // Add more here...
422}
423