blob: 08a73bc743999489e6d61c7e098c70b9852fd565 [file] [log] [blame]
Chris Craika3ac0a22014-01-06 12:43:42 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <android/bitmap.h>
18#include "JNIHelpers.h"
19#include "utils/log.h"
20#include "FrameSequence.h"
21
22#include "FrameSequenceJNI.h"
23
24#define JNI_PACKAGE "android/support/rastermill"
25
26static struct {
27 jclass clazz;
28 jmethodID ctor;
29} gFrameSequenceClassInfo;
30
31////////////////////////////////////////////////////////////////////////////////
32// Frame sequence
33////////////////////////////////////////////////////////////////////////////////
34
35static jobject createJavaFrameSequence(JNIEnv* env, FrameSequence* frameSequence) {
36 if (!frameSequence) {
37 return NULL;
38 }
39 return env->NewObject(gFrameSequenceClassInfo.clazz, gFrameSequenceClassInfo.ctor,
Chris Craike36c5d62014-01-13 19:37:04 -080040 reinterpret_cast<jlong>(frameSequence),
Chris Craika3ac0a22014-01-06 12:43:42 -080041 frameSequence->getWidth(),
42 frameSequence->getHeight(),
Chris Craike36c5d62014-01-13 19:37:04 -080043 frameSequence->isOpaque(),
Chris Craika3ac0a22014-01-06 12:43:42 -080044 frameSequence->getFrameCount(),
Chris Craike36c5d62014-01-13 19:37:04 -080045 frameSequence->getDefaultLoopCount());
Chris Craika3ac0a22014-01-06 12:43:42 -080046}
47
48static jobject nativeDecodeByteArray(JNIEnv* env, jobject clazz,
49 jbyteArray byteArray, jint offset, jint length) {
50 jbyte* bytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(byteArray, NULL));
51 if (bytes == NULL) {
52 jniThrowException(env, ILLEGAL_STATE_EXEPTION,
53 "couldn't read array bytes");
54 return NULL;
55 }
Chris Craik9d34bc32014-04-09 16:31:18 -070056 MemoryStream stream(bytes + offset, length);
Chris Craika3ac0a22014-01-06 12:43:42 -080057 FrameSequence* frameSequence = FrameSequence::create(&stream);
58 env->ReleasePrimitiveArrayCritical(byteArray, bytes, 0);
59 return createJavaFrameSequence(env, frameSequence);
60}
61
62static jobject nativeDecodeStream(JNIEnv* env, jobject clazz,
63 jobject istream, jbyteArray byteArray) {
64 JavaInputStream stream(env, istream, byteArray);
65 FrameSequence* frameSequence = FrameSequence::create(&stream);
66 return createJavaFrameSequence(env, frameSequence);
67}
68
69static void nativeDestroyFrameSequence(JNIEnv* env, jobject clazz,
Chris Craike36c5d62014-01-13 19:37:04 -080070 jlong frameSequenceLong) {
71 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong);
Chris Craika3ac0a22014-01-06 12:43:42 -080072 delete frameSequence;
73}
74
Chris Craike36c5d62014-01-13 19:37:04 -080075static jlong nativeCreateState(JNIEnv* env, jobject clazz, jlong frameSequenceLong) {
76 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong);
Chris Craika3ac0a22014-01-06 12:43:42 -080077 FrameSequenceState* state = frameSequence->createState();
Chris Craike36c5d62014-01-13 19:37:04 -080078 return reinterpret_cast<jlong>(state);
Chris Craika3ac0a22014-01-06 12:43:42 -080079}
80
81////////////////////////////////////////////////////////////////////////////////
82// Frame sequence state
83////////////////////////////////////////////////////////////////////////////////
84
85static void nativeDestroyState(
Chris Craike36c5d62014-01-13 19:37:04 -080086 JNIEnv* env, jobject clazz, jlong frameSequenceStateLong) {
Chris Craika3ac0a22014-01-06 12:43:42 -080087 FrameSequenceState* frameSequenceState =
Chris Craike36c5d62014-01-13 19:37:04 -080088 reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong);
Chris Craika3ac0a22014-01-06 12:43:42 -080089 delete frameSequenceState;
90}
91
92static jlong JNICALL nativeGetFrame(
Chris Craike36c5d62014-01-13 19:37:04 -080093 JNIEnv* env, jobject clazz, jlong frameSequenceStateLong, jint frameNr,
Chris Craika3ac0a22014-01-06 12:43:42 -080094 jobject bitmap, jint previousFrameNr) {
95 FrameSequenceState* frameSequenceState =
Chris Craike36c5d62014-01-13 19:37:04 -080096 reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong);
Chris Craika3ac0a22014-01-06 12:43:42 -080097 int ret;
98 AndroidBitmapInfo info;
99 void* pixels;
100 if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
101
102 jniThrowException(env, ILLEGAL_STATE_EXEPTION,
103 "Couldn't get info from Bitmap ");
104 return 0;
105 }
106
107 if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
108 jniThrowException(env, ILLEGAL_STATE_EXEPTION,
109 "Bitmap pixels couldn't be locked");
110 return 0;
111 }
112
113 int pixelStride = info.stride >> 2;
114 jlong delayMs = frameSequenceState->drawFrame(frameNr,
115 (Color8888*) pixels, pixelStride, previousFrameNr);
116
117 AndroidBitmap_unlockPixels(env, bitmap);
118 return delayMs;
119}
120
121static JNINativeMethod gMethods[] = {
122 { "nativeDecodeByteArray",
123 "([BII)L" JNI_PACKAGE "/FrameSequence;",
124 (void*) nativeDecodeByteArray
125 },
126 { "nativeDecodeStream",
127 "(Ljava/io/InputStream;[B)L" JNI_PACKAGE "/FrameSequence;",
128 (void*) nativeDecodeStream
129 },
130 { "nativeDestroyFrameSequence",
Chris Craike36c5d62014-01-13 19:37:04 -0800131 "(J)V",
Chris Craika3ac0a22014-01-06 12:43:42 -0800132 (void*) nativeDestroyFrameSequence
133 },
134 { "nativeCreateState",
Chris Craike36c5d62014-01-13 19:37:04 -0800135 "(J)J",
Chris Craika3ac0a22014-01-06 12:43:42 -0800136 (void*) nativeCreateState
137 },
138 { "nativeGetFrame",
Chris Craike36c5d62014-01-13 19:37:04 -0800139 "(JILandroid/graphics/Bitmap;I)J",
Chris Craika3ac0a22014-01-06 12:43:42 -0800140 (void*) nativeGetFrame
141 },
Chris Craik2e201492014-01-14 18:36:50 -0800142 { "nativeDestroyState",
Chris Craike36c5d62014-01-13 19:37:04 -0800143 "(J)V",
Chris Craika3ac0a22014-01-06 12:43:42 -0800144 (void*) nativeDestroyState
145 },
146};
147
148jint FrameSequence_OnLoad(JNIEnv* env) {
149 // Get jclass with env->FindClass.
150 // Register methods with env->RegisterNatives.
151 gFrameSequenceClassInfo.clazz = env->FindClass(JNI_PACKAGE "/FrameSequence");
152 if (!gFrameSequenceClassInfo.clazz) {
153 ALOGW("Failed to find " JNI_PACKAGE "/FrameSequence");
154 return -1;
155 }
156 gFrameSequenceClassInfo.clazz = (jclass)env->NewGlobalRef(gFrameSequenceClassInfo.clazz);
157
Chris Craike36c5d62014-01-13 19:37:04 -0800158 gFrameSequenceClassInfo.ctor = env->GetMethodID(gFrameSequenceClassInfo.clazz, "<init>", "(JIIZII)V");
Chris Craika3ac0a22014-01-06 12:43:42 -0800159 if (!gFrameSequenceClassInfo.ctor) {
160 ALOGW("Failed to find constructor for FrameSequence - was it stripped?");
161 return -1;
162 }
163
164 return env->RegisterNatives(gFrameSequenceClassInfo.clazz, gMethods, METHOD_COUNT(gMethods));
165}