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> 24eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkBitmap.h> 25d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber#include <media/IMediaHTTPService.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/mediametadataretriever.h> 2795d3f86fed2cab71a446f2b9ab38458ee91e3b65Elliott Hughes#include <media/mediascanner.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/media/VideoFrame.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h" 3379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#include "android_media_Utils.h" 34d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber#include "android_util_Binder.h" 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct fields_t { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID context; 41c371a02e7cf504e9a926ca29c33e63b658c2cef7James Dong jclass bitmapClazz; // Must be a global ref 420e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jfieldID nativeBitmap; 4353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong jmethodID createBitmapMethod; 449f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong jmethodID createScaledBitmapMethod; 45c371a02e7cf504e9a926ca29c33e63b658c2cef7James Dong jclass configClazz; // Must be a global ref 460e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jmethodID createConfigMethod; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic fields_t fields; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic Mutex sLock; 514935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissenstatic const char* const kClassPathName = "android/media/MediaMetadataRetriever"; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message) 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (opStatus == (status_t) INVALID_OPERATION) { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", NULL); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (opStatus != (status_t) OK) { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strlen(message) > 230) { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the message is too long, don't bother displaying the status code. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException( env, exception, message); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msg[256]; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Append the status code to the message. 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(msg, "%s: status = 0x%X", message, opStatus); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException( env, exception, msg); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz) 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since it is called internally by other methods that are protected 73075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetLongField(thiz, fields.context); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retriever; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 77075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic void setRetriever(JNIEnv* env, jobject thiz, MediaMetadataRetriever* retriever) 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since it is called internally by other methods that are protected 80075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetLongField(thiz, fields.context); 81075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, fields.context, (jlong) retriever); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 845b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huberstatic void 855b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huberandroid_media_MediaMetadataRetriever_setDataSourceAndHeaders( 86d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path, 8717524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong jobjectArray keys, jobjectArray values) { 8817524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong 8971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("setDataSource"); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 925b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber jniThrowException( 935b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber env, 945b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber "java/lang/IllegalStateException", "No retriever available"); 955b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 985b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!path) { 1005b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber jniThrowException( 1015b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber env, "java/lang/IllegalArgumentException", "Null pointer"); 1025b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1065b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber const char *tmp = env->GetStringUTFChars(path, NULL); 1075bb357f4ccdb573efbe1476a7f20e82f454b3a93Andreas Huber if (!tmp) { // OutOfMemoryError exception already thrown 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1115bb357f4ccdb573efbe1476a7f20e82f454b3a93Andreas Huber String8 pathStr(tmp); 1125b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber env->ReleaseStringUTFChars(path, tmp); 1135b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber tmp = NULL; 1145b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't let somebody trick us in to reading some random block of memory 1165b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber if (strncmp("mem://", pathStr.string(), 6) == 0) { 1175b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber jniThrowException( 1185b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber env, "java/lang/IllegalArgumentException", "Invalid pathname"); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1225b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber // We build a similar KeyedVector out of it. 1235b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber KeyedVector<String8, String8> headersVector; 12479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong if (!ConvertKeyValueArraysToKeyedVector( 12579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong env, keys, values, &headersVector)) { 12679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong return; 1275b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber } 128d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber 129d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber sp<IMediaHTTPService> httpService; 130d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber if (httpServiceBinderObj != NULL) { 131d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj); 132d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber httpService = interface_cast<IMediaHTTPService>(binder); 133d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber } 134d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber 1355b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber process_media_retriever_call( 1365b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber env, 1375b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber retriever->setDataSource( 138d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber httpService, 139d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber pathStr.string(), 140d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber headersVector.size() > 0 ? &headersVector : NULL), 1415b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 1425b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber "java/lang/RuntimeException", 1435b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber "setDataSource failed"); 1445b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber} 1455b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 14871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("setDataSource"); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fileDescriptor) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 158a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < 0 || length < 0 || fd < 0) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < 0) { 161075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat ALOGE("negative offset (%lld)", (long long)offset); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (length < 0) { 164075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat ALOGE("negative length (%lld)", (long long)length); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd < 0) { 1673762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid file descriptor"); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed"); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 175ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirotemplate<typename T> 176ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirostatic void rotate0(T* dst, const T* src, size_t width, size_t height) 177ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro{ 178ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro memcpy(dst, src, width * height * sizeof(T)); 179ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro} 180ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 181ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirotemplate<typename T> 182ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirostatic void rotate90(T* dst, const T* src, size_t width, size_t height) 183ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro{ 184ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t i = 0; i < height; ++i) { 185ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t j = 0; j < width; ++j) { 186ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro dst[j * height + height - 1 - i] = src[i * width + j]; 187ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 188ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 189ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro} 190ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 191ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirotemplate<typename T> 192ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirostatic void rotate180(T* dst, const T* src, size_t width, size_t height) 193ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro{ 194ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t i = 0; i < height; ++i) { 195ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t j = 0; j < width; ++j) { 196ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro dst[(height - 1 - i) * width + width - 1 - j] = src[i * width + j]; 197ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 198ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 199ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro} 200ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 201ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirotemplate<typename T> 202ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirostatic void rotate270(T* dst, const T* src, size_t width, size_t height) 203ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro{ 204ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t i = 0; i < height; ++i) { 205ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro for (size_t j = 0; j < width; ++j) { 206ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro dst[(width - 1 - j) * height + i] = src[i * width + j]; 207ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 208ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 209ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro} 210ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 211ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirotemplate<typename T> 212ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapirostatic void rotate(T *dst, const T *src, size_t width, size_t height, int angle) 213ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro{ 214ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro switch (angle) { 215ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro case 0: 216ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro rotate0(dst, src, width, height); 217ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro break; 218ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro case 90: 219ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro rotate90(dst, src, width, height); 220ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro break; 221ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro case 180: 222ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro rotate180(dst, src, width, height); 223ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro break; 224ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro case 270: 225ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro rotate270(dst, src, width, height); 226ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro break; 227ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 228ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro} 229ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 230faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dongstatic jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option) 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 23271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Call native method to retrieve a video frame 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VideoFrame *videoFrame = NULL; 241faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameMemory != 0) { // cast the shared structure to a VideoFrame object 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project videoFrame = static_cast<VideoFrame *>(frameMemory->pointer()); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (videoFrame == NULL) { 2463762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("getFrameAtTime: videoFrame is a NULL pointer"); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Dimension = %dx%d and bytes = %d", 2510e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayWidth, 2520e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mDisplayHeight, 2530e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong videoFrame->mSize); 2540e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2550e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jobject config = env->CallStaticObjectMethod( 2560e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.configClazz, 2570e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createConfigMethod, 2580e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkBitmap::kRGB_565_Config); 2590e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 26058fad0bf141109f1aed820f4d57985c116e05b61Ashok Bhat uint32_t width, height; 2619f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong bool swapWidthAndHeight = false; 262ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) { 2639f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong width = videoFrame->mHeight; 2649f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong height = videoFrame->mWidth; 2659f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong swapWidthAndHeight = true; 266ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } else { 2679f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong width = videoFrame->mWidth; 2689f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong height = videoFrame->mHeight; 269ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro } 270ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 2710e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong jobject jBitmap = env->CallStaticObjectMethod( 2720e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.bitmapClazz, 2730e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapMethod, 274ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro width, 275ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro height, 2760e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong config); 277c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao if (jBitmap == NULL) { 278c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao if (env->ExceptionCheck()) { 279c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao env->ExceptionClear(); 280c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao } 281c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao ALOGE("getFrameAtTime: create Bitmap failed!"); 282c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao return NULL; 283c847a4835b2233d28f6479deeed0592d267ee7bdwang, biao } 284ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro 2850e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong SkBitmap *bitmap = 28636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap); 2870e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2880e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong bitmap->lockPixels(); 289ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro rotate((uint16_t*)bitmap->getPixels(), 290ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)), 2919f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong videoFrame->mWidth, 2929f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong videoFrame->mHeight, 293ae12a50a35c0d8425430d0e934c022ecb9cd4936Carl Shapiro videoFrame->mRotationAngle); 2940e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong bitmap->unlockPixels(); 2950e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 2969f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong if (videoFrame->mDisplayWidth != videoFrame->mWidth || 2979f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong videoFrame->mDisplayHeight != videoFrame->mHeight) { 29858fad0bf141109f1aed820f4d57985c116e05b61Ashok Bhat uint32_t displayWidth = videoFrame->mDisplayWidth; 29958fad0bf141109f1aed820f4d57985c116e05b61Ashok Bhat uint32_t displayHeight = videoFrame->mDisplayHeight; 3009f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong if (swapWidthAndHeight) { 3019f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong displayWidth = videoFrame->mDisplayHeight; 3029f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong displayHeight = videoFrame->mDisplayWidth; 3039f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong } 30471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("Bitmap dimension is scaled from %dx%d to %dx%d", 3059f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong width, height, displayWidth, displayHeight); 3069f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong jobject scaledBitmap = env->CallStaticObjectMethod(fields.bitmapClazz, 3079f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong fields.createScaledBitmapMethod, 3089f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong jBitmap, 3099f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong displayWidth, 3109f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong displayHeight, 3119f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong true); 3129f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong return scaledBitmap; 3139f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong } 3149f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong 3150e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return jBitmap; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 318df9b349b960fff95dff4fcf8b2661899e33059daJames Dongstatic jbyteArray android_media_MediaMetadataRetriever_getEmbeddedPicture( 319df9b349b960fff95dff4fcf8b2661899e33059daJames Dong JNIEnv *env, jobject thiz, jint pictureType) 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 32171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("getEmbeddedPicture: %d", pictureType); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaAlbumArt* mediaAlbumArt = NULL; 328df9b349b960fff95dff4fcf8b2661899e33059daJames Dong 329df9b349b960fff95dff4fcf8b2661899e33059daJames Dong // FIXME: 330df9b349b960fff95dff4fcf8b2661899e33059daJames Dong // Use pictureType to retrieve the intended embedded picture and also change 331df9b349b960fff95dff4fcf8b2661899e33059daJames Dong // the method name to getEmbeddedPicture(). 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<IMemory> albumArtMemory = retriever->extractAlbumArt(); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (albumArtMemory != 0) { // cast the shared structure to a MediaAlbumArt object 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer()); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mediaAlbumArt == NULL) { 3373762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("getEmbeddedPicture: Call to getEmbeddedPicture failed."); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34195d3f86fed2cab71a446f2b9ab38458ee91e3b65Elliott Hughes jbyteArray array = env->NewByteArray(mediaAlbumArt->size()); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!array) { // OutOfMemoryError exception has already been thrown. 3433762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("getEmbeddedPicture: OutOfMemoryError is thrown."); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 34595d3f86fed2cab71a446f2b9ab38458ee91e3b65Elliott Hughes const jbyte* data = 34695d3f86fed2cab71a446f2b9ab38458ee91e3b65Elliott Hughes reinterpret_cast<const jbyte*>(mediaAlbumArt->data()); 34795d3f86fed2cab71a446f2b9ab38458ee91e3b65Elliott Hughes env->SetByteArrayRegion(array, 0, mediaAlbumArt->size(), data); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to delete mediaAlbumArt here 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return array; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject android_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jint keyCode) 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 35671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("extractMetadata"); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "No retriever available"); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* value = retriever->extractMetadata(keyCode); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!value) { 36471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("extractMetadata: Metadata is not found"); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("extractMetadata: value (%s) for keyCode(%d)", value, keyCode); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return env->NewStringUTF(value); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz) 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 37371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("release"); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Mutex::Autolock lock(sLock); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = getRetriever(env, thiz); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete retriever; 377075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat setRetriever(env, thiz, (MediaMetadataRetriever*) 0); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz) 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 38271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("native_finalize"); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_media_MediaMetadataRetriever_release(env, thiz); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3874935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// This function gets a field ID, which in turn causes class initialization. 3884935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// It is called from a static block in MediaMetadataRetriever, which won't run until the 3894935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// first time an instance of this class is used. 3904935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissenstatic void android_media_MediaMetadataRetriever_native_init(JNIEnv *env) 3914935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen{ 3924935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen jclass clazz = env->FindClass(kClassPathName); 3934935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (clazz == NULL) { 3944935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 3954935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 3964935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 397075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat fields.context = env->GetFieldID(clazz, "mNativeContext", "J"); 3984935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (fields.context == NULL) { 3994935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 4004935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 4014935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 40246e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom jclass bitmapClazz = env->FindClass("android/graphics/Bitmap"); 40346e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom if (bitmapClazz == NULL) { 40446e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom return; 40546e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom } 40646e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom fields.bitmapClazz = (jclass) env->NewGlobalRef(bitmapClazz); 4074935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen if (fields.bitmapClazz == NULL) { 4084935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen return; 4094935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen } 4100e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createBitmapMethod = 4110e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong env->GetStaticMethodID(fields.bitmapClazz, "createBitmap", 4120e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "(IILandroid/graphics/Bitmap$Config;)" 4130e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "Landroid/graphics/Bitmap;"); 4140e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.createBitmapMethod == NULL) { 4150e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4160e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4179f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong fields.createScaledBitmapMethod = 4189f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong env->GetStaticMethodID(fields.bitmapClazz, "createScaledBitmap", 4199f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong "(Landroid/graphics/Bitmap;IIZ)" 4209f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong "Landroid/graphics/Bitmap;"); 4219f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong if (fields.createScaledBitmapMethod == NULL) { 4229f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong return; 4239f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong } 42436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "J"); 4250e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.nativeBitmap == NULL) { 42646e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom return; 4270e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4280e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong 42946e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom jclass configClazz = env->FindClass("android/graphics/Bitmap$Config"); 43046e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom if (configClazz == NULL) { 43146e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom return; 43246e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom } 43346e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom fields.configClazz = (jclass) env->NewGlobalRef(configClazz); 4340e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.configClazz == NULL) { 4350e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4360e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4370e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong fields.createConfigMethod = 4380e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong env->GetStaticMethodID(fields.configClazz, "nativeToConfig", 4390e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong "(I)Landroid/graphics/Bitmap$Config;"); 4400e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong if (fields.createConfigMethod == NULL) { 4410e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong return; 4420e4b535b439f2c8bd4f7ba820f81bf74336bae76James Dong } 4434935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen} 4444935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz) 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 44771f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("native_setup"); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaMetadataRetriever* retriever = new MediaMetadataRetriever(); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retriever == 0) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 453075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat setRetriever(env, thiz, retriever); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// JNI mapping between Java methods and native methods 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod nativeMethods[] = { 45817524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong { 45917524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong "_setDataSource", 460d2506a506303ed94fd1991cf986b825b870a67c5Andreas Huber "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", 46117524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders 46217524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong }, 46317524dc0d296146c8ffb3f692dc8ab05fee5b1e0James Dong 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD}, 465faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime}, 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata}, 467df9b349b960fff95dff4fcf8b2661899e33059daJames Dong {"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture}, 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"release", "()V", (void *)android_media_MediaMetadataRetriever_release}, 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize}, 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup}, 4714935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen {"native_init", "()V", (void *)android_media_MediaMetadataRetriever_native_init}, 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4744935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// This function only registers the native methods, and is called from 4754935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen// JNI_OnLoad in android_media_MediaPlayer.cpp 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_MediaMetadataRetriever(JNIEnv *env) 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods 4794935d05eaa306cef88cf0ab13eca386f270409ecMarco Nelissen (env, kClassPathName, nativeMethods, NELEM(nativeMethods)); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 481