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