MediaMetadataRetriever.java revision c9706f0262a2f399f95e0d78ba2b7616e08d0069
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;
24import android.os.ParcelFileDescriptor;
25import java.io.FileDescriptor;
26import java.io.IOException;
27import java.io.FileNotFoundException;
28
29/**
30 * MediaMetadataRetriever class provides a unified interface for retrieving
31 * frame and meta data from an input media file.
32 * {@hide}
33 */
34public class MediaMetadataRetriever
35{
36    static {
37        System.loadLibrary("media_jni");
38        native_init();
39    }
40
41    // The field below is accessed by native methods
42    @SuppressWarnings("unused")
43    private int mNativeContext;
44
45    public MediaMetadataRetriever() {
46        native_setup();
47    }
48
49    /**
50     * Call this method before setDataSource() so that the mode becomes
51     * effective for subsequent operations. This method can be called only once
52     * at the beginning if the intended mode of operation for a
53     * MediaMetadataRetriever object remains the same for its whole lifetime,
54     * and thus it is unnecessary to call this method each time setDataSource()
55     * is called. If this is not never called (which is allowed), by default the
56     * intended mode of operation is to both capture frame and retrieve meta
57     * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY).
58     * Often, this may not be what one wants, since doing this has negative
59     * performance impact on execution time of a call to setDataSource(), since
60     * both types of operations may be time consuming.
61     *
62     * @param mode The intended mode of operation. Can be any combination of
63     * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY:
64     * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY:
65     *    For neither frame capture nor meta data retrieval
66     * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only
67     * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only
68     * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY:
69     *    For both frame capture and meta data retrieval
70     */
71    public native void setMode(int mode);
72
73    /**
74     * @return the current mode of operation. A negative return value indicates
75     * some runtime error has occurred.
76     */
77    public native int getMode();
78
79    /**
80     * Sets the data source (file pathname) to use. Call this
81     * method before the rest of the methods in this class. This method may be
82     * time-consuming.
83     *
84     * @param path The path of the input media file.
85     * @throws IllegalArgumentException If the path is invalid.
86     */
87    public native void setDataSource(String path) throws IllegalArgumentException;
88
89    /**
90     * Sets the data source (FileDescriptor) to use.  It is the caller's
91     * responsibility to close the file descriptor. It is safe to do so as soon
92     * as this call returns. Call this method before the rest of the methods in
93     * this class. This method may be time-consuming.
94     *
95     * @param fd the FileDescriptor for the file you want to play
96     * @param offset the offset into the file where the data to be played starts,
97     * in bytes. It must be non-negative
98     * @param length the length in bytes of the data to be played. It must be
99     * non-negative.
100     * @throws IllegalArgumentException if the arguments are invalid
101     */
102    public native void setDataSource(FileDescriptor fd, long offset, long length)
103            throws IllegalArgumentException;
104
105    /**
106     * Sets the data source (FileDescriptor) to use. It is the caller's
107     * responsibility to close the file descriptor. It is safe to do so as soon
108     * as this call returns. Call this method before the rest of the methods in
109     * this class. This method may be time-consuming.
110     *
111     * @param fd the FileDescriptor for the file you want to play
112     * @throws IllegalArgumentException if the FileDescriptor is invalid
113     */
114    public void setDataSource(FileDescriptor fd)
115            throws IllegalArgumentException {
116        // intentionally less than LONG_MAX
117        setDataSource(fd, 0, 0x7ffffffffffffffL);
118    }
119
120    /**
121     * Sets the data source as a content Uri. Call this method before
122     * the rest of the methods in this class. This method may be time-consuming.
123     *
124     * @param context the Context to use when resolving the Uri
125     * @param uri the Content URI of the data you want to play
126     * @throws IllegalArgumentException if the Uri is invalid
127     * @throws SecurityException if the Uri cannot be used due to lack of
128     * permission.
129     */
130    public void setDataSource(Context context, Uri uri)
131        throws IllegalArgumentException, SecurityException {
132        if (uri == null) {
133            throw new IllegalArgumentException();
134        }
135
136        String scheme = uri.getScheme();
137        if(scheme == null || scheme.equals("file")) {
138            setDataSource(uri.getPath());
139            return;
140        }
141
142        AssetFileDescriptor fd = null;
143        try {
144            ContentResolver resolver = context.getContentResolver();
145            try {
146                fd = resolver.openAssetFileDescriptor(uri, "r");
147            } catch(FileNotFoundException e) {
148                throw new IllegalArgumentException();
149            }
150            if (fd == null) {
151                throw new IllegalArgumentException();
152            }
153            FileDescriptor descriptor = fd.getFileDescriptor();
154            if (!descriptor.valid()) {
155                throw new IllegalArgumentException();
156            }
157            // Note: using getDeclaredLength so that our behavior is the same
158            // as previous versions when the content provider is returning
159            // a full file.
160            if (fd.getDeclaredLength() < 0) {
161                setDataSource(descriptor);
162            } else {
163                setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength());
164            }
165            return;
166        } catch (SecurityException ex) {
167        } finally {
168            try {
169                if (fd != null) {
170                    fd.close();
171                }
172            } catch(IOException ioEx) {
173            }
174        }
175        setDataSource(uri.toString());
176    }
177
178    /**
179     * Call this method after setDataSource(). This method retrieves the
180     * meta data value associated with the keyCode.
181     *
182     * The keyCode currently supported is listed below as METADATA_XXX
183     * constants. With any other value, it returns a null pointer.
184     *
185     * @param keyCode One of the constants listed below at the end of the class.
186     * @return The meta data value associate with the given keyCode on success;
187     * null on failure.
188     */
189    public native String extractMetadata(int keyCode);
190
191    /**
192     * Call this method after setDataSource(). This method finds a
193     * representative frame if successful and returns it as a bitmap. This is
194     * useful for generating a thumbnail for an input media source.
195     *
196     * @return A Bitmap containing a representative video frame, which
197     *         can be null, if such a frame cannot be retrieved.
198     */
199    public native Bitmap captureFrame();
200
201    /**
202     * Call this method after setDataSource(). This method finds the optional
203     * graphic or album art associated (embedded or external url linked) the
204     * related data source.
205     *
206     * @return null if no such graphic is found.
207     */
208    public native byte[] extractAlbumArt();
209
210    /**
211     * Call it when one is done with the object. This method releases the memory
212     * allocated internally.
213     */
214    public native void release();
215    private native void native_setup();
216    private static native void native_init();
217
218    private native final void native_finalize();
219
220    @Override
221    protected void finalize() throws Throwable {
222        try {
223            native_finalize();
224        } finally {
225            super.finalize();
226        }
227    }
228
229    public static final int MODE_GET_METADATA_ONLY  = 0x01;
230    public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;
231
232    /*
233     * Do not change these values without updating their counterparts
234     * in include/media/mediametadataretriever.h!
235     */
236    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
237    public static final int METADATA_KEY_ALBUM           = 1;
238    public static final int METADATA_KEY_ARTIST          = 2;
239    public static final int METADATA_KEY_AUTHOR          = 3;
240    public static final int METADATA_KEY_COMPOSER        = 4;
241    public static final int METADATA_KEY_DATE            = 5;
242    public static final int METADATA_KEY_GENRE           = 6;
243    public static final int METADATA_KEY_TITLE           = 7;
244    public static final int METADATA_KEY_YEAR            = 8;
245    public static final int METADATA_KEY_DURATION        = 9;
246    public static final int METADATA_KEY_NUM_TRACKS      = 10;
247    public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
248    public static final int METADATA_KEY_CODEC           = 12;
249    public static final int METADATA_KEY_RATING          = 13;
250    public static final int METADATA_KEY_COMMENT         = 14;
251    public static final int METADATA_KEY_COPYRIGHT       = 15;
252    public static final int METADATA_KEY_BIT_RATE        = 16;
253    public static final int METADATA_KEY_FRAME_RATE      = 17;
254    public static final int METADATA_KEY_VIDEO_FORMAT    = 18;
255    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
256    public static final int METADATA_KEY_VIDEO_WIDTH     = 20;
257    public static final int METADATA_KEY_WRITER          = 21;
258    // Add more here...
259}
260