1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
#include "CreateJavaOutputStreamAdaptor.h"
#include "GraphicsJNI.h"
#include "ScopedLocalRef.h"
#include "SkFrontBufferedStream.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "SkUtils.h"
#include "Utils.h"
#include "core_jni_helpers.h"
#include <androidfw/Asset.h>
#include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <jni.h>
#include <netinet/in.h>
static jclass gMovie_class;
static jmethodID gMovie_constructorMethodID;
static jfieldID gMovie_nativeInstanceID;
jobject create_jmovie(JNIEnv* env, SkMovie* moov) {
if (NULL == moov) {
return NULL;
}
return env->NewObject(gMovie_class, gMovie_constructorMethodID,
static_cast<jlong>(reinterpret_cast<uintptr_t>(moov)));
}
static SkMovie* J2Movie(JNIEnv* env, jobject movie) {
SkASSERT(env);
SkASSERT(movie);
SkASSERT(env->IsInstanceOf(movie, gMovie_class));
SkMovie* m = (SkMovie*)env->GetLongField(movie, gMovie_nativeInstanceID);
SkASSERT(m);
return m;
}
///////////////////////////////////////////////////////////////////////////////
static jint movie_width(JNIEnv* env, jobject movie) {
NPE_CHECK_RETURN_ZERO(env, movie);
return static_cast<jint>(J2Movie(env, movie)->width());
}
static jint movie_height(JNIEnv* env, jobject movie) {
NPE_CHECK_RETURN_ZERO(env, movie);
return static_cast<jint>(J2Movie(env, movie)->height());
}
static jboolean movie_isOpaque(JNIEnv* env, jobject movie) {
NPE_CHECK_RETURN_ZERO(env, movie);
return J2Movie(env, movie)->isOpaque() ? JNI_TRUE : JNI_FALSE;
}
static jint movie_duration(JNIEnv* env, jobject movie) {
NPE_CHECK_RETURN_ZERO(env, movie);
return static_cast<jint>(J2Movie(env, movie)->duration());
}
static jboolean movie_setTime(JNIEnv* env, jobject movie, jint ms) {
NPE_CHECK_RETURN_ZERO(env, movie);
return J2Movie(env, movie)->setTime(ms) ? JNI_TRUE : JNI_FALSE;
}
static void movie_draw(JNIEnv* env, jobject movie, jlong canvasHandle,
jfloat fx, jfloat fy, jlong paintHandle) {
NPE_CHECK_RETURN_VOID(env, movie);
android::Canvas* c = reinterpret_cast<android::Canvas*>(canvasHandle);
const android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle);
// Canvas should never be NULL. However paint is an optional parameter and
// therefore may be NULL.
SkASSERT(c != NULL);
SkMovie* m = J2Movie(env, movie);
const SkBitmap& b = m->bitmap();
c->drawBitmap(b, fx, fy, p);
}
static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
if (asset == NULL) return NULL;
android::AssetStreamAdaptor stream(asset);
SkMovie* moov = SkMovie::DecodeStream(&stream);
return create_jmovie(env, moov);
}
static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
NPE_CHECK_RETURN_ZERO(env, istream);
jbyteArray byteArray = env->NewByteArray(16*1024);
ScopedLocalRef<jbyteArray> scoper(env, byteArray);
SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
if (NULL == strm) {
return 0;
}
// Need to buffer enough input to be able to rewind as much as might be read by a decoder
// trying to determine the stream's format. The only decoder for movies is GIF, which
// will only read 6.
// FIXME: Get this number from SkImageDecoder
// bufferedStream takes ownership of strm
std::unique_ptr<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
SkASSERT(bufferedStream.get() != NULL);
SkMovie* moov = SkMovie::DecodeStream(bufferedStream.get());
return create_jmovie(env, moov);
}
static jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
jbyteArray byteArray,
jint offset, jint length) {
NPE_CHECK_RETURN_ZERO(env, byteArray);
int totalLength = env->GetArrayLength(byteArray);
if ((offset | length) < 0 || offset + length > totalLength) {
doThrowAIOOBE(env);
return 0;
}
AutoJavaByteArray ar(env, byteArray);
SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
return create_jmovie(env, moov);
}
static void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
SkMovie* movie = (SkMovie*) movieHandle;
delete movie;
}
//////////////////////////////////////////////////////////////////////////////////////////////
static const JNINativeMethod gMethods[] = {
{ "width", "()I", (void*)movie_width },
{ "height", "()I", (void*)movie_height },
{ "isOpaque", "()Z", (void*)movie_isOpaque },
{ "duration", "()I", (void*)movie_duration },
{ "setTime", "(I)Z", (void*)movie_setTime },
{ "nDraw", "(JFFJ)V",
(void*)movie_draw },
{ "nativeDecodeAsset", "(J)Landroid/graphics/Movie;",
(void*)movie_decodeAsset },
{ "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
(void*)movie_decodeStream },
{ "nativeDestructor","(J)V", (void*)movie_destructor },
{ "decodeByteArray", "([BII)Landroid/graphics/Movie;",
(void*)movie_decodeByteArray },
};
int register_android_graphics_Movie(JNIEnv* env)
{
gMovie_class = android::FindClassOrDie(env, "android/graphics/Movie");
gMovie_class = android::MakeGlobalRefOrDie(env, gMovie_class);
gMovie_constructorMethodID = android::GetMethodIDOrDie(env, gMovie_class, "<init>", "(J)V");
gMovie_nativeInstanceID = android::GetFieldIDOrDie(env, gMovie_class, "mNativeMovie", "J");
return android::RegisterMethodsOrDie(env, "android/graphics/Movie", gMethods, NELEM(gMethods));
}
|