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