FrameSequenceJNI.cpp revision 2e20149189469ac45426c3f1f7df067995a5e811
1/* 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, 40 reinterpret_cast<jlong>(frameSequence), 41 frameSequence->getWidth(), 42 frameSequence->getHeight(), 43 frameSequence->isOpaque(), 44 frameSequence->getFrameCount(), 45 frameSequence->getDefaultLoopCount()); 46} 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 } 56 bytes += offset; 57 MemoryStream stream(bytes, length); 58 FrameSequence* frameSequence = FrameSequence::create(&stream); 59 env->ReleasePrimitiveArrayCritical(byteArray, bytes, 0); 60 return createJavaFrameSequence(env, frameSequence); 61} 62 63static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, 64 jobject istream, jbyteArray byteArray) { 65 JavaInputStream stream(env, istream, byteArray); 66 FrameSequence* frameSequence = FrameSequence::create(&stream); 67 return createJavaFrameSequence(env, frameSequence); 68} 69 70static void nativeDestroyFrameSequence(JNIEnv* env, jobject clazz, 71 jlong frameSequenceLong) { 72 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong); 73 delete frameSequence; 74} 75 76static jlong nativeCreateState(JNIEnv* env, jobject clazz, jlong frameSequenceLong) { 77 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceLong); 78 FrameSequenceState* state = frameSequence->createState(); 79 return reinterpret_cast<jlong>(state); 80} 81 82//////////////////////////////////////////////////////////////////////////////// 83// Frame sequence state 84//////////////////////////////////////////////////////////////////////////////// 85 86static void nativeDestroyState( 87 JNIEnv* env, jobject clazz, jlong frameSequenceStateLong) { 88 FrameSequenceState* frameSequenceState = 89 reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong); 90 delete frameSequenceState; 91} 92 93static jlong JNICALL nativeGetFrame( 94 JNIEnv* env, jobject clazz, jlong frameSequenceStateLong, jint frameNr, 95 jobject bitmap, jint previousFrameNr) { 96 FrameSequenceState* frameSequenceState = 97 reinterpret_cast<FrameSequenceState*>(frameSequenceStateLong); 98 int ret; 99 AndroidBitmapInfo info; 100 void* pixels; 101 if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) { 102 103 jniThrowException(env, ILLEGAL_STATE_EXEPTION, 104 "Couldn't get info from Bitmap "); 105 return 0; 106 } 107 108 if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) { 109 jniThrowException(env, ILLEGAL_STATE_EXEPTION, 110 "Bitmap pixels couldn't be locked"); 111 return 0; 112 } 113 114 int pixelStride = info.stride >> 2; 115 jlong delayMs = frameSequenceState->drawFrame(frameNr, 116 (Color8888*) pixels, pixelStride, previousFrameNr); 117 118 AndroidBitmap_unlockPixels(env, bitmap); 119 return delayMs; 120} 121 122static JNINativeMethod gMethods[] = { 123 { "nativeDecodeByteArray", 124 "([BII)L" JNI_PACKAGE "/FrameSequence;", 125 (void*) nativeDecodeByteArray 126 }, 127 { "nativeDecodeStream", 128 "(Ljava/io/InputStream;[B)L" JNI_PACKAGE "/FrameSequence;", 129 (void*) nativeDecodeStream 130 }, 131 { "nativeDestroyFrameSequence", 132 "(J)V", 133 (void*) nativeDestroyFrameSequence 134 }, 135 { "nativeCreateState", 136 "(J)J", 137 (void*) nativeCreateState 138 }, 139 { "nativeGetFrame", 140 "(JILandroid/graphics/Bitmap;I)J", 141 (void*) nativeGetFrame 142 }, 143 { "nativeDestroyState", 144 "(J)V", 145 (void*) nativeDestroyState 146 }, 147}; 148 149jint FrameSequence_OnLoad(JNIEnv* env) { 150 // Get jclass with env->FindClass. 151 // Register methods with env->RegisterNatives. 152 gFrameSequenceClassInfo.clazz = env->FindClass(JNI_PACKAGE "/FrameSequence"); 153 if (!gFrameSequenceClassInfo.clazz) { 154 ALOGW("Failed to find " JNI_PACKAGE "/FrameSequence"); 155 return -1; 156 } 157 gFrameSequenceClassInfo.clazz = (jclass)env->NewGlobalRef(gFrameSequenceClassInfo.clazz); 158 159 gFrameSequenceClassInfo.ctor = env->GetMethodID(gFrameSequenceClassInfo.clazz, "<init>", "(JIIZII)V"); 160 if (!gFrameSequenceClassInfo.ctor) { 161 ALOGW("Failed to find constructor for FrameSequence - was it stripped?"); 162 return -1; 163 } 164 165 return env->RegisterNatives(gFrameSequenceClassInfo.clazz, gMethods, METHOD_COUNT(gMethods)); 166} 167