MediaMetadataRetriever.java revision 3dec7d563a2f3e1eb967ce2054a00b6620e3558c
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