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