Movie.cpp revision 3449789b9ca58fee7e5cd02ff89d544f4a6bc9b5
1304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger#include "Canvas.h"
2ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "ScopedLocalRef.h"
37315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III#include "SkFrontBufferedStream.h"
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMovie.h"
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkStream.h"
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkTemplates.h"
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkUtils.h"
9ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "Utils.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CreateJavaOutputStreamAdaptor.h"
116ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
14b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h>
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass       gMovie_class;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID    gMovie_constructorMethodID;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID     gMovie_nativeInstanceID;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjobject create_jmovie(JNIEnv* env, SkMovie* moov) {
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == moov) {
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
27cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes    return env->NewObject(gMovie_class, gMovie_constructorMethodID,
28dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat            static_cast<jlong>(reinterpret_cast<uintptr_t>(moov)));
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkMovie* J2Movie(JNIEnv* env, jobject movie) {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(movie);
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env->IsInstanceOf(movie, gMovie_class));
35dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    SkMovie* m = (SkMovie*)env->GetLongField(movie, gMovie_nativeInstanceID);
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(m);
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return m;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
42dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_width(JNIEnv* env, jobject movie) {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
44dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->width());
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
47dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_height(JNIEnv* env, jobject movie) {
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
49dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->height());
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_isOpaque(JNIEnv* env, jobject movie) {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
54dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return J2Movie(env, movie)->isOpaque() ? JNI_TRUE : JNI_FALSE;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
57dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_duration(JNIEnv* env, jobject movie) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
59dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return static_cast<jint>(J2Movie(env, movie)->duration());
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jboolean movie_setTime(JNIEnv* env, jobject movie, jint ms) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
64dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    return J2Movie(env, movie)->setTime(ms) ? JNI_TRUE : JNI_FALSE;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenbergerstatic void movie_draw(JNIEnv* env, jobject movie, jlong canvasHandle,
68ab22c1c792bc5f422a029a4ab6a23861e44136d8Derek Sollenberger                       jfloat fx, jfloat fy, jlong paintHandle) {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_VOID(env, movie);
70304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger
71304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    android::Canvas* c = reinterpret_cast<android::Canvas*>(canvasHandle);
72304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    const android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle);
73304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger
74304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    // Canvas should never be NULL. However paint is an optional parameter and
75304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    // therefore may be NULL.
76304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    SkASSERT(c != NULL);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* m = J2Movie(env, movie);
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkBitmap& b = m->bitmap();
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
812e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III    c->drawBitmap(b, fx, fy, p);
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
857315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
867315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    if (asset == NULL) return NULL;
873449789b9ca58fee7e5cd02ff89d544f4a6bc9b5Leon Scroggins III    SkAutoTDelete<SkStreamRewindable> stream(new android::AssetStreamAdaptor(asset));
887315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkMovie* moov = SkMovie::DecodeStream(stream.get());
897315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    return create_jmovie(env, moov);
907315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III}
917315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
938451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, istream);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
967315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    jbyteArray byteArray = env->NewByteArray(16*1024);
977315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    ScopedLocalRef<jbyteArray> scoper(env, byteArray);
987315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == strm) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1037315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // Need to buffer enough input to be able to rewind as much as might be read by a decoder
1047315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // trying to determine the stream's format. The only decoder for movies is GIF, which
1057315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // will only read 6.
1067315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    // FIXME: Get this number from SkImageDecoder
1073449789b9ca58fee7e5cd02ff89d544f4a6bc9b5Leon Scroggins III    // bufferedStream takes ownership of strm
1083449789b9ca58fee7e5cd02ff89d544f4a6bc9b5Leon Scroggins III    SkAutoTDelete<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
1097315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkASSERT(bufferedStream.get() != NULL);
1107315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III
1117315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    SkMovie* moov = SkMovie::DecodeStream(bufferedStream);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     jbyteArray byteArray,
117dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat                                     jint offset, jint length) {
1188451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, byteArray);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int totalLength = env->GetArrayLength(byteArray);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((offset | length) < 0 || offset + length > totalLength) {
1238451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowAIOOBE(env);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaByteArray   ar(env, byteArray);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
132dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
133dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    SkMovie* movie = (SkMovie*) movieHandle;
13408d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka    delete movie;
13508d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka}
13608d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "width",    "()I",  (void*)movie_width  },
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "height",   "()I",  (void*)movie_height  },
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "isOpaque", "()Z",  (void*)movie_isOpaque  },
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "duration", "()I",  (void*)movie_duration  },
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "setTime",  "(I)Z", (void*)movie_setTime  },
145304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger    {   "nDraw",    "(JFFJ)V",
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_draw  },
147dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    { "nativeDecodeAsset", "(J)Landroid/graphics/Movie;",
1487315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III                            (void*)movie_decodeAsset },
1497315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III    { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeStream },
151dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat    { "nativeDestructor","(J)V", (void*)movie_destructor },
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "decodeByteArray", "([BII)Landroid/graphics/Movie;",
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeByteArray },
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Movie(JNIEnv* env)
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
158ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gMovie_class = android::FindClassOrDie(env, "android/graphics/Movie");
159ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gMovie_class = android::MakeGlobalRefOrDie(env, gMovie_class);
1608451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
161ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gMovie_constructorMethodID = android::GetMethodIDOrDie(env, gMovie_class, "<init>", "(J)V");
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
163ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    gMovie_nativeInstanceID = android::GetFieldIDOrDie(env, gMovie_class, "mNativeMovie", "J");
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
165ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Movie", gMethods, NELEM(gMethods));
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
167