android_media_MediaMetadataRetriever.cpp revision 0e4b535b439f2c8bd4f7ba820f81bf74336bae76
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2008, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "MediaMetadataRetrieverJNI" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/threads.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <core/SkBitmap.h> 250e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 260e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong// Please do not enable "USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR" 270e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong// This mode will be removed and it is kept here for 280e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong// convenient comparsion just in case. Will be removed soon. 290e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong// Tests show that this mode is also ~30ms slower, 300e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong// when rotation is involved. 310e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#define USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR 0 320e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 330e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#if (!USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR) 340e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#include <core/SkCanvas.h> 350e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#include <core/SkDevice.h> 360e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#include <core/SkScalar.h> 370e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#endif 380e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/mediametadataretriever.h> 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/media/VideoFrame.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h" 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct fields_t { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID context; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass bitmapClazz; 520e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jmethodID bitmapConstructor; 540e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jmethodID createBitmapRotationMethod; 550e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#else 560e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jfieldID nativeBitmap; 5753ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jmethodID createBitmapMethod; 580e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jclass configClazz; 590e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jmethodID createConfigMethod; 600e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#endif 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic fields_t fields; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic Mutex sLock; 654935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissenstatic const char* const kClassPathName = "android/media/MediaMetadataRetriever"; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message) 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (opStatus == (status_t) INVALID_OPERATION) { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", NULL); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (opStatus != (status_t) OK) { 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strlen(message) > 230) { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the message is too long, don't bother displaying the status code. 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException( env, exception, message); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msg[256]; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Append the status code to the message. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(msg, "%s: status = 0x%X", message, opStatus); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException( env, exception, msg); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz) 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since it is called internally by other methods that are protected 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retriever; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void setRetriever(JNIEnv* env, jobject thiz, int retriever) 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since it is called internally by other methods that are protected 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetIntField(thiz, fields.context); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(thiz, fields.context, retriever); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_setDataSource(JNIEnv *env, jobject thiz, jstring path) 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("setDataSource"); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!path) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", "Null pointer"); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *pathStr = env->GetStringUTFChars(path, NULL); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!pathStr) { // OutOfMemoryError exception already thrown 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't let somebody trick us in to reading some random block of memory 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strncmp("mem://", pathStr, 6) == 0) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid pathname"); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project process_media_retriever_call(env, retriever->setDataSource(pathStr), "java/lang/RuntimeException", "setDataSource failed"); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(path, pathStr); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("setDataSource"); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fileDescriptor) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd = getParcelFileDescriptorFD(env, fileDescriptor); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < 0 || length < 0 || fd < 0) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < 0) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("negative offset (%lld)", offset); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (length < 0) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("negative length (%lld)", length); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd < 0) { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("invalid file descriptor"); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed"); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_setMode(JNIEnv *env, jobject thiz, jint mode) 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("setMode"); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project process_media_retriever_call(env, retriever->setMode(mode), "java/lang/RuntimeException", "setMode failed"); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 166faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dongstatic jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option) 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 168faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong LOGV("getFrameAtTime: %lld us option: %d", timeUs, option); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Call native method to retrieve a video frame 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VideoFrame *videoFrame = NULL; 177faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameMemory != 0) { // cast the shared structure to a VideoFrame object 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project videoFrame = static_cast<VideoFrame *>(frameMemory->pointer()); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (videoFrame == NULL) { 182faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong LOGE("getFrameAtTime: videoFrame is a NULL pointer"); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1860e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong LOGV("Dimension = %dx%d and bytes = %d", 1870e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayWidth, 1880e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayHeight, 1890e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mSize); 1900e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 1910e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR 19253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jobject matrix = NULL; 19353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong if (videoFrame->mRotationAngle != 0) { 19453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong LOGD("Create a rotation matrix: %d degrees", videoFrame->mRotationAngle); 19553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jclass matrixClazz = env->FindClass("android/graphics/Matrix"); 19653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong if (matrixClazz == NULL) { 19753ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jniThrowException(env, "java/lang/RuntimeException", 19853ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "Can't find android/graphics/Matrix"); 19953ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong return NULL; 20053ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 20153ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jmethodID matrixConstructor = 20253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->GetMethodID(matrixClazz, "<init>", "()V"); 20353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong if (matrixConstructor == NULL) { 20453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jniThrowException(env, "java/lang/RuntimeException", 20553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "Can't find Matrix constructor"); 20653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong return NULL; 20753ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 20853ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong matrix = 20953ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->NewObject(matrixClazz, matrixConstructor); 21053ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong if (matrix == NULL) { 21153ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong LOGE("Could not create a Matrix object"); 21253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong return NULL; 21353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 21453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong 21553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong LOGV("Rotate the matrix: %d degrees", videoFrame->mRotationAngle); 21653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jmethodID setRotateMethod = 21753ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->GetMethodID(matrixClazz, "setRotate", "(F)V"); 21853ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong if (setRotateMethod == NULL) { 21953ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jniThrowException(env, "java/lang/RuntimeException", 22053ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "Can't find Matrix setRotate method"); 22153ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong return NULL; 22253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 22353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->CallVoidMethod(matrix, setRotateMethod, 1.0 * videoFrame->mRotationAngle); 22453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->DeleteLocalRef(matrixClazz); 22553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 22653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create a SkBitmap to hold the pixels 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkBitmap *bitmap = new SkBitmap(); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bitmap == NULL) { 230faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong LOGE("getFrameAtTime: cannot instantiate a SkBitmap object."); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bitmap->setConfig(SkBitmap::kRGB_565_Config, videoFrame->mDisplayWidth, videoFrame->mDisplayHeight); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!bitmap->allocPixels()) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete bitmap; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("failed to allocate pixel buffer"); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy((uint8_t*)bitmap->getPixels(), (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Since internally SkBitmap uses reference count to manage the reference to 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // its pixels, it is important that the pixels (along with SkBitmap) be 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // available after creating the Bitmap is returned to Java app. 24453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jobject jSrcBitmap = env->NewObject(fields.bitmapClazz, 24588b77412286115b158d906369b62515d773f21bcJames Dong fields.bitmapConstructor, (int) bitmap, NULL, true, NULL, -1); 24653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong 2470e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jobject jBitmap = env->CallStaticObjectMethod( 2480e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.bitmapClazz, 2490e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapRotationMethod, 25053ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jSrcBitmap, // source Bitmap 25153ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong 0, // x 25253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong 0, // y 25353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong videoFrame->mDisplayWidth, // width 25453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong videoFrame->mDisplayHeight, // height 25553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong matrix, // transform matrix 25653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong false); // filter 2570e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2580e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#else 2590e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2600e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jobject config = env->CallStaticObjectMethod( 2610e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.configClazz, 2620e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createConfigMethod, 2630e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkBitmap::kRGB_565_Config); 2640e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2650e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jobject jBitmap = env->CallStaticObjectMethod( 2660e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.bitmapClazz, 2670e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapMethod, 2680e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayWidth, 2690e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayHeight, 2700e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong config); 2710e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkBitmap *bitmap = 2720e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong (SkBitmap *) env->GetIntField(jBitmap, fields.nativeBitmap); 2730e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2740e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong bitmap->lockPixels(); 2750e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2760e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong memcpy((uint8_t*)bitmap->getPixels(), 2770e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize); 2780e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2790e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong bitmap->unlockPixels(); 2800e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2810e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (videoFrame->mRotationAngle != 0) { 2820e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkDevice device(*bitmap); 2830e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkCanvas canvas(&device); 2840e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong canvas.rotate((SkScalar) (videoFrame->mRotationAngle * 1.0)); 2850e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong canvas.drawBitmap(*bitmap, 0, 0); 2860e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 2870e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#endif 2880e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong LOGV("Return a new bitmap constructed with the rotation matrix"); 2890e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return jBitmap; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz) 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("extractAlbumArt"); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaAlbumArt* mediaAlbumArt = NULL; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<IMemory> albumArtMemory = retriever->extractAlbumArt(); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (albumArtMemory != 0) { // cast the shared structure to a MediaAlbumArt object 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer()); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mediaAlbumArt == NULL) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("extractAlbumArt: Call to extractAlbumArt failed."); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int len = mediaAlbumArt->mSize; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray array = env->NewByteArray(len); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!array) { // OutOfMemoryError exception has already been thrown. 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("extractAlbumArt: OutOfMemoryError is thrown."); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* bytes = env->GetByteArrayElements(array, NULL); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bytes != NULL) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(bytes, data, len); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(array, bytes, 0); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to delete mediaAlbumArt here 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return array; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject android_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jint keyCode) 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("extractMetadata"); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* value = retriever->extractMetadata(keyCode); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!value) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("extractMetadata: Metadata is not found"); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("extractMetadata: value (%s) for keyCode(%d)", value, keyCode); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return env->NewStringUTF(value); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz) 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("release"); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock lock(sLock); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete retriever; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRetriever(env, thiz, 0); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz) 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("native_finalize"); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_media_MediaMetadataRetriever_release(env, thiz); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3604935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// This function gets a field ID, which in turn causes class initialization. 3614935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// It is called from a static block in MediaMetadataRetriever, which won't run until the 3624935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// first time an instance of this class is used. 3634935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissenstatic void android_media_MediaMetadataRetriever_native_init(JNIEnv *env) 3644935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen{ 3654935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jclass clazz = env->FindClass(kClassPathName); 3664935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (clazz == NULL) { 3674935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaMetadataRetriever"); 3684935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 3694935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 3704935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 3714935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 3724935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (fields.context == NULL) { 3734935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaMetadataRetriever.mNativeContext"); 3744935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 3754935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 3764935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 3774935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen fields.bitmapClazz = env->FindClass("android/graphics/Bitmap"); 3784935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (fields.bitmapClazz == NULL) { 3794935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap"); 3804935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 3814935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 3820e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR 38388b77412286115b158d906369b62515d773f21bcJames Dong fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(I[BZ[BI)V"); 3844935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (fields.bitmapConstructor == NULL) { 3854935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor"); 3864935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 3874935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 3880e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapRotationMethod = 38953ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong env->GetStaticMethodID(fields.bitmapClazz, "createBitmap", 39053ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)" 39153ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "Landroid/graphics/Bitmap;"); 3920e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.createBitmapRotationMethod == NULL) { 39353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jniThrowException(env, "java/lang/RuntimeException", 39453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong "Can't find Bitmap.createBitmap method"); 39553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong return; 39653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong } 3970e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#else 3980e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapMethod = 3990e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong env->GetStaticMethodID(fields.bitmapClazz, "createBitmap", 4000e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "(IILandroid/graphics/Bitmap$Config;)" 4010e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Landroid/graphics/Bitmap;"); 4020e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.createBitmapMethod == NULL) { 4030e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jniThrowException(env, "java/lang/RuntimeException", 4040e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Can't find Bitmap.createBitmap(int, int, Config) method"); 4050e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4060e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4070e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "I"); 4080e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.nativeBitmap == NULL) { 4090e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jniThrowException(env, "java/lang/RuntimeException", 4100e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Can't find Bitmap.mNativeBitmap field"); 4110e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4120e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 4130e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.configClazz = env->FindClass("android/graphics/Bitmap$Config"); 4140e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.configClazz == NULL) { 4150e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jniThrowException(env, "java/lang/RuntimeException", 4160e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Can't find Bitmap$Config class"); 4170e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4180e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4190e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createConfigMethod = 4200e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong env->GetStaticMethodID(fields.configClazz, "nativeToConfig", 4210e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "(I)Landroid/graphics/Bitmap$Config;"); 4220e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.createConfigMethod == NULL) { 4230e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jniThrowException(env, "java/lang/RuntimeException", 4240e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Can't find Bitmap$Config.nativeToConfig(int) method"); 4250e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4260e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4270e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong#endif 4284935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen} 4294935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz) 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("native_setup"); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = new MediaMetadataRetriever(); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRetriever(env, thiz, (int)retriever); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// JNI mapping between Java methods and native methods 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod nativeMethods[] = { 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource}, 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setMode", "(I)V", (void *)android_media_MediaMetadataRetriever_setMode}, 446faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata}, 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"extractAlbumArt", "()[B", (void *)android_media_MediaMetadataRetriever_extractAlbumArt}, 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"release", "()V", (void *)android_media_MediaMetadataRetriever_release}, 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize}, 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup}, 4524935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen {"native_init", "()V", (void *)android_media_MediaMetadataRetriever_native_init}, 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4554935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// This function only registers the native methods, and is called from 4564935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// JNI_OnLoad in android_media_MediaPlayer.cpp 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_MediaMetadataRetriever(JNIEnv *env) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods 4604935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen (env, kClassPathName, nativeMethods, NELEM(nativeMethods)); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 462