MediaMetadataRetriever.java revision c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716b
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; 24 25import java.io.FileDescriptor; 26import java.io.FileNotFoundException; 27import java.io.IOException; 28 29/** 30 * MediaMetadataRetriever class provides a unified interface for retrieving 31 * frame and meta data from an input media file. 32 */ 33public class MediaMetadataRetriever 34{ 35 static { 36 System.loadLibrary("media_jni"); 37 native_init(); 38 } 39 40 // The field below is accessed by native methods 41 @SuppressWarnings("unused") 42 private int mNativeContext; 43 44 private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF; 45 46 public MediaMetadataRetriever() { 47 native_setup(); 48 } 49 50 /** 51 * Sets the data source (file pathname) to use. Call this 52 * method before the rest of the methods in this class. This method may be 53 * time-consuming. 54 * 55 * @param path The path of the input media file. 56 * @throws IllegalArgumentException If the path is invalid. 57 */ 58 public native void setDataSource(String path) throws IllegalArgumentException; 59 60 /** 61 * Sets the data source (FileDescriptor) to use. It is the caller's 62 * responsibility to close the file descriptor. It is safe to do so as soon 63 * as this call returns. Call this method before the rest of the methods in 64 * this class. This method may be time-consuming. 65 * 66 * @param fd the FileDescriptor for the file you want to play 67 * @param offset the offset into the file where the data to be played starts, 68 * in bytes. It must be non-negative 69 * @param length the length in bytes of the data to be played. It must be 70 * non-negative. 71 * @throws IllegalArgumentException if the arguments are invalid 72 */ 73 public native void setDataSource(FileDescriptor fd, long offset, long length) 74 throws IllegalArgumentException; 75 76 /** 77 * Sets the data source (FileDescriptor) to use. It is the caller's 78 * responsibility to close the file descriptor. It is safe to do so as soon 79 * as this call returns. Call this method before the rest of the methods in 80 * this class. This method may be time-consuming. 81 * 82 * @param fd the FileDescriptor for the file you want to play 83 * @throws IllegalArgumentException if the FileDescriptor is invalid 84 */ 85 public void setDataSource(FileDescriptor fd) 86 throws IllegalArgumentException { 87 // intentionally less than LONG_MAX 88 setDataSource(fd, 0, 0x7ffffffffffffffL); 89 } 90 91 /** 92 * Sets the data source as a content Uri. Call this method before 93 * the rest of the methods in this class. This method may be time-consuming. 94 * 95 * @param context the Context to use when resolving the Uri 96 * @param uri the Content URI of the data you want to play 97 * @throws IllegalArgumentException if the Uri is invalid 98 * @throws SecurityException if the Uri cannot be used due to lack of 99 * permission. 100 */ 101 public void setDataSource(Context context, Uri uri) 102 throws IllegalArgumentException, SecurityException { 103 if (uri == null) { 104 throw new IllegalArgumentException(); 105 } 106 107 String scheme = uri.getScheme(); 108 if(scheme == null || scheme.equals("file")) { 109 setDataSource(uri.getPath()); 110 return; 111 } 112 113 AssetFileDescriptor fd = null; 114 try { 115 ContentResolver resolver = context.getContentResolver(); 116 try { 117 fd = resolver.openAssetFileDescriptor(uri, "r"); 118 } catch(FileNotFoundException e) { 119 throw new IllegalArgumentException(); 120 } 121 if (fd == null) { 122 throw new IllegalArgumentException(); 123 } 124 FileDescriptor descriptor = fd.getFileDescriptor(); 125 if (!descriptor.valid()) { 126 throw new IllegalArgumentException(); 127 } 128 // Note: using getDeclaredLength so that our behavior is the same 129 // as previous versions when the content provider is returning 130 // a full file. 131 if (fd.getDeclaredLength() < 0) { 132 setDataSource(descriptor); 133 } else { 134 setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength()); 135 } 136 return; 137 } catch (SecurityException ex) { 138 } finally { 139 try { 140 if (fd != null) { 141 fd.close(); 142 } 143 } catch(IOException ioEx) { 144 } 145 } 146 setDataSource(uri.toString()); 147 } 148 149 /** 150 * Call this method after setDataSource(). This method retrieves the 151 * meta data value associated with the keyCode. 152 * 153 * The keyCode currently supported is listed below as METADATA_XXX 154 * constants. With any other value, it returns a null pointer. 155 * 156 * @param keyCode One of the constants listed below at the end of the class. 157 * @return The meta data value associate with the given keyCode on success; 158 * null on failure. 159 */ 160 public native String extractMetadata(int keyCode); 161 162 /** 163 * Call this method after setDataSource(). This method finds a 164 * representative frame close to the given time position by considering 165 * the given option if possible, and returns it as a bitmap. This is 166 * useful for generating a thumbnail for an input data source or just 167 * obtain and display a frame at the given time position. 168 * 169 * @param timeUs The time position where the frame will be retrieved. 170 * When retrieving the frame at the given time position, there is no 171 * guarantee that the data source has a frame located at the position. 172 * When this happens, a frame nearby will be returned. If timeUs is 173 * negative, time position and option will ignored, and any frame 174 * that the implementation considers as representative may be returned. 175 * 176 * @param option a hint on how the frame is found. Use 177 * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame 178 * that has a timestamp earlier than or the same as timeUs. Use 179 * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame 180 * that has a timestamp later than or the same as timeUs. Use 181 * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame 182 * that has a timestamp closest to or the same as timeUs. Use 183 * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may 184 * or may not be a sync frame but is closest to or the same as timeUs. 185 * {@link #OPTION_CLOSEST} often has larger performance overhead compared 186 * to the other options if there is no sync frame located at timeUs. 187 * 188 * @return A Bitmap containing a representative video frame, which 189 * can be null, if such a frame cannot be retrieved. 190 */ 191 public Bitmap getFrameAtTime(long timeUs, int option) { 192 if (option < OPTION_PREVIOUS_SYNC || 193 option > OPTION_CLOSEST) { 194 throw new IllegalArgumentException("Unsupported option: " + option); 195 } 196 197 return _getFrameAtTime(timeUs, option); 198 } 199 200 /** 201 * Call this method after setDataSource(). This method finds a 202 * representative frame close to the given time position if possible, 203 * and returns it as a bitmap. This is useful for generating a thumbnail 204 * for an input data source. Call this method if one does not care 205 * how the frame is found as long as it is close to the given time; 206 * otherwise, please call {@link #getFrameAtTime(long, int)}. 207 * 208 * @param timeUs The time position where the frame will be retrieved. 209 * When retrieving the frame at the given time position, there is no 210 * guarentee that the data source has a frame located at the position. 211 * When this happens, a frame nearby will be returned. If timeUs is 212 * negative, time position and option will ignored, and any frame 213 * that the implementation considers as representative may be returned. 214 * 215 * @return A Bitmap containing a representative video frame, which 216 * can be null, if such a frame cannot be retrieved. 217 * 218 * @see #getFrameAtTime(long, int) 219 */ 220 public Bitmap getFrameAtTime(long timeUs) { 221 return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC); 222 } 223 224 /** 225 * Call this method after setDataSource(). This method finds a 226 * representative frame at any time position if possible, 227 * and returns it as a bitmap. This is useful for generating a thumbnail 228 * for an input data source. Call this method if one does not 229 * care about where the frame is located; otherwise, please call 230 * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)} 231 * 232 * @return A Bitmap containing a representative video frame, which 233 * can be null, if such a frame cannot be retrieved. 234 * 235 * @see #getFrameAtTime(long) 236 * @see #getFrameAtTime(long, int) 237 */ 238 public Bitmap getFrameAtTime() { 239 return getFrameAtTime(-1, OPTION_CLOSEST_SYNC); 240 } 241 242 private native Bitmap _getFrameAtTime(long timeUs, int option); 243 244 245 /** 246 * Call this method after setDataSource(). This method finds the optional 247 * graphic or album art associated associated with the data source. If 248 * there are more than one pictures, (any) one of them is returned. 249 * 250 * @return null if no such graphic is found. 251 */ 252 public byte[] getEmbeddedPicture() { 253 return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY); 254 } 255 256 private native byte[] getEmbeddedPicture(int pictureType); 257 258 /** 259 * Call it when one is done with the object. This method releases the memory 260 * allocated internally. 261 */ 262 public native void release(); 263 private native void native_setup(); 264 private static native void native_init(); 265 266 private native final void native_finalize(); 267 268 @Override 269 protected void finalize() throws Throwable { 270 try { 271 native_finalize(); 272 } finally { 273 super.finalize(); 274 } 275 } 276 277 /** 278 * Option used in method {@link #getFrameAtTime(long, int)} to get a 279 * frame at a specified location. 280 * 281 * @see #getFrameAtTime(long, int) 282 */ 283 /* Do not change these option values without updating their counterparts 284 * in include/media/stagefright/MediaSource.h! 285 */ 286 /** 287 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 288 * a sync (or key) frame associated with a data source that is located 289 * right before or at the given time. 290 * 291 * @see #getFrameAtTime(long, int) 292 */ 293 public static final int OPTION_PREVIOUS_SYNC = 0x00; 294 /** 295 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 296 * a sync (or key) frame associated with a data source that is located 297 * right after or at the given time. 298 * 299 * @see #getFrameAtTime(long, int) 300 */ 301 public static final int OPTION_NEXT_SYNC = 0x01; 302 /** 303 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 304 * a sync (or key) frame associated with a data source that is located 305 * closest to (in time) or at the given time. 306 * 307 * @see #getFrameAtTime(long, int) 308 */ 309 public static final int OPTION_CLOSEST_SYNC = 0x02; 310 /** 311 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 312 * a frame (not necessarily a key frame) associated with a data source that 313 * is located closest to or at the given time. 314 * 315 * @see #getFrameAtTime(long, int) 316 */ 317 public static final int OPTION_CLOSEST = 0x03; 318 319 /* 320 * Do not change these metadata key values without updating their 321 * counterparts in include/media/mediametadataretriever.h! 322 */ 323 /** 324 * The metadata key to retrieve the numberic string describing the 325 * order of the audio data source on its original recording. 326 */ 327 public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; 328 /** 329 * The metadata key to retrieve the information about the album title 330 * of the data source. 331 */ 332 public static final int METADATA_KEY_ALBUM = 1; 333 /** 334 * The metadata key to retrieve the information about the artist of 335 * the data source. 336 */ 337 public static final int METADATA_KEY_ARTIST = 2; 338 /** 339 * The metadata key to retrieve the information about the author of 340 * the data source. 341 */ 342 public static final int METADATA_KEY_AUTHOR = 3; 343 /** 344 * The metadata key to retrieve the information about the composer of 345 * the data source. 346 */ 347 public static final int METADATA_KEY_COMPOSER = 4; 348 /** 349 * The metadata key to retrieve the date when the data source was created 350 * or modified. 351 */ 352 public static final int METADATA_KEY_DATE = 5; 353 /** 354 * The metadata key to retrieve the content type or genre of the data 355 * source. 356 */ 357 public static final int METADATA_KEY_GENRE = 6; 358 /** 359 * The metadata key to retrieve the data source title. 360 */ 361 public static final int METADATA_KEY_TITLE = 7; 362 /** 363 * The metadata key to retrieve the year when the data source was created 364 * or modified. 365 */ 366 public static final int METADATA_KEY_YEAR = 8; 367 /** 368 * The metadata key to retrieve the playback duration of the data source. 369 */ 370 public static final int METADATA_KEY_DURATION = 9; 371 /** 372 * The metadata key to retrieve the number of tracks, such as audio, video, 373 * text, in the data source, such as a mp4 or 3gpp file. 374 */ 375 public static final int METADATA_KEY_NUM_TRACKS = 10; 376 /** 377 * The metadata key to retrieve the information of the writer (such as 378 * lyricist) of the data source. 379 */ 380 public static final int METADATA_KEY_WRITER = 11; 381 /** 382 * The metadata key to retrieve the mime type of the data source. Some 383 * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", 384 * etc. 385 */ 386 public static final int METADATA_KEY_MIMETYPE = 12; 387 /** 388 * The metadata key to retrieve the information about the performers or 389 * artist associated with the data source. 390 */ 391 public static final int METADATA_KEY_ALBUMARTIST = 13; 392 /** 393 * The metadata key to retrieve the numberic string that describes which 394 * part of a set the audio data source comes from. 395 */ 396 public static final int METADATA_KEY_DISC_NUMBER = 14; 397 /** 398 * The metadata key to retrieve the music album compilation status. 399 */ 400 public static final int METADATA_KEY_COMPILATION = 15; 401 /** 402 * If this key exists the media contains audio content. 403 */ 404 public static final int METADATA_KEY_HAS_AUDIO = 16; 405 /** 406 * If this key exists the media contains video content. 407 */ 408 public static final int METADATA_KEY_HAS_VIDEO = 17; 409 /** 410 * If the media contains video, this key retrieves its width. 411 */ 412 public static final int METADATA_KEY_VIDEO_WIDTH = 18; 413 /** 414 * If the media contains video, this key retrieves its height. 415 */ 416 public static final int METADATA_KEY_VIDEO_HEIGHT = 19; 417 /** 418 * This key retrieves the average bitrate (in bits/sec), if available. 419 */ 420 public static final int METADATA_KEY_BITRATE = 20; 421 // Add more here... 422} 423