Merge "media: Add scaled video thumbnail extractor api." into oc-mr1-dev
am: 26a4940296
Change-Id: Ibfa5394a612dcec663b1d8b4a301f94b1f2fb49e
This commit is contained in:
@@ -22742,6 +22742,7 @@ package android.media {
|
||||
method public android.graphics.Bitmap getFrameAtTime(long, int);
|
||||
method public android.graphics.Bitmap getFrameAtTime(long);
|
||||
method public android.graphics.Bitmap getFrameAtTime();
|
||||
method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
|
||||
method public void release();
|
||||
method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.lang.IllegalArgumentException;
|
||||
|
||||
@@ -24686,6 +24686,7 @@ package android.media {
|
||||
method public android.graphics.Bitmap getFrameAtTime(long, int);
|
||||
method public android.graphics.Bitmap getFrameAtTime(long);
|
||||
method public android.graphics.Bitmap getFrameAtTime();
|
||||
method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
|
||||
method public void release();
|
||||
method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.lang.IllegalArgumentException;
|
||||
|
||||
@@ -22878,6 +22878,7 @@ package android.media {
|
||||
method public android.graphics.Bitmap getFrameAtTime(long, int);
|
||||
method public android.graphics.Bitmap getFrameAtTime(long);
|
||||
method public android.graphics.Bitmap getFrameAtTime();
|
||||
method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
|
||||
method public void release();
|
||||
method public void setDataSource(java.lang.String) throws java.lang.IllegalArgumentException;
|
||||
method public void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.lang.IllegalArgumentException;
|
||||
|
||||
@@ -246,7 +246,7 @@ public class MediaMetadataRetriever
|
||||
* {@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
|
||||
* @return A Bitmap containing a representative video frame, which
|
||||
* can be null, if such a frame cannot be retrieved.
|
||||
*/
|
||||
public Bitmap getFrameAtTime(long timeUs, int option) {
|
||||
@@ -255,7 +255,58 @@ public class MediaMetadataRetriever
|
||||
throw new IllegalArgumentException("Unsupported option: " + option);
|
||||
}
|
||||
|
||||
return _getFrameAtTime(timeUs, option);
|
||||
return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a video frame near a given timestamp scaled to a desired size.
|
||||
* Call this method after setDataSource(). This method finds a representative
|
||||
* frame close to the given time position by considering the given option
|
||||
* if possible, and returns it as a bitmap with same aspect ratio as the source
|
||||
* while scaling it so that it fits into the desired size of dst_width by dst_height.
|
||||
* This is useful for generating a thumbnail for an input data source or just to
|
||||
* obtain a scaled frame at the given time position.
|
||||
*
|
||||
* @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 dst_width expected output bitmap width
|
||||
* @param dst_height expected output bitmap height
|
||||
* @return A Bitmap of size not larger than dst_width by dst_height 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.
|
||||
*/
|
||||
public Bitmap getScaledFrameAtTime(
|
||||
long timeUs, int option, int dst_width, int dst_height) {
|
||||
if (option < OPTION_PREVIOUS_SYNC ||
|
||||
option > OPTION_CLOSEST) {
|
||||
throw new IllegalArgumentException("Unsupported option: " + option);
|
||||
}
|
||||
if (dst_width <= 0) {
|
||||
throw new IllegalArgumentException("Invalid width: " + dst_width);
|
||||
}
|
||||
if (dst_height <= 0) {
|
||||
throw new IllegalArgumentException("Invalid height: " + dst_height);
|
||||
}
|
||||
|
||||
return _getFrameAtTime(timeUs, option, dst_width, dst_height);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,8 +324,8 @@ public class MediaMetadataRetriever
|
||||
* negative, time position and option will ignored, and any frame
|
||||
* that the implementation considers as representative may be returned.
|
||||
*
|
||||
* @return A Bitmap containing a representative video frame, which
|
||||
* can be null, if such a frame cannot be retrieved.
|
||||
* @return A Bitmap of size dst_widthxdst_height containing a representative
|
||||
* video frame, which can be null, if such a frame cannot be retrieved.
|
||||
*
|
||||
* @see #getFrameAtTime(long, int)
|
||||
*/
|
||||
@@ -297,17 +348,16 @@ public class MediaMetadataRetriever
|
||||
* @see #getFrameAtTime(long, int)
|
||||
*/
|
||||
public Bitmap getFrameAtTime() {
|
||||
return getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
|
||||
return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/);
|
||||
}
|
||||
|
||||
private native Bitmap _getFrameAtTime(long timeUs, int option);
|
||||
private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height);
|
||||
|
||||
|
||||
/**
|
||||
* Call this method after setDataSource(). This method finds the optional
|
||||
* graphic or album/cover art associated associated with the data source. If
|
||||
* there are more than one pictures, (any) one of them is returned.
|
||||
*
|
||||
*
|
||||
* @return null if no such graphic is found.
|
||||
*/
|
||||
public byte[] getEmbeddedPicture() {
|
||||
|
||||
@@ -244,9 +244,11 @@ static void rotate(T *dst, const T *src, size_t width, size_t height, int angle)
|
||||
}
|
||||
}
|
||||
|
||||
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
|
||||
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
|
||||
JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height)
|
||||
{
|
||||
ALOGV("getFrameAtTime: %lld us option: %d", (long long)timeUs, option);
|
||||
ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d",
|
||||
(long long)timeUs, option, dst_width, dst_height);
|
||||
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
|
||||
if (retriever == 0) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
|
||||
@@ -274,15 +276,19 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env,
|
||||
fields.createConfigMethod,
|
||||
GraphicsJNI::colorTypeToLegacyBitmapConfig(kRGB_565_SkColorType));
|
||||
|
||||
uint32_t width, height;
|
||||
uint32_t width, height, displayWidth, displayHeight;
|
||||
bool swapWidthAndHeight = false;
|
||||
if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
|
||||
width = videoFrame->mHeight;
|
||||
height = videoFrame->mWidth;
|
||||
swapWidthAndHeight = true;
|
||||
displayWidth = videoFrame->mDisplayHeight;
|
||||
displayHeight = videoFrame->mDisplayWidth;
|
||||
} else {
|
||||
width = videoFrame->mWidth;
|
||||
height = videoFrame->mHeight;
|
||||
displayWidth = videoFrame->mDisplayWidth;
|
||||
displayHeight = videoFrame->mDisplayHeight;
|
||||
}
|
||||
|
||||
jobject jBitmap = env->CallStaticObjectMethod(
|
||||
@@ -308,22 +314,26 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env,
|
||||
videoFrame->mHeight,
|
||||
videoFrame->mRotationAngle);
|
||||
|
||||
if (videoFrame->mDisplayWidth != videoFrame->mWidth ||
|
||||
videoFrame->mDisplayHeight != videoFrame->mHeight) {
|
||||
uint32_t displayWidth = videoFrame->mDisplayWidth;
|
||||
uint32_t displayHeight = videoFrame->mDisplayHeight;
|
||||
if (swapWidthAndHeight) {
|
||||
displayWidth = videoFrame->mDisplayHeight;
|
||||
displayHeight = videoFrame->mDisplayWidth;
|
||||
}
|
||||
if (dst_width <= 0 || dst_height <= 0) {
|
||||
dst_width = displayWidth;
|
||||
dst_height = displayHeight;
|
||||
} else {
|
||||
float factor = std::min((float)dst_width / (float)displayWidth,
|
||||
(float)dst_height / (float)displayHeight);
|
||||
dst_width = std::round(displayWidth * factor);
|
||||
dst_height = std::round(displayHeight * factor);
|
||||
}
|
||||
|
||||
if ((uint32_t)dst_width != videoFrame->mWidth ||
|
||||
(uint32_t)dst_height != videoFrame->mHeight) {
|
||||
ALOGV("Bitmap dimension is scaled from %dx%d to %dx%d",
|
||||
width, height, displayWidth, displayHeight);
|
||||
width, height, dst_width, dst_height);
|
||||
jobject scaledBitmap = env->CallStaticObjectMethod(fields.bitmapClazz,
|
||||
fields.createScaledBitmapMethod,
|
||||
jBitmap,
|
||||
displayWidth,
|
||||
displayHeight,
|
||||
true);
|
||||
fields.createScaledBitmapMethod,
|
||||
jBitmap,
|
||||
dst_width,
|
||||
dst_height,
|
||||
true);
|
||||
return scaledBitmap;
|
||||
}
|
||||
|
||||
@@ -474,7 +484,7 @@ static const JNINativeMethod nativeMethods[] = {
|
||||
|
||||
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
|
||||
{"_setDataSource", "(Landroid/media/MediaDataSource;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
|
||||
{"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
|
||||
{"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
|
||||
{"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
|
||||
{"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
|
||||
{"release", "()V", (void *)android_media_MediaMetadataRetriever_release},
|
||||
|
||||
Reference in New Issue
Block a user