FrameSequenceJNI.cpp revision a3ac0a2df64dcfb8b0b01f1cf05e9afd1439e1f4
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<jint>(frameSequence), 41 frameSequence->getWidth(), 42 frameSequence->getHeight(), 43 frameSequence->getFrameCount(), 44 frameSequence->isOpaque()); 45} 46 47static jobject nativeDecodeByteArray(JNIEnv* env, jobject clazz, 48 jbyteArray byteArray, jint offset, jint length) { 49 jbyte* bytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(byteArray, NULL)); 50 if (bytes == NULL) { 51 jniThrowException(env, ILLEGAL_STATE_EXEPTION, 52 "couldn't read array bytes"); 53 return NULL; 54 } 55 bytes += offset; 56 MemoryStream stream(bytes, length); 57 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, 70 jint frameSequenceInt) { 71 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceInt); 72 delete frameSequence; 73} 74 75static jint nativeCreateState(JNIEnv* env, jobject clazz, jint frameSequenceInt) { 76 FrameSequence* frameSequence = reinterpret_cast<FrameSequence*>(frameSequenceInt); 77 FrameSequenceState* state = frameSequence->createState(); 78 return reinterpret_cast<jint>(state); 79} 80 81//////////////////////////////////////////////////////////////////////////////// 82// Frame sequence state 83//////////////////////////////////////////////////////////////////////////////// 84 85static void nativeDestroyState( 86 JNIEnv* env, jobject clazz, jint frameSequenceStateInt) { 87 FrameSequenceState* frameSequenceState = 88 reinterpret_cast<FrameSequenceState*>(frameSequenceStateInt); 89 delete frameSequenceState; 90} 91 92static jlong JNICALL nativeGetFrame( 93 JNIEnv* env, jobject clazz, jint frameSequenceStateInt, jint frameNr, 94 jobject bitmap, jint previousFrameNr) { 95 FrameSequenceState* frameSequenceState = 96 reinterpret_cast<FrameSequenceState*>(frameSequenceStateInt); 97 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", 131 "(I)V", 132 (void*) nativeDestroyFrameSequence 133 }, 134 { "nativeCreateState", 135 "(I)I", 136 (void*) nativeCreateState 137 }, 138 { "nativeGetFrame", 139 "(IILandroid/graphics/Bitmap;I)J", 140 (void*) nativeGetFrame 141 }, 142 { "nativeDestroyFrameSequence", 143 "(I)V", 144 (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 158 gFrameSequenceClassInfo.ctor = env->GetMethodID(gFrameSequenceClassInfo.clazz, "<init>", "(IIIIZ)V"); 159 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} 166