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