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 17 package android.media; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.res.AssetFileDescriptor; 26 import android.graphics.Bitmap; 27 import android.net.Uri; 28 import android.os.Build; 29 import android.os.IBinder; 30 31 import java.io.FileDescriptor; 32 import java.io.FileInputStream; 33 import java.io.FileNotFoundException; 34 import java.io.IOException; 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.List; 38 import java.util.Map; 39 40 /** 41 * MediaMetadataRetriever class provides a unified interface for retrieving 42 * frame and meta data from an input media file. 43 */ 44 public class MediaMetadataRetriever implements AutoCloseable { 45 static { 46 System.loadLibrary("media_jni"); native_init()47 native_init(); 48 } 49 50 // The field below is accessed by native methods 51 @SuppressWarnings("unused") 52 private long mNativeContext; 53 54 private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF; 55 MediaMetadataRetriever()56 public MediaMetadataRetriever() { 57 native_setup(); 58 } 59 60 /** 61 * Sets the data source (file pathname) to use. Call this 62 * method before the rest of the methods in this class. This method may be 63 * time-consuming. 64 * 65 * @param path The path of the input media file. 66 * @throws IllegalArgumentException If the path is invalid. 67 */ setDataSource(String path)68 public void setDataSource(String path) throws IllegalArgumentException { 69 if (path == null) { 70 throw new IllegalArgumentException(); 71 } 72 73 try (FileInputStream is = new FileInputStream(path)) { 74 FileDescriptor fd = is.getFD(); 75 setDataSource(fd, 0, 0x7ffffffffffffffL); 76 } catch (FileNotFoundException fileEx) { 77 throw new IllegalArgumentException(); 78 } catch (IOException ioEx) { 79 throw new IllegalArgumentException(); 80 } 81 } 82 83 /** 84 * Sets the data source (URI) to use. Call this 85 * method before the rest of the methods in this class. This method may be 86 * time-consuming. 87 * 88 * @param uri The URI of the input media. 89 * @param headers the headers to be sent together with the request for the data 90 * @throws IllegalArgumentException If the URI is invalid. 91 */ setDataSource(String uri, Map<String, String> headers)92 public void setDataSource(String uri, Map<String, String> headers) 93 throws IllegalArgumentException { 94 int i = 0; 95 String[] keys = new String[headers.size()]; 96 String[] values = new String[headers.size()]; 97 for (Map.Entry<String, String> entry: headers.entrySet()) { 98 keys[i] = entry.getKey(); 99 values[i] = entry.getValue(); 100 ++i; 101 } 102 103 _setDataSource( 104 MediaHTTPService.createHttpServiceBinderIfNecessary(uri), 105 uri, 106 keys, 107 values); 108 } 109 _setDataSource( IBinder httpServiceBinder, String uri, String[] keys, String[] values)110 private native void _setDataSource( 111 IBinder httpServiceBinder, String uri, String[] keys, String[] values) 112 throws IllegalArgumentException; 113 114 /** 115 * Sets the data source (FileDescriptor) to use. It is the caller's 116 * responsibility to close the file descriptor. It is safe to do so as soon 117 * as this call returns. Call this method before the rest of the methods in 118 * this class. This method may be time-consuming. 119 * 120 * @param fd the FileDescriptor for the file you want to play 121 * @param offset the offset into the file where the data to be played starts, 122 * in bytes. It must be non-negative 123 * @param length the length in bytes of the data to be played. It must be 124 * non-negative. 125 * @throws IllegalArgumentException if the arguments are invalid 126 */ setDataSource(FileDescriptor fd, long offset, long length)127 public native void setDataSource(FileDescriptor fd, long offset, long length) 128 throws IllegalArgumentException; 129 130 /** 131 * Sets the data source (FileDescriptor) to use. It is the caller's 132 * responsibility to close the file descriptor. It is safe to do so as soon 133 * as this call returns. Call this method before the rest of the methods in 134 * this class. This method may be time-consuming. 135 * 136 * @param fd the FileDescriptor for the file you want to play 137 * @throws IllegalArgumentException if the FileDescriptor is invalid 138 */ setDataSource(FileDescriptor fd)139 public void setDataSource(FileDescriptor fd) 140 throws IllegalArgumentException { 141 // intentionally less than LONG_MAX 142 setDataSource(fd, 0, 0x7ffffffffffffffL); 143 } 144 145 /** 146 * Sets the data source as a content Uri. Call this method before 147 * the rest of the methods in this class. This method may be time-consuming. 148 * 149 * @param context the Context to use when resolving the Uri 150 * @param uri the Content URI of the data you want to play 151 * @throws IllegalArgumentException if the Uri is invalid 152 * @throws SecurityException if the Uri cannot be used due to lack of 153 * permission. 154 */ setDataSource(Context context, Uri uri)155 public void setDataSource(Context context, Uri uri) 156 throws IllegalArgumentException, SecurityException { 157 if (uri == null) { 158 throw new IllegalArgumentException(); 159 } 160 161 String scheme = uri.getScheme(); 162 if(scheme == null || scheme.equals("file")) { 163 setDataSource(uri.getPath()); 164 return; 165 } 166 167 AssetFileDescriptor fd = null; 168 try { 169 ContentResolver resolver = context.getContentResolver(); 170 try { 171 fd = resolver.openAssetFileDescriptor(uri, "r"); 172 } catch(FileNotFoundException e) { 173 throw new IllegalArgumentException(); 174 } 175 if (fd == null) { 176 throw new IllegalArgumentException(); 177 } 178 FileDescriptor descriptor = fd.getFileDescriptor(); 179 if (!descriptor.valid()) { 180 throw new IllegalArgumentException(); 181 } 182 // Note: using getDeclaredLength so that our behavior is the same 183 // as previous versions when the content provider is returning 184 // a full file. 185 if (fd.getDeclaredLength() < 0) { 186 setDataSource(descriptor); 187 } else { 188 setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength()); 189 } 190 return; 191 } catch (SecurityException ex) { 192 } finally { 193 try { 194 if (fd != null) { 195 fd.close(); 196 } 197 } catch(IOException ioEx) { 198 } 199 } 200 setDataSource(uri.toString()); 201 } 202 203 /** 204 * Sets the data source (MediaDataSource) to use. 205 * 206 * @param dataSource the MediaDataSource for the media you want to play 207 */ setDataSource(MediaDataSource dataSource)208 public void setDataSource(MediaDataSource dataSource) 209 throws IllegalArgumentException { 210 _setDataSource(dataSource); 211 } 212 _setDataSource(MediaDataSource dataSource)213 private native void _setDataSource(MediaDataSource dataSource) 214 throws IllegalArgumentException; 215 216 /** 217 * Call this method after setDataSource(). This method retrieves the 218 * meta data value associated with the keyCode. 219 * 220 * The keyCode currently supported is listed below as METADATA_XXX 221 * constants. With any other value, it returns a null pointer. 222 * 223 * @param keyCode One of the constants listed below at the end of the class. 224 * @return The meta data value associate with the given keyCode on success; 225 * null on failure. 226 */ extractMetadata(int keyCode)227 public native String extractMetadata(int keyCode); 228 229 /** 230 * Call this method after setDataSource(). This method finds a 231 * representative frame close to the given time position by considering 232 * the given option if possible, and returns it as a bitmap. 233 * 234 * <p>If you don't need a full-resolution 235 * frame (for example, because you need a thumbnail image), use 236 * {@link #getScaledFrameAtTime getScaledFrameAtTime()} instead of this 237 * method.</p> 238 * 239 * @param timeUs The time position where the frame will be retrieved. 240 * When retrieving the frame at the given time position, there is no 241 * guarantee that the data source has a frame located at the position. 242 * When this happens, a frame nearby will be returned. If timeUs is 243 * negative, time position and option will ignored, and any frame 244 * that the implementation considers as representative may be returned. 245 * 246 * @param option a hint on how the frame is found. Use 247 * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame 248 * that has a timestamp earlier than or the same as timeUs. Use 249 * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame 250 * that has a timestamp later than or the same as timeUs. Use 251 * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame 252 * that has a timestamp closest to or the same as timeUs. Use 253 * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may 254 * or may not be a sync frame but is closest to or the same as timeUs. 255 * {@link #OPTION_CLOSEST} often has larger performance overhead compared 256 * to the other options if there is no sync frame located at timeUs. 257 * 258 * @return A Bitmap containing a representative video frame, which 259 * can be null, if such a frame cannot be retrieved. 260 */ getFrameAtTime(long timeUs, @Option int option)261 public Bitmap getFrameAtTime(long timeUs, @Option int option) { 262 if (option < OPTION_PREVIOUS_SYNC || 263 option > OPTION_CLOSEST) { 264 throw new IllegalArgumentException("Unsupported option: " + option); 265 } 266 267 return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/); 268 } 269 270 /** 271 * Retrieve a video frame near a given timestamp scaled to a desired size. 272 * Call this method after setDataSource(). This method finds a representative 273 * frame close to the given time position by considering the given option 274 * if possible, and returns it as a bitmap with same aspect ratio as the source 275 * while scaling it so that it fits into the desired size of dst_width by dst_height. 276 * This is useful for generating a thumbnail for an input data source or just to 277 * obtain a scaled frame at the given time position. 278 * 279 * @param timeUs The time position in microseconds where the frame will be retrieved. 280 * When retrieving the frame at the given time position, there is no 281 * guarantee that the data source has a frame located at the position. 282 * When this happens, a frame nearby will be returned. If timeUs is 283 * negative, time position and option will ignored, and any frame 284 * that the implementation considers as representative may be returned. 285 * 286 * @param option a hint on how the frame is found. Use 287 * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame 288 * that has a timestamp earlier than or the same as timeUs. Use 289 * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame 290 * that has a timestamp later than or the same as timeUs. Use 291 * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame 292 * that has a timestamp closest to or the same as timeUs. Use 293 * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may 294 * or may not be a sync frame but is closest to or the same as timeUs. 295 * {@link #OPTION_CLOSEST} often has larger performance overhead compared 296 * to the other options if there is no sync frame located at timeUs. 297 * 298 * @param dstWidth expected output bitmap width 299 * @param dstHeight expected output bitmap height 300 * @return A Bitmap of size not larger than dstWidth by dstHeight containing a 301 * scaled video frame, which can be null, if such a frame cannot be retrieved. 302 * @throws IllegalArgumentException if passed in invalid option or width by height 303 * is less than or equal to 0. 304 */ getScaledFrameAtTime( long timeUs, @Option int option, int dstWidth, int dstHeight)305 public Bitmap getScaledFrameAtTime( 306 long timeUs, @Option int option, int dstWidth, int dstHeight) { 307 if (option < OPTION_PREVIOUS_SYNC || 308 option > OPTION_CLOSEST) { 309 throw new IllegalArgumentException("Unsupported option: " + option); 310 } 311 if (dstWidth <= 0) { 312 throw new IllegalArgumentException("Invalid width: " + dstWidth); 313 } 314 if (dstHeight <= 0) { 315 throw new IllegalArgumentException("Invalid height: " + dstHeight); 316 } 317 318 return _getFrameAtTime(timeUs, option, dstWidth, dstHeight); 319 } 320 321 /** 322 * Call this method after setDataSource(). This method finds a 323 * representative frame close to the given time position if possible, 324 * and returns it as a bitmap. Call this method if one does not care 325 * how the frame is found as long as it is close to the given time; 326 * otherwise, please call {@link #getFrameAtTime(long, int)}. 327 * 328 * <p>If you don't need a full-resolution 329 * frame (for example, because you need a thumbnail image), use 330 * {@link #getScaledFrameAtTime getScaledFrameAtTime()} instead of this 331 * method.</p> 332 * 333 * @param timeUs The time position where the frame will be retrieved. 334 * When retrieving the frame at the given time position, there is no 335 * guarentee that the data source has a frame located at the position. 336 * When this happens, a frame nearby will be returned. If timeUs is 337 * negative, time position and option will ignored, and any frame 338 * that the implementation considers as representative may be returned. 339 * 340 * @return A Bitmap of size dst_widthxdst_height containing a representative 341 * video frame, which can be null, if such a frame cannot be retrieved. 342 * 343 * @see #getFrameAtTime(long, int) 344 */ getFrameAtTime(long timeUs)345 public Bitmap getFrameAtTime(long timeUs) { 346 return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC); 347 } 348 349 /** 350 * Call this method after setDataSource(). This method finds a 351 * representative frame at any time position if possible, 352 * and returns it as a bitmap. Call this method if one does not 353 * care about where the frame is located; otherwise, please call 354 * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)} 355 * 356 * <p>If you don't need a full-resolution 357 * frame (for example, because you need a thumbnail image), use 358 * {@link #getScaledFrameAtTime getScaledFrameAtTime()} instead of this 359 * method.</p> 360 * 361 * @return A Bitmap containing a representative video frame, which 362 * can be null, if such a frame cannot be retrieved. 363 * 364 * @see #getFrameAtTime(long) 365 * @see #getFrameAtTime(long, int) 366 */ getFrameAtTime()367 public Bitmap getFrameAtTime() { 368 return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/); 369 } 370 _getFrameAtTime(long timeUs, int option, int width, int height)371 private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height); 372 373 public static final class BitmapParams { 374 private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888; 375 private Bitmap.Config outActualConfig = Bitmap.Config.ARGB_8888; 376 377 /** 378 * Create a default BitmapParams object. By default, it uses {@link Bitmap.Config#ARGB_8888} 379 * as the preferred bitmap config. 380 */ BitmapParams()381 public BitmapParams() {} 382 383 /** 384 * Set the preferred bitmap config for the decoder to decode into. 385 * 386 * If not set, or the request cannot be met, the decoder will output 387 * in {@link Bitmap.Config#ARGB_8888} config by default. 388 * 389 * After decode, the actual config used can be retrieved by {@link #getActualConfig()}. 390 * 391 * @param config the preferred bitmap config to use. 392 */ setPreferredConfig(@onNull Bitmap.Config config)393 public void setPreferredConfig(@NonNull Bitmap.Config config) { 394 if (config == null) { 395 throw new IllegalArgumentException("preferred config can't be null"); 396 } 397 inPreferredConfig = config; 398 } 399 400 /** 401 * Retrieve the preferred bitmap config in the params. 402 * 403 * @return the preferred bitmap config. 404 */ getPreferredConfig()405 public @NonNull Bitmap.Config getPreferredConfig() { 406 return inPreferredConfig; 407 } 408 409 /** 410 * Get the actual bitmap config used to decode the bitmap after the decoding. 411 * 412 * @return the actual bitmap config used. 413 */ getActualConfig()414 public @NonNull Bitmap.Config getActualConfig() { 415 return outActualConfig; 416 } 417 } 418 419 /** 420 * This method retrieves a video frame by its index. It should only be called 421 * after {@link #setDataSource}. 422 * 423 * After the bitmap is returned, you can query the actual parameters that were 424 * used to create the bitmap from the {@code BitmapParams} argument, for instance 425 * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}. 426 * 427 * @param frameIndex 0-based index of the video frame. The frame index must be that of 428 * a valid frame. The total number of frames available for retrieval can be queried 429 * via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key. 430 * @param params BitmapParams that controls the returned bitmap config (such as pixel formats). 431 * 432 * @throws IllegalStateException if the container doesn't contain video or image sequences. 433 * @throws IllegalArgumentException if the requested frame index does not exist. 434 * 435 * @return A Bitmap containing the requested video frame, or null if the retrieval fails. 436 * 437 * @see #getFrameAtIndex(int) 438 * @see #getFramesAtIndex(int, int, BitmapParams) 439 * @see #getFramesAtIndex(int, int) 440 */ getFrameAtIndex(int frameIndex, @NonNull BitmapParams params)441 public Bitmap getFrameAtIndex(int frameIndex, @NonNull BitmapParams params) { 442 List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1, params); 443 return bitmaps.get(0); 444 } 445 446 /** 447 * This method is similar to {@link #getFrameAtIndex(int, BitmapParams)} except that 448 * the default for {@link BitmapParams} will be used. 449 * 450 * @param frameIndex 0-based index of the video frame. The frame index must be that of 451 * a valid frame. The total number of frames available for retrieval can be queried 452 * via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key. 453 * 454 * @throws IllegalStateException if the container doesn't contain video or image sequences. 455 * @throws IllegalArgumentException if the requested frame index does not exist. 456 * 457 * @return A Bitmap containing the requested video frame, or null if the retrieval fails. 458 * 459 * @see #getFrameAtIndex(int, BitmapParams) 460 * @see #getFramesAtIndex(int, int, BitmapParams) 461 * @see #getFramesAtIndex(int, int) 462 */ getFrameAtIndex(int frameIndex)463 public Bitmap getFrameAtIndex(int frameIndex) { 464 List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1); 465 return bitmaps.get(0); 466 } 467 468 /** 469 * This method retrieves a consecutive set of video frames starting at the 470 * specified index. It should only be called after {@link #setDataSource}. 471 * 472 * If the caller intends to retrieve more than one consecutive video frames, 473 * this method is preferred over {@link #getFrameAtIndex(int, BitmapParams)} for efficiency. 474 * 475 * After the bitmaps are returned, you can query the actual parameters that were 476 * used to create the bitmaps from the {@code BitmapParams} argument, for instance 477 * to query the bitmap config used for the bitmaps with {@link BitmapParams#getActualConfig}. 478 * 479 * @param frameIndex 0-based index of the first video frame to retrieve. The frame index 480 * must be that of a valid frame. The total number of frames available for retrieval 481 * can be queried via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key. 482 * @param numFrames number of consecutive video frames to retrieve. Must be a positive 483 * value. The stream must contain at least numFrames frames starting at frameIndex. 484 * @param params BitmapParams that controls the returned bitmap config (such as pixel formats). 485 * 486 * @throws IllegalStateException if the container doesn't contain video or image sequences. 487 * @throws IllegalArgumentException if the frameIndex or numFrames is invalid, or the 488 * stream doesn't contain at least numFrames starting at frameIndex. 489 490 * @return An list of Bitmaps containing the requested video frames. The returned 491 * array could contain less frames than requested if the retrieval fails. 492 * 493 * @see #getFrameAtIndex(int, BitmapParams) 494 * @see #getFrameAtIndex(int) 495 * @see #getFramesAtIndex(int, int) 496 */ getFramesAtIndex( int frameIndex, int numFrames, @NonNull BitmapParams params)497 public @NonNull List<Bitmap> getFramesAtIndex( 498 int frameIndex, int numFrames, @NonNull BitmapParams params) { 499 return getFramesAtIndexInternal(frameIndex, numFrames, params); 500 } 501 502 /** 503 * This method is similar to {@link #getFramesAtIndex(int, int, BitmapParams)} except that 504 * the default for {@link BitmapParams} will be used. 505 * 506 * @param frameIndex 0-based index of the first video frame to retrieve. The frame index 507 * must be that of a valid frame. The total number of frames available for retrieval 508 * can be queried via the {@link #METADATA_KEY_VIDEO_FRAME_COUNT} key. 509 * @param numFrames number of consecutive video frames to retrieve. Must be a positive 510 * value. The stream must contain at least numFrames frames starting at frameIndex. 511 * 512 * @throws IllegalStateException if the container doesn't contain video or image sequences. 513 * @throws IllegalArgumentException if the frameIndex or numFrames is invalid, or the 514 * stream doesn't contain at least numFrames starting at frameIndex. 515 516 * @return An list of Bitmaps containing the requested video frames. The returned 517 * array could contain less frames than requested if the retrieval fails. 518 * 519 * @see #getFrameAtIndex(int, BitmapParams) 520 * @see #getFrameAtIndex(int) 521 * @see #getFramesAtIndex(int, int, BitmapParams) 522 */ getFramesAtIndex(int frameIndex, int numFrames)523 public @NonNull List<Bitmap> getFramesAtIndex(int frameIndex, int numFrames) { 524 return getFramesAtIndexInternal(frameIndex, numFrames, null); 525 } 526 getFramesAtIndexInternal( int frameIndex, int numFrames, @Nullable BitmapParams params)527 private @NonNull List<Bitmap> getFramesAtIndexInternal( 528 int frameIndex, int numFrames, @Nullable BitmapParams params) { 529 if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO))) { 530 throw new IllegalStateException("Does not contail video or image sequences"); 531 } 532 int frameCount = Integer.parseInt( 533 extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT)); 534 if (frameIndex < 0 || numFrames < 1 535 || frameIndex >= frameCount 536 || frameIndex > frameCount - numFrames) { 537 throw new IllegalArgumentException("Invalid frameIndex or numFrames: " 538 + frameIndex + ", " + numFrames); 539 } 540 return _getFrameAtIndex(frameIndex, numFrames, params); 541 } 542 _getFrameAtIndex( int frameIndex, int numFrames, @Nullable BitmapParams params)543 private native @NonNull List<Bitmap> _getFrameAtIndex( 544 int frameIndex, int numFrames, @Nullable BitmapParams params); 545 546 /** 547 * This method retrieves a still image by its index. It should only be called 548 * after {@link #setDataSource}. 549 * 550 * After the bitmap is returned, you can query the actual parameters that were 551 * used to create the bitmap from the {@code BitmapParams} argument, for instance 552 * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}. 553 * 554 * @param imageIndex 0-based index of the image. 555 * @param params BitmapParams that controls the returned bitmap config (such as pixel formats). 556 * 557 * @throws IllegalStateException if the container doesn't contain still images. 558 * @throws IllegalArgumentException if the requested image does not exist. 559 * 560 * @return the requested still image, or null if the image cannot be retrieved. 561 * 562 * @see #getImageAtIndex(int) 563 * @see #getPrimaryImage(BitmapParams) 564 * @see #getPrimaryImage() 565 */ getImageAtIndex(int imageIndex, @NonNull BitmapParams params)566 public Bitmap getImageAtIndex(int imageIndex, @NonNull BitmapParams params) { 567 return getImageAtIndexInternal(imageIndex, params); 568 } 569 570 /** 571 * @hide 572 * 573 * This method retrieves the thumbnail image for a still image if it's available. 574 * It should only be called after {@link #setDataSource}. 575 * 576 * @param imageIndex 0-based index of the image, negative value indicates primary image. 577 * @param params BitmapParams that controls the returned bitmap config (such as pixel formats). 578 * @param targetSize intended size of one edge (wdith or height) of the thumbnail, 579 * this is a heuristic for the framework to decide whether the embedded 580 * thumbnail should be used. 581 * @param maxPixels maximum pixels of thumbnail, this is a heuristic for the frameowrk to 582 * decide whehther the embedded thumnbail (or a downscaled version of it) 583 * should be used. 584 * @return the retrieved thumbnail, or null if no suitable thumbnail is available. 585 */ getThumbnailImageAtIndex( int imageIndex, @NonNull BitmapParams params, int targetSize, int maxPixels)586 public native @Nullable Bitmap getThumbnailImageAtIndex( 587 int imageIndex, @NonNull BitmapParams params, int targetSize, int maxPixels); 588 589 /** 590 * This method is similar to {@link #getImageAtIndex(int, BitmapParams)} except that 591 * the default for {@link BitmapParams} will be used. 592 * 593 * @param imageIndex 0-based index of the image. 594 * 595 * @throws IllegalStateException if the container doesn't contain still images. 596 * @throws IllegalArgumentException if the requested image does not exist. 597 * 598 * @return the requested still image, or null if the image cannot be retrieved. 599 * 600 * @see #getImageAtIndex(int, BitmapParams) 601 * @see #getPrimaryImage(BitmapParams) 602 * @see #getPrimaryImage() 603 */ getImageAtIndex(int imageIndex)604 public Bitmap getImageAtIndex(int imageIndex) { 605 return getImageAtIndexInternal(imageIndex, null); 606 } 607 608 /** 609 * This method retrieves the primary image of the media content. It should only 610 * be called after {@link #setDataSource}. 611 * 612 * After the bitmap is returned, you can query the actual parameters that were 613 * used to create the bitmap from the {@code BitmapParams} argument, for instance 614 * to query the bitmap config used for the bitmap with {@link BitmapParams#getActualConfig}. 615 * 616 * @param params BitmapParams that controls the returned bitmap config (such as pixel formats). 617 * 618 * @return the primary image, or null if it cannot be retrieved. 619 * 620 * @throws IllegalStateException if the container doesn't contain still images. 621 * 622 * @see #getImageAtIndex(int, BitmapParams) 623 * @see #getImageAtIndex(int) 624 * @see #getPrimaryImage() 625 */ getPrimaryImage(@onNull BitmapParams params)626 public Bitmap getPrimaryImage(@NonNull BitmapParams params) { 627 return getImageAtIndexInternal(-1, params); 628 } 629 630 /** 631 * This method is similar to {@link #getPrimaryImage(BitmapParams)} except that 632 * the default for {@link BitmapParams} will be used. 633 * 634 * @return the primary image, or null if it cannot be retrieved. 635 * 636 * @throws IllegalStateException if the container doesn't contain still images. 637 * 638 * @see #getImageAtIndex(int, BitmapParams) 639 * @see #getImageAtIndex(int) 640 * @see #getPrimaryImage(BitmapParams) 641 */ getPrimaryImage()642 public Bitmap getPrimaryImage() { 643 return getImageAtIndexInternal(-1, null); 644 } 645 getImageAtIndexInternal(int imageIndex, @Nullable BitmapParams params)646 private Bitmap getImageAtIndexInternal(int imageIndex, @Nullable BitmapParams params) { 647 if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) { 648 throw new IllegalStateException("Does not contail still images"); 649 } 650 651 String imageCount = extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT); 652 if (imageIndex >= Integer.parseInt(imageCount)) { 653 throw new IllegalArgumentException("Invalid image index: " + imageCount); 654 } 655 656 return _getImageAtIndex(imageIndex, params); 657 } 658 _getImageAtIndex(int imageIndex, @Nullable BitmapParams params)659 private native Bitmap _getImageAtIndex(int imageIndex, @Nullable BitmapParams params); 660 661 /** 662 * Call this method after setDataSource(). This method finds the optional 663 * graphic or album/cover art associated associated with the data source. If 664 * there are more than one pictures, (any) one of them is returned. 665 * 666 * @return null if no such graphic is found. 667 */ getEmbeddedPicture()668 public byte[] getEmbeddedPicture() { 669 return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY); 670 } 671 672 @UnsupportedAppUsage getEmbeddedPicture(int pictureType)673 private native byte[] getEmbeddedPicture(int pictureType); 674 675 @Override close()676 public void close() { 677 release(); 678 } 679 680 /** 681 * Call it when one is done with the object. This method releases the memory 682 * allocated internally. 683 */ release()684 public native void release(); 685 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) native_setup()686 private native void native_setup(); 687 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) native_init()688 private static native void native_init(); 689 690 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) native_finalize()691 private native final void native_finalize(); 692 693 @Override finalize()694 protected void finalize() throws Throwable { 695 try { 696 native_finalize(); 697 } finally { 698 super.finalize(); 699 } 700 } 701 702 /** 703 * Option used in method {@link #getFrameAtTime(long, int)} to get a 704 * frame at a specified location. 705 * 706 * @see #getFrameAtTime(long, int) 707 */ 708 /* Do not change these option values without updating their counterparts 709 * in include/media/MediaSource.h! 710 */ 711 /** 712 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 713 * a sync (or key) frame associated with a data source that is located 714 * right before or at the given time. 715 * 716 * @see #getFrameAtTime(long, int) 717 */ 718 public static final int OPTION_PREVIOUS_SYNC = 0x00; 719 /** 720 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 721 * a sync (or key) frame associated with a data source that is located 722 * right after or at the given time. 723 * 724 * @see #getFrameAtTime(long, int) 725 */ 726 public static final int OPTION_NEXT_SYNC = 0x01; 727 /** 728 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 729 * a sync (or key) frame associated with a data source that is located 730 * closest to (in time) or at the given time. 731 * 732 * @see #getFrameAtTime(long, int) 733 */ 734 public static final int OPTION_CLOSEST_SYNC = 0x02; 735 /** 736 * This option is used with {@link #getFrameAtTime(long, int)} to retrieve 737 * a frame (not necessarily a key frame) associated with a data source that 738 * is located closest to or at the given time. 739 * 740 * @see #getFrameAtTime(long, int) 741 */ 742 public static final int OPTION_CLOSEST = 0x03; 743 744 /** @hide */ 745 @IntDef(flag = true, prefix = { "OPTION_" }, value = { 746 OPTION_PREVIOUS_SYNC, 747 OPTION_NEXT_SYNC, 748 OPTION_CLOSEST_SYNC, 749 OPTION_CLOSEST, 750 }) 751 @Retention(RetentionPolicy.SOURCE) 752 public @interface Option {} 753 754 /* 755 * Do not change these metadata key values without updating their 756 * counterparts in include/media/mediametadataretriever.h! 757 */ 758 /** 759 * The metadata key to retrieve the numeric string describing the 760 * order of the audio data source on its original recording. 761 */ 762 public static final int METADATA_KEY_CD_TRACK_NUMBER = 0; 763 /** 764 * The metadata key to retrieve the information about the album title 765 * of the data source. 766 */ 767 public static final int METADATA_KEY_ALBUM = 1; 768 /** 769 * The metadata key to retrieve the information about the artist of 770 * the data source. 771 */ 772 public static final int METADATA_KEY_ARTIST = 2; 773 /** 774 * The metadata key to retrieve the information about the author of 775 * the data source. 776 */ 777 public static final int METADATA_KEY_AUTHOR = 3; 778 /** 779 * The metadata key to retrieve the information about the composer of 780 * the data source. 781 */ 782 public static final int METADATA_KEY_COMPOSER = 4; 783 /** 784 * The metadata key to retrieve the date when the data source was created 785 * or modified. 786 */ 787 public static final int METADATA_KEY_DATE = 5; 788 /** 789 * The metadata key to retrieve the content type or genre of the data 790 * source. 791 */ 792 public static final int METADATA_KEY_GENRE = 6; 793 /** 794 * The metadata key to retrieve the data source title. 795 */ 796 public static final int METADATA_KEY_TITLE = 7; 797 /** 798 * The metadata key to retrieve the year when the data source was created 799 * or modified. 800 */ 801 public static final int METADATA_KEY_YEAR = 8; 802 /** 803 * The metadata key to retrieve the playback duration of the data source. 804 */ 805 public static final int METADATA_KEY_DURATION = 9; 806 /** 807 * The metadata key to retrieve the number of tracks, such as audio, video, 808 * text, in the data source, such as a mp4 or 3gpp file. 809 */ 810 public static final int METADATA_KEY_NUM_TRACKS = 10; 811 /** 812 * The metadata key to retrieve the information of the writer (such as 813 * lyricist) of the data source. 814 */ 815 public static final int METADATA_KEY_WRITER = 11; 816 /** 817 * The metadata key to retrieve the mime type of the data source. Some 818 * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb", 819 * etc. 820 */ 821 public static final int METADATA_KEY_MIMETYPE = 12; 822 /** 823 * The metadata key to retrieve the information about the performers or 824 * artist associated with the data source. 825 */ 826 public static final int METADATA_KEY_ALBUMARTIST = 13; 827 /** 828 * The metadata key to retrieve the numberic string that describes which 829 * part of a set the audio data source comes from. 830 */ 831 public static final int METADATA_KEY_DISC_NUMBER = 14; 832 /** 833 * The metadata key to retrieve the music album compilation status. 834 */ 835 public static final int METADATA_KEY_COMPILATION = 15; 836 /** 837 * If this key exists the media contains audio content. 838 */ 839 public static final int METADATA_KEY_HAS_AUDIO = 16; 840 /** 841 * If this key exists the media contains video content. 842 */ 843 public static final int METADATA_KEY_HAS_VIDEO = 17; 844 /** 845 * If the media contains video, this key retrieves its width. 846 */ 847 public static final int METADATA_KEY_VIDEO_WIDTH = 18; 848 /** 849 * If the media contains video, this key retrieves its height. 850 */ 851 public static final int METADATA_KEY_VIDEO_HEIGHT = 19; 852 /** 853 * This key retrieves the average bitrate (in bits/sec), if available. 854 */ 855 public static final int METADATA_KEY_BITRATE = 20; 856 /** 857 * This key retrieves the language code of text tracks, if available. 858 * If multiple text tracks present, the return value will look like: 859 * "eng:chi" 860 * @hide 861 */ 862 public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES = 21; 863 /** 864 * If this key exists the media is drm-protected. 865 * @hide 866 */ 867 public static final int METADATA_KEY_IS_DRM = 22; 868 /** 869 * This key retrieves the location information, if available. 870 * The location should be specified according to ISO-6709 standard, under 871 * a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude 872 * of 180 degrees will be retrieved as "+180.0000-90.0000/", for instance. 873 */ 874 public static final int METADATA_KEY_LOCATION = 23; 875 /** 876 * This key retrieves the video rotation angle in degrees, if available. 877 * The video rotation angle may be 0, 90, 180, or 270 degrees. 878 */ 879 public static final int METADATA_KEY_VIDEO_ROTATION = 24; 880 /** 881 * This key retrieves the original capture framerate, if it's 882 * available. The capture framerate will be a floating point 883 * number. 884 */ 885 public static final int METADATA_KEY_CAPTURE_FRAMERATE = 25; 886 /** 887 * If this key exists the media contains still image content. 888 */ 889 public static final int METADATA_KEY_HAS_IMAGE = 26; 890 /** 891 * If the media contains still images, this key retrieves the number 892 * of still images. 893 */ 894 public static final int METADATA_KEY_IMAGE_COUNT = 27; 895 /** 896 * If the media contains still images, this key retrieves the image 897 * index of the primary image. 898 */ 899 public static final int METADATA_KEY_IMAGE_PRIMARY = 28; 900 /** 901 * If the media contains still images, this key retrieves the width 902 * of the primary image. 903 */ 904 public static final int METADATA_KEY_IMAGE_WIDTH = 29; 905 /** 906 * If the media contains still images, this key retrieves the height 907 * of the primary image. 908 */ 909 public static final int METADATA_KEY_IMAGE_HEIGHT = 30; 910 /** 911 * If the media contains still images, this key retrieves the rotation 912 * angle (in degrees clockwise) of the primary image. The image rotation 913 * angle must be one of 0, 90, 180, or 270 degrees. 914 */ 915 public static final int METADATA_KEY_IMAGE_ROTATION = 31; 916 /** 917 * If the media contains video and this key exists, it retrieves the 918 * total number of frames in the video sequence. 919 */ 920 public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32; 921 922 /** 923 * If the media contains EXIF data, this key retrieves the offset value 924 * of the data. 925 */ 926 public static final int METADATA_KEY_EXIF_OFFSET = 33; 927 928 /** 929 * If the media contains EXIF data, this key retrieves the length of the 930 * data. 931 */ 932 public static final int METADATA_KEY_EXIF_LENGTH = 34; 933 934 /** 935 * This key retrieves the color standard, if available. 936 * 937 * @see MediaFormat#COLOR_STANDARD_BT709 938 * @see MediaFormat#COLOR_STANDARD_BT601_PAL 939 * @see MediaFormat#COLOR_STANDARD_BT601_NTSC 940 * @see MediaFormat#COLOR_STANDARD_BT2020 941 * 942 * @hide 943 */ 944 public static final int METADATA_KEY_COLOR_STANDARD = 35; 945 946 /** 947 * This key retrieves the color transfer, if available. 948 * 949 * @see MediaFormat#COLOR_TRANSFER_LINEAR 950 * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO 951 * @see MediaFormat#COLOR_TRANSFER_ST2084 952 * @see MediaFormat#COLOR_TRANSFER_HLG 953 * 954 * @hide 955 */ 956 public static final int METADATA_KEY_COLOR_TRANSFER = 36; 957 958 /** 959 * This key retrieves the color range, if available. 960 * 961 * @see MediaFormat#COLOR_RANGE_LIMITED 962 * @see MediaFormat#COLOR_RANGE_FULL 963 * 964 * @hide 965 */ 966 public static final int METADATA_KEY_COLOR_RANGE = 37; 967 // Add more here... 968 969 /** 970 * This key retrieves the sample rate, if available. 971 * @hide 972 */ 973 public static final int METADATA_KEY_SAMPLERATE = 38; 974 975 /** 976 * This key retrieves the bits per sample, if available. 977 * @hide 978 */ 979 public static final int METADATA_KEY_BITS_PER_SAMPLE = 39; 980 } 981