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