Loading api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -25387,6 +25387,7 @@ package android.media { method public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getFrameAtIndex(int); method public android.graphics.Bitmap getFrameAtTime(long, int); method public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getFrameAtTime(long); method public android.graphics.Bitmap getFrameAtTime(); method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); Loading @@ -25396,6 +25397,7 @@ package android.media { method public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getPrimaryImage(); method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int); method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public void release(); method public void setDataSource(String) throws java.lang.IllegalArgumentException; method public void setDataSource(String, java.util.Map<java.lang.String,java.lang.String>) throws java.lang.IllegalArgumentException; media/java/android/media/MediaMetadataRetriever.java +100 −10 Original line number Diff line number Diff line Loading @@ -226,6 +226,44 @@ public class MediaMetadataRetriever implements AutoCloseable { */ public native String extractMetadata(int keyCode); /** * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)} * except that the device will choose the actual {@link Bitmap.Config} to use. * * @param timeUs The time position where the frame will be retrieved. * When retrieving the frame at the given time position, there is no * guarantee that the data source has a frame located at the position. * When this happens, a frame nearby will be returned. If timeUs is * negative, time position and option will ignored, and any frame * that the implementation considers as representative may be returned. * * @param option a hint on how the frame is found. Use * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame * that has a timestamp earlier than or the same as timeUs. Use * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame * that has a timestamp later than or the same as timeUs. Use * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame * that has a timestamp closest to or the same as timeUs. Use * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may * or may not be a sync frame but is closest to or the same as timeUs. * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @return A Bitmap containing a representative video frame, which can be null, * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can * be used to query the actual {@link Bitmap.Config}. * * @see {@link #getFrameAtTime(long, int, BitmapParams)} */ public Bitmap getFrameAtTime(long timeUs, @Option int option) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, null); } /** * Call this method after setDataSource(). This method finds a * representative frame close to the given time position by considering Loading Loading @@ -255,16 +293,60 @@ public class MediaMetadataRetriever implements AutoCloseable { * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @param params BitmapParams that controls the returned bitmap config * (such as pixel formats). * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. * * @see {@link #getFrameAtTime(long, int)} */ public Bitmap getFrameAtTime(long timeUs, @Option int option) { public Bitmap getFrameAtTime( long timeUs, @Option int option, @NonNull BitmapParams params) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/); return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, params); } /** * This method is similar to {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)} * except that the device will choose the actual {@link Bitmap.Config} to use. * * @param timeUs The time position in microseconds where the frame will be retrieved. * When retrieving the frame at the given time position, there is no * guarantee that the data source has a frame located at the position. * When this happens, a frame nearby will be returned. If timeUs is * negative, time position and option will ignored, and any frame * that the implementation considers as representative may be returned. * * @param option a hint on how the frame is found. Use * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame * that has a timestamp earlier than or the same as timeUs. Use * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame * that has a timestamp later than or the same as timeUs. Use * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame * that has a timestamp closest to or the same as timeUs. Use * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may * or may not be a sync frame but is closest to or the same as timeUs. * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @param dstWidth expected output bitmap width * @param dstHeight expected output bitmap height * @return A Bitmap containing a representative video frame, which can be null, * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can * be used to query the actual {@link Bitmap.Config}. * @throws IllegalArgumentException if passed in invalid option or width by height * is less than or equal to 0. * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)} */ public Bitmap getScaledFrameAtTime( long timeUs, @Option int option, int dstWidth, int dstHeight) { validate(option, dstWidth, dstHeight); return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null); } /** Loading Loading @@ -297,15 +379,23 @@ public class MediaMetadataRetriever implements AutoCloseable { * * @param dstWidth expected output bitmap width * @param dstHeight expected output bitmap height * @param params BitmapParams that controls the returned bitmap config * (such as pixel formats). * * @return A Bitmap of size not larger than dstWidth by dstHeight containing a * scaled video frame, which can be null, if such a frame cannot be retrieved. * @throws IllegalArgumentException if passed in invalid option or width by height * is less than or equal to 0. * @see {@link #getScaledFrameAtTime(long, int, int, int)} */ public Bitmap getScaledFrameAtTime( long timeUs, @Option int option, int dstWidth, int dstHeight) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { public Bitmap getScaledFrameAtTime(long timeUs, @Option int option, int dstWidth, int dstHeight, @NonNull BitmapParams params) { validate(option, dstWidth, dstHeight); return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, params); } private void validate(@Option int option, int dstWidth, int dstHeight) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } if (dstWidth <= 0) { Loading @@ -314,8 +404,6 @@ public class MediaMetadataRetriever implements AutoCloseable { if (dstHeight <= 0) { throw new IllegalArgumentException("Invalid height: " + dstHeight); } return _getFrameAtTime(timeUs, option, dstWidth, dstHeight); } /** Loading Loading @@ -365,10 +453,12 @@ public class MediaMetadataRetriever implements AutoCloseable { * @see #getFrameAtTime(long, int) */ public Bitmap getFrameAtTime() { return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/); return _getFrameAtTime( -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null); } private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height); private native Bitmap _getFrameAtTime( long timeUs, int option, int width, int height, @Nullable BitmapParams params); public static final class BitmapParams { private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888; Loading media/jni/android_media_MediaMetadataRetriever.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -350,9 +350,10 @@ static jobject getBitmapFromVideoFrame( return jBitmap; } static int getColorFormat(JNIEnv *env, jobject options) { static int getColorFormat(JNIEnv *env, jobject options, int defaultPreferred = HAL_PIXEL_FORMAT_RGBA_8888) { if (options == NULL) { return HAL_PIXEL_FORMAT_RGBA_8888; return defaultPreferred; } ScopedLocalRef<jobject> inConfig(env, env->GetObjectField(options, fields.inPreferredConfig)); Loading Loading @@ -383,7 +384,8 @@ static SkColorType setOutColorType(JNIEnv *env, int colorFormat, jobject options } static jobject android_media_MediaMetadataRetriever_getFrameAtTime( JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height) JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height, jobject params) { ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d", (long long)timeUs, option, dst_width, dst_height); Loading @@ -392,10 +394,13 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime( jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); return NULL; } // For getFrameAtTime family of calls, default to HAL_PIXEL_FORMAT_RGB_565 // to keep the behavior consistent with older releases int colorFormat = getColorFormat(env, params, HAL_PIXEL_FORMAT_RGB_565); // Call native method to retrieve a video frame VideoFrame *videoFrame = NULL; sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option); sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option, colorFormat); // TODO: Using unsecurePointer() has some associated security pitfalls // (see declaration for details). // Either document why it is safe in this case or address the Loading @@ -408,7 +413,9 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime( return NULL; } return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, kRGB_565_SkColorType); SkColorType outColorType = setOutColorType(env, colorFormat, params); return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, outColorType); } static jobject android_media_MediaMetadataRetriever_getImageAtIndex( Loading Loading @@ -739,7 +746,7 @@ static const JNINativeMethod nativeMethods[] = { (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, {"_setDataSource", "(Landroid/media/MediaDataSource;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceCallback}, {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;", {"_getFrameAtTime", "(JIIILandroid/media/MediaMetadataRetriever$BitmapParams;)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, { "_getImageAtIndex", Loading Loading
api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -25387,6 +25387,7 @@ package android.media { method public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getFrameAtIndex(int); method public android.graphics.Bitmap getFrameAtTime(long, int); method public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getFrameAtTime(long); method public android.graphics.Bitmap getFrameAtTime(); method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); Loading @@ -25396,6 +25397,7 @@ package android.media { method public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams); method public android.graphics.Bitmap getPrimaryImage(); method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int); method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams); method public void release(); method public void setDataSource(String) throws java.lang.IllegalArgumentException; method public void setDataSource(String, java.util.Map<java.lang.String,java.lang.String>) throws java.lang.IllegalArgumentException;
media/java/android/media/MediaMetadataRetriever.java +100 −10 Original line number Diff line number Diff line Loading @@ -226,6 +226,44 @@ public class MediaMetadataRetriever implements AutoCloseable { */ public native String extractMetadata(int keyCode); /** * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)} * except that the device will choose the actual {@link Bitmap.Config} to use. * * @param timeUs The time position where the frame will be retrieved. * When retrieving the frame at the given time position, there is no * guarantee that the data source has a frame located at the position. * When this happens, a frame nearby will be returned. If timeUs is * negative, time position and option will ignored, and any frame * that the implementation considers as representative may be returned. * * @param option a hint on how the frame is found. Use * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame * that has a timestamp earlier than or the same as timeUs. Use * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame * that has a timestamp later than or the same as timeUs. Use * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame * that has a timestamp closest to or the same as timeUs. Use * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may * or may not be a sync frame but is closest to or the same as timeUs. * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @return A Bitmap containing a representative video frame, which can be null, * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can * be used to query the actual {@link Bitmap.Config}. * * @see {@link #getFrameAtTime(long, int, BitmapParams)} */ public Bitmap getFrameAtTime(long timeUs, @Option int option) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, null); } /** * Call this method after setDataSource(). This method finds a * representative frame close to the given time position by considering Loading Loading @@ -255,16 +293,60 @@ public class MediaMetadataRetriever implements AutoCloseable { * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @param params BitmapParams that controls the returned bitmap config * (such as pixel formats). * * @return A Bitmap containing a representative video frame, which * can be null, if such a frame cannot be retrieved. * * @see {@link #getFrameAtTime(long, int)} */ public Bitmap getFrameAtTime(long timeUs, @Option int option) { public Bitmap getFrameAtTime( long timeUs, @Option int option, @NonNull BitmapParams params) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/); return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, params); } /** * This method is similar to {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)} * except that the device will choose the actual {@link Bitmap.Config} to use. * * @param timeUs The time position in microseconds where the frame will be retrieved. * When retrieving the frame at the given time position, there is no * guarantee that the data source has a frame located at the position. * When this happens, a frame nearby will be returned. If timeUs is * negative, time position and option will ignored, and any frame * that the implementation considers as representative may be returned. * * @param option a hint on how the frame is found. Use * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame * that has a timestamp earlier than or the same as timeUs. Use * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame * that has a timestamp later than or the same as timeUs. Use * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame * that has a timestamp closest to or the same as timeUs. Use * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may * or may not be a sync frame but is closest to or the same as timeUs. * {@link #OPTION_CLOSEST} often has larger performance overhead compared * to the other options if there is no sync frame located at timeUs. * * @param dstWidth expected output bitmap width * @param dstHeight expected output bitmap height * @return A Bitmap containing a representative video frame, which can be null, * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can * be used to query the actual {@link Bitmap.Config}. * @throws IllegalArgumentException if passed in invalid option or width by height * is less than or equal to 0. * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)} */ public Bitmap getScaledFrameAtTime( long timeUs, @Option int option, int dstWidth, int dstHeight) { validate(option, dstWidth, dstHeight); return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null); } /** Loading Loading @@ -297,15 +379,23 @@ public class MediaMetadataRetriever implements AutoCloseable { * * @param dstWidth expected output bitmap width * @param dstHeight expected output bitmap height * @param params BitmapParams that controls the returned bitmap config * (such as pixel formats). * * @return A Bitmap of size not larger than dstWidth by dstHeight containing a * scaled video frame, which can be null, if such a frame cannot be retrieved. * @throws IllegalArgumentException if passed in invalid option or width by height * is less than or equal to 0. * @see {@link #getScaledFrameAtTime(long, int, int, int)} */ public Bitmap getScaledFrameAtTime( long timeUs, @Option int option, int dstWidth, int dstHeight) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { public Bitmap getScaledFrameAtTime(long timeUs, @Option int option, int dstWidth, int dstHeight, @NonNull BitmapParams params) { validate(option, dstWidth, dstHeight); return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, params); } private void validate(@Option int option, int dstWidth, int dstHeight) { if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) { throw new IllegalArgumentException("Unsupported option: " + option); } if (dstWidth <= 0) { Loading @@ -314,8 +404,6 @@ public class MediaMetadataRetriever implements AutoCloseable { if (dstHeight <= 0) { throw new IllegalArgumentException("Invalid height: " + dstHeight); } return _getFrameAtTime(timeUs, option, dstWidth, dstHeight); } /** Loading Loading @@ -365,10 +453,12 @@ public class MediaMetadataRetriever implements AutoCloseable { * @see #getFrameAtTime(long, int) */ public Bitmap getFrameAtTime() { return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/); return _getFrameAtTime( -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null); } private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height); private native Bitmap _getFrameAtTime( long timeUs, int option, int width, int height, @Nullable BitmapParams params); public static final class BitmapParams { private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888; Loading
media/jni/android_media_MediaMetadataRetriever.cpp +13 −6 Original line number Diff line number Diff line Loading @@ -350,9 +350,10 @@ static jobject getBitmapFromVideoFrame( return jBitmap; } static int getColorFormat(JNIEnv *env, jobject options) { static int getColorFormat(JNIEnv *env, jobject options, int defaultPreferred = HAL_PIXEL_FORMAT_RGBA_8888) { if (options == NULL) { return HAL_PIXEL_FORMAT_RGBA_8888; return defaultPreferred; } ScopedLocalRef<jobject> inConfig(env, env->GetObjectField(options, fields.inPreferredConfig)); Loading Loading @@ -383,7 +384,8 @@ static SkColorType setOutColorType(JNIEnv *env, int colorFormat, jobject options } static jobject android_media_MediaMetadataRetriever_getFrameAtTime( JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height) JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height, jobject params) { ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d", (long long)timeUs, option, dst_width, dst_height); Loading @@ -392,10 +394,13 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime( jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); return NULL; } // For getFrameAtTime family of calls, default to HAL_PIXEL_FORMAT_RGB_565 // to keep the behavior consistent with older releases int colorFormat = getColorFormat(env, params, HAL_PIXEL_FORMAT_RGB_565); // Call native method to retrieve a video frame VideoFrame *videoFrame = NULL; sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option); sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option, colorFormat); // TODO: Using unsecurePointer() has some associated security pitfalls // (see declaration for details). // Either document why it is safe in this case or address the Loading @@ -408,7 +413,9 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime( return NULL; } return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, kRGB_565_SkColorType); SkColorType outColorType = setOutColorType(env, colorFormat, params); return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, outColorType); } static jobject android_media_MediaMetadataRetriever_getImageAtIndex( Loading Loading @@ -739,7 +746,7 @@ static const JNINativeMethod nativeMethods[] = { (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, {"_setDataSource", "(Landroid/media/MediaDataSource;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceCallback}, {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;", {"_getFrameAtTime", "(JIIILandroid/media/MediaMetadataRetriever$BitmapParams;)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, { "_getImageAtIndex", Loading