diff options
Diffstat (limited to 'media/jni/android_media_MediaMetadataRetriever.cpp')
| -rw-r--r-- | media/jni/android_media_MediaMetadataRetriever.cpp | 131 |
1 files changed, 99 insertions, 32 deletions
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 3d7dbf9..73aea2a 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -28,16 +28,18 @@ #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" +#include "android_media_Utils.h" using namespace android; struct fields_t { jfieldID context; - jclass bitmapClazz; + jclass bitmapClazz; // Must be a global ref jfieldID nativeBitmap; jmethodID createBitmapMethod; - jclass configClazz; + jmethodID createScaledBitmapMethod; + jclass configClazz; // Must be a global ref jmethodID createConfigMethod; }; @@ -76,32 +78,64 @@ static void setRetriever(JNIEnv* env, jobject thiz, int retriever) env->SetIntField(thiz, fields.context, retriever); } -static void android_media_MediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path) -{ +static void +android_media_MediaMetadataRetriever_setDataSourceAndHeaders( + JNIEnv *env, jobject thiz, jstring path, + jobjectArray keys, jobjectArray values) { + LOGV("setDataSource"); MediaMetadataRetriever* retriever = getRetriever(env, thiz); if (retriever == 0) { - jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); + jniThrowException( + env, + "java/lang/IllegalStateException", "No retriever available"); + return; } + if (!path) { - jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer"); + jniThrowException( + env, "java/lang/IllegalArgumentException", "Null pointer"); + return; } - const char *pathStr = env->GetStringUTFChars(path, NULL); - if (!pathStr) { // OutOfMemoryError exception already thrown + const char *tmp = env->GetStringUTFChars(path, NULL); + if (!tmp) { // OutOfMemoryError exception already thrown return; } + String8 pathStr(tmp); + env->ReleaseStringUTFChars(path, tmp); + tmp = NULL; + // Don't let somebody trick us in to reading some random block of memory - if (strncmp("mem://", pathStr, 6) == 0) { - jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid pathname"); + if (strncmp("mem://", pathStr.string(), 6) == 0) { + jniThrowException( + env, "java/lang/IllegalArgumentException", "Invalid pathname"); return; } - process_media_retriever_call(env, retriever->setDataSource(pathStr), "java/lang/RuntimeException", "setDataSource failed"); - env->ReleaseStringUTFChars(path, pathStr); + // We build a similar KeyedVector out of it. + KeyedVector<String8, String8> headersVector; + if (!ConvertKeyValueArraysToKeyedVector( + env, keys, values, &headersVector)) { + return; + } + process_media_retriever_call( + env, + retriever->setDataSource( + pathStr.string(), headersVector.size() > 0 ? &headersVector : NULL), + + "java/lang/RuntimeException", + "setDataSource failed"); +} + + +static void android_media_MediaMetadataRetriever_setDataSource( + JNIEnv *env, jobject thiz, jstring path) { + android_media_MediaMetadataRetriever_setDataSourceAndHeaders( + env, thiz, path, NULL, NULL); } static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) @@ -116,7 +150,7 @@ static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jo jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return; } - int fd = getParcelFileDescriptorFD(env, fileDescriptor); + int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); if (offset < 0 || length < 0 || fd < 0) { if (offset < 0) { LOGE("negative offset (%lld)", offset); @@ -219,12 +253,14 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, SkBitmap::kRGB_565_Config); size_t width, height; + bool swapWidthAndHeight = false; if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) { - width = videoFrame->mDisplayHeight; - height = videoFrame->mDisplayWidth; + width = videoFrame->mHeight; + height = videoFrame->mWidth; + swapWidthAndHeight = true; } else { - width = videoFrame->mDisplayWidth; - height = videoFrame->mDisplayHeight; + width = videoFrame->mWidth; + height = videoFrame->mHeight; } jobject jBitmap = env->CallStaticObjectMethod( @@ -240,11 +276,30 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, bitmap->lockPixels(); rotate((uint16_t*)bitmap->getPixels(), (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)), - videoFrame->mDisplayWidth, - videoFrame->mDisplayHeight, + videoFrame->mWidth, + videoFrame->mHeight, videoFrame->mRotationAngle); bitmap->unlockPixels(); + if (videoFrame->mDisplayWidth != videoFrame->mWidth || + videoFrame->mDisplayHeight != videoFrame->mHeight) { + size_t displayWidth = videoFrame->mDisplayWidth; + size_t displayHeight = videoFrame->mDisplayHeight; + if (swapWidthAndHeight) { + displayWidth = videoFrame->mDisplayHeight; + displayHeight = videoFrame->mDisplayWidth; + } + LOGV("Bitmap dimension is scaled from %dx%d to %dx%d", + width, height, displayWidth, displayHeight); + jobject scaledBitmap = env->CallStaticObjectMethod(fields.bitmapClazz, + fields.createScaledBitmapMethod, + jBitmap, + displayWidth, + displayHeight, + true); + return scaledBitmap; + } + return jBitmap; } @@ -328,19 +383,20 @@ static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env) { jclass clazz = env->FindClass(kClassPathName); if (clazz == NULL) { - jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaMetadataRetriever"); return; } fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); if (fields.context == NULL) { - jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaMetadataRetriever.mNativeContext"); return; } - fields.bitmapClazz = env->FindClass("android/graphics/Bitmap"); + jclass bitmapClazz = env->FindClass("android/graphics/Bitmap"); + if (bitmapClazz == NULL) { + return; + } + fields.bitmapClazz = (jclass) env->NewGlobalRef(bitmapClazz); if (fields.bitmapClazz == NULL) { - jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap"); return; } fields.createBitmapMethod = @@ -348,28 +404,32 @@ static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env) "(IILandroid/graphics/Bitmap$Config;)" "Landroid/graphics/Bitmap;"); if (fields.createBitmapMethod == NULL) { - jniThrowException(env, "java/lang/RuntimeException", - "Can't find Bitmap.createBitmap(int, int, Config) method"); + return; + } + fields.createScaledBitmapMethod = + env->GetStaticMethodID(fields.bitmapClazz, "createScaledBitmap", + "(Landroid/graphics/Bitmap;IIZ)" + "Landroid/graphics/Bitmap;"); + if (fields.createScaledBitmapMethod == NULL) { return; } fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "I"); if (fields.nativeBitmap == NULL) { - jniThrowException(env, "java/lang/RuntimeException", - "Can't find Bitmap.mNativeBitmap field"); + return; } - fields.configClazz = env->FindClass("android/graphics/Bitmap$Config"); + jclass configClazz = env->FindClass("android/graphics/Bitmap$Config"); + if (configClazz == NULL) { + return; + } + fields.configClazz = (jclass) env->NewGlobalRef(configClazz); if (fields.configClazz == NULL) { - jniThrowException(env, "java/lang/RuntimeException", - "Can't find Bitmap$Config class"); return; } fields.createConfigMethod = env->GetStaticMethodID(fields.configClazz, "nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;"); if (fields.createConfigMethod == NULL) { - jniThrowException(env, "java/lang/RuntimeException", - "Can't find Bitmap$Config.nativeToConfig(int) method"); return; } } @@ -388,6 +448,13 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje // JNI mapping between Java methods and native methods static JNINativeMethod nativeMethods[] = { {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource}, + + { + "_setDataSource", + "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", + (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders + }, + {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata}, |
