blob: f17209f4cf5ac2e5aa00e813f11f33c535d7bc1e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaMetadataRetrieverJNI"
20
21#include <assert.h>
22#include <utils/Log.h>
23#include <utils/threads.h>
24#include <core/SkBitmap.h>
Andreas Huberd2506a52014-01-29 10:32:46 -080025#include <media/IMediaHTTPService.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include <media/mediametadataretriever.h>
27#include <private/media/VideoFrame.h>
28
29#include "jni.h"
30#include "JNIHelp.h"
31#include "android_runtime/AndroidRuntime.h"
James Dong79f407c2011-05-05 12:50:04 -070032#include "android_media_Utils.h"
Andreas Huberd2506a52014-01-29 10:32:46 -080033#include "android_util_Binder.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35
36using namespace android;
37
38struct fields_t {
39 jfieldID context;
James Dongc371a022011-04-06 12:16:07 -070040 jclass bitmapClazz; // Must be a global ref
James Dong0e4b5352010-12-19 13:05:33 -080041 jfieldID nativeBitmap;
James Dong53ebc722010-11-08 16:04:27 -080042 jmethodID createBitmapMethod;
James Dong9f2cde32011-03-18 17:55:06 -070043 jmethodID createScaledBitmapMethod;
James Dongc371a022011-04-06 12:16:07 -070044 jclass configClazz; // Must be a global ref
James Dong0e4b5352010-12-19 13:05:33 -080045 jmethodID createConfigMethod;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046};
47
48static fields_t fields;
49static Mutex sLock;
Marco Nelissen4935d052009-08-03 11:12:58 -070050static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
52static void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message)
53{
54 if (opStatus == (status_t) INVALID_OPERATION) {
55 jniThrowException(env, "java/lang/IllegalStateException", NULL);
56 } else if (opStatus != (status_t) OK) {
57 if (strlen(message) > 230) {
58 // If the message is too long, don't bother displaying the status code.
59 jniThrowException( env, exception, message);
60 } else {
61 char msg[256];
62 // Append the status code to the message.
63 sprintf(msg, "%s: status = 0x%X", message, opStatus);
64 jniThrowException( env, exception, msg);
65 }
66 }
67}
68
69static MediaMetadataRetriever* getRetriever(JNIEnv* env, jobject thiz)
70{
71 // No lock is needed, since it is called internally by other methods that are protected
Ashok Bhat075e9a12014-01-06 13:45:09 +000072 MediaMetadataRetriever* retriever = (MediaMetadataRetriever*) env->GetLongField(thiz, fields.context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 return retriever;
74}
75
Ashok Bhat075e9a12014-01-06 13:45:09 +000076static void setRetriever(JNIEnv* env, jobject thiz, MediaMetadataRetriever* retriever)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077{
78 // No lock is needed, since it is called internally by other methods that are protected
Ashok Bhat075e9a12014-01-06 13:45:09 +000079 MediaMetadataRetriever *old = (MediaMetadataRetriever*) env->GetLongField(thiz, fields.context);
80 env->SetLongField(thiz, fields.context, (jlong) retriever);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081}
82
Andreas Huber5b7ced62011-03-21 10:25:44 -070083static void
84android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
Andreas Huberd2506a52014-01-29 10:32:46 -080085 JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
James Dong17524dc2011-05-04 13:41:58 -070086 jobjectArray keys, jobjectArray values) {
87
Steve Block71f2cf12011-10-20 11:56:00 +010088 ALOGV("setDataSource");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
90 if (retriever == 0) {
Andreas Huber5b7ced62011-03-21 10:25:44 -070091 jniThrowException(
92 env,
93 "java/lang/IllegalStateException", "No retriever available");
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 return;
96 }
97
Andreas Huber5b7ced62011-03-21 10:25:44 -070098 if (!path) {
99 jniThrowException(
100 env, "java/lang/IllegalArgumentException", "Null pointer");
101
102 return;
103 }
104
105 const char *tmp = env->GetStringUTFChars(path, NULL);
Andreas Huber5bb357f2011-03-21 11:55:01 -0700106 if (!tmp) { // OutOfMemoryError exception already thrown
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 return;
108 }
109
Andreas Huber5bb357f2011-03-21 11:55:01 -0700110 String8 pathStr(tmp);
Andreas Huber5b7ced62011-03-21 10:25:44 -0700111 env->ReleaseStringUTFChars(path, tmp);
112 tmp = NULL;
113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 // Don't let somebody trick us in to reading some random block of memory
Andreas Huber5b7ced62011-03-21 10:25:44 -0700115 if (strncmp("mem://", pathStr.string(), 6) == 0) {
116 jniThrowException(
117 env, "java/lang/IllegalArgumentException", "Invalid pathname");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 return;
119 }
120
Andreas Huber5b7ced62011-03-21 10:25:44 -0700121 // We build a similar KeyedVector out of it.
122 KeyedVector<String8, String8> headersVector;
James Dong79f407c2011-05-05 12:50:04 -0700123 if (!ConvertKeyValueArraysToKeyedVector(
124 env, keys, values, &headersVector)) {
125 return;
Andreas Huber5b7ced62011-03-21 10:25:44 -0700126 }
Andreas Huberd2506a52014-01-29 10:32:46 -0800127
128 sp<IMediaHTTPService> httpService;
129 if (httpServiceBinderObj != NULL) {
130 sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
131 httpService = interface_cast<IMediaHTTPService>(binder);
132 }
133
Andreas Huber5b7ced62011-03-21 10:25:44 -0700134 process_media_retriever_call(
135 env,
136 retriever->setDataSource(
Andreas Huberd2506a52014-01-29 10:32:46 -0800137 httpService,
138 pathStr.string(),
139 headersVector.size() > 0 ? &headersVector : NULL),
Andreas Huber5b7ced62011-03-21 10:25:44 -0700140
141 "java/lang/RuntimeException",
142 "setDataSource failed");
143}
144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
146{
Steve Block71f2cf12011-10-20 11:56:00 +0100147 ALOGV("setDataSource");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
149 if (retriever == 0) {
150 jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
151 return;
152 }
153 if (!fileDescriptor) {
154 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
155 return;
156 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700157 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 if (offset < 0 || length < 0 || fd < 0) {
159 if (offset < 0) {
Ashok Bhat075e9a12014-01-06 13:45:09 +0000160 ALOGE("negative offset (%lld)", (long long)offset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 }
162 if (length < 0) {
Ashok Bhat075e9a12014-01-06 13:45:09 +0000163 ALOGE("negative length (%lld)", (long long)length);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 }
165 if (fd < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000166 ALOGE("invalid file descriptor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 }
168 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
169 return;
170 }
171 process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
172}
173
Carl Shapiroae12a502011-01-20 23:13:09 -0800174template<typename T>
175static void rotate0(T* dst, const T* src, size_t width, size_t height)
176{
177 memcpy(dst, src, width * height * sizeof(T));
178}
179
180template<typename T>
181static void rotate90(T* dst, const T* src, size_t width, size_t height)
182{
183 for (size_t i = 0; i < height; ++i) {
184 for (size_t j = 0; j < width; ++j) {
185 dst[j * height + height - 1 - i] = src[i * width + j];
186 }
187 }
188}
189
190template<typename T>
191static void rotate180(T* dst, const T* src, size_t width, size_t height)
192{
193 for (size_t i = 0; i < height; ++i) {
194 for (size_t j = 0; j < width; ++j) {
195 dst[(height - 1 - i) * width + width - 1 - j] = src[i * width + j];
196 }
197 }
198}
199
200template<typename T>
201static void rotate270(T* dst, const T* src, size_t width, size_t height)
202{
203 for (size_t i = 0; i < height; ++i) {
204 for (size_t j = 0; j < width; ++j) {
205 dst[(width - 1 - j) * height + i] = src[i * width + j];
206 }
207 }
208}
209
210template<typename T>
211static void rotate(T *dst, const T *src, size_t width, size_t height, int angle)
212{
213 switch (angle) {
214 case 0:
215 rotate0(dst, src, width, height);
216 break;
217 case 90:
218 rotate90(dst, src, width, height);
219 break;
220 case 180:
221 rotate180(dst, src, width, height);
222 break;
223 case 270:
224 rotate270(dst, src, width, height);
225 break;
226 }
227}
228
James Dongfaf09ba2010-12-02 17:42:08 -0800229static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230{
Steve Block71f2cf12011-10-20 11:56:00 +0100231 ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
233 if (retriever == 0) {
234 jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
235 return NULL;
236 }
237
238 // Call native method to retrieve a video frame
239 VideoFrame *videoFrame = NULL;
James Dongfaf09ba2010-12-02 17:42:08 -0800240 sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 if (frameMemory != 0) { // cast the shared structure to a VideoFrame object
242 videoFrame = static_cast<VideoFrame *>(frameMemory->pointer());
243 }
244 if (videoFrame == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000245 ALOGE("getFrameAtTime: videoFrame is a NULL pointer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 return NULL;
247 }
248
Steve Block71f2cf12011-10-20 11:56:00 +0100249 ALOGV("Dimension = %dx%d and bytes = %d",
James Dong0e4b5352010-12-19 13:05:33 -0800250 videoFrame->mDisplayWidth,
251 videoFrame->mDisplayHeight,
252 videoFrame->mSize);
253
James Dong0e4b5352010-12-19 13:05:33 -0800254 jobject config = env->CallStaticObjectMethod(
255 fields.configClazz,
256 fields.createConfigMethod,
257 SkBitmap::kRGB_565_Config);
258
Carl Shapiroae12a502011-01-20 23:13:09 -0800259 size_t width, height;
James Dong9f2cde32011-03-18 17:55:06 -0700260 bool swapWidthAndHeight = false;
Carl Shapiroae12a502011-01-20 23:13:09 -0800261 if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
James Dong9f2cde32011-03-18 17:55:06 -0700262 width = videoFrame->mHeight;
263 height = videoFrame->mWidth;
264 swapWidthAndHeight = true;
Carl Shapiroae12a502011-01-20 23:13:09 -0800265 } else {
James Dong9f2cde32011-03-18 17:55:06 -0700266 width = videoFrame->mWidth;
267 height = videoFrame->mHeight;
Carl Shapiroae12a502011-01-20 23:13:09 -0800268 }
269
James Dong0e4b5352010-12-19 13:05:33 -0800270 jobject jBitmap = env->CallStaticObjectMethod(
271 fields.bitmapClazz,
272 fields.createBitmapMethod,
Carl Shapiroae12a502011-01-20 23:13:09 -0800273 width,
274 height,
James Dong0e4b5352010-12-19 13:05:33 -0800275 config);
Carl Shapiroae12a502011-01-20 23:13:09 -0800276
James Dong0e4b5352010-12-19 13:05:33 -0800277 SkBitmap *bitmap =
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000278 (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap);
James Dong0e4b5352010-12-19 13:05:33 -0800279
280 bitmap->lockPixels();
Carl Shapiroae12a502011-01-20 23:13:09 -0800281 rotate((uint16_t*)bitmap->getPixels(),
282 (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
James Dong9f2cde32011-03-18 17:55:06 -0700283 videoFrame->mWidth,
284 videoFrame->mHeight,
Carl Shapiroae12a502011-01-20 23:13:09 -0800285 videoFrame->mRotationAngle);
James Dong0e4b5352010-12-19 13:05:33 -0800286 bitmap->unlockPixels();
287
James Dong9f2cde32011-03-18 17:55:06 -0700288 if (videoFrame->mDisplayWidth != videoFrame->mWidth ||
289 videoFrame->mDisplayHeight != videoFrame->mHeight) {
290 size_t displayWidth = videoFrame->mDisplayWidth;
291 size_t displayHeight = videoFrame->mDisplayHeight;
292 if (swapWidthAndHeight) {
293 displayWidth = videoFrame->mDisplayHeight;
294 displayHeight = videoFrame->mDisplayWidth;
295 }
Steve Block71f2cf12011-10-20 11:56:00 +0100296 ALOGV("Bitmap dimension is scaled from %dx%d to %dx%d",
James Dong9f2cde32011-03-18 17:55:06 -0700297 width, height, displayWidth, displayHeight);
298 jobject scaledBitmap = env->CallStaticObjectMethod(fields.bitmapClazz,
299 fields.createScaledBitmapMethod,
300 jBitmap,
301 displayWidth,
302 displayHeight,
303 true);
304 return scaledBitmap;
305 }
306
James Dong0e4b5352010-12-19 13:05:33 -0800307 return jBitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308}
309
James Dongdf9b3492011-01-04 15:03:48 -0800310static jbyteArray android_media_MediaMetadataRetriever_getEmbeddedPicture(
311 JNIEnv *env, jobject thiz, jint pictureType)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312{
Steve Block71f2cf12011-10-20 11:56:00 +0100313 ALOGV("getEmbeddedPicture: %d", pictureType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
315 if (retriever == 0) {
316 jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
317 return NULL;
318 }
319 MediaAlbumArt* mediaAlbumArt = NULL;
James Dongdf9b3492011-01-04 15:03:48 -0800320
321 // FIXME:
322 // Use pictureType to retrieve the intended embedded picture and also change
323 // the method name to getEmbeddedPicture().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 sp<IMemory> albumArtMemory = retriever->extractAlbumArt();
325 if (albumArtMemory != 0) { // cast the shared structure to a MediaAlbumArt object
326 mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer());
327 }
328 if (mediaAlbumArt == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000329 ALOGE("getEmbeddedPicture: Call to getEmbeddedPicture failed.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 return NULL;
331 }
332
333 unsigned int len = mediaAlbumArt->mSize;
334 char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt);
335 jbyteArray array = env->NewByteArray(len);
336 if (!array) { // OutOfMemoryError exception has already been thrown.
Steve Block3762c312012-01-06 19:20:56 +0000337 ALOGE("getEmbeddedPicture: OutOfMemoryError is thrown.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 } else {
339 jbyte* bytes = env->GetByteArrayElements(array, NULL);
340 if (bytes != NULL) {
341 memcpy(bytes, data, len);
342 env->ReleaseByteArrayElements(array, bytes, 0);
343 }
344 }
345
346 // No need to delete mediaAlbumArt here
347 return array;
348}
349
350static jobject android_media_MediaMetadataRetriever_extractMetadata(JNIEnv *env, jobject thiz, jint keyCode)
351{
Steve Block71f2cf12011-10-20 11:56:00 +0100352 ALOGV("extractMetadata");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
354 if (retriever == 0) {
355 jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
356 return NULL;
357 }
358 const char* value = retriever->extractMetadata(keyCode);
359 if (!value) {
Steve Block71f2cf12011-10-20 11:56:00 +0100360 ALOGV("extractMetadata: Metadata is not found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 return NULL;
362 }
Steve Block71f2cf12011-10-20 11:56:00 +0100363 ALOGV("extractMetadata: value (%s) for keyCode(%d)", value, keyCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 return env->NewStringUTF(value);
365}
366
367static void android_media_MediaMetadataRetriever_release(JNIEnv *env, jobject thiz)
368{
Steve Block71f2cf12011-10-20 11:56:00 +0100369 ALOGV("release");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 Mutex::Autolock lock(sLock);
371 MediaMetadataRetriever* retriever = getRetriever(env, thiz);
372 delete retriever;
Ashok Bhat075e9a12014-01-06 13:45:09 +0000373 setRetriever(env, thiz, (MediaMetadataRetriever*) 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374}
375
376static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz)
377{
Steve Block71f2cf12011-10-20 11:56:00 +0100378 ALOGV("native_finalize");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected
380 android_media_MediaMetadataRetriever_release(env, thiz);
381}
382
Marco Nelissen4935d052009-08-03 11:12:58 -0700383// This function gets a field ID, which in turn causes class initialization.
384// It is called from a static block in MediaMetadataRetriever, which won't run until the
385// first time an instance of this class is used.
386static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
387{
388 jclass clazz = env->FindClass(kClassPathName);
389 if (clazz == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700390 return;
391 }
392
Ashok Bhat075e9a12014-01-06 13:45:09 +0000393 fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
Marco Nelissen4935d052009-08-03 11:12:58 -0700394 if (fields.context == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700395 return;
396 }
397
Brian Carlstrom46e18c112011-04-05 22:44:45 -0700398 jclass bitmapClazz = env->FindClass("android/graphics/Bitmap");
399 if (bitmapClazz == NULL) {
400 return;
401 }
402 fields.bitmapClazz = (jclass) env->NewGlobalRef(bitmapClazz);
Marco Nelissen4935d052009-08-03 11:12:58 -0700403 if (fields.bitmapClazz == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700404 return;
405 }
James Dong0e4b5352010-12-19 13:05:33 -0800406 fields.createBitmapMethod =
407 env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
408 "(IILandroid/graphics/Bitmap$Config;)"
409 "Landroid/graphics/Bitmap;");
410 if (fields.createBitmapMethod == NULL) {
James Dong0e4b5352010-12-19 13:05:33 -0800411 return;
412 }
James Dong9f2cde32011-03-18 17:55:06 -0700413 fields.createScaledBitmapMethod =
414 env->GetStaticMethodID(fields.bitmapClazz, "createScaledBitmap",
415 "(Landroid/graphics/Bitmap;IIZ)"
416 "Landroid/graphics/Bitmap;");
417 if (fields.createScaledBitmapMethod == NULL) {
James Dong9f2cde32011-03-18 17:55:06 -0700418 return;
419 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000420 fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "J");
James Dong0e4b5352010-12-19 13:05:33 -0800421 if (fields.nativeBitmap == NULL) {
Brian Carlstrom46e18c112011-04-05 22:44:45 -0700422 return;
James Dong0e4b5352010-12-19 13:05:33 -0800423 }
424
Brian Carlstrom46e18c112011-04-05 22:44:45 -0700425 jclass configClazz = env->FindClass("android/graphics/Bitmap$Config");
426 if (configClazz == NULL) {
427 return;
428 }
429 fields.configClazz = (jclass) env->NewGlobalRef(configClazz);
James Dong0e4b5352010-12-19 13:05:33 -0800430 if (fields.configClazz == NULL) {
James Dong0e4b5352010-12-19 13:05:33 -0800431 return;
432 }
433 fields.createConfigMethod =
434 env->GetStaticMethodID(fields.configClazz, "nativeToConfig",
435 "(I)Landroid/graphics/Bitmap$Config;");
436 if (fields.createConfigMethod == NULL) {
James Dong0e4b5352010-12-19 13:05:33 -0800437 return;
438 }
Marco Nelissen4935d052009-08-03 11:12:58 -0700439}
440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
442{
Steve Block71f2cf12011-10-20 11:56:00 +0100443 ALOGV("native_setup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 MediaMetadataRetriever* retriever = new MediaMetadataRetriever();
445 if (retriever == 0) {
446 jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
447 return;
448 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000449 setRetriever(env, thiz, retriever);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450}
451
452// JNI mapping between Java methods and native methods
453static JNINativeMethod nativeMethods[] = {
James Dong17524dc2011-05-04 13:41:58 -0700454 {
455 "_setDataSource",
Andreas Huberd2506a52014-01-29 10:32:46 -0800456 "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
James Dong17524dc2011-05-04 13:41:58 -0700457 (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
458 },
459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
James Dongfaf09ba2010-12-02 17:42:08 -0800461 {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
James Dongdf9b3492011-01-04 15:03:48 -0800463 {"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 {"release", "()V", (void *)android_media_MediaMetadataRetriever_release},
465 {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
466 {"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
Marco Nelissen4935d052009-08-03 11:12:58 -0700467 {"native_init", "()V", (void *)android_media_MediaMetadataRetriever_native_init},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468};
469
Marco Nelissen4935d052009-08-03 11:12:58 -0700470// This function only registers the native methods, and is called from
471// JNI_OnLoad in android_media_MediaPlayer.cpp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472int register_android_media_MediaMetadataRetriever(JNIEnv *env)
473{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 return AndroidRuntime::registerNativeMethods
Marco Nelissen4935d052009-08-03 11:12:58 -0700475 (env, kClassPathName, nativeMethods, NELEM(nativeMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476}